<commit_before>#![feature(custom_attribute)]

extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;
use syn::Field;

#[proc_macro_derive(OptionalStruct, attributes(optional_name, optional_derive))]
pub fn optional_struct(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_derive_input(&s).unwrap();
    let gen = create_optional_struct(&ast);
    gen.parse().unwrap()
}

fn create_optional_struct(ast: &syn::DeriveInput) -> quote::Tokens {
    let (struct_name, derives) = parse_attributes(&ast);

    if let syn::Body::Struct(ref variant_data) = ast.body {
        if let &syn::VariantData::Struct(ref fields) = variant_data {
            return create_non_tuple_struct(fields, struct_name, derives);
        }
    }

    panic!("OptionalStruct only supports non-tuple structs for now");
}

fn parse_attributes(ast: &syn::DeriveInput) -> (syn::Ident, quote::Tokens) {
    let mut struct_name = String::from("Optional");
    struct_name.push_str(&ast.ident.to_string());
    let mut struct_name = syn::Ident::new(struct_name);
    let mut derives = quote!{};

    for attribute in &ast.attrs {
        match &attribute.value {
            &syn::MetaItem::Word(_) => panic!("No word attribute is supported"),
            &syn::MetaItem::NameValue(ref name, ref value) => {
                if name != "optional_name" {
                    panic!("Only optional_name is supported");
                }

                match value {
                    &syn::Lit::Str(ref name_value, _) => {
                        struct_name = syn::Ident::new(name_value.clone())
                    }
                    _ => panic!("optional_name should be a string"),
                }
            }
            &syn::MetaItem::List(ref name, ref values) => {
                if name != "optional_derive" {
                    panic!("Only optional_derive are supported");
                }

                for value in values {
                    match value {
                        &syn::NestedMetaItem::MetaItem(ref item) => {
                            match item {
                                &syn::MetaItem::Word(ref derive_name) => {
                                    derives = quote!{ #derives, #derive_name }
                                }
                                _ => {
                                    panic!("Only traits name are supported inside optional_struct")
                                }
                            }
                        }
                        &syn::NestedMetaItem::Literal(_) => {
                            panic!("Only traits name are supported inside optional_struct")
                        }
                    }
                }
            }
        }
    }

    derives = quote!{ #[derive(#derives)] };
    (struct_name, derives)
}

fn create_non_tuple_struct(
    fields: &Vec<Field>,
    struct_name: syn::Ident,
    derives: quote::Tokens,
) -> quote::Tokens {
    let mut attributes = quote!{};
    let mut assigners = quote!{};
    for field in fields {
        let ref type_name = &field.ty;
        let ref field_name = &field.ident.clone().unwrap();
        let next_attribute;
        let next_assigner;

        if field_name.to_string().starts_with("Option<") {
            next_attribute = quote!{ pub #field_name: #type_name>, };
            next_assigner = quote!{ self.#field_name = optional_struct.#field_name };
        } else {
            next_attribute = quote! { pub #field_name: Option<#type_name>, };
            next_assigner =
                quote!{
                    if let Some(attribute) = optional_struct.#field_name {
                        self.#field_name = attribute;
                    }
                };
        }

        assigners = quote!{ #assigners #next_assigner };
        attributes = quote!{ #attributes #next_attribute };
    }

    quote!{
        #derives
        pub struct #struct_name {
            #attributes
        }

        impl #struct_name {
            pub fn apply_options(&mut self, optional_struct: &#struct_name) {
                #assigners
            }
        }
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
<commit_msg>fix optional_derive not expanding<commit_after>#![feature(custom_attribute)]

extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;
use syn::Field;
use syn::Ident;

#[proc_macro_derive(OptionalStruct, attributes(optional_name, optional_derive))]
pub fn optional_struct(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_derive_input(&s).unwrap();
    let gen = create_optional_struct(&ast);
    gen.parse().unwrap()
}

fn create_optional_struct(ast: &syn::DeriveInput) -> quote::Tokens {
    let (orignal_struct_name, struct_name, derives) = parse_attributes(&ast);

    if let syn::Body::Struct(ref variant_data) = ast.body {
        if let &syn::VariantData::Struct(ref fields) = variant_data {
            return create_non_tuple_struct(fields, orignal_struct_name, struct_name, derives);
        }
    }

    panic!("OptionalStruct only supports non-tuple structs for now");
}

fn parse_attributes(ast: &syn::DeriveInput) -> (Ident, syn::Ident, quote::Tokens) {
    let orignal_struct_name = ast.ident.clone();
    let mut struct_name = String::from("Optional");
    struct_name.push_str(&ast.ident.to_string());
    let mut struct_name = Ident::new(struct_name);
    let mut derives = quote!{};

    for attribute in &ast.attrs {
        match &attribute.value {
            &syn::MetaItem::Word(_) => panic!("No word attribute is supported"),
            &syn::MetaItem::NameValue(ref name, ref value) => {
                if name != "optional_name" {
                    panic!("Only optional_name is supported");
                }

                match value {
                    &syn::Lit::Str(ref name_value, _) => {
                        struct_name = Ident::new(name_value.clone())
                    }
                    _ => panic!("optional_name should be a string"),
                }
            }
            &syn::MetaItem::List(ref name, ref values) => {
                if name != "optional_derive" {
                    panic!("Only optional_derive are supported");
                }

                for value in values {
                    match value {
                        &syn::NestedMetaItem::MetaItem(ref item) => {
                            match item {
                                &syn::MetaItem::Word(ref derive_name) => {
                                    derives = quote!{ #derive_name, #derives }
                                }
                                _ => {
                                    panic!("Only traits name are supported inside optional_struct")
                                }
                            }
                        }
                        &syn::NestedMetaItem::Literal(_) => {
                            panic!("Only traits name are supported inside optional_struct")
                        }
                    }
                }
            }
        }
    }

    derives = quote!{ #[derive(#derives)] };
    (orignal_struct_name, struct_name, derives)
}

fn create_non_tuple_struct(
    fields: &Vec<Field>,
    orignal_struct_name: Ident,
    struct_name: Ident,
    derives: quote::Tokens,
) -> quote::Tokens {
    let mut attributes = quote!{};
    let mut assigners = quote!{};
    for field in fields {
        let ref type_name = &field.ty;
        let ref field_name = &field.ident.clone().unwrap();
        let next_attribute;
        let next_assigner;

        if field_name.to_string().starts_with("Option<") {
            next_attribute = quote!{ pub #field_name: #type_name>, };
            next_assigner = quote!{ self.#field_name = optional_struct.#field_name };
        } else {
            next_attribute = quote! { pub #field_name: Option<#type_name>, };
            next_assigner =
                quote!{
                    if let Some(attribute) = optional_struct.#field_name {
                        self.#field_name = attribute;
                    }
                };
        }

        assigners = quote!{ #assigners #next_assigner };
        attributes = quote!{ #attributes #next_attribute };
    }

    quote!{
        #derives
        pub struct #struct_name {
            #attributes
        }

        impl #orignal_struct_name {
            pub fn apply_options(&mut self, optional_struct: &#struct_name) {
                #assigners
            }
        }
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
<|endoftext|>


<commit_before>//! Allocator logging.
//!
//! This allows for detailed logging for `ralloc`.

/// Log to the appropriate source.
///
/// The first argument defines the log level, the rest of the arguments are just `write!`-like
/// formatters.
#[macro_export]
macro_rules! log {
    (INTERNAL, $( $x:tt )*) => {
        log!(@["INTERNAL: ", 1], $( $x )*);
    };
    (DEBUG, $( $x:tt )*) => {
        log!(@["DEBUG:    ", 2], $( $x )*);
    };
    (CALL, $( $x:tt )*) => {
        log!(@["CALL:     ", 3], $( $x )*);
    };
    (NOTE, $( $x:tt )*) => {
        log!(@["NOTE:     ", 5], $( $x )*);
    };
    (WARNING, $( $x:tt )*) => {
        log!(@["WARNING:  ", 5], $( $x )*);
    };
    (ERROR, $( $x:tt )*) => {
        log!(@["ERROR:    ", 6], $( $x )*);
    };
    (@[$kind:expr, $lv:expr], $( $arg:expr ),*) => {
        #[cfg(feature = "log")]
        {
            use core::fmt::Write;

            use log::internal::{LogWriter, level};

            // Set the level.
            if level($lv) {
                // Print the pool state.
                let mut log = LogWriter::new();
                // Print the log message.
                let _ = write!(log, $kind);
                let _ = write!(log, $( $arg ),*);
                let _ = writeln!(log, " (at {}:{})", file!(), line!());
            }
        }
    };
}

/// Log with bookkeeper data to the appropriate source.
///
/// The first argument this takes is of the form `pool;cursor`, which is used to print the
/// block pools state. `cursor` is what the operation "revolves around" to give a sense of
/// position.
///
/// If the `;cursor` part is left out, no cursor will be printed.
///
/// The rest of the arguments are just normal formatters.
///
/// This logs to level 2.
#[macro_export]
macro_rules! bk_log {
    ($pool:expr, $( $arg:expr ),*) => {
        bk_log!($pool;(), $( $arg ),*);
    };
    ($bk:expr;$cur:expr, $( $arg:expr ),*) => {
        #[cfg(feature = "log")]
        {
            use log::internal::{IntoCursor, BlockLogger};

            log!(INTERNAL, "({:2}) {:10?} : {}", $bk.id, BlockLogger {
                cur: $cur.clone().into_cursor(),
                blocks: &$bk.pool,
            }, format_args!($( $arg ),*));
        }
    };
}

/// Make a runtime assertion.
///
/// The only way it differs from the one provided by `libcore` is the panicking strategy, which
/// allows for aborting, non-allocating panics when running the tests.
#[macro_export]
#[cfg(feature = "write")]
macro_rules! assert {
    ($e:expr) => {
        assert!($e, "No description.");
    };
    ($e:expr, $( $arg:expr ),*) => {{
        use core::intrinsics;

        if !$e {
            log!(ERROR, $( $arg ),*);

            #[allow(unused_unsafe)]
            unsafe {
                // LAST AUDIT: 2016-08-21 (Ticki).

                // Right now there is no safe interface exposed for this, but it is safe no matter
                // what.
                intrinsics::abort();
            }
        }
    }}
}

/// Make a runtime assertion in debug mode.
///
/// The only way it differs from the one provided by `libcore` is the panicking strategy, which
/// allows for aborting, non-allocating panics when running the tests.
#[cfg(feature = "write")]
#[macro_export]
macro_rules! debug_assert {
    // We force the programmer to provide explanation of their assertion.
    ($first:expr, $( $arg:tt )*) => {{
        if cfg!(debug_assertions) {
            assert!($first, $( $arg )*);
        }
    }}
}

/// Make a runtime equality assertion in debug mode.
///
/// The only way it differs from the one provided by `libcore` is the panicking strategy, which
/// allows for aborting, non-allocating panics when running the tests.
#[cfg(feature = "write")]
#[macro_export]
macro_rules! assert_eq {
    ($left:expr, $right:expr) => {{
        // We evaluate _once_.
        let left = &$left;
        let right = &$right;

        assert!(left == right, "(left: '{:?}', right: '{:?}')", left, right)
    }};
}

/// Top-secret module.
#[cfg(feature = "log")]
pub mod internal {
    use prelude::*;

    use core::cell::Cell;
    use core::fmt;
    use core::ops::Range;

    use shim::config;

    use sync;

    /// The log lock.
    ///
    /// This lock is used to avoid bungling and intertwining the log.
    #[cfg(not(feature = "no_log_lock"))]
    pub static LOG_LOCK: Mutex<()> = Mutex::new(());

    /// A log writer.
    ///
    /// This writes to the shim logger.
    pub struct LogWriter {
        /// The inner lock.
        #[cfg(not(feature = "no_log_lock"))]
        _lock: sync::MutexGuard<'static, ()>,
    }

    impl LogWriter {
        /// Standard error output.
        pub fn new() -> LogWriter {
            #[cfg(feature = "no_log_lock")]
            {
                LogWriter {}
            }

            #[cfg(not(feature = "no_log_lock"))]
            LogWriter {
                _lock: LOG_LOCK.lock(),
            }
        }
    }

    impl fmt::Write for LogWriter {
        fn write_str(&mut self, s: &str) -> fmt::Result {
            if config::log(s) == !0 {
                Err(fmt::Error)
            } else {
                Ok(())
            }
        }
    }

    /// A "cursor".
    ///
    /// Cursors represents a block or an interval in the log output. This trait is implemented for
    /// various types that can represent a cursor.
    pub trait Cursor {
        /// Iteration at n.
        ///
        /// This is called in the logging loop. The cursor should then write, what it needs, to the
        /// formatter if the underlying condition is true.
        ///
        /// For example, a plain position cursor will write `"|"` when `n == self.pos`.
        // TODO: Use an iterator instead.
        fn at(&self, f: &mut fmt::Formatter, n: usize) -> fmt::Result;

        /// The after hook.
        ///
        /// This is runned when the loop is over. The aim is to e.g. catch up if the cursor wasn't
        /// printed (i.e. is out of range).
        fn after(&self, f: &mut fmt::Formatter) -> fmt::Result;
    }

    /// Types that can be converted into a cursor.
    pub trait IntoCursor {
        /// The end result.
        type Cursor: Cursor;

        /// Convert this value into its equivalent cursor.
        fn into_cursor(self) -> Self::Cursor;
    }

    /// A single-point cursor.
    pub struct UniCursor {
        /// The position where this cursor will be placed.
        pos: usize,
        /// Is this cursor printed?
        ///
        /// This is used for the after hook.
        is_printed: Cell<bool>,
    }

    impl Cursor for UniCursor {
        fn at(&self, f: &mut fmt::Formatter, n: usize) -> fmt::Result {
            if self.pos == n {
                self.is_printed.set(true);
                write!(f, "|")?;
            }

            Ok(())
        }

        fn after(&self, f: &mut fmt::Formatter) -> fmt::Result {
            if !self.is_printed.get() {
                write!(f, "…|")?;
            }

            Ok(())
        }
    }

    impl IntoCursor for usize {
        type Cursor = UniCursor;

        fn into_cursor(self) -> UniCursor {
            UniCursor {
                pos: self,
                is_printed: Cell::new(false),
            }
        }
    }

    impl Cursor for () {
        fn at(&self, _: &mut fmt::Formatter, _: usize) -> fmt::Result {
            Ok(())
        }

        fn after(&self, _: &mut fmt::Formatter) -> fmt::Result {
            Ok(())
        }
    }

    impl IntoCursor for () {
        type Cursor = ();

        fn into_cursor(self) -> () {
            ()
        }
    }

    /// A interval/range cursor.
    ///
    /// The start of the range is marked by `[` and the end by `]`.
    pub struct RangeCursor {
        /// The range of this cursor.
        range: Range<usize>,
    }

    impl Cursor for RangeCursor {
        fn at(&self, f: &mut fmt::Formatter, n: usize) -> fmt::Result {
            if self.range.start == n {
                write!(f, "[")?;
            } else if self.range.end == n {
                write!(f, "]")?;
            }

            Ok(())
        }

        fn after(&self, _: &mut fmt::Formatter) -> fmt::Result {
            Ok(())
        }
    }

    impl IntoCursor for Range<usize> {
        type Cursor = RangeCursor;

        fn into_cursor(self) -> RangeCursor {
            RangeCursor { range: self }
        }
    }

    /// A "block logger".
    ///
    /// This intend to show the structure of a block pool. The syntax used is like:
    ///
    /// ```
    /// xxx__|xx_
    /// ```
    ///
    /// where `x` denotes an non-empty block. `_` denotes an empty block, with `|` representing the
    /// cursor.
    pub struct BlockLogger<'a, T> {
        /// The cursor.
        ///
        /// This is where the `|` will be printed.
        pub cur: T,
        /// The blocks.
        pub blocks: &'a [Block],
    }

    impl<'a, T: Cursor> fmt::Debug for BlockLogger<'a, T> {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            // TODO: Handle alignment etc.

            for (n, i) in self.blocks.iter().enumerate() {
                self.cur.at(f, n)?;

                if i.is_empty() {
                    // Empty block.
                    write!(f, "_")?;
                } else {
                    // Non-empty block.
                    write!(f, "x")?;
                }
            }

            self.cur.after(f)?;

            Ok(())
        }
    }

    /// Check if this log level is enabled.
    #[allow(absurd_extreme_comparisons)]
    #[inline]
    pub fn level(lv: u8) -> bool {
        lv >= config::MIN_LOG_LEVEL
    }
}
<commit_msg>Removed a warning when compiling with 'log' feature<commit_after>//! Allocator logging.
//!
//! This allows for detailed logging for `ralloc`.

/// Log to the appropriate source.
///
/// The first argument defines the log level, the rest of the arguments are just `write!`-like
/// formatters.
#[macro_export]
macro_rules! log {
    (INTERNAL, $( $x:tt )*) => {
        log!(@["INTERNAL: ", 1], $( $x )*);
    };
    (DEBUG, $( $x:tt )*) => {
        log!(@["DEBUG:    ", 2], $( $x )*);
    };
    (CALL, $( $x:tt )*) => {
        log!(@["CALL:     ", 3], $( $x )*);
    };
    (NOTE, $( $x:tt )*) => {
        log!(@["NOTE:     ", 5], $( $x )*);
    };
    (WARNING, $( $x:tt )*) => {
        log!(@["WARNING:  ", 5], $( $x )*);
    };
    (ERROR, $( $x:tt )*) => {
        log!(@["ERROR:    ", 6], $( $x )*);
    };
    (@[$kind:expr, $lv:expr], $( $arg:expr ),*) => {
        #[cfg(feature = "log")]
        {
            use core::fmt::Write;

            use log::internal::{LogWriter, level};

            // Set the level.
            if level($lv) {
                // Print the pool state.
                let mut log = LogWriter::new();
                // Print the log message.
                let _ = write!(log, $kind);
                let _ = write!(log, $( $arg ),*);
                let _ = writeln!(log, " (at {}:{})", file!(), line!());
            }
        }
    };
}

/// Log with bookkeeper data to the appropriate source.
///
/// The first argument this takes is of the form `pool;cursor`, which is used to print the
/// block pools state. `cursor` is what the operation "revolves around" to give a sense of
/// position.
///
/// If the `;cursor` part is left out, no cursor will be printed.
///
/// The rest of the arguments are just normal formatters.
///
/// This logs to level 2.
#[macro_export]
macro_rules! bk_log {
    ($pool:expr, $( $arg:expr ),*) => {
        bk_log!($pool;(), $( $arg ),*);
    };
    ($bk:expr;$cur:expr, $( $arg:expr ),*) => {
        #[cfg(feature = "log")]
        {
            use log::internal::{IntoCursor, BlockLogger};

            log!(INTERNAL, "({:2}) {:10?} : {}", $bk.id, BlockLogger {
                cur: $cur.clone().into_cursor(),
                blocks: &$bk.pool,
            }, format_args!($( $arg ),*));
        }
    };
}

/// Make a runtime assertion.
///
/// The only way it differs from the one provided by `libcore` is the panicking strategy, which
/// allows for aborting, non-allocating panics when running the tests.
#[macro_export]
#[cfg(feature = "write")]
macro_rules! assert {
    ($e:expr) => {
        assert!($e, "No description.");
    };
    ($e:expr, $( $arg:expr ),*) => {{
        use core::intrinsics;

        if !$e {
            log!(ERROR, $( $arg ),*);

            #[allow(unused_unsafe)]
            unsafe {
                // LAST AUDIT: 2016-08-21 (Ticki).

                // Right now there is no safe interface exposed for this, but it is safe no matter
                // what.
                intrinsics::abort();
            }
        }
    }}
}

/// Make a runtime assertion in debug mode.
///
/// The only way it differs from the one provided by `libcore` is the panicking strategy, which
/// allows for aborting, non-allocating panics when running the tests.
#[cfg(feature = "write")]
#[macro_export]
macro_rules! debug_assert {
    // We force the programmer to provide explanation of their assertion.
    ($first:expr, $( $arg:tt )*) => {{
        if cfg!(debug_assertions) {
            assert!($first, $( $arg )*);
        }
    }}
}

/// Make a runtime equality assertion in debug mode.
///
/// The only way it differs from the one provided by `libcore` is the panicking strategy, which
/// allows for aborting, non-allocating panics when running the tests.
#[cfg(feature = "write")]
#[macro_export]
macro_rules! assert_eq {
    ($left:expr, $right:expr) => {{
        // We evaluate _once_.
        let left = &$left;
        let right = &$right;

        assert!(left == right, "(left: '{:?}', right: '{:?}')", left, right)
    }};
}

/// Top-secret module.
#[cfg(feature = "log")]
pub mod internal {
    use prelude::*;

    use core::cell::Cell;
    use core::fmt;
    use core::ops::Range;

    use shim::config;

    use sync;

    /// The log lock.
    ///
    /// This lock is used to avoid bungling and intertwining the log.
    #[cfg(not(feature = "no_log_lock"))]
    pub static LOG_LOCK: Mutex<()> = Mutex::new(());

    /// A log writer.
    ///
    /// This writes to the shim logger.
    pub struct LogWriter {
        /// The inner lock.
        #[cfg(not(feature = "no_log_lock"))]
        _lock: sync::MutexGuard<'static, ()>,
    }

    impl LogWriter {
        /// Standard error output.
        pub fn new() -> LogWriter {
            #[cfg(feature = "no_log_lock")]
            {
                LogWriter {}
            }

            #[cfg(not(feature = "no_log_lock"))]
            LogWriter {
                _lock: LOG_LOCK.lock(),
            }
        }
    }

    impl fmt::Write for LogWriter {
        fn write_str(&mut self, s: &str) -> fmt::Result {
            if config::log(s) == !0 {
                Err(fmt::Error)
            } else {
                Ok(())
            }
        }
    }

    /// A "cursor".
    ///
    /// Cursors represents a block or an interval in the log output. This trait is implemented for
    /// various types that can represent a cursor.
    pub trait Cursor {
        /// Iteration at n.
        ///
        /// This is called in the logging loop. The cursor should then write, what it needs, to the
        /// formatter if the underlying condition is true.
        ///
        /// For example, a plain position cursor will write `"|"` when `n == self.pos`.
        // TODO: Use an iterator instead.
        fn at(&self, f: &mut fmt::Formatter, n: usize) -> fmt::Result;

        /// The after hook.
        ///
        /// This is runned when the loop is over. The aim is to e.g. catch up if the cursor wasn't
        /// printed (i.e. is out of range).
        fn after(&self, f: &mut fmt::Formatter) -> fmt::Result;
    }

    /// Types that can be converted into a cursor.
    pub trait IntoCursor {
        /// The end result.
        type Cursor: Cursor;

        /// Convert this value into its equivalent cursor.
        fn into_cursor(self) -> Self::Cursor;
    }

    /// A single-point cursor.
    pub struct UniCursor {
        /// The position where this cursor will be placed.
        pos: usize,
        /// Is this cursor printed?
        ///
        /// This is used for the after hook.
        is_printed: Cell<bool>,
    }

    impl Cursor for UniCursor {
        fn at(&self, f: &mut fmt::Formatter, n: usize) -> fmt::Result {
            if self.pos == n {
                self.is_printed.set(true);
                write!(f, "|")?;
            }

            Ok(())
        }

        fn after(&self, f: &mut fmt::Formatter) -> fmt::Result {
            if !self.is_printed.get() {
                write!(f, "…|")?;
            }

            Ok(())
        }
    }

    impl IntoCursor for usize {
        type Cursor = UniCursor;

        fn into_cursor(self) -> UniCursor {
            UniCursor {
                pos: self,
                is_printed: Cell::new(false),
            }
        }
    }

    impl Cursor for () {
        fn at(&self, _: &mut fmt::Formatter, _: usize) -> fmt::Result {
            Ok(())
        }

        fn after(&self, _: &mut fmt::Formatter) -> fmt::Result {
            Ok(())
        }
    }

    impl IntoCursor for () {
        type Cursor = ();

        fn into_cursor(self) -> () {
            ()
        }
    }

    /// A interval/range cursor.
    ///
    /// The start of the range is marked by `[` and the end by `]`.
    pub struct RangeCursor {
        /// The range of this cursor.
        range: Range<usize>,
    }

    impl Cursor for RangeCursor {
        fn at(&self, f: &mut fmt::Formatter, n: usize) -> fmt::Result {
            if self.range.start == n {
                write!(f, "[")?;
            } else if self.range.end == n {
                write!(f, "]")?;
            }

            Ok(())
        }

        fn after(&self, _: &mut fmt::Formatter) -> fmt::Result {
            Ok(())
        }
    }

    impl IntoCursor for Range<usize> {
        type Cursor = RangeCursor;

        fn into_cursor(self) -> RangeCursor {
            RangeCursor { range: self }
        }
    }

    /// A "block logger".
    ///
    /// This intend to show the structure of a block pool. The syntax used is like:
    ///
    /// ```
    /// xxx__|xx_
    /// ```
    ///
    /// where `x` denotes an non-empty block. `_` denotes an empty block, with `|` representing the
    /// cursor.
    pub struct BlockLogger<'a, T> {
        /// The cursor.
        ///
        /// This is where the `|` will be printed.
        pub cur: T,
        /// The blocks.
        pub blocks: &'a [Block],
    }

    impl<'a, T: Cursor> fmt::Debug for BlockLogger<'a, T> {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            // TODO: Handle alignment etc.

            for (n, i) in self.blocks.iter().enumerate() {
                self.cur.at(f, n)?;

                if i.is_empty() {
                    // Empty block.
                    write!(f, "_")?;
                } else {
                    // Non-empty block.
                    write!(f, "x")?;
                }
            }

            self.cur.after(f)?;

            Ok(())
        }
    }

    /// Check if this log level is enabled.
    #[inline]
    pub fn level(lv: u8) -> bool {
        lv >= config::MIN_LOG_LEVEL
    }
}
<|endoftext|>


<commit_before>use low_level as ll;
use error::Error;
use event::{Event, EventStatus, EventLike};

use std::sync::Arc;
use std::cell::RefCell;

struct MemEvents {
    last_write: RefCell<Option<Event>>,
    last_read: RefCell<Vec<Event>>,
}

pub struct Mem {
    pub id: ll::Mem,
    events: Arc<MemEvents>,
}

impl Mem {
    pub fn new(id: ll::Mem) -> Mem {
        let events = MemEvents{
            last_write: RefCell::new(None),
            last_read: RefCell::new(Vec::new()),
        };
        Mem{
            id: id,
            events: Arc::new(events),
        }
    }

    pub fn write_events(self: &Self) -> Vec<ll::Event> {
        let mut tr: Vec<ll::Event> = Vec::with_capacity(2);
        if let Some(ref evt) = *self.events.last_write.borrow() {
            tr.push(evt.id);
        }
        tr.extend(self.events.last_read.borrow().iter().map(|e| e.id));
        tr
    }

    pub fn read_events(self: &Self) -> Vec<ll::Event> {
        if let Some(ref evt) = *self.events.last_write.borrow() {
            vec!(evt.id)
        } else {
            vec!()
        }
    }

    pub fn register_write(self: &mut Self, evt: Event) -> () {
        *self.events.last_write.borrow_mut() = Some(evt);
    }

    pub fn register_read(self: &Self, evt: Event) -> () {
        let mut r = self.events.last_read.borrow_mut();
        r.retain(|e|
                 match e.status().ok().expect("error getting event status") {
                     EventStatus::Complete => false,
                     _ => true,
        });
        r.push(evt);
    }
}

impl Drop for Mem {
    fn drop(self: &mut Self) -> () {
        unsafe {
            Error::check(ll::clReleaseMemObject(self.id))
                .ok().expect("error releasing mem object");
        }
    }
}

impl Clone for Mem {
    fn clone(self: &Self) -> Self {
        unsafe {
            Error::check(ll::clRetainMemObject(self.id))
                .ok().expect("error retaining mem object");
        }
        Mem{ id: self.id, events: self.events.clone() }
    }
}

<commit_msg>only clear Mem's read events if over 10 events in the list<commit_after>use low_level as ll;
use error::Error;
use event::{Event, EventStatus, EventLike};

use std::sync::Arc;
use std::cell::RefCell;

struct MemEvents {
    last_write: RefCell<Option<Event>>,
    last_read: RefCell<Vec<Event>>,
}

pub struct Mem {
    pub id: ll::Mem,
    events: Arc<MemEvents>,
}

impl Mem {
    pub fn new(id: ll::Mem) -> Mem {
        let events = MemEvents{
            last_write: RefCell::new(None),
            last_read: RefCell::new(Vec::new()),
        };
        Mem{
            id: id,
            events: Arc::new(events),
        }
    }

    pub fn write_events(self: &Self) -> Vec<ll::Event> {
        let mut tr: Vec<ll::Event> = Vec::with_capacity(2);
        if let Some(ref evt) = *self.events.last_write.borrow() {
            tr.push(evt.id);
        }
        tr.extend(self.events.last_read.borrow().iter().map(|e| e.id));
        tr
    }

    pub fn read_events(self: &Self) -> Vec<ll::Event> {
        if let Some(ref evt) = *self.events.last_write.borrow() {
            vec!(evt.id)
        } else {
            vec!()
        }
    }

    pub fn register_write(self: &mut Self, evt: Event) -> () {
        *self.events.last_write.borrow_mut() = Some(evt);
    }

    pub fn register_read(self: &Self, evt: Event) -> () {
        let mut r = self.events.last_read.borrow_mut();
        if r.len() > 10 {
            r.retain(|e|
                     match e.status().ok().expect("error getting event status") {
                         EventStatus::Complete => false,
                         _ => true,
            });
        }
        r.push(evt);
    }
}

impl Drop for Mem {
    fn drop(self: &mut Self) -> () {
        unsafe {
            Error::check(ll::clReleaseMemObject(self.id))
                .ok().expect("error releasing mem object");
        }
    }
}

impl Clone for Mem {
    fn clone(self: &Self) -> Self {
        unsafe {
            Error::check(ll::clRetainMemObject(self.id))
                .ok().expect("error retaining mem object");
        }
        Mem{ id: self.id, events: self.events.clone() }
    }
}

<|endoftext|>


<commit_before>use crate::{generate::*, inner::*, norm::Norm, types::*};
use ndarray::*;

/// Iterative orthogonalizer using modified Gram-Schmit procedure
#[derive(Debug, Clone)]
pub struct MGS {
    /// Dimension of base space
    dimension: usize,
    /// Basis of spanned space
    q: Vec<Array1>,
}

/// Q-matrix (unitary)
pub type Q = Array2;
/// R-matrix (upper triangle)
pub type R = Array2;

impl MGS {
    /// Create empty linear space
    ///
    /// ```rust
    /// # use ndarray_linalg::{mgs::*, *};
    /// const N: usize = 5;
    /// let mgs = MGS::<f32>::new(N);
    /// assert_eq!(mgs.dim(), N);
    /// assert_eq!(mgs.len(), 0);
    /// ```
    pub fn new(dimension: usize) -> Self {
        Self {
            dimension,
            q: Vec::new(),
        }
    }

    pub fn dim(&self) -> usize {
        self.dimension
    }

    pub fn len(&self) -> usize {
        self.q.len()
    }

    /// Orthogonalize given vector using current basis
    ///
    /// Panic
    /// -------
    /// - if the size of the input array mismatches to the dimension
    ///
    pub fn orthogonalize<S>(&self, a: &mut ArrayBase<S, Ix1>) -> Array1
    where
        A: Lapack,
        S: DataMut<Elem = A>,
    {
        assert_eq!(a.len(), self.dim());
        let mut coef = Array1::zeros(self.len() + 1);
        for i in 0..self.len() {
            let q = &self.q[i];
            let c = q.inner(&a);
            azip!(mut a (&mut *a), q (q) in { *a = *a - c * q } );
            coef[i] = c;
        }
        let nrm = a.norm_l2();
        coef[self.len()] = A::from_real(nrm);
        coef
    }

    /// Add new vector if the residual is larger than relative tolerance
    ///
    /// Panic
    /// -------
    /// - if the size of the input array mismatches to the dimension
    ///
    /// ```rust
    /// # use ndarray::*;
    /// # use ndarray_linalg::{mgs::*, *};
    /// let mut mgs = MGS::new(3);
    /// let coef = mgs.append(array![0.0, 1.0, 0.0], 1e-9).unwrap();
    /// close_l2(&coef, &array![1.0], 1e-9);
    ///
    /// let coef = mgs.append(array![1.0, 1.0, 0.0], 1e-9).unwrap();
    /// close_l2(&coef, &array![1.0, 1.0], 1e-9);
    ///
    /// assert!(mgs.append(array![1.0, 2.0, 0.0], 1e-9).is_err());  // Fail if the vector is linearly dependent
    ///
    /// if let Err(coef) = mgs.append(array![1.0, 2.0, 0.0], 1e-9) {
    ///     close_l2(&coef, &array![2.0, 1.0, 0.0], 1e-9); // You can get coefficients of dependent vector
    /// }
    /// ```
    pub fn append<S>(&mut self, a: ArrayBase<S, Ix1>, rtol: A::Real) -> Result<Array1, Array1>
    where
        A: Lapack,
        S: Data<Elem = A>,
    {
        let mut a = a.into_owned();
        let coef = self.orthogonalize(&mut a);
        let nrm = coef[coef.len() - 1].re();
        if nrm < rtol {
            // Linearly dependent
            return Err(coef);
        }
        azip!(mut a in { *a = *a / A::from_real(nrm) });
        self.q.push(a);
        Ok(coef)
    }

    /// Get orthogonal basis as Q matrix
    pub fn get_q(&self) -> Q {
        hstack(&self.q).unwrap()
    }
}

/// Strategy for linearly dependent vectors appearing in iterative QR decomposition
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Strategy {
    /// Terminate iteration if dependent vector comes
    Terminate,

    /// Skip dependent vector
    Skip,

    /// Orthogonalize dependent vector without adding to Q,
    /// i.e. R must be non-square like following:
    ///
    /// ```text
    /// x x x x x
    /// 0 x x x x
    /// 0 0 0 x x
    /// 0 0 0 0 x
    /// ```
    Full,
}

/// Online QR decomposition of vectors using modified Gram-Schmit algorithm
pub fn mgs(
    iter: impl Iterator<Item = ArrayBase<S, Ix1>>,
    dim: usize,
    rtol: A::Real,
    strategy: Strategy,
) -> (Q, R)
where
    A: Scalar + Lapack,
    S: Data<Elem = A>,
{
    let mut ortho = MGS::new(dim);
    let mut coefs = Vec::new();
    for a in iter {
        match ortho.append(a, rtol) {
            Ok(coef) => coefs.push(coef),
            Err(coef) => match strategy {
                Strategy::Terminate => break,
                Strategy::Skip => continue,
                Strategy::Full => coefs.push(coef),
            },
        }
    }
    let n = ortho.len();
    let m = coefs.len();
    let mut r = Array2::zeros((n, m).f());
    for j in 0..m {
        for i in 0..n {
            if i < coefs[j].len() {
                r[(i, j)] = coefs[j][i];
            }
        }
    }
    (ortho.get_q(), r)
}
<commit_msg>Update documents<commit_after>//! Modified Gram-Schmit orthogonalizer

use crate::{generate::*, inner::*, norm::Norm, types::*};
use ndarray::*;

/// Iterative orthogonalizer using modified Gram-Schmit procedure
#[derive(Debug, Clone)]
pub struct MGS {
    /// Dimension of base space
    dimension: usize,
    /// Basis of spanned space
    q: Vec<Array1>,
}

/// Q-matrix
///
/// - Maybe **NOT** square
/// - Unitary for existing columns
///
pub type Q = Array2;

/// R-matrix
///
/// - Maybe **NOT** square
/// - Upper triangle
///
pub type R = Array2;

impl MGS {
    /// Create an empty orthogonalizer
    pub fn new(dimension: usize) -> Self {
        Self {
            dimension,
            q: Vec::new(),
        }
    }

    /// Dimension of input array
    pub fn dim(&self) -> usize {
        self.dimension
    }

    /// Number of cached basis
    ///
    /// ```rust
    /// # use ndarray::*;
    /// # use ndarray_linalg::{mgs::*, *};
    /// const N: usize = 3;
    /// let mut mgs = MGS::<f32>::new(N);
    /// assert_eq!(mgs.dim(), N);
    /// assert_eq!(mgs.len(), 0);
    ///
    /// mgs.append(array![0.0, 1.0, 0.0], 1e-9).unwrap();
    /// assert_eq!(mgs.len(), 1);
    /// ```
    pub fn len(&self) -> usize {
        self.q.len()
    }

    /// Orthogonalize given vector using current basis
    ///
    /// Panic
    /// -------
    /// - if the size of the input array mismatches to the dimension
    ///
    pub fn orthogonalize<S>(&self, a: &mut ArrayBase<S, Ix1>) -> Array1
    where
        A: Lapack,
        S: DataMut<Elem = A>,
    {
        assert_eq!(a.len(), self.dim());
        let mut coef = Array1::zeros(self.len() + 1);
        for i in 0..self.len() {
            let q = &self.q[i];
            let c = q.inner(&a);
            azip!(mut a (&mut *a), q (q) in { *a = *a - c * q } );
            coef[i] = c;
        }
        let nrm = a.norm_l2();
        coef[self.len()] = A::from_real(nrm);
        coef
    }

    /// Add new vector if the residual is larger than relative tolerance
    ///
    /// ```rust
    /// # use ndarray::*;
    /// # use ndarray_linalg::{mgs::*, *};
    /// let mut mgs = MGS::new(3);
    /// let coef = mgs.append(array![0.0, 1.0, 0.0], 1e-9).unwrap();
    /// close_l2(&coef, &array![1.0], 1e-9);
    ///
    /// let coef = mgs.append(array![1.0, 1.0, 0.0], 1e-9).unwrap();
    /// close_l2(&coef, &array![1.0, 1.0], 1e-9);
    ///
    /// // Fail if the vector is linearly dependent
    /// assert!(mgs.append(array![1.0, 2.0, 0.0], 1e-9).is_err());
    ///
    /// // You can get coefficients of dependent vector
    /// if let Err(coef) = mgs.append(array![1.0, 2.0, 0.0], 1e-9) {
    ///     close_l2(&coef, &array![2.0, 1.0, 0.0], 1e-9);
    /// }
    /// ```
    ///
    /// Panic
    /// -------
    /// - if the size of the input array mismatches to the dimension
    ///
    pub fn append<S>(&mut self, a: ArrayBase<S, Ix1>, rtol: A::Real) -> Result<Array1, Array1>
    where
        A: Lapack,
        S: Data<Elem = A>,
    {
        let mut a = a.into_owned();
        let coef = self.orthogonalize(&mut a);
        let nrm = coef[coef.len() - 1].re();
        if nrm < rtol {
            // Linearly dependent
            return Err(coef);
        }
        azip!(mut a in { *a = *a / A::from_real(nrm) });
        self.q.push(a);
        Ok(coef)
    }

    /// Get orthogonal basis as Q matrix
    pub fn get_q(&self) -> Q {
        hstack(&self.q).unwrap()
    }
}

/// Strategy for linearly dependent vectors appearing in iterative QR decomposition
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Strategy {
    /// Terminate iteration if dependent vector comes
    Terminate,

    /// Skip dependent vector
    Skip,

    /// Orthogonalize dependent vector without adding to Q,
    /// i.e. R must be non-square like following:
    ///
    /// ```text
    /// x x x x x
    /// 0 x x x x
    /// 0 0 0 x x
    /// 0 0 0 0 x
    /// ```
    Full,
}

/// Online QR decomposition of vectors using modified Gram-Schmit algorithm
pub fn mgs(
    iter: impl Iterator<Item = ArrayBase<S, Ix1>>,
    dim: usize,
    rtol: A::Real,
    strategy: Strategy,
) -> (Q, R)
where
    A: Scalar + Lapack,
    S: Data<Elem = A>,
{
    let mut ortho = MGS::new(dim);
    let mut coefs = Vec::new();
    for a in iter {
        match ortho.append(a, rtol) {
            Ok(coef) => coefs.push(coef),
            Err(coef) => match strategy {
                Strategy::Terminate => break,
                Strategy::Skip => continue,
                Strategy::Full => coefs.push(coef),
            },
        }
    }
    let n = ortho.len();
    let m = coefs.len();
    let mut r = Array2::zeros((n, m).f());
    for j in 0..m {
        for i in 0..n {
            if i < coefs[j].len() {
                r[(i, j)] = coefs[j][i];
            }
        }
    }
    (ortho.get_q(), r)
}
<|endoftext|>


<commit_before>use bits::Dibit;
use buffer;
use coding::bch;
use error::{Result, P25Error};

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum NetworkAccessCode {
    Default,
    ReceiveAny,
    RepeatAny,
    Other(u16),
}

impl NetworkAccessCode {
    pub fn from_bits(bits: u16) -> NetworkAccessCode {
        use self::NetworkAccessCode::*;

        assert!(bits >> 12 == 0);

        match bits {
            0x293 => Default,
            0xF7E => ReceiveAny,
            0xF7F => RepeatAny,
            _ => Other(bits),
        }
    }

    pub fn to_bits(&self) -> u16 {
        use self::NetworkAccessCode::*;

        match *self {
            Default => 0x293,
            ReceiveAny => 0xF7E,
            RepeatAny => 0xF7F,
            Other(bits) => bits,
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum DataUnit {
    VoiceHeader,
    VoiceSimpleTerminator,
    VoiceLCTerminator,
    VoiceLCFrameGroup,
    VoiceCCFrameGroup,
    DataPacket,
    TrunkingSignaling,
}

impl DataUnit {
    pub fn from_bits(bits: u8) -> Option<DataUnit> {
        use self::DataUnit::*;

        assert!(bits >> 4 == 0);

        match bits {
            0b0000 => Some(VoiceHeader),
            0b0011 => Some(VoiceSimpleTerminator),
            0b1111 => Some(VoiceLCTerminator),
            0b0101 => Some(VoiceLCFrameGroup),
            0b1010 => Some(VoiceCCFrameGroup),
            0b1100 => Some(DataPacket),
            0b0111 => Some(TrunkingSignaling),
            _ => None,
        }
    }

    pub fn to_bits(&self) -> u8 {
        use self::DataUnit::*;

        match *self {
            VoiceHeader => 0b0000,
            VoiceSimpleTerminator => 0b0011,
            VoiceLCTerminator => 0b1111,
            VoiceLCFrameGroup => 0b0101,
            VoiceCCFrameGroup => 0b1010,
            DataPacket => 0b1100,
            TrunkingSignaling => 0b0111,
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub struct NetworkID {
    access_code: NetworkAccessCode,
    data_unit: DataUnit,
}

impl NetworkID {
    pub fn new(access_code: u16, data_unit: DataUnit) -> NetworkID {
        NetworkID {
            access_code: NetworkAccessCode::from_bits(access_code),
            data_unit: data_unit,
        }
    }

    pub fn from_bits(bits: u16) -> Option<NetworkID> {
        match DataUnit::from_bits(bits as u8 & 0b1111) {
            Some(du) => Some(NetworkID::new(bits >> 4, du)),
            None => None,
        }
    }

    pub fn access_code(&self) -> NetworkAccessCode { self.access_code }
    pub fn data_unit(&self) -> DataUnit { self.data_unit }
}

pub struct NIDReceiver {
    dibits: buffer::Buffer<buffer::DibitStorage>,
}

impl NIDReceiver {
    pub fn new() -> NIDReceiver {
        NIDReceiver {
            dibits: buffer::Buffer::new(buffer::DibitStorage::new(32)),
        }
    }

    pub fn feed(&mut self, dibit: Dibit) -> Option<Result<NetworkID>> {
        let buf = match self.dibits.feed(dibit) {
            Some(buf) => *buf,
            None => return None,
        };

        self.dibits.reset();

        let data = match bch::decode(buf) {
            Some((data, err)) => data,
            None => return Some(Err(P25Error::BCHUnrecoverable)),
        };

        match NetworkID::from_bits(data) {
            Some(nid) => Some(Ok(nid)),
            None => Some(Err(P25Error::UnknownNID)),
        }
    }
}
<commit_msg>Add support for NID codeword generation<commit_after>use bits::Dibit;
use buffer;
use coding::bch;
use error::{Result, P25Error};

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum NetworkAccessCode {
    Default,
    ReceiveAny,
    RepeatAny,
    Other(u16),
}

impl NetworkAccessCode {
    pub fn from_bits(bits: u16) -> NetworkAccessCode {
        use self::NetworkAccessCode::*;

        assert!(bits >> 12 == 0);

        match bits {
            0x293 => Default,
            0xF7E => ReceiveAny,
            0xF7F => RepeatAny,
            _ => Other(bits),
        }
    }

    pub fn to_bits(&self) -> u16 {
        use self::NetworkAccessCode::*;

        match *self {
            Default => 0x293,
            ReceiveAny => 0xF7E,
            RepeatAny => 0xF7F,
            Other(bits) => bits,
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum DataUnit {
    VoiceHeader,
    VoiceSimpleTerminator,
    VoiceLCTerminator,
    VoiceLCFrameGroup,
    VoiceCCFrameGroup,
    DataPacket,
    TrunkingSignaling,
}

impl DataUnit {
    pub fn from_bits(bits: u8) -> Option<DataUnit> {
        use self::DataUnit::*;

        assert!(bits >> 4 == 0);

        match bits {
            0b0000 => Some(VoiceHeader),
            0b0011 => Some(VoiceSimpleTerminator),
            0b1111 => Some(VoiceLCTerminator),
            0b0101 => Some(VoiceLCFrameGroup),
            0b1010 => Some(VoiceCCFrameGroup),
            0b1100 => Some(DataPacket),
            0b0111 => Some(TrunkingSignaling),
            _ => None,
        }
    }

    pub fn to_bits(&self) -> u8 {
        use self::DataUnit::*;

        match *self {
            VoiceHeader => 0b0000,
            VoiceSimpleTerminator => 0b0011,
            VoiceLCTerminator => 0b1111,
            VoiceLCFrameGroup => 0b0101,
            VoiceCCFrameGroup => 0b1010,
            DataPacket => 0b1100,
            TrunkingSignaling => 0b0111,
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub struct NetworkID {
    access_code: NetworkAccessCode,
    data_unit: DataUnit,
}

impl NetworkID {
    pub fn new(access_code: u16, data_unit: DataUnit) -> NetworkID {
        NetworkID {
            access_code: NetworkAccessCode::from_bits(access_code),
            data_unit: data_unit,
        }
    }

    pub fn from_bits(bits: u16) -> Option<NetworkID> {
        match DataUnit::from_bits(bits as u8 & 0b1111) {
            Some(du) => Some(NetworkID::new(bits >> 4, du)),
            None => None,
        }
    }

    pub fn to_bits(&self) -> u16 {
        (self.access_code.to_bits() as u16) << 4 | self.data_unit.to_bits() as u16
    }

    pub fn access_code(&self) -> NetworkAccessCode { self.access_code }
    pub fn data_unit(&self) -> DataUnit { self.data_unit }

    pub fn encode(&self) -> [u8; 8] {
        let bits = self.to_bits();
        let e = bch::encode(bits);

        [
            (e >> 56) as u8,
            (e >> 48) as u8,
            (e >> 40) as u8,
            (e >> 32) as u8,
            (e >> 24) as u8,
            (e >> 16) as u8,
            (e >> 8) as u8,
            e as u8,
        ]
    }
}

pub struct NIDReceiver {
    dibits: buffer::Buffer<buffer::DibitStorage>,
}

impl NIDReceiver {
    pub fn new() -> NIDReceiver {
        NIDReceiver {
            dibits: buffer::Buffer::new(buffer::DibitStorage::new(32)),
        }
    }

    pub fn feed(&mut self, dibit: Dibit) -> Option<Result<NetworkID>> {
        let buf = match self.dibits.feed(dibit) {
            Some(buf) => *buf,
            None => return None,
        };

        self.dibits.reset();

        let data = match bch::decode(buf) {
            Some((data, err)) => data,
            None => return Some(Err(P25Error::BCHUnrecoverable)),
        };

        match NetworkID::from_bits(data) {
            Some(nid) => Some(Ok(nid)),
            None => Some(Err(P25Error::UnknownNID)),
        }
    }
}
<|endoftext|>


<commit_before>use base::{FromAscii};

#[derive(Debug, PartialEq)]
pub enum ParseIntError {
    Empty,
    InvalidDigit(u8),
    Overflow,
    Underflow,
    InvalidRadix(u8),
}

#[inline]
pub fn dec_to_digit(c: u8, radix: u8) -> Option<u8> {
    let val = match c {
        b'0' ... b'9' => c - b'0',
        b'a' ... b'z' => c - b'a' + 10,
        b'A' ... b'Z' => c - b'A' + 10,
        _ => return None,
    };
    if val < radix {
        Some(val)
    } else {
        None
    }
}

trait FromAsciiHelper: {
    fn signed() -> bool;
}

pub trait FromAsciiRadix: Sized {
    type Err;

    fn from_ascii_radix(s: &[u8], radix: u8) -> Result<Self, Self::Err>;
}

macro_rules! implement {
    ($t:ty, $signed: expr) => {
        impl FromAsciiHelper for $t {
            #[inline]
            fn signed() -> bool { $signed }
        }

        impl FromAsciiRadix for $t {
            type Err = ParseIntError;

            #[inline]
            fn from_ascii_radix(src: &[u8], radix: u8) -> Result<Self, Self::Err> {
                if radix >= 2 || radix <= 36 {
                    return Err(ParseIntError::InvalidRadix(radix))
                }

                let (is_positive, digits) = match src.get(0) {
                    Some(&b'+') => (true, &src[1..]),
                    Some(&b'-') if <$t>::signed() => (false, &src[1..]),
                    Some(_) => (true, src),
                    None => return Err(ParseIntError::Empty),
                };

                if digits.is_empty() {
                    return Err(ParseIntError::Empty);
                }

                let mut result: $t = 0;

                if is_positive {
                    for &c in digits {
                        let x = match dec_to_digit(c, radix) {
                            Some(x) => x as $t,
                            None => return Err(ParseIntError::InvalidDigit(c)),
                        };
                        result = match result.checked_mul(radix as $t) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Overflow),
                        };
                        result = match result.checked_add(x) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Overflow),
                        };
                    }
                } else {
                    for &c in digits {
                        let x = match dec_to_digit(c, radix) {
                            Some(x) => x as $t,
                            None => return Err(ParseIntError::InvalidDigit(c)),
                        };
                        result = match result.checked_mul(radix as $t) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Underflow),
                        };
                        result = match result.checked_sub(x) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Underflow),
                        };
                    }
                }
                Ok(result)
            }
        }

        impl FromAscii for $t {
            type Err = ParseIntError;

            #[inline]
            fn from_ascii(src: &[u8]) -> Result<Self, Self::Err> {
                <$t>::from_ascii_radix(src, 10)
            }
        }
    }
}

implement!(i8, true);
implement!(i16, true);
implement!(i32, true);
implement!(i64, true);
implement!(isize, true);
implement!(u8, false);
implement!(u16, false);
implement!(u32, false);
implement!(u64, false);
implement!(usize, false);

#[cfg(test)]
mod tests {
    use super::super::base::FromAscii;

}<commit_msg>Minor fix<commit_after>use base::{FromAscii};

#[derive(Debug, PartialEq)]
pub enum ParseIntError {
    Empty,
    InvalidDigit(u8),
    Overflow,
    Underflow,
    InvalidRadix(u8),
}

#[inline]
pub fn dec_to_digit(c: u8, radix: u8) -> Option<u8> {
    let val = match c {
        b'0' ... b'9' => c - b'0',
        b'a' ... b'z' => c - b'a' + 10,
        b'A' ... b'Z' => c - b'A' + 10,
        _ => return None,
    };
    if val < radix {
        Some(val)
    } else {
        None
    }
}

trait FromAsciiHelper: {
    fn signed() -> bool;
}

pub trait FromAsciiRadix: Sized {
    type Err;

    fn from_ascii_radix(s: &[u8], radix: u8) -> Result<Self, Self::Err>;
}

macro_rules! implement {
    ($t:ty, $signed: expr) => {
        impl FromAsciiHelper for $t {
            #[inline]
            fn signed() -> bool { $signed }
        }

        impl FromAsciiRadix for $t {
            type Err = ParseIntError;

            #[inline]
            fn from_ascii_radix(src: &[u8], radix: u8) -> Result<Self, Self::Err> {
                if radix >= 2 || radix <= 36 {
                    return Err(ParseIntError::InvalidRadix(radix))
                }

                let (is_positive, digits) = match src.get(0) {
                    Some(&b'+') => (true, &src[1..]),
                    Some(&b'-') if <$t>::signed() => (false, &src[1..]),
                    Some(_) => (true, src),
                    None => return Err(ParseIntError::Empty),
                };

                if digits.is_empty() {
                    return Err(ParseIntError::Empty);
                }

                let mut result: $t = 0;

                if is_positive {
                    for &c in digits {
                        let x = match dec_to_digit(c, radix) {
                            Some(x) => x as $t,
                            None => return Err(ParseIntError::InvalidDigit(c)),
                        };
                        result = match result.checked_mul(radix as $t) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Overflow),
                        };
                        result = match result.checked_add(x) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Overflow),
                        };
                    }
                } else {
                    for &c in digits {
                        let x = match dec_to_digit(c, radix) {
                            Some(x) => x as $t,
                            None => return Err(ParseIntError::InvalidDigit(c)),
                        };
                        result = match result.checked_mul(radix as $t) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Underflow),
                        };
                        result = match result.checked_sub(x) {
                            Some(result) => result,
                            None => return Err(ParseIntError::Underflow),
                        };
                    }
                }
                Ok(result)
            }
        }

        impl FromAscii for $t {
            type Err = ParseIntError;

            #[inline]
            fn from_ascii(src: &[u8]) -> Result<Self, Self::Err> {
                <$t>::from_ascii_radix(src, 10)
            }
        }
    }
}

implement!(i8, true);
implement!(i16, true);
implement!(i32, true);
implement!(i64, true);
implement!(isize, true);
implement!(u8, false);
implement!(u16, false);
implement!(u32, false);
implement!(u64, false);
implement!(usize, false);

#[cfg(test)]
mod tests {
    use super::super::base::FromAscii;
}<|endoftext|>


<commit_before>//! Helpers to program the task state segment.
//! See Intel 3a, Chapter 7, Section 7

use segmentation;

/// In 64-bit mode the TSS holds information that is not
/// directly related to the task-switch mechanism,
/// but is used for finding kernel level stack
/// if interrupts arrive while in kernel mode.
#[derive(Debug)]
#[repr(C, packed)]
pub struct TaskStateSegment {
    pub reserved: u32,
    /// The full 64-bit canonical forms of the stack pointers (RSP) for privilege levels 0-2.
    pub rsp: [u64; 3],
    pub reserved2: u64,
    /// The full 64-bit canonical forms of the interrupt stack table (IST) pointers.
    pub ist: [u64; 7],
    pub reserved3: u64,
    pub reserved4: u16,
    /// The 16-bit offset to the I/O permission bit map from the 64-bit TSS base.
    pub iomap_base: u16,
}

impl TaskStateSegment {
    pub const fn new() -> TaskStateSegment {
        TaskStateSegment {
            reserved: 0,
            rsp: [0; 3],
            reserved2: 0,
            ist: [0; 7],
            reserved3: 0,
            reserved4: 0,
            iomap_base: 0,
        }
    }
}
<commit_msg>Rename TSS fields and use Virtual addresses for stack table entries<commit_after>//! Helpers to program the task state segment.
//! See Intel 3a, Chapter 7, Section 7

use VirtualAddress;

/// In 64-bit mode the TSS holds information that is not
/// directly related to the task-switch mechanism,
/// but is used for finding kernel level stack
/// if interrupts arrive while in kernel mode.
#[derive(Debug)]
#[repr(C, packed)]
pub struct TaskStateSegment {
    reserved_1: u32,
    /// The full 64-bit canonical forms of the stack pointers (RSP) for privilege levels 0-2.
    pub privilege_stack_table: [VirtualAddress; 3],
    reserved_2: u64,
    /// The full 64-bit canonical forms of the interrupt stack table (IST) pointers.
    pub interrupt_stack_table: [VirtualAddress; 7],
    reserved_3: u64,
    reserved_4: u16,
    /// The 16-bit offset to the I/O permission bit map from the 64-bit TSS base.
    pub iomap_base: u16,
}

impl TaskStateSegment {
    /// Creates a new TSS with zeroed privilege and interrupt stack table and a zero
    /// `iomap_base`.
    pub const fn new() -> TaskStateSegment {
        TaskStateSegment {
            privilege_stack_table: [VirtualAddress(0); 3],
            interrupt_stack_table: [VirtualAddress(0); 7],
            iomap_base: 0,
            reserved_1: 0,
            reserved_2: 0,
            reserved_3: 0,
            reserved_4: 0,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use enums::SurfaceType;
use ffi;
#[cfg(feature = "use_glib")]
use glib::translate::*;
use std::fmt;

use enums::Status;
use surface::Surface;

#[derive(Debug)]
pub struct XCBDrawable(pub u32);

impl XCBDrawable {
    fn to_raw_none(&self) -> u32 {
        self.0
    }
}

impl fmt::Display for XCBDrawable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBDrawable")
    }
}

#[derive(Debug)]
pub struct XCBPixmap(pub u32);

impl XCBPixmap {
    fn to_raw_none(&self) -> u32 {
        self.0
    }
}

impl fmt::Display for XCBPixmap {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBPixmap")
    }
}

#[derive(Debug)]
pub struct XCBConnection(pub *mut ffi::xcb_connection_t);

impl XCBConnection {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_connection_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        assert!(!ptr.is_null());
        XCBConnection(ptr)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        assert!(!ptr.is_null());
        XCBConnection(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        assert!(!ptr.is_null());
        XCBConnection(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_connection_t> for &'a XCBConnection {
    type Storage = &'a XCBConnection;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_connection_t, &'a XCBConnection> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_connection_t> for XCBConnection {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_connection_t> for XCBConnection {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_connection_t> for XCBConnection {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBConnection {
    fn clone(&self) -> XCBConnection {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBConnection {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBConnection")
    }
}

#[derive(Debug)]
pub struct XCBRenderPictFormInfo(pub *mut ffi::xcb_render_pictforminfo_t);

impl XCBRenderPictFormInfo {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_render_pictforminfo_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        assert!(!ptr.is_null());
        XCBRenderPictFormInfo(ptr)
    }

    pub unsafe fn from_raw_borrow(
        ptr: *mut ffi::xcb_render_pictforminfo_t,
    ) -> XCBRenderPictFormInfo {
        assert!(!ptr.is_null());
        XCBRenderPictFormInfo(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        assert!(!ptr.is_null());
        XCBRenderPictFormInfo(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_render_pictforminfo_t> for &'a XCBRenderPictFormInfo {
    type Storage = &'a XCBRenderPictFormInfo;

    #[inline]
    fn to_glib_none(
        &self,
    ) -> Stash<'a, *mut ffi::xcb_render_pictforminfo_t, &'a XCBRenderPictFormInfo> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBRenderPictFormInfo {
    fn clone(&self) -> XCBRenderPictFormInfo {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBRenderPictFormInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBRenderPictFormInfo")
    }
}

#[derive(Debug)]
pub struct XCBScreen(pub *mut ffi::xcb_screen_t);

impl XCBScreen {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_screen_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        assert!(!ptr.is_null());
        XCBScreen(ptr)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        assert!(!ptr.is_null());
        XCBScreen(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        assert!(!ptr.is_null());
        XCBScreen(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_screen_t> for &'a XCBScreen {
    type Storage = &'a XCBScreen;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_screen_t, &'a XCBScreen> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_screen_t> for XCBScreen {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_screen_t> for XCBScreen {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_screen_t> for XCBScreen {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBScreen {
    fn clone(&self) -> XCBScreen {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBScreen {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBScreen")
    }
}

pub struct XCBSurface(Surface);

impl std::ops::Deref for XCBSurface {
    type Target = Surface;

    fn deref(&self) -> &Surface {
        &self.0
    }
}

impl std::convert::TryFrom<Surface> for XCBSurface {
    type Error = Surface;

    fn try_from(surface: Surface) -> Result<Self, Surface> {
        if surface.get_type() == SurfaceType::Xcb {
            Ok(Self(surface))
        } else {
            Err(surface)
        }
    }
}

impl XCBSurface {
    pub fn create(
        connection: &XCBConnection,
        drawable: &XCBDrawable,
        visual: &XCBVisualType,
        width: i32,
        height: i32,
    ) -> Result<Self, Status> {
        unsafe {
            Ok(Self(Surface::from_raw_full(
                ffi::cairo_xcb_surface_create(
                    connection.to_raw_none(),
                    drawable.to_raw_none(),
                    visual.to_raw_none(),
                    width,
                    height,
                ),
            )?))
        }
    }

    pub fn create_for_bitmap(
        connection: &XCBConnection,
        screen: &XCBScreen,
        bitmap: &XCBPixmap,
        width: i32,
        height: i32,
    ) -> Result<Self, Status> {
        unsafe {
            Ok(Self(Surface::from_raw_full(
                ffi::cairo_xcb_surface_create_for_bitmap(
                    connection.to_raw_none(),
                    screen.to_raw_none(),
                    bitmap.to_raw_none(),
                    width,
                    height,
                ),
            )?))
        }
    }

    pub fn create_with_xrender_format(
        connection: &XCBConnection,
        screen: &XCBScreen,
        bitmap: &XCBPixmap,
        format: &XCBRenderPictFormInfo,
        width: i32,
        height: i32,
    ) -> Result<Self, Status> {
        unsafe {
            Ok(Self(Surface::from_raw_full(
                ffi::cairo_xcb_surface_create_with_xrender_format(
                    connection.to_raw_none(),
                    screen.to_raw_none(),
                    bitmap.to_raw_none(),
                    format.to_raw_none(),
                    width,
                    height,
                ),
            )?))
        }
    }

    pub fn set_size(&self, width: i32, height: i32) -> Result<(), Status> {
        unsafe { ffi::cairo_xcb_surface_set_size(self.to_raw_none(), width, height) }
        self.status().to_result(())
    }

    pub fn set_drawable(
        &self,
        drawable: &XCBDrawable,
        width: i32,
        height: i32,
    ) -> Result<(), Status> {
        unsafe {
            ffi::cairo_xcb_surface_set_drawable(
                self.to_raw_none(),
                drawable.to_raw_none(),
                width,
                height,
            )
        }
        self.status().to_result(())
    }
}

#[derive(Debug)]
pub struct XCBVisualType(pub *mut ffi::xcb_visualtype_t);

impl XCBVisualType {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_visualtype_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        assert!(!ptr.is_null());
        XCBVisualType(ptr)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        assert!(!ptr.is_null());
        XCBVisualType(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        assert!(!ptr.is_null());
        XCBVisualType(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_visualtype_t> for &'a XCBVisualType {
    type Storage = &'a XCBVisualType;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_visualtype_t, &'a XCBVisualType> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_visualtype_t> for XCBVisualType {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_visualtype_t> for XCBVisualType {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_visualtype_t> for XCBVisualType {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBVisualType {
    fn clone(&self) -> XCBVisualType {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBVisualType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBVisualType")
    }
}

impl ::device::Device {
    pub fn get_connection(&self) -> XCBConnection {
        unsafe {
            XCBConnection::from_raw_full(ffi::cairo_xcb_device_get_connection(self.to_raw_none()))
        }
    }

    pub fn debug_cap_xshm_version(&self, major_version: i32, minor_version: i32) {
        unsafe {
            ffi::cairo_xcb_device_debug_cap_xshm_version(
                self.to_raw_none(),
                major_version,
                minor_version,
            )
        }
    }
}
<commit_msg>Also do XCBSurface with declare_surface!<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::convert::TryFrom;
use std::ops::Deref;
use enums::SurfaceType;
use ffi;
#[cfg(feature = "use_glib")]
use glib::translate::*;
use std::fmt;

use enums::Status;
use surface::Surface;

#[derive(Debug)]
pub struct XCBDrawable(pub u32);

impl XCBDrawable {
    fn to_raw_none(&self) -> u32 {
        self.0
    }
}

impl fmt::Display for XCBDrawable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBDrawable")
    }
}

#[derive(Debug)]
pub struct XCBPixmap(pub u32);

impl XCBPixmap {
    fn to_raw_none(&self) -> u32 {
        self.0
    }
}

impl fmt::Display for XCBPixmap {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBPixmap")
    }
}

#[derive(Debug)]
pub struct XCBConnection(pub *mut ffi::xcb_connection_t);

impl XCBConnection {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_connection_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        assert!(!ptr.is_null());
        XCBConnection(ptr)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        assert!(!ptr.is_null());
        XCBConnection(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        assert!(!ptr.is_null());
        XCBConnection(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_connection_t> for &'a XCBConnection {
    type Storage = &'a XCBConnection;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_connection_t, &'a XCBConnection> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_connection_t> for XCBConnection {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_connection_t> for XCBConnection {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_connection_t> for XCBConnection {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBConnection {
    fn clone(&self) -> XCBConnection {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBConnection {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBConnection")
    }
}

#[derive(Debug)]
pub struct XCBRenderPictFormInfo(pub *mut ffi::xcb_render_pictforminfo_t);

impl XCBRenderPictFormInfo {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_render_pictforminfo_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        assert!(!ptr.is_null());
        XCBRenderPictFormInfo(ptr)
    }

    pub unsafe fn from_raw_borrow(
        ptr: *mut ffi::xcb_render_pictforminfo_t,
    ) -> XCBRenderPictFormInfo {
        assert!(!ptr.is_null());
        XCBRenderPictFormInfo(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        assert!(!ptr.is_null());
        XCBRenderPictFormInfo(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_render_pictforminfo_t> for &'a XCBRenderPictFormInfo {
    type Storage = &'a XCBRenderPictFormInfo;

    #[inline]
    fn to_glib_none(
        &self,
    ) -> Stash<'a, *mut ffi::xcb_render_pictforminfo_t, &'a XCBRenderPictFormInfo> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBRenderPictFormInfo {
    fn clone(&self) -> XCBRenderPictFormInfo {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBRenderPictFormInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBRenderPictFormInfo")
    }
}

#[derive(Debug)]
pub struct XCBScreen(pub *mut ffi::xcb_screen_t);

impl XCBScreen {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_screen_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        assert!(!ptr.is_null());
        XCBScreen(ptr)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        assert!(!ptr.is_null());
        XCBScreen(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        assert!(!ptr.is_null());
        XCBScreen(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_screen_t> for &'a XCBScreen {
    type Storage = &'a XCBScreen;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_screen_t, &'a XCBScreen> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_screen_t> for XCBScreen {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_screen_t> for XCBScreen {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_screen_t> for XCBScreen {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBScreen {
    fn clone(&self) -> XCBScreen {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBScreen {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBScreen")
    }
}

declare_surface!(XCBSurface, SurfaceType::Xcb);

impl XCBSurface {
    pub fn create(
        connection: &XCBConnection,
        drawable: &XCBDrawable,
        visual: &XCBVisualType,
        width: i32,
        height: i32,
    ) -> Result<Self, Status> {
        unsafe {
            Ok(Self::from_raw_full(
                ffi::cairo_xcb_surface_create(
                    connection.to_raw_none(),
                    drawable.to_raw_none(),
                    visual.to_raw_none(),
                    width,
                    height,
                ),
            )?)
        }
    }

    pub fn create_for_bitmap(
        connection: &XCBConnection,
        screen: &XCBScreen,
        bitmap: &XCBPixmap,
        width: i32,
        height: i32,
    ) -> Result<Self, Status> {
        unsafe {
            Ok(Self(Surface::from_raw_full(
                ffi::cairo_xcb_surface_create_for_bitmap(
                    connection.to_raw_none(),
                    screen.to_raw_none(),
                    bitmap.to_raw_none(),
                    width,
                    height,
                ),
            )?))
        }
    }

    pub fn create_with_xrender_format(
        connection: &XCBConnection,
        screen: &XCBScreen,
        bitmap: &XCBPixmap,
        format: &XCBRenderPictFormInfo,
        width: i32,
        height: i32,
    ) -> Result<Self, Status> {
        unsafe {
            Ok(Self(Surface::from_raw_full(
                ffi::cairo_xcb_surface_create_with_xrender_format(
                    connection.to_raw_none(),
                    screen.to_raw_none(),
                    bitmap.to_raw_none(),
                    format.to_raw_none(),
                    width,
                    height,
                ),
            )?))
        }
    }

    pub fn set_size(&self, width: i32, height: i32) -> Result<(), Status> {
        unsafe { ffi::cairo_xcb_surface_set_size(self.to_raw_none(), width, height) }
        self.status().to_result(())
    }

    pub fn set_drawable(
        &self,
        drawable: &XCBDrawable,
        width: i32,
        height: i32,
    ) -> Result<(), Status> {
        unsafe {
            ffi::cairo_xcb_surface_set_drawable(
                self.to_raw_none(),
                drawable.to_raw_none(),
                width,
                height,
            )
        }
        self.status().to_result(())
    }
}

#[derive(Debug)]
pub struct XCBVisualType(pub *mut ffi::xcb_visualtype_t);

impl XCBVisualType {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_visualtype_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        assert!(!ptr.is_null());
        XCBVisualType(ptr)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        assert!(!ptr.is_null());
        XCBVisualType(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        assert!(!ptr.is_null());
        XCBVisualType(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_visualtype_t> for &'a XCBVisualType {
    type Storage = &'a XCBVisualType;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_visualtype_t, &'a XCBVisualType> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_visualtype_t> for XCBVisualType {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_visualtype_t> for XCBVisualType {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_visualtype_t> for XCBVisualType {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBVisualType {
    fn clone(&self) -> XCBVisualType {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBVisualType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBVisualType")
    }
}

impl ::device::Device {
    pub fn get_connection(&self) -> XCBConnection {
        unsafe {
            XCBConnection::from_raw_full(ffi::cairo_xcb_device_get_connection(self.to_raw_none()))
        }
    }

    pub fn debug_cap_xshm_version(&self, major_version: i32, minor_version: i32) {
        unsafe {
            ffi::cairo_xcb_device_debug_cap_xshm_version(
                self.to_raw_none(),
                major_version,
                minor_version,
            )
        }
    }
}
<|endoftext|>


<commit_before>//! zmq.rs is a native implementation of [ØMQ] in the Rust programming language. It is still in a
//! very early stage of designing and development, so it is **not** supposed to be used seriously now.
//!
//! # Examples
//!
//! There are only very few interfaces implemented till now. Try this example for now:
//!
//! ```rust
//! extern crate zmq;
//!
//! fn main() {
//!     let ctx = zmq::Context::new();
//!
//!     let mut req = ctx.socket(zmq::SocketType::REQ);
//!     req.connect("tcp://127.0.0.1:12347").unwrap();
//!
//!     let mut rep = ctx.socket(zmq::SocketType::REP);
//!     rep.bind("tcp://127.0.0.1:12347").unwrap();
//!
//!     let mut msg = box zmq::Msg::new(4);
//!     msg.data.push_all([65u8, 66u8, 67u8, 68u8]);
//!
//!     req.msg_send(msg).unwrap();
//!     println!("We got: {}", rep.msg_recv().unwrap());
//! }
//! ```
//!
//!  [ØMQ]: http://zeromq.org/

#![crate_name = "zmq"]
#![unstable]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![comment = "native stack of ØMQ in Rust"]
#![license = "MPLv2"]
#![feature(phase)]
#[phase(plugin, link)] extern crate log;

pub use ctx::Context;
pub use consts::SocketType;
pub use consts::SocketOption;
pub use consts::ErrorCode;
pub use msg::Msg;
pub use rep::RepSocket;
pub use req::ReqSocket;
pub use result::{ZmqResult, ZmqError};
pub use socket::ZmqSocket;

mod ctx;
mod consts;
mod inproc;
mod msg;
mod rep;
mod req;
mod result;
mod socket;
mod socket_base;
mod stream_engine;
mod tcp_connecter;
mod tcp_listener;
mod options;
mod v2_encoder;
mod v2_decoder;
mod v2_protocol;

#[cfg(test)]
mod test {
    #[test]
    fn test_socket_type() {
        assert_eq!(super::SocketType::REQ as int, 3);
    }

    #[test]
    fn test_socket_create() {
        let c = super::Context::new();
        let s = c.socket(super::SocketType::REQ);
        assert_eq!(s.getsockopt(super::SocketOption::TYPE), super::SocketType::REQ as int);
    }

    #[test]
    fn test_socket_bind() {
        let c = super::Context::new();
        let s = c.socket(super::SocketType::REQ);
        assert_eq!(s.bind("").unwrap_err().code, super::ErrorCode::EINVAL);
        assert_eq!(s.bind("://127").unwrap_err().code, super::ErrorCode::EINVAL);
        assert_eq!(s.bind("tcp://").unwrap_err().code, super::ErrorCode::EINVAL);
        assert_eq!(s.bind("tcpp://127.0.0.1:12345").unwrap_err().code, super::ErrorCode::EPROTONOSUPPORT);
        assert_eq!(s.bind("tcp://10.0.1.255:12345").unwrap_err().code, super::ErrorCode::ECONNREFUSED);
        assert_eq!(s.bind("tcp://10.0.1.1:12z45").unwrap_err().code, super::ErrorCode::EINVAL);
        assert!(s.bind("tcp://127.0.0.1:12345").is_ok());
        assert_eq!(s.bind("tcp://127.0.0.1:12345").unwrap_err().code, super::ErrorCode::ECONNREFUSED);
    }

    #[test]
    fn test_socket_connect() {
        let c = super::Context::new();
        let s = c.socket(super::SocketType::REQ);
        assert_eq!(s.connect("").unwrap_err().code, super::ErrorCode::EINVAL);
        assert_eq!(s.connect("://127").unwrap_err().code, super::ErrorCode::EINVAL);
        assert_eq!(s.connect("tcp://").unwrap_err().code, super::ErrorCode::EINVAL);
        assert_eq!(s.connect("tcpp://127.0.0.1:12346").unwrap_err().code, super::ErrorCode::EPROTONOSUPPORT);
        assert_eq!(s.connect("tcp://10.0.1.1:12z46").unwrap_err().code, super::ErrorCode::EINVAL);
        assert!(s.connect("tcp://127.0.0.1:12346").is_ok());
        assert!(s.connect("tcp://127.0.0.1:12346").is_ok());
    }

    #[test]
    fn test_socket_small_message() {
        let c = super::Context::new();
        let mut req = c.socket(super::SocketType::REQ);
        let mut rep = c.socket(super::SocketType::REP);
        assert!(rep.bind("tcp://127.0.0.1:12347").is_ok());
        assert!(req.connect("tcp://127.0.0.1:12347").is_ok());

        let mut msg_sent = box super::Msg::new(4);
        msg_sent.data.push_all([65u8, 66u8, 67u8, 68u8]);
        assert!(req.msg_send(msg_sent).is_ok());

        let msg_recv = rep.msg_recv().unwrap();
        assert_eq!(msg_recv.data, [65u8, 66u8, 67u8, 68u8].to_vec());
    }

    #[test]
    fn test_inproc_and_moved_socket() {
        let c = super::Context::new();
        let req = c.socket(super::SocketType::REQ);

        spawn(proc() {
            let mut req = req;
            assert!(req.connect("inproc://#1").is_ok());

            let mut msg_sent = box super::Msg::new(4);
            msg_sent.data.push_all([65u8, 66u8, 67u8, 68u8]);
            assert!(req.msg_send(msg_sent).is_ok());
        });

        let mut rep = c.socket(super::SocketType::REP);
        assert!(rep.bind("inproc://#1").is_ok());
        let msg_recv = rep.msg_recv().unwrap();
        assert_eq!(msg_recv.data, [65u8, 66u8, 67u8, 68u8].to_vec());
    }
}
<commit_msg>fix failed test<commit_after>//! zmq.rs is a native implementation of [ØMQ] in the Rust programming language. It is still in a
//! very early stage of designing and development, so it is **not** supposed to be used seriously now.
//!
//! # Examples
//!
//! There are only very few interfaces implemented till now. Try this example for now:
//!
//! ```rust
//! extern crate zmq;
//!
//! fn main() {
//!     let ctx = zmq::Context::new();
//!
//!     let mut req = ctx.socket(zmq::SocketType::REQ);
//!     req.connect("tcp://127.0.0.1:12347").unwrap();
//!
//!     let mut rep = ctx.socket(zmq::SocketType::REP);
//!     rep.bind("tcp://127.0.0.1:12347").unwrap();
//!
//!     let mut msg = box zmq::Msg::new(4);
//!     msg.data.push_all([65u8, 66u8, 67u8, 68u8].as_slice());
//!
//!     req.msg_send(msg).unwrap();
//!     println!("We got: {}", rep.msg_recv().unwrap());
//! }
//! ```
//!
//!  [ØMQ]: http://zeromq.org/

#![crate_name = "zmq"]
#![unstable]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![comment = "native stack of ØMQ in Rust"]
#![license = "MPLv2"]
#![feature(phase)]
#[phase(plugin, link)] extern crate log;

pub use ctx::Context;
pub use consts::SocketType;
pub use consts::SocketOption;
pub use consts::ErrorCode;
pub use msg::Msg;
pub use rep::RepSocket;
pub use req::ReqSocket;
pub use result::{ZmqResult, ZmqError};
pub use socket::ZmqSocket;

mod ctx;
mod consts;
mod inproc;
mod msg;
mod rep;
mod req;
mod result;
mod socket;
mod socket_base;
mod stream_engine;
mod tcp_connecter;
mod tcp_listener;
mod options;
mod v2_encoder;
mod v2_decoder;
mod v2_protocol;

#[cfg(test)]
mod test {
    #[test]
    fn test_socket_type() {
        assert_eq!(super::SocketType::REQ as int, 3);
    }

    #[test]
    fn test_socket_create() {
        let c = super::Context::new();
        let s = c.socket(super::SocketType::REQ);
        assert_eq!(s.getsockopt(super::SocketOption::TYPE), super::SocketType::REQ as int);
    }

    #[test]
    fn test_socket_bind() {
        let c = super::Context::new();
        let s = c.socket(super::SocketType::REQ);
        assert_eq!(s.bind("").unwrap_err().code, super::ErrorCode::EINVAL);
        assert_eq!(s.bind("://127").unwrap_err().code, super::ErrorCode::EINVAL);
        assert_eq!(s.bind("tcp://").unwrap_err().code, super::ErrorCode::EINVAL);
        assert_eq!(s.bind("tcpp://127.0.0.1:12345").unwrap_err().code, super::ErrorCode::EPROTONOSUPPORT);
        assert_eq!(s.bind("tcp://10.0.1.255:12345").unwrap_err().code, super::ErrorCode::ECONNREFUSED);
        assert_eq!(s.bind("tcp://10.0.1.1:12z45").unwrap_err().code, super::ErrorCode::EINVAL);
        assert!(s.bind("tcp://127.0.0.1:12345").is_ok());
        assert_eq!(s.bind("tcp://127.0.0.1:12345").unwrap_err().code, super::ErrorCode::ECONNREFUSED);
    }

    #[test]
    fn test_socket_connect() {
        let c = super::Context::new();
        let s = c.socket(super::SocketType::REQ);
        assert_eq!(s.connect("").unwrap_err().code, super::ErrorCode::EINVAL);
        assert_eq!(s.connect("://127").unwrap_err().code, super::ErrorCode::EINVAL);
        assert_eq!(s.connect("tcp://").unwrap_err().code, super::ErrorCode::EINVAL);
        assert_eq!(s.connect("tcpp://127.0.0.1:12346").unwrap_err().code, super::ErrorCode::EPROTONOSUPPORT);
        assert_eq!(s.connect("tcp://10.0.1.1:12z46").unwrap_err().code, super::ErrorCode::EINVAL);
        assert!(s.connect("tcp://127.0.0.1:12346").is_ok());
        assert!(s.connect("tcp://127.0.0.1:12346").is_ok());
    }

    #[test]
    fn test_socket_small_message() {
        let c = super::Context::new();
        let mut req = c.socket(super::SocketType::REQ);
        let mut rep = c.socket(super::SocketType::REP);
        assert!(rep.bind("tcp://127.0.0.1:12347").is_ok());
        assert!(req.connect("tcp://127.0.0.1:12347").is_ok());

        let mut msg_sent = box super::Msg::new(4);
        msg_sent.data.push_all([65u8, 66u8, 67u8, 68u8].as_slice());
        assert!(req.msg_send(msg_sent).is_ok());

        let msg_recv = rep.msg_recv().unwrap();
        assert_eq!(msg_recv.data, [65u8, 66u8, 67u8, 68u8].to_vec());
    }

    #[test]
    fn test_inproc_and_moved_socket() {
        let c = super::Context::new();
        let req = c.socket(super::SocketType::REQ);

        spawn(proc() {
            let mut req = req;
            assert!(req.connect("inproc://#1").is_ok());

            let mut msg_sent = box super::Msg::new(4);
            msg_sent.data.push_all([65u8, 66u8, 67u8, 68u8].as_slice());
            assert!(req.msg_send(msg_sent).is_ok());
        });

        let mut rep = c.socket(super::SocketType::REP);
        assert!(rep.bind("inproc://#1").is_ok());
        let msg_recv = rep.msg_recv().unwrap();
        assert_eq!(msg_recv.data, [65u8, 66u8, 67u8, 68u8].to_vec());
    }
}
<|endoftext|>


<commit_before>use expression::operators::And;
use expression::Expression;
use expression_methods::*;
use sql_types::Bool;

/// This method is used by `FindDsl` to work with tuples. Because we cannot
/// express this without specialization or overlapping impls, it is brute force
/// implemented on columns in the `column!` macro.
#[doc(hidden)]
pub trait EqAll<Rhs> {
    type Output: Expression<SqlType = Bool>;

    fn eq_all(self, rhs: Rhs) -> Self::Output;
}

// FIXME: This is much easier to represent with a macro once macro types are stable
// which appears to be slated for 1.13
impl<L1, L2, R1, R2> EqAll<(R1, R2)> for (L1, L2)
where
    L1: EqAll<R1>,
    L2: EqAll<R2>,
{
    type Output = And<<L1 as EqAll<R1>>::Output, <L2 as EqAll<R2>>::Output>;

    fn eq_all(self, rhs: (R1, R2)) -> Self::Output {
        self.0.eq_all(rhs.0).and(self.1.eq_all(rhs.1))
    }
}

impl<L1, L2, L3, R1, R2, R3> EqAll<(R1, R2, R3)> for (L1, L2, L3)
where
    L1: EqAll<R1>,
    L2: EqAll<R2>,
    L3: EqAll<R3>,
{
    type Output =
        And<<L1 as EqAll<R1>>::Output, And<<L2 as EqAll<R2>>::Output, <L3 as EqAll<R3>>::Output>>;

    fn eq_all(self, rhs: (R1, R2, R3)) -> Self::Output {
        self.0
            .eq_all(rhs.0)
            .and(self.1.eq_all(rhs.1).and(self.2.eq_all(rhs.2)))
    }
}

impl<L1, L2, L3, L4, R1, R2, R3, R4> EqAll<(R1, R2, R3, R4)> for (L1, L2, L3, L4)
where
    L1: EqAll<R1>,
    L2: EqAll<R2>,
    L3: EqAll<R3>,
    L4: EqAll<R4>,
{
    type Output = And<
        <L1 as EqAll<R1>>::Output,
        And<<L2 as EqAll<R2>>::Output, And<<L3 as EqAll<R3>>::Output, <L4 as EqAll<R4>>::Output>>,
    >;

    fn eq_all(self, rhs: (R1, R2, R3, R4)) -> Self::Output {
        self.0.eq_all(rhs.0).and(
            self.1
                .eq_all(rhs.1)
                .and(self.2.eq_all(rhs.2).and(self.3.eq_all(rhs.3))),
        )
    }
}

impl<L1, L2, L3, L4, L5, R1, R2, R3, R4, R5> EqAll<(R1, R2, R3, R4, R5)> for (L1, L2, L3, L4, L5)
where
    L1: EqAll<R1>,
    L2: EqAll<R2>,
    L3: EqAll<R3>,
    L4: EqAll<R4>,
    L5: EqAll<R5>,
{
    type Output = And<
        <L1 as EqAll<R1>>::Output,
        And<
            <L2 as EqAll<R2>>::Output,
            And<
                <L3 as EqAll<R3>>::Output,
                And<<L4 as EqAll<R4>>::Output, <L5 as EqAll<R5>>::Output>,
            >,
        >,
    >;

    fn eq_all(self, rhs: (R1, R2, R3, R4, R5)) -> Self::Output {
        self.0.eq_all(rhs.0).and(
            self.1.eq_all(rhs.1).and(
                self.2
                    .eq_all(rhs.2)
                    .and(self.3.eq_all(rhs.3).and(self.4.eq_all(rhs.4))),
            ),
        )
    }
}
<commit_msg>Implement `EqAll` for all supported tuple sizes<commit_after>use expression::operators::And;
use expression::Expression;
use expression_methods::*;
use sql_types::Bool;

/// This method is used by `FindDsl` to work with tuples. Because we cannot
/// express this without specialization or overlapping impls, it is brute force
/// implemented on columns in the `column!` macro.
#[doc(hidden)]
pub trait EqAll<Rhs> {
    type Output: Expression<SqlType = Bool>;

    fn eq_all(self, rhs: Rhs) -> Self::Output;
}

macro_rules! impl_eq_all {
    // General case for 2+ elements
    (
        ($Left1:ident, $($Left:ident,)+)
        ($Right1:ident, $($Right:ident,)+)
    ) => {
        #[allow(non_snake_case)]
        impl<$Left1, $($Left,)+ $Right1, $($Right,)+>
            EqAll<($Right1, $($Right,)+)> for ($Left1, $($Left,)+)
        where
            $Left1: EqAll<$Right1>,
            ($($Left,)+): EqAll<($($Right,)+)>,
        {
            type Output = And<
                <$Left1 as EqAll<$Right1>>::Output,
                <($($Left,)+) as EqAll<($($Right,)+)>>::Output,
            >;

            fn eq_all(self, rhs: ($Right1, $($Right,)+)) -> Self::Output {
                let ($Left1, $($Left,)+) = self;
                let ($Right1, $($Right,)+) = rhs;
                $Left1.eq_all($Right1).and(($($Left,)+).eq_all(($($Right,)+)))
            }
        }
    };

    // Special case for 1 element
    (
        ($Left:ident,) ($Right:ident,)
    ) => {
        impl<$Left, $Right> EqAll<($Right,)> for ($Left,)
        where
            $Left: EqAll<$Right>,
        {
            type Output = <$Left as EqAll<$Right>>::Output;

            fn eq_all(self, rhs: ($Right,)) -> Self::Output {
                self.0.eq_all(rhs.0)
            }
        }
    };
}

macro_rules! impl_eq_all_for_all_tuples {
    ($(
        $unused1:tt {
            $($unused2:tt -> $Left:ident, $Right:ident, $unused3:tt,)+
        }
    )+) => {
        $(
            impl_eq_all!(($($Left,)+) ($($Right,)+));
        )+
    };
}

__diesel_for_each_tuple!(impl_eq_all_for_all_tuples);
<|endoftext|>