<commit_before>extern crate rand;
pub mod parse;
pub mod eval;

#[cfg(test)]
mod tests {
    use ::parse::{Parser,BlockKind,SrcBlock,
                  LogicKind,SrcKind,VarKind,ExpectKind};
    use ::eval::{Eval,Evaluator};

    struct Data;
    impl Eval for Data {
        fn eval (&self, lookup: &str) -> Option<VarKind> {
            match lookup {
                "some_item" => {
                    Some(VarKind::from(false))
                },
                "some_weight" => {
                    Some(VarKind::from(4.0f32))
                },
                "other_weight" => {
                    Some(VarKind::from(5.0f32))
                },
                "name" => {
                    Some(VarKind::from("Io".to_owned()))
                }
                _ => None
            }
        }
    }

    fn test_block () -> &'static str {
        "root\n
    unequipped !some_item\n
    has_weight some_weight < 5.0\n
    some_comp:any [\nunequipped \nhas_weight\n]\n
\n
    if unequipped \"you're looking for something?\"\n
\n
    if all \"welcome, \nlook around\"\n
;"
    }

    fn qsym_block () -> &'static str {
        "root\n
    if '!some_item \"you're looking for something?\"\n
;"
    }

    fn qsym_comp_block () -> &'static str {
        "root\n
    has_weight some_weight < 5.0\n
    some_comp:any [has_weight '!some_item ]\n
    ;"
    }

    fn if_vec_block () -> &'static str {
        "root\n
    if '!some_item [\n
        \"you're looking for something?\"\n
        \"welcome, \nlook around\"\n
        next store]\n
;"
    }

    fn eval_str_block () -> &'static str {
        "root\n
        has_weight some_weight < 5.0\n
        some_comp:all [has_weight '!some_item ]\n
    if some_comp \"looks like you are `some_weight kgs heavy, `name\"\n
;"
    }

    fn compare_env_block () -> &'static str {
        "root\n
    weight some_weight < other_weight\n
    if weight next store\n
;"
    }

    #[test]
    fn parse_block() {
        let src = test_block();
        let block = Parser::parse_blocks(src);

        let block_ = [BlockKind::Src(
            SrcBlock {
                name: "root".to_owned(),
                src: vec![SrcKind::Logic("unequipped".to_owned(),
                                         LogicKind::IsNot("some_item".to_owned())),

                          SrcKind::Logic("has_weight".to_owned(),
                                         LogicKind::LT(VarKind::String("some_weight".to_owned()), VarKind::Num(5.0f32))),
                          SrcKind::Composite("some_comp".to_owned(),
                                             ExpectKind::Any,
                                             vec!["unequipped".to_owned(),"has_weight".to_owned()]),
                          SrcKind::If(ExpectKind::Ref("unequipped".to_owned()),
                                      vec![VarKind::String("you're looking for something?".to_owned())],
                                      None),
                          SrcKind::If(ExpectKind::All,
                                      vec![VarKind::String("welcome, \nlook around".to_owned())],
                                      None)]
            })];

        for (n,n_) in block.iter().zip(block_.iter()) {
            assert_eq!(n,n_);
        }
    }

    #[test]
    fn parse_qsym_block() {
        let src = qsym_block();
        let block = Parser::parse_blocks(src);
        match &block[0] {
            &BlockKind::Src(ref b) => {
                let r;
                match b.src[0] {
                    SrcKind::Logic(ref qsym,_) => { r = qsym; },
                    _ => panic!("unknown source found")
                }

                match b.src[1] {
                    SrcKind::If(ref x,_,_) => {
                        match x {
                            &ExpectKind::Ref(ref r_) => {
                                assert_eq!(r,r_);
                            },
                            _ => panic!("unknown expect found")
                        }
                    },
                    _ => panic!("unknown source found")
                }
            },
            _ => panic!("unknown block found")
        }
    }

    #[test]
    fn parse_qsym_comp_block() {
        let src = qsym_comp_block();
        let block = Parser::parse_blocks(src);

        match &block[0] {
            &BlockKind::Src(ref b) => {
                let r;
                match b.src[1] {
                    SrcKind::Logic(ref qsym,_) => { r = qsym; },
                    _ => panic!("unknown source found")
                }

                match b.src[2] {
                    SrcKind::Composite(_,_,ref x) => {
                        assert_eq!(r,&x[1]);
                    },
                    _ => panic!("unknown source found")
                }
            },
            _ => panic!("unknown block found")
        }
    }

    #[test]
    fn parse_if_vec_block() {
        let src = if_vec_block();
        let block = Parser::parse_blocks(src);

        match &block[0] {
            &BlockKind::Src(ref b) => {
                match b.src[1] {
                    SrcKind::If(_,_, ref next) => {
                        assert!(next.is_some());
                        assert_eq!(next,&Some("store".to_owned()));
                    },
                    _ => panic!("unknown source found")
                }
            },
            _ => panic!("unknown block found")
        }
    }

    #[test]
    fn parse_eval_str_block() {
        let src = eval_str_block();
        let block = Parser::parse_blocks(src);
        let data = Data;

        let ev = Evaluator::new(&block[0], &data);
        let (vars,_node) = ev.block();

        assert_eq!(vars[0], VarKind::String("looks like you are 4 kgs heavy, Io".to_owned()));
    }

    #[test]
    fn parse_compare_env_block() {
        let src = compare_env_block();
        let block = Parser::parse_blocks(src);
        let data = Data;

        let ev = Evaluator::new(&block[0], &data);
        let (_vars,node) = ev.block();

        assert_eq!(node, Some("store".to_string()));
    }
}
<commit_msg>use into<commit_after>extern crate rand;
pub mod parse;
pub mod eval;

#[cfg(test)]
mod tests {
    use ::parse::{Parser,BlockKind,SrcBlock,
                  LogicKind,SrcKind,VarKind,ExpectKind};
    use ::eval::{Eval,Evaluator};

    struct Data;
    impl Eval for Data {
        fn eval (&self, lookup: &str) -> Option<VarKind> {
            match lookup {
                "some_item" => {
                    Some(false.into())
                },
                "some_weight" => {
                    Some(4.0 .into())
                },
                "other_weight" => {
                    Some(5.0 .into())
                },
                "name" => {
                    Some("Io".into())
                }
                _ => None
            }
        }
    }

    fn test_block () -> &'static str {
        "root\n
    unequipped !some_item\n
    has_weight some_weight < 5.0\n
    some_comp:any [\nunequipped \nhas_weight\n]\n
\n
    if unequipped \"you're looking for something?\"\n
\n
    if all \"welcome, \nlook around\"\n
;"
    }

    fn qsym_block () -> &'static str {
        "root\n
    if '!some_item \"you're looking for something?\"\n
;"
    }

    fn qsym_comp_block () -> &'static str {
        "root\n
    has_weight some_weight < 5.0\n
    some_comp:any [has_weight '!some_item ]\n
    ;"
    }

    fn if_vec_block () -> &'static str {
        "root\n
    if '!some_item [\n
        \"you're looking for something?\"\n
        \"welcome, \nlook around\"\n
        next store]\n
;"
    }

    fn eval_str_block () -> &'static str {
        "root\n
        has_weight some_weight < 5.0\n
        some_comp:all [has_weight '!some_item ]\n
    if some_comp \"looks like you are `some_weight kgs heavy, `name\"\n
;"
    }

    fn compare_env_block () -> &'static str {
        "root\n
    weight some_weight < other_weight\n
    if weight next store\n
;"
    }

    #[test]
    fn parse_block() {
        let src = test_block();
        let block = Parser::parse_blocks(src);

        let block_ = [BlockKind::Src(
            SrcBlock {
                name: "root".to_owned(),
                src: vec![SrcKind::Logic("unequipped".to_owned(),
                                         LogicKind::IsNot("some_item".to_owned())),

                          SrcKind::Logic("has_weight".to_owned(),
                                         LogicKind::LT(VarKind::String("some_weight".to_owned()), VarKind::Num(5.0f32))),
                          SrcKind::Composite("some_comp".to_owned(),
                                             ExpectKind::Any,
                                             vec!["unequipped".to_owned(),"has_weight".to_owned()]),
                          SrcKind::If(ExpectKind::Ref("unequipped".to_owned()),
                                      vec![VarKind::String("you're looking for something?".to_owned())],
                                      None),
                          SrcKind::If(ExpectKind::All,
                                      vec![VarKind::String("welcome, \nlook around".to_owned())],
                                      None)]
            })];

        for (n,n_) in block.iter().zip(block_.iter()) {
            assert_eq!(n,n_);
        }
    }

    #[test]
    fn parse_qsym_block() {
        let src = qsym_block();
        let block = Parser::parse_blocks(src);
        match &block[0] {
            &BlockKind::Src(ref b) => {
                let r;
                match b.src[0] {
                    SrcKind::Logic(ref qsym,_) => { r = qsym; },
                    _ => panic!("unknown source found")
                }

                match b.src[1] {
                    SrcKind::If(ref x,_,_) => {
                        match x {
                            &ExpectKind::Ref(ref r_) => {
                                assert_eq!(r,r_);
                            },
                            _ => panic!("unknown expect found")
                        }
                    },
                    _ => panic!("unknown source found")
                }
            },
            _ => panic!("unknown block found")
        }
    }

    #[test]
    fn parse_qsym_comp_block() {
        let src = qsym_comp_block();
        let block = Parser::parse_blocks(src);

        match &block[0] {
            &BlockKind::Src(ref b) => {
                let r;
                match b.src[1] {
                    SrcKind::Logic(ref qsym,_) => { r = qsym; },
                    _ => panic!("unknown source found")
                }

                match b.src[2] {
                    SrcKind::Composite(_,_,ref x) => {
                        assert_eq!(r,&x[1]);
                    },
                    _ => panic!("unknown source found")
                }
            },
            _ => panic!("unknown block found")
        }
    }

    #[test]
    fn parse_if_vec_block() {
        let src = if_vec_block();
        let block = Parser::parse_blocks(src);

        match &block[0] {
            &BlockKind::Src(ref b) => {
                match b.src[1] {
                    SrcKind::If(_,_, ref next) => {
                        assert!(next.is_some());
                        assert_eq!(next,&Some("store".to_owned()));
                    },
                    _ => panic!("unknown source found")
                }
            },
            _ => panic!("unknown block found")
        }
    }

    #[test]
    fn parse_eval_str_block() {
        let src = eval_str_block();
        let block = Parser::parse_blocks(src);
        let data = Data;

        let ev = Evaluator::new(&block[0], &data);
        let (vars,_node) = ev.block();

        assert_eq!(vars[0], VarKind::String("looks like you are 4 kgs heavy, Io".to_owned()));
    }

    #[test]
    fn parse_compare_env_block() {
        let src = compare_env_block();
        let block = Parser::parse_blocks(src);
        let data = Data;

        let ev = Evaluator::new(&block[0], &data);
        let (_vars,node) = ev.block();

        assert_eq!(node, Some("store".to_string()));
    }
}
<|endoftext|>


<commit_before>//! libc - Raw FFI bindings to platforms' system libraries
//!
//! [Documentation for other platforms][pd].
//!
//! [pd]: https://rust-lang.github.io/libc/#platform-specific-documentation
#![crate_name = "libc"]
#![crate_type = "rlib"]
#![allow(
    renamed_and_removed_lints, // Keep this order.
    unknown_lints, // Keep this order.
    bad_style,
    overflowing_literals,
    improper_ctypes,
    // This lint is renamed but we run CI for old stable rustc so should be here.
    redundant_semicolon,
    redundant_semicolons
)]
#![cfg_attr(libc_deny_warnings, deny(warnings))]
// Attributes needed when building as part of the standard library
#![cfg_attr(
    feature = "rustc-dep-of-std",
    feature(cfg_target_vendor, link_cfg, no_core)
)]
#![cfg_attr(libc_thread_local, feature(thread_local))]
// Enable extra lints:
#![cfg_attr(feature = "extra_traits", deny(missing_debug_implementations))]
#![deny(missing_copy_implementations, safe_packed_borrows)]
#![no_std]
#![cfg_attr(feature = "rustc-dep-of-std", no_core)]
#![cfg_attr(
    any(feature = "rustc-dep-of-std", target_os = "redox"),
    feature(static_nobundle)
)]
#![cfg_attr(libc_const_extern_fn, feature(const_extern_fn))]

#[macro_use]
mod macros;

cfg_if! {
    if #[cfg(feature = "rustc-dep-of-std")] {
        extern crate rustc_std_workspace_core as core;
        #[allow(unused_imports)]
        use core::iter;
        #[allow(unused_imports)]
        use core::ops;
        #[allow(unused_imports)]
        use core::option;
    }
}

cfg_if! {
    if #[cfg(libc_priv_mod_use)] {
        #[cfg(libc_core_cvoid)]
        #[allow(unused_imports)]
        use core::ffi;
        #[allow(unused_imports)]
        use core::fmt;
        #[allow(unused_imports)]
        use core::hash;
        #[allow(unused_imports)]
        use core::num;
        #[allow(unused_imports)]
        use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::option::Option;
    } else {
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::fmt;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::hash;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::num;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::option::Option;
    }
}

cfg_if! {
    if #[cfg(windows)] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod windows;
        pub use windows::*;
    } else if #[cfg(target_os = "cloudabi")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod cloudabi;
        pub use cloudabi::*;
    } else if #[cfg(target_os = "fuchsia")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod fuchsia;
        pub use fuchsia::*;
    } else if #[cfg(target_os = "switch")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod switch;
        pub use switch::*;
    } else if #[cfg(target_os = "psp")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod psp;
        pub use psp::*;
    } else if #[cfg(target_os = "vxworks")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod vxworks;
        pub use vxworks::*;
    } else if #[cfg(unix)] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod unix;
        pub use unix::*;
    } else if #[cfg(target_os = "hermit")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod hermit;
        pub use hermit::*;
    } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod sgx;
        pub use sgx::*;
    } else if #[cfg(any(target_env = "wasi", target_os = "wasi"))] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod wasi;
        pub use wasi::*;
    } else {
        // non-supported targets: empty...
    }
}
<commit_msg>Fix conflict between no_std and no_core when building rustc with custom libc<commit_after>//! libc - Raw FFI bindings to platforms' system libraries
//!
//! [Documentation for other platforms][pd].
//!
//! [pd]: https://rust-lang.github.io/libc/#platform-specific-documentation
#![crate_name = "libc"]
#![crate_type = "rlib"]
#![allow(
    renamed_and_removed_lints, // Keep this order.
    unknown_lints, // Keep this order.
    bad_style,
    overflowing_literals,
    improper_ctypes,
    // This lint is renamed but we run CI for old stable rustc so should be here.
    redundant_semicolon,
    redundant_semicolons
)]
#![cfg_attr(libc_deny_warnings, deny(warnings))]
// Attributes needed when building as part of the standard library
#![cfg_attr(
    feature = "rustc-dep-of-std",
    feature(cfg_target_vendor, link_cfg, no_core)
)]
#![cfg_attr(libc_thread_local, feature(thread_local))]
// Enable extra lints:
#![cfg_attr(feature = "extra_traits", deny(missing_debug_implementations))]
#![deny(missing_copy_implementations, safe_packed_borrows)]
#![cfg_attr(not(feature = "rustc-dep-of-std"), no_std)]
#![cfg_attr(feature = "rustc-dep-of-std", no_core)]
#![cfg_attr(
    any(feature = "rustc-dep-of-std", target_os = "redox"),
    feature(static_nobundle)
)]
#![cfg_attr(libc_const_extern_fn, feature(const_extern_fn))]

#[macro_use]
mod macros;

cfg_if! {
    if #[cfg(feature = "rustc-dep-of-std")] {
        extern crate rustc_std_workspace_core as core;
        #[allow(unused_imports)]
        use core::iter;
        #[allow(unused_imports)]
        use core::ops;
        #[allow(unused_imports)]
        use core::option;
    }
}

cfg_if! {
    if #[cfg(libc_priv_mod_use)] {
        #[cfg(libc_core_cvoid)]
        #[allow(unused_imports)]
        use core::ffi;
        #[allow(unused_imports)]
        use core::fmt;
        #[allow(unused_imports)]
        use core::hash;
        #[allow(unused_imports)]
        use core::num;
        #[allow(unused_imports)]
        use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::option::Option;
    } else {
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::fmt;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::hash;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::num;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::option::Option;
    }
}

cfg_if! {
    if #[cfg(windows)] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod windows;
        pub use windows::*;
    } else if #[cfg(target_os = "cloudabi")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod cloudabi;
        pub use cloudabi::*;
    } else if #[cfg(target_os = "fuchsia")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod fuchsia;
        pub use fuchsia::*;
    } else if #[cfg(target_os = "switch")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod switch;
        pub use switch::*;
    } else if #[cfg(target_os = "psp")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod psp;
        pub use psp::*;
    } else if #[cfg(target_os = "vxworks")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod vxworks;
        pub use vxworks::*;
    } else if #[cfg(unix)] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod unix;
        pub use unix::*;
    } else if #[cfg(target_os = "hermit")] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod hermit;
        pub use hermit::*;
    } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod sgx;
        pub use sgx::*;
    } else if #[cfg(any(target_env = "wasi", target_os = "wasi"))] {
        mod fixed_width_ints;
        pub use fixed_width_ints::*;

        mod wasi;
        pub use wasi::*;
    } else {
        // non-supported targets: empty...
    }
}
<|endoftext|>


<commit_before>//! #rust-amqp
//! [![Build Status](https://travis-ci.org/Antti/rust-amqp.svg)](https:
//! //travis-ci.org/Antti/rust-amqp)
//!
//! AMQ protocol implementation in pure rust.
//!
//! > Note:
//! > The project is still in very early stages of development,
//! > it implements all the protocol parsing, but not all the protocol methods
//! are wrapped/easy to use.
//! > Expect the API to be changed in the future.
//!
//! ## What it currently can do:
//! Connect to server
//! Open/close channels
//! Declare queues/exchanges
//! All the methods from the Basic class are implemented, including get,
//! publish, ack, nack, reject, consume. So you can send/receive messages.
//!
//! Have a look at the examples in examples folder.
//!
//!
//! ### Connecting to the server & openning channel:
//! >Note: Currently it can't connect using TLS connections.
//!
//! ```ignore
//! use amqp::session::Session;
//! use amqp::table;
//!
//! let mut session = Session::open_url("amqp://localhost/").unwrap();
//! let mut channel = session.open_channel(1).unwrap();
//! ```
//!
//! ### Declaring queue:
//! ```ignore
//! use amqp::table;
//! The arguments come in following order:
//! queue: &str, passive: bool, durable: bool, exclusive: bool, auto_delete:
//! bool, nowait: bool, arguments: Table
//! let queue_declare = channel.queue_declare("my_queue_name", false, true,
//! false, false, false, table::new());
//! ```
//!
//! ### Publishing message:
//! ```ignore
//! channel.basic_publish("", "my_queue_name", true, false,
//! amqp::protocol::basic::BasicProperties{ content_type:
//! Some("text".to_string()), ..Default::default()}, (b"Hello from
//! rust!").to_vec());
//! ```
//!
//! This will send message: "Hello from rust!" to the queue named
//! "my_queue_name".
//!
//! The messages have type of Vec<u8>, so if you want to send string, first you
//! must convert it to Vec<u8>.
//!
//! ## Development notes:
//!
//! The methods encoding/decoding code is generated using codegen.rb &
//! amqp-rabbitmq-0.9.1.json spec.
//!
//! To generate a new spec, run:
//!
//! ```sh
//! make
//! ```
//!
//! To build project, use cargo:
//!
//! ```sh
//! cargo build
//! ```
//!
//! To build examples:
//! ```sh
//! cargo test
//! ```

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

// extern crate bst;
extern crate url;
extern crate byteorder;
extern crate bit_vec;

#[cfg(feature = "tls")]
extern crate openssl;

#[macro_use]
extern crate log;

#[macro_use]
extern crate enum_primitive;

mod connection;
mod channel;
mod framing;
mod session;
mod basic;
mod amqp_error;
mod table;

pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
pub mod protocol;

pub use session::{Session, Options};
pub use channel::{Channel, ConsumerCallBackFn, Consumer};
pub use table::{Table, TableEntry};
pub use basic::{Basic, GetResult};
pub use session::AMQPScheme;
<commit_msg>Expose AMQPError.<commit_after>//! #rust-amqp
//! [![Build Status](https://travis-ci.org/Antti/rust-amqp.svg)](https:
//! //travis-ci.org/Antti/rust-amqp)
//!
//! AMQ protocol implementation in pure rust.
//!
//! > Note:
//! > The project is still in very early stages of development,
//! > it implements all the protocol parsing, but not all the protocol methods
//! are wrapped/easy to use.
//! > Expect the API to be changed in the future.
//!
//! ## What it currently can do:
//! Connect to server
//! Open/close channels
//! Declare queues/exchanges
//! All the methods from the Basic class are implemented, including get,
//! publish, ack, nack, reject, consume. So you can send/receive messages.
//!
//! Have a look at the examples in examples folder.
//!
//!
//! ### Connecting to the server & openning channel:
//! >Note: Currently it can't connect using TLS connections.
//!
//! ```ignore
//! use amqp::session::Session;
//! use amqp::table;
//!
//! let mut session = Session::open_url("amqp://localhost/").unwrap();
//! let mut channel = session.open_channel(1).unwrap();
//! ```
//!
//! ### Declaring queue:
//! ```ignore
//! use amqp::table;
//! The arguments come in following order:
//! queue: &str, passive: bool, durable: bool, exclusive: bool, auto_delete:
//! bool, nowait: bool, arguments: Table
//! let queue_declare = channel.queue_declare("my_queue_name", false, true,
//! false, false, false, table::new());
//! ```
//!
//! ### Publishing message:
//! ```ignore
//! channel.basic_publish("", "my_queue_name", true, false,
//! amqp::protocol::basic::BasicProperties{ content_type:
//! Some("text".to_string()), ..Default::default()}, (b"Hello from
//! rust!").to_vec());
//! ```
//!
//! This will send message: "Hello from rust!" to the queue named
//! "my_queue_name".
//!
//! The messages have type of Vec<u8>, so if you want to send string, first you
//! must convert it to Vec<u8>.
//!
//! ## Development notes:
//!
//! The methods encoding/decoding code is generated using codegen.rb &
//! amqp-rabbitmq-0.9.1.json spec.
//!
//! To generate a new spec, run:
//!
//! ```sh
//! make
//! ```
//!
//! To build project, use cargo:
//!
//! ```sh
//! cargo build
//! ```
//!
//! To build examples:
//! ```sh
//! cargo test
//! ```

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

// extern crate bst;
extern crate url;
extern crate byteorder;
extern crate bit_vec;

#[cfg(feature = "tls")]
extern crate openssl;

#[macro_use]
extern crate log;

#[macro_use]
extern crate enum_primitive;

mod connection;
mod channel;
mod framing;
mod session;
mod basic;
mod amqp_error;
mod table;

pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
pub mod protocol;

pub use session::{Session, Options};
pub use channel::{Channel, ConsumerCallBackFn, Consumer};
pub use table::{Table, TableEntry};
pub use basic::{Basic, GetResult};
pub use session::AMQPScheme;
pub use amqp_error::AMQPError;
<|endoftext|>


<commit_before>#[macro_use]
extern crate nix;
extern crate libc;
extern crate num_cpus;
extern crate chrono;
extern crate kafka;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate toml;

pub mod collector;
pub mod syscall;
pub mod aggregator;
pub mod config;
mod error;
mod value;
<commit_msg>crate and module declarations<commit_after>#[macro_use]
extern crate nix;
extern crate libc;
extern crate num_cpus;
extern crate chrono;
extern crate kafka;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate toml;
#[macro_use]
extern crate nom;
extern crate glob;

pub mod collector;
pub mod syscall;
pub mod aggregator;
pub mod config;
pub mod state;
mod error;
mod value;
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use std::result;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
    }
}

/// Result type returned from methods that can have `spi::Error`s.
pub type Result<T> = result::Result<T, Error>;

pub struct Spi {}

impl Spi {
    pub fn new() -> Result<Spi> {
        Ok(Spi {})
    }
}
<commit_msg>Flesh out Spi methods and required enums<commit_after>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use std::fs::{File, OpenOptions};
use std::io;
use std::result;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
/// IO error.
        Io(err: io::Error) { description(err.description()) from() }
    }
}

/// Result type returned from methods that can have `spi::Error`s.
pub type Result<T> = result::Result<T, Error>;

mod ioctl {}

pub enum Device {
    Spi0 = 0, // Enabled by default
    Spi1 = 1, // Requires additional configuration
}

pub enum ChipEnable {
    Ce0 = 0, // SPI0: BCM GPIO 8    SPI1: BCM GPIO 18
    Ce1 = 1, // SPI0: BCM GPIO 7    SPI1: BCM GPIO 17
    Ce2 = 2, // SPI0: N/A,          SPI1: BCM GPIO 16
}

pub enum Mode {
    Mode0 = 0, // CPOL 0, CPHA 0
    Mode1 = 1, // CPOL 0, CPHA 1
    Mode2 = 2, // CPOL 1, CPHA 0
    Mode3 = 3, // CPOL 1, CPHA 1
}

pub struct Spi {
    spidev: File,
}

impl Spi {
    pub fn new(device: Device, chip_enable: ChipEnable, mode: Mode, speed: u32) -> Result<Spi> {
        let spidev = OpenOptions::new().read(true).write(true).open(format!(
            "/dev/spidev{}.{}",
            device as u8, chip_enable as u8
        ))?;

        Ok(Spi { spidev })
    }

    pub fn read(&self, mut buffer: &[u8]) -> Result<()> {
        Ok(())
    }

    pub fn write(&self, buffer: &[u8]) -> Result<()> {
        Ok(())
    }

    pub fn transfer(&self, mut read_buffer: &[u8], write_buffer: &[u8]) -> Result<()> {
        Ok(())
    }
}
<|endoftext|>


<commit_before>use crate::syntax::symbol::{self, Symbol};
use crate::syntax::{ExternFn, Pair, Types};

const CXXBRIDGE: &str = "cxxbridge1";

macro_rules! join {
    ($($segment:expr),+ $(,)?) => {
        symbol::join(&[$(&$segment),+])
    };
}

pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
    match &efn.receiver {
        Some(receiver) => {
            let receiver_ident = types.resolve(&receiver.ty);
            join!(
                efn.name.namespace,
                CXXBRIDGE,
                receiver_ident.name.cxx,
                efn.name.rust,
            )
        }
        None => join!(efn.name.namespace, CXXBRIDGE, efn.name.rust),
    }
}

pub fn operator(receiver: &Pair, operator: &'static str) -> Symbol {
    join!(
        receiver.namespace,
        CXXBRIDGE,
        receiver.cxx,
        "operator",
        operator,
    )
}

// The C half of a function pointer trampoline.
pub fn c_trampoline(efn: &ExternFn, var: &Pair, types: &Types) -> Symbol {
    join!(extern_fn(efn, types), var.rust, 0)
}

// The Rust half of a function pointer trampoline.
pub fn r_trampoline(efn: &ExternFn, var: &Pair, types: &Types) -> Symbol {
    join!(extern_fn(efn, types), var.rust, 1)
}
<commit_msg>Document the possible arrangements of mangled symbols<commit_after>// Mangled symbol arrangements:
//
//   (a) One-off internal symbol.
//          pattern:  {CXXBRIDGE} $ {NAME}
//          examples:
//             - cxxbridge1$exception
//          defining characteristics:
//             - 2 segments
//             - starts with cxxbridge
//
//   (b) Behavior on a builtin binding without generic parameter.
//          pattern:  {CXXBRIDGE} $ {TYPE} $ {NAME}
//          examples:
//             - cxxbridge1$string$len
//          defining characteristics:
//             - 3 segments
//             - starts with cxxbridge
//
//   (c) Behavior on a builtin binding with generic parameter.
//          pattern:  {CXXBRIDGE} $ {TYPE} $ {PARAM...} $ {NAME}
//          examples:
//             - cxxbridge1$box$org$rust$Struct$alloc
//             - cxxbridge1$unique_ptr$std$vector$u8$drop
//          defining characteristics:
//             - 4+ segments
//             - starts with cxxbridge
//
//   (d) User-defined extern function.
//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {NAME}
//          examples:
//             - cxxbridge1$new_client
//             - org$rust$cxxbridge1$new_client
//          defining characteristics:
//             - cxxbridge is second from end
//          FIXME: conflict with (a) if they collide with one of our one-off symbol names in the global namespace
//
//   (e) User-defined extern member function.
//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE} $ {NAME}
//          examples:
//             - org$cxxbridge1$Struct$get
//          defining characteristics:
//             - cxxbridge is third from end
//          FIXME: conflict with (b) if e.g. user binds a type in global namespace that collides with our builtin type names
//
//   (f) Operator overload.
//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE} $ operator $ {NAME}
//          examples:
//             - org$rust$cxxbridge1$Struct$operator$eq
//          defining characteristics:
//             - second segment from end is `operator` (not possible in type or namespace names)
//
//   (g) Closure trampoline.
//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE?} $ {NAME} $ {ARGUMENT} $ {DIRECTION}
//          examples:
//             - org$rust$cxxbridge1$Struct$invoke$f$0
//          defining characteristics:
//             - last symbol is `0` (C half) or `1` (Rust half) which are not legal identifiers on their own

use crate::syntax::symbol::{self, Symbol};
use crate::syntax::{ExternFn, Pair, Types};

const CXXBRIDGE: &str = "cxxbridge1";

macro_rules! join {
    ($($segment:expr),+ $(,)?) => {
        symbol::join(&[$(&$segment),+])
    };
}

pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
    match &efn.receiver {
        Some(receiver) => {
            let receiver_ident = types.resolve(&receiver.ty);
            join!(
                efn.name.namespace,
                CXXBRIDGE,
                receiver_ident.name.cxx,
                efn.name.rust,
            )
        }
        None => join!(efn.name.namespace, CXXBRIDGE, efn.name.rust),
    }
}

pub fn operator(receiver: &Pair, operator: &'static str) -> Symbol {
    join!(
        receiver.namespace,
        CXXBRIDGE,
        receiver.cxx,
        "operator",
        operator,
    )
}

// The C half of a function pointer trampoline.
pub fn c_trampoline(efn: &ExternFn, var: &Pair, types: &Types) -> Symbol {
    join!(extern_fn(efn, types), var.rust, 0)
}

// The Rust half of a function pointer trampoline.
pub fn r_trampoline(efn: &ExternFn, var: &Pair, types: &Types) -> Symbol {
    join!(extern_fn(efn, types), var.rust, 1)
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use color::Color;
use select::SelectResults;
use computed::ComputedStyle;
use n::h::CssHintLength;
use n::u::float_to_css_fixed;
use values::*;
use n;

pub struct CompleteSelectResults {
    inner: SelectResults
}

pub impl<'self> CompleteSelectResults {
    fn new_root(root: SelectResults) -> CompleteSelectResults {
        CompleteSelectResults {
            inner: root
        }
    }

    fn new_from_parent(parent: &CompleteSelectResults,
                       child: SelectResults) -> CompleteSelectResults {
        let mut child = child;

        // New lifetime
        {
            let parent_computed = parent.computed_style();
            let mut child_computed = child.computed_style();
            //let net_parent_computed = &parent_computed.inner.inner;
            let net_child_computed = &/*mut*/ child_computed.inner;
            // FIXME: Need to get real font sizes
            let cb: n::c::ComputeFontSizeCb =
                |parent: &Option<n::h::CssHint>, child: &n::h::CssHint| -> n::h::CssHint {
                match *child {
                    CssHintLength(n::t::CssUnitEm(child_em)) => {
                        match *parent {
                            Some(CssHintLength(parent_unit)) => {
                                // CSS3 Values 5.1.1: Multiply parent unit by child unit.
                                let mut new_value =
                                    n::u::css_fixed_to_float(parent_unit.to_css_fixed());
                                new_value *= n::u::css_fixed_to_float(child_em);
                                let unit = parent_unit.modify(n::u::float_to_css_fixed(
                                    new_value));
                                CssHintLength(unit)
                            }
                            _ => n::h::CssHintLength(n::t::CssUnitEm(child_em)),
                        }
                    }
                    CssHintLength(unit) => CssHintLength(unit),
                    _ => {
                        n::h::CssHintLength(n::t::CssUnitPx(float_to_css_fixed(16.0)))
                    }
                }
            };
            // XXX: Need an aliasable &mut here
            let net_result_computed: &mut n::c::CssComputedStyle = unsafe { cast::transmute(net_child_computed) };
            let net_child_computed: &mut n::c::CssComputedStyle = unsafe { cast::transmute(&child_computed.inner) };
            let net_parent_computed = &parent_computed.inner.inner;
            n::c::compose(net_parent_computed, net_child_computed, cb, net_result_computed);
        }

        CompleteSelectResults {
            inner: child
        }
    }

    fn computed_style(&'self self) -> CompleteStyle<'self> {
        CompleteStyle {
            inner: self.inner.computed_style()
        }
    }
}

pub struct CompleteStyle<'self> {
    inner: ComputedStyle<'self>
}

impl<'self> CompleteStyle<'self> {

    // CSS 2.1, Section 8 - Box model

    pub fn margin_top(&self) -> CSSMargin {
        strip(self.inner.margin_top())
    }

    pub fn margin_right(&self) -> CSSMargin {
        strip(self.inner.margin_right())
    }

    pub fn margin_bottom(&self) -> CSSMargin {
        strip(self.inner.margin_bottom())
    }

    pub fn margin_left(&self) -> CSSMargin {
        strip(self.inner.margin_left())
    }

    pub fn border_top_width(&self) -> CSSBorderWidth {
        strip(self.inner.border_top_width())
    }

    pub fn border_right_width(&self) -> CSSBorderWidth {
        strip(self.inner.border_right_width())
    }

    pub fn border_bottom_width(&self) -> CSSBorderWidth {
        strip(self.inner.border_bottom_width())
    }

    pub fn border_left_width(&self) -> CSSBorderWidth {
        strip(self.inner.border_left_width())
    }

    pub fn border_top_color(&self) -> Color {
        strip(self.inner.border_top_color())
    }

    pub fn border_top_color(&self) -> Color {
        strip(self.inner.border_top_color())
    }

    pub fn border_right_color(&self) -> Color {
        strip(self.inner.border_right_color())
    }

    pub fn border_bottom_color(&self) -> Color {
        strip(self.inner.border_bottom_color())
    }

    pub fn border_left_color(&self) -> Color {
        strip(self.inner.border_left_color())
    }

    // CSS 2.1, Section 9 - Visual formatting model

    pub fn display(&self, root: bool) -> CSSDisplay {
        strip(self.inner.display(root))
    }

    pub fn position(&self) -> CSSPosition {
        strip(self.inner.position())
    }

    pub fn float(&self) -> CSSFloat {
        strip(self.inner.float())
    }

    // CSS 2.1, Section 10 - Visual formatting model details

    pub fn width(&self) -> CSSWidth {
        strip(self.inner.width())
    }

    pub fn height(&self) -> CSSHeight {
        strip(self.inner.height())
    }

    pub fn line_height(&self) -> CSSLineHeight {
        strip(self.inner.line_height())
    }

    // CSS 2.1, Section 11 - Visual effects

    // CSS 2.1, Section 12 - Generated content, automatic numbering, and lists

    // CSS 2.1, Section 13 - Paged media

    // CSS 2.1, Section 14 - Colors and Backgrounds

    pub fn background_color(&self) -> Color {
        strip(self.inner.background_color())
    }

    pub fn color(&self) -> Color {
        strip(self.inner.color())
    }

    // CSS 2.1, Section 15 - Fonts

    pub fn font_family(&self) -> ~[CSSFontFamily] {
        strip(self.inner.font_family())
    }

    pub fn font_style(&self) -> CSSFontStyle {
        strip(self.inner.font_style())
    }

    pub fn font_weight(&self) -> CSSFontWeight {
        strip(self.inner.font_weight())
    }

    pub fn font_size(&self) -> CSSFontSize {
        strip(self.inner.font_size())
    }

    // CSS 2.1, Section 16 - Text

    pub fn text_align(&self) -> CSSTextAlign {
        strip(self.inner.text_align())
    }

    // CSS 2.1, Section 17 - Tables

    // CSS 2.1, Section 18 - User interface

}

fn strip<T>(value: CSSValue<T>) -> T {
    match value {
        Inherit => fail!(~"unexpected 'inherit' value in complete style"),
        Specified(v) => v
    }
}

<commit_msg>Remove unused mut.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use color::Color;
use select::SelectResults;
use computed::ComputedStyle;
use n::h::CssHintLength;
use n::u::float_to_css_fixed;
use values::*;
use n;

pub struct CompleteSelectResults {
    inner: SelectResults
}

pub impl<'self> CompleteSelectResults {
    fn new_root(root: SelectResults) -> CompleteSelectResults {
        CompleteSelectResults {
            inner: root
        }
    }

    fn new_from_parent(parent: &CompleteSelectResults,
                       child: SelectResults) -> CompleteSelectResults {
        // New lifetime
        {
            let parent_computed = parent.computed_style();
            let child_computed = child.computed_style();
            //let net_parent_computed = &parent_computed.inner.inner;
            let net_child_computed = &/*mut*/ child_computed.inner;
            // FIXME: Need to get real font sizes
            let cb: n::c::ComputeFontSizeCb =
                |parent: &Option<n::h::CssHint>, child: &n::h::CssHint| -> n::h::CssHint {
                match *child {
                    CssHintLength(n::t::CssUnitEm(child_em)) => {
                        match *parent {
                            Some(CssHintLength(parent_unit)) => {
                                // CSS3 Values 5.1.1: Multiply parent unit by child unit.
                                let mut new_value =
                                    n::u::css_fixed_to_float(parent_unit.to_css_fixed());
                                new_value *= n::u::css_fixed_to_float(child_em);
                                let unit = parent_unit.modify(n::u::float_to_css_fixed(
                                    new_value));
                                CssHintLength(unit)
                            }
                            _ => n::h::CssHintLength(n::t::CssUnitEm(child_em)),
                        }
                    }
                    CssHintLength(unit) => CssHintLength(unit),
                    _ => {
                        n::h::CssHintLength(n::t::CssUnitPx(float_to_css_fixed(16.0)))
                    }
                }
            };
            // XXX: Need an aliasable &mut here
            let net_result_computed: &mut n::c::CssComputedStyle = unsafe { cast::transmute(net_child_computed) };
            let net_child_computed: &mut n::c::CssComputedStyle = unsafe { cast::transmute(&child_computed.inner) };
            let net_parent_computed = &parent_computed.inner.inner;
            n::c::compose(net_parent_computed, net_child_computed, cb, net_result_computed);
        }

        CompleteSelectResults {
            inner: child
        }
    }

    fn computed_style(&'self self) -> CompleteStyle<'self> {
        CompleteStyle {
            inner: self.inner.computed_style()
        }
    }
}

pub struct CompleteStyle<'self> {
    inner: ComputedStyle<'self>
}

impl<'self> CompleteStyle<'self> {

    // CSS 2.1, Section 8 - Box model

    pub fn margin_top(&self) -> CSSMargin {
        strip(self.inner.margin_top())
    }

    pub fn margin_right(&self) -> CSSMargin {
        strip(self.inner.margin_right())
    }

    pub fn margin_bottom(&self) -> CSSMargin {
        strip(self.inner.margin_bottom())
    }

    pub fn margin_left(&self) -> CSSMargin {
        strip(self.inner.margin_left())
    }

    pub fn border_top_width(&self) -> CSSBorderWidth {
        strip(self.inner.border_top_width())
    }

    pub fn border_right_width(&self) -> CSSBorderWidth {
        strip(self.inner.border_right_width())
    }

    pub fn border_bottom_width(&self) -> CSSBorderWidth {
        strip(self.inner.border_bottom_width())
    }

    pub fn border_left_width(&self) -> CSSBorderWidth {
        strip(self.inner.border_left_width())
    }

    pub fn border_top_color(&self) -> Color {
        strip(self.inner.border_top_color())
    }

    pub fn border_top_color(&self) -> Color {
        strip(self.inner.border_top_color())
    }

    pub fn border_right_color(&self) -> Color {
        strip(self.inner.border_right_color())
    }

    pub fn border_bottom_color(&self) -> Color {
        strip(self.inner.border_bottom_color())
    }

    pub fn border_left_color(&self) -> Color {
        strip(self.inner.border_left_color())
    }

    // CSS 2.1, Section 9 - Visual formatting model

    pub fn display(&self, root: bool) -> CSSDisplay {
        strip(self.inner.display(root))
    }

    pub fn position(&self) -> CSSPosition {
        strip(self.inner.position())
    }

    pub fn float(&self) -> CSSFloat {
        strip(self.inner.float())
    }

    // CSS 2.1, Section 10 - Visual formatting model details

    pub fn width(&self) -> CSSWidth {
        strip(self.inner.width())
    }

    pub fn height(&self) -> CSSHeight {
        strip(self.inner.height())
    }

    pub fn line_height(&self) -> CSSLineHeight {
        strip(self.inner.line_height())
    }

    // CSS 2.1, Section 11 - Visual effects

    // CSS 2.1, Section 12 - Generated content, automatic numbering, and lists

    // CSS 2.1, Section 13 - Paged media

    // CSS 2.1, Section 14 - Colors and Backgrounds

    pub fn background_color(&self) -> Color {
        strip(self.inner.background_color())
    }

    pub fn color(&self) -> Color {
        strip(self.inner.color())
    }

    // CSS 2.1, Section 15 - Fonts

    pub fn font_family(&self) -> ~[CSSFontFamily] {
        strip(self.inner.font_family())
    }

    pub fn font_style(&self) -> CSSFontStyle {
        strip(self.inner.font_style())
    }

    pub fn font_weight(&self) -> CSSFontWeight {
        strip(self.inner.font_weight())
    }

    pub fn font_size(&self) -> CSSFontSize {
        strip(self.inner.font_size())
    }

    // CSS 2.1, Section 16 - Text

    pub fn text_align(&self) -> CSSTextAlign {
        strip(self.inner.text_align())
    }

    // CSS 2.1, Section 17 - Tables

    // CSS 2.1, Section 18 - User interface

}

fn strip<T>(value: CSSValue<T>) -> T {
    match value {
        Inherit => fail!(~"unexpected 'inherit' value in complete style"),
        Specified(v) => v
    }
}

<|endoftext|>


<commit_before>extern crate scroll;
extern crate goblin;
use goblin::archive::*;
use scroll::Pread;
use std::path::Path;
use std::fs::File;

#[test]
fn parse_file_header() {
    let file_header: [u8; SIZEOF_HEADER] = [0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x30, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                            0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38,
                                            0x32, 0x34, 0x34, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x60, 0x0a];
    let buffer = &file_header[..];
    match buffer.pread::<MemberHeader>(0) {
        Err(_) => assert!(false),
        Ok(file_header2) => {
            let file_header = MemberHeader {
                identifier: [0x2f,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,],
                timestamp: [48, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32],
                owner_id: [48, 32, 32, 32, 32, 32],
                group_id: [48, 32, 32, 32, 32, 32],
                mode: [48, 32, 32, 32, 32, 32, 32, 32],
                file_size: [56, 50, 52, 52, 32, 32, 32, 32, 32, 32],
                terminator: [96, 10] };
            assert_eq!(file_header, file_header2)
        }
    }
}

#[test]
fn parse_archive() {
    let crt1a: Vec<u8> = include!("../etc/crt1a.rs");
    const START: &'static str = "_start";
    match Archive::parse(&crt1a) {
        Ok(archive) => {
            assert_eq!(archive.member_of_symbol(START), Some("crt1.o"));
            if let Some(member) = archive.get("crt1.o") {
                assert_eq!(member.offset, 194);
                assert_eq!(member.size(), 1928)
            } else {
                println!("could not get crt1.o");
                assert!(false)
            }
        },
        Err(err) => {println!("could not parse archive: {:?}", err); assert!(false)}
    };
}

#[test]
fn parse_self() {
    use std::io::Read;
    let path = Path::new("target").join("debug").join("libgoblin.rlib");
    let buffer = {
        let mut fd = File::open(path).expect("open file");
        let mut v = Vec::new();
        fd.read_to_end(&mut v).expect("read file");
        v
    };

    let archive = Archive::parse(&buffer).expect("parse rlib");

    // check that the archive has a useful symbol table by counting the total number of symbols
    let symbol_count = archive.summarize().into_iter()
        .map(|(_member_name, _member_index, ref symbols)| symbols.len())
        .fold(0, |sum,symbol_count| sum + symbol_count);
    assert!(symbol_count > 500);

    let goblin_object_name = archive.members()
        .into_iter()
        .filter(|member| {
            println!("member: {:?}", member);
            member.ends_with("goblin-archive.o")    // < 1.18
                || (member.starts_with("goblin") && member.ends_with("0.o")) // >= 1.18 && < 1.22
                || (member.starts_with("goblin") && member.ends_with("rust-cgu.o")) // >= 1.22
        })
        .next()
        .expect("goblin-<hash>.0.o not found");

    let bytes = archive.extract(goblin_object_name, &buffer).expect("extract goblin object");
    match goblin::Object::parse(&bytes).expect("parse object") {
        goblin::Object::Elf(elf) => {
            assert!(elf.entry == 0);
            assert!(elf.bias == 0);
        }
        goblin::Object::Mach(goblin::mach::Mach::Binary(macho)) => {
            assert_eq!(macho.header.filetype, goblin::mach::header::MH_OBJECT);
            assert_eq!(macho.entry, 0);
        }
        other => {
            println!("unexpected Object::parse result: {:?}", other);
            assert!(false);
        }
    }
}
<commit_msg>tests: update archive parse_self for latest codegen units<commit_after>extern crate scroll;
extern crate goblin;
use goblin::archive::*;
use scroll::Pread;
use std::path::Path;
use std::fs::File;

#[test]
fn parse_file_header() {
    let file_header: [u8; SIZEOF_HEADER] = [0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x30, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                            0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38,
                                            0x32, 0x34, 0x34, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x60, 0x0a];
    let buffer = &file_header[..];
    match buffer.pread::<MemberHeader>(0) {
        Err(_) => assert!(false),
        Ok(file_header2) => {
            let file_header = MemberHeader {
                identifier: [0x2f,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,],
                timestamp: [48, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32],
                owner_id: [48, 32, 32, 32, 32, 32],
                group_id: [48, 32, 32, 32, 32, 32],
                mode: [48, 32, 32, 32, 32, 32, 32, 32],
                file_size: [56, 50, 52, 52, 32, 32, 32, 32, 32, 32],
                terminator: [96, 10] };
            assert_eq!(file_header, file_header2)
        }
    }
}

#[test]
fn parse_archive() {
    let crt1a: Vec<u8> = include!("../etc/crt1a.rs");
    const START: &'static str = "_start";
    match Archive::parse(&crt1a) {
        Ok(archive) => {
            assert_eq!(archive.member_of_symbol(START), Some("crt1.o"));
            if let Some(member) = archive.get("crt1.o") {
                assert_eq!(member.offset, 194);
                assert_eq!(member.size(), 1928)
            } else {
                println!("could not get crt1.o");
                assert!(false)
            }
        },
        Err(err) => {println!("could not parse archive: {:?}", err); assert!(false)}
    };
}

#[test]
fn parse_self() {
    use std::io::Read;
    let path = Path::new("target").join("debug").join("libgoblin.rlib");
    let buffer = {
        let mut fd = File::open(path).expect("open file");
        let mut v = Vec::new();
        fd.read_to_end(&mut v).expect("read file");
        v
    };

    let archive = Archive::parse(&buffer).expect("parse rlib");

    // check that the archive has a useful symbol table by counting the total number of symbols
    let symbol_count = archive.summarize().into_iter()
        .map(|(_member_name, _member_index, ref symbols)| symbols.len())
        .fold(0, |sum,symbol_count| sum + symbol_count);
    assert!(symbol_count > 500);

    let goblin_object_name = archive.members()
        .into_iter()
        .filter(|member| {
            println!("member: {:?}", member);
            member.ends_with("goblin-archive.o")    // < 1.18
                || (member.starts_with("goblin") && member.ends_with("0.o")) // >= 1.18 && < 1.22
                || (member.starts_with("goblin") && member.ends_with("rust-cgu.o")) // = 1.22
                || (member.starts_with("goblin") && member.ends_with("rcgu.o")) // >= nightly 1.23
        })
        .next()
        .expect("goblin-<hash>.0.o not found");

    let bytes = archive.extract(goblin_object_name, &buffer).expect("extract goblin object");
    match goblin::Object::parse(&bytes).expect("parse object") {
        goblin::Object::Elf(elf) => {
            assert!(elf.entry == 0);
            assert!(elf.bias == 0);
        }
        goblin::Object::Mach(goblin::mach::Mach::Binary(macho)) => {
            assert_eq!(macho.header.filetype, goblin::mach::header::MH_OBJECT);
            assert_eq!(macho.entry, 0);
        }
        other => {
            println!("unexpected Object::parse result: {:?}", other);
            assert!(false);
        }
    }
}
<|endoftext|>


<commit_before>#[test]
fn dogfood() {
    if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) {
        return;
    }
    let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let clippy_cmd = std::path::Path::new(&root_dir)
        .join("target")
        .join(env!("PROFILE"))
        .join("cargo-clippy");

    let output = std::process::Command::new(clippy_cmd)
        .current_dir(root_dir)
        .env("CLIPPY_DOGFOOD", "1")
        .arg("clippy-preview")
        .arg("--all-targets")
        .arg("--all-features")
        .arg("--")
        .args(&["-D", "clippy::all"])
        .args(&["-D", "clippy::internal"])
        .args(&["-D", "clippy::pedantic"])
        .output()
        .unwrap();
    println!("status: {}", output.status);
    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));

    assert!(output.status.success());
}

#[test]
fn dogfood_tests() {
    if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) {
        return;
    }
    let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let clippy_cmd = std::path::Path::new(&root_dir)
        .join("target")
        .join(env!("PROFILE"))
        .join("cargo-clippy");

    for d in &[
        "clippy_workspace_tests",
        "clippy_workspace_tests/src",
        "clippy_workspace_tests/subcrate",
        "clippy_workspace_tests/subcrate/src",
        "clippy_dev",
        "rustc_tools_util",
    ] {
        let output = std::process::Command::new(&clippy_cmd)
            .current_dir(root_dir.join(d))
            .env("CLIPPY_DOGFOOD", "1")
            .arg("clippy")
            .arg("--")
            .args(&["-D", "clippy::all"])
            .args(&["-D", "clippy::pedantic"])
            .output()
            .unwrap();
        println!("status: {}", output.status);
        println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
        println!("stderr: {}", String::from_utf8_lossy(&output.stderr));

        assert!(output.status.success());
    }
}
<commit_msg>Auto merge of #4513 - matthiaskrgr:dogdood_incrcomp, r=llogiq<commit_after>#[test]
fn dogfood_clippy() {
    // run clippy on itself and fail the test if lint warnings are reported
    if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) {
        return;
    }
    let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let clippy_binary = std::path::Path::new(&root_dir)
        .join("target")
        .join(env!("PROFILE"))
        .join("cargo-clippy");

    let output = std::process::Command::new(clippy_binary)
        .current_dir(root_dir)
        .env("CLIPPY_DOGFOOD", "1")
        .env("CARGO_INCREMENTAL", "0")
        .arg("clippy-preview")
        .arg("--all-targets")
        .arg("--all-features")
        .arg("--")
        .args(&["-D", "clippy::all"])
        .args(&["-D", "clippy::internal"])
        .args(&["-D", "clippy::pedantic"])
        .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
        .output()
        .unwrap();
    println!("status: {}", output.status);
    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));

    assert!(output.status.success());
}

#[test]
fn dogfood_subprojects() {
    // run clippy on remaining subprojects and fail the test if lint warnings are reported
    if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) {
        return;
    }
    let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let clippy_binary = std::path::Path::new(&root_dir)
        .join("target")
        .join(env!("PROFILE"))
        .join("cargo-clippy");

    for d in &[
        "clippy_workspace_tests",
        "clippy_workspace_tests/src",
        "clippy_workspace_tests/subcrate",
        "clippy_workspace_tests/subcrate/src",
        "clippy_dev",
        "rustc_tools_util",
    ] {
        let output = std::process::Command::new(&clippy_binary)
            .current_dir(root_dir.join(d))
            .env("CLIPPY_DOGFOOD", "1")
            .env("CARGO_INCREMENTAL", "0")
            .arg("clippy")
            .arg("--")
            .args(&["-D", "clippy::all"])
            .args(&["-D", "clippy::pedantic"])
            .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
            .output()
            .unwrap();
        println!("status: {}", output.status);
        println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
        println!("stderr: {}", String::from_utf8_lossy(&output.stderr));

        assert!(output.status.success());
    }
}
<|endoftext|>


<commit_before>use super::*;
use odbc_sys::*;
use std::marker::PhantomData;

/// A `Statement` is most easily thought of as an SQL statement, such as
/// `SELECT * FROM Employee`.
///
/// * The statement's state
/// * The current statement-level diagnostics
/// * The addresses of the application variables bound to the statement's
/// parameters and result set
///   columns
/// * The current settings of each statement attribute
///
/// See [Statement Handles][1]
///
/// Specific to the rust wrapper of an ODBC Statement is, that we do keep track
/// of the lifetimes of
/// the parent `Connection`, parameters as well as `columns` bound to the
/// `Statement`. Since it is
/// possible to unbind the parameters and columns we have to keep track of
/// their lifetimes
/// seperatly.
///
/// [1]: https://docs.microsoft.com/sql/odbc/reference/develop-app/statement-handles
#[derive(Debug)]
pub struct Statement<'con, 'param, 'col, C = NoCursor, A = Unprepared> {
    cursor: PhantomData<C>,
    access_plan: PhantomData<A>,
    /// Statement may not outlive parameters bound to it.
    parameters: PhantomData<&'param [u8]>,
    columns: PhantomData<&'col [u8]>,
    handle: HStmt<'con>,
}

/// Cursor state of `Statement`. A statement is likely to enter this state
/// after executing e.g a
/// `SELECT` query.
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum Open {}
/// State used by `Statement`. A statement is likely to enter this state after
/// executing e.g. a
/// `CREATE TABLE` statement.
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum NoCursor {}
/// Cursor state of `Statement`. A statement will enter this state after a
/// successful call to
/// `fetch()`
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum Positioned {}
/// State used by `Statement`. A statement will enter this state after a
/// successful call to
/// `prepare()`.
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum Prepared {}
/// State used by `Statement`. Indicates that no Access Plan has been created,
/// yet.
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum Unprepared {}

/// Implemented by the `Open` and `Positioned` states for `Statement`.
pub trait CursorState {}
impl CursorState for Open {}
impl CursorState for Positioned {}

impl<'con, 'param, 'col, S, A> Statement<'con, 'param, 'col, S, A> {
    /// Provides access to the raw ODBC Statement Handle
    pub fn as_raw(&self) -> SQLHSTMT {
        self.handle.as_raw()
    }

    /// Binds a parameter to a parameter marker in an SQL Statement
    ///
    /// # Result
    /// This method will destroy the statement and create a new one which may not outlive the bound
    /// parameter. This is to ensure that the statement will not derefernce an invalid pointer
    /// during execution. Use `reset_parameters` to reset the bound parameters and increase the
    /// `'param` lifetime back to `'static`.
    ///
    /// # Arguments
    /// * `parameter_number` - Index of the marker to bind to the parameter. Starting at `1`
    /// * `parameter_type` - SQL Type of the parameter
    /// * `value` - Reference to bind to the marker
    ///
    /// See [SQLBindParameter Function][1]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlbindparameter-function#columnsize-argument
    pub fn bind_input_parameter<'p, T>(
        mut self,
        parameter_number: SQLUSMALLINT,
        parameter_type: DataType,
        value: Option<&'p T>,
    ) -> Return<Statement<'con, 'p, 'col, S, A>, Self>
    where
        T: CDataType + ?Sized,
        'param: 'p,
    {
        unsafe {
            match self.handle.bind_input_parameter(
                parameter_number,
                parameter_type,
                value,
            ) {
                Success(()) => Success(self.transit()),
                Info(()) => Info(self.transit()),
                Error(()) => Error(self.transit()),
            }
        }
    }

    /// Binds a buffer and an indicator to a column.
    ///
    /// See [SQLBindCol][1]:
    /// [1]: [https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlbindcol-function]
    pub fn bind_col<'col_new, T>(
        mut self,
        column_number: SQLUSMALLINT,
        value: &'col_new mut T,
        indicator: &'col_new mut SQLLEN,
    ) -> Return<Statement<'con, 'param, 'col_new, S, A>, Self>
    where
        T: CDataType + ?Sized,
        'col: 'col_new,
    {
        unsafe {
            match self.handle.bind_col(column_number, value, indicator) {
                Success(()) => Success(self.transit()),
                Info(()) => Info(self.transit()),
                Error(()) => Error(self.transit()),
            }
        }
    }

    /// Unbinds the parameters from the parameter markers
    pub fn reset_parameters(mut self) -> Statement<'con, 'static, 'col, S, A> {
        self.handle.reset_parameters().unwrap();
        self.transit()
    }

    /// Unbinds column buffers from result set.
    pub fn reset_columns(mut self) -> Statement<'con, 'param, 'static, S, A> {
        self.handle.reset_columns().unwrap();
        self.transit()
    }

    fn transit<'p, 'c, S2, A2>(self) -> Statement<'con, 'p, 'c, S2, A2> {
        Statement {
            handle: self.handle,
            parameters: PhantomData,
            columns: PhantomData,
            cursor: PhantomData,
            access_plan: PhantomData,
        }
    }
}

impl<'con, 'param, 'col, C, A> Statement<'con, 'param, 'col, C, A>
where
    C: CursorState,
{
    /// Returns the number of columns of the result set
    ///
    /// See [SQLNumResultCols][1]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlnumresultcols-function
    pub fn num_result_cols(&self) -> Return<SQLSMALLINT> {
        self.handle.num_result_cols()
    }

    /// Advances Cursor to next row
    ///
    /// See [SQLFetch][1]
    /// See [Fetching a Row of Data][2]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlfetch-function
    /// [2]: https://docs.microsoft.com/sql/odbc/reference/develop-app/fetching-a-row-of-data
    pub fn fetch(
        mut self,
    ) -> ReturnOption<
        Statement<'con, 'param, 'col, Positioned, A>,
        Statement<'con, 'param, 'col, NoCursor, A>,
    > {
        match self.handle.fetch() {
            ReturnOption::Success(()) => ReturnOption::Success(self.transit()),
            ReturnOption::Info(()) => ReturnOption::Info(self.transit()),
            ReturnOption::NoData(()) => ReturnOption::NoData(self.transit()),
            ReturnOption::Error(()) => ReturnOption::Error(self.transit()),
        }
    }

    /// Closes the cursor. Cursors only need to be closed explicitly if the
    /// Statement handle is
    /// intended to be reused, but a result set is not consumed.
    ///
    /// See [SQLCloseCursor][1]
    /// See [Closing the Cursor][2]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlclosecursor-function
    /// [2]: https://docs.microsoft.com/sql/odbc/reference/develop-app/closing-the-cursor
    pub fn close_cursor(
        mut self,
    ) -> Return<Statement<'con, 'param, 'col, NoCursor>, Statement<'con, 'param, 'col, C, A>> {
        match self.handle.close_cursor() {
            Success(()) => Success(self.transit()),
            Info(()) => Info(self.transit()),
            Error(()) => Error(self.transit()),
        }
    }

    /// Return information about result set column
    ///
    /// See [SQLDescribeCol Function][1]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqldescribecol-function
    pub fn describe_col<T>(
        &mut self,
        column_number: SQLUSMALLINT,
        column_name: &mut T,
        column_name_indicator: &mut SQLSMALLINT,
        nullable: &mut Nullable,
    ) -> Return<Option<DataType>>
    where
        T: OutputBuffer + ?Sized,
    {
        let mut data_type = SQL_UNKNOWN_TYPE;
        let mut column_size = 0;
        let mut decimal_digits = 0;
        self.handle.describe_col(
            column_number,
            column_name,
            column_name_indicator,
            &mut data_type,
            &mut column_size,
            &mut decimal_digits,
            nullable
        ).map(|()| DataType::new(data_type, column_size, decimal_digits))
    }
}

impl<'con, 'param, 'col> Statement<'con, 'param, 'col, NoCursor, Unprepared> {
    /// Allocates a new `Statement`
    pub fn with_parent(parent: &'con Connection) -> Return<Self> {
        HStmt::allocate(parent.as_hdbc()).map(|handle| {
            Statement {
                handle,
                parameters: PhantomData,
                cursor: PhantomData,
                columns: PhantomData,
                access_plan: PhantomData,
            }
        })
    }

    /// Prepares a `Statement` for execution by creating an Access Plan.
    ///
    /// See [SQLPrepare Function][1]
    /// See [Prepare and Execute a Statement (ODBC)][2]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlprepare-function
    /// [2]: https://docs.microsoft.com/sql/relational-databases/native-client-odbc-how-to/execute-queries/prepare-and-execute-a-statement-odbc
    pub fn prepare<T>(
        mut self,
        statement_text: &T,
    ) -> Return<
        Statement<'con, 'param, 'col, NoCursor, Prepared>,
        Statement<'con, 'param, 'col, NoCursor>,
    >
    where
        T: SqlStr + ?Sized,
    {
        // According to the state transition table preparing statements which are
        // already prepared
        // is possible. However we would need to check the status code in order to
        // decide which
        // state the `Statement` is in the case of an error. So for now we only support
        // preparing
        // freshly allocated statements until someone has a use case for 'repreparing'
        // a statement.
        match self.handle.prepare(statement_text) {
            Success(()) => Success(self.transit()),
            Info(()) => Info(self.transit()),
            Error(()) => Error(self.transit()),
        }
    }

    /// Executes a preparable statement, using the current values of the
    /// parametr marker variables.
    ///
    /// * See [SQLExecDirect][1]
    /// * See [Direct Execution][2]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlexecdirect-function
    /// [2]: https://docs.microsoft.com/sql/odbc/reference/develop-app/direct-execution-odbc
    pub fn exec_direct<T>(
        mut self,
        statement_text: &T,
    ) -> ReturnOption<
        ResultSet<'con, 'param, 'col, Unprepared>,
        Statement<'con, 'param, 'col, NoCursor>,
    >
    where
        T: SqlStr + ?Sized,
    {
        match self.handle.exec_direct(statement_text) {
            ReturnOption::Success(()) => ReturnOption::Success(self.transit()),
            ReturnOption::Info(()) => ReturnOption::Info(self.transit()),
            ReturnOption::NoData(()) => ReturnOption::NoData(self.transit()),
            ReturnOption::Error(()) => ReturnOption::Error(self.transit()),
        }
    }
}

impl<'con, 'param, 'col> Statement<'con, 'param, 'col, NoCursor, Prepared> {
    /// Executes a prepared statement, using the current values fo the
    /// parameter marker variables
    /// if any parameter markers exist in the statement.
    ///
    /// See [SQLExecute Function][1]
    /// See [Prepared Execution][2]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlexecute-function
    /// [2]: https://docs.microsoft.com/sql/odbc/reference/develop-app/prepared-execution-odbc
    pub fn execute(mut self) -> ReturnOption<ResultSet<'con, 'param, 'col, Prepared>, Self> {
        match self.handle.execute() {
            ReturnOption::Success(()) => ReturnOption::Success(self.transit()),
            ReturnOption::Info(()) => ReturnOption::Info(self.transit()),
            ReturnOption::Error(()) => ReturnOption::Error(self.transit()),
            ReturnOption::NoData(()) => ReturnOption::NoData(self.transit()),
        }
    }
}

impl<'con, 'param, 'col, A> Statement<'con, 'param, 'col, Positioned, A> {
    /// Retrieves data for a single column or output parameter.
    ///
    /// See [SQLGetData][1]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlgetdata-function
    pub fn get_data<T>(
        &mut self,
        col_or_param_num: SQLUSMALLINT,
        target: &mut T,
    ) -> ReturnOption<Indicator>
    where
        T: CDataType + ?Sized,
    {
        self.handle.get_data(col_or_param_num, target)
    }
}

impl<'con, 'param, 'col, C> Diagnostics for Statement<'con, 'param, 'col, C> {
    fn diagnostics(
        &self,
        rec_number: SQLSMALLINT,
        message_text: &mut [SQLCHAR],
    ) -> ReturnOption<DiagResult> {
        self.handle.diagnostics(rec_number, message_text)
    }
}
<commit_msg>add describe col for prepared states<commit_after>use super::*;
use odbc_sys::*;
use std::marker::PhantomData;

/// A `Statement` is most easily thought of as an SQL statement, such as
/// `SELECT * FROM Employee`.
///
/// * The statement's state
/// * The current statement-level diagnostics
/// * The addresses of the application variables bound to the statement's
/// parameters and result set
///   columns
/// * The current settings of each statement attribute
///
/// See [Statement Handles][1]
///
/// Specific to the rust wrapper of an ODBC Statement is, that we do keep track
/// of the lifetimes of
/// the parent `Connection`, parameters as well as `columns` bound to the
/// `Statement`. Since it is
/// possible to unbind the parameters and columns we have to keep track of
/// their lifetimes
/// seperatly.
///
/// [1]: https://docs.microsoft.com/sql/odbc/reference/develop-app/statement-handles
#[derive(Debug)]
pub struct Statement<'con, 'param, 'col, C = NoCursor, A = Unprepared> {
    cursor: PhantomData<C>,
    access_plan: PhantomData<A>,
    /// Statement may not outlive parameters bound to it.
    parameters: PhantomData<&'param [u8]>,
    columns: PhantomData<&'col [u8]>,
    handle: HStmt<'con>,
}

/// Cursor state of `Statement`. A statement is likely to enter this state
/// after executing e.g a
/// `SELECT` query.
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum Open {}
/// State used by `Statement`. A statement is likely to enter this state after
/// executing e.g. a
/// `CREATE TABLE` statement.
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum NoCursor {}
/// Cursor state of `Statement`. A statement will enter this state after a
/// successful call to
/// `fetch()`
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum Positioned {}
/// State used by `Statement`. A statement will enter this state after a
/// successful call to
/// `prepare()`.
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum Prepared {}
/// State used by `Statement`. Indicates that no Access Plan has been created,
/// yet.
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum Unprepared {}

/// Implemented by the `Open` and `Positioned` states for `Statement`.
pub trait CursorState {}
impl CursorState for Open {}
impl CursorState for Positioned {}

impl<'con, 'param, 'col, S, A> Statement<'con, 'param, 'col, S, A> {
    /// Provides access to the raw ODBC Statement Handle
    pub fn as_raw(&self) -> SQLHSTMT {
        self.handle.as_raw()
    }

    /// Binds a parameter to a parameter marker in an SQL Statement
    ///
    /// # Result
    /// This method will destroy the statement and create a new one which may not outlive the bound
    /// parameter. This is to ensure that the statement will not derefernce an invalid pointer
    /// during execution. Use `reset_parameters` to reset the bound parameters and increase the
    /// `'param` lifetime back to `'static`.
    ///
    /// # Arguments
    /// * `parameter_number` - Index of the marker to bind to the parameter. Starting at `1`
    /// * `parameter_type` - SQL Type of the parameter
    /// * `value` - Reference to bind to the marker
    ///
    /// See [SQLBindParameter Function][1]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlbindparameter-function#columnsize-argument
    pub fn bind_input_parameter<'p, T>(
        mut self,
        parameter_number: SQLUSMALLINT,
        parameter_type: DataType,
        value: Option<&'p T>,
    ) -> Return<Statement<'con, 'p, 'col, S, A>, Self>
    where
        T: CDataType + ?Sized,
        'param: 'p,
    {
        unsafe {
            match self.handle.bind_input_parameter(
                parameter_number,
                parameter_type,
                value,
            ) {
                Success(()) => Success(self.transit()),
                Info(()) => Info(self.transit()),
                Error(()) => Error(self.transit()),
            }
        }
    }

    /// Binds a buffer and an indicator to a column.
    ///
    /// See [SQLBindCol][1]:
    /// [1]: [https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlbindcol-function]
    pub fn bind_col<'col_new, T>(
        mut self,
        column_number: SQLUSMALLINT,
        value: &'col_new mut T,
        indicator: &'col_new mut SQLLEN,
    ) -> Return<Statement<'con, 'param, 'col_new, S, A>, Self>
    where
        T: CDataType + ?Sized,
        'col: 'col_new,
    {
        unsafe {
            match self.handle.bind_col(column_number, value, indicator) {
                Success(()) => Success(self.transit()),
                Info(()) => Info(self.transit()),
                Error(()) => Error(self.transit()),
            }
        }
    }

    /// Unbinds the parameters from the parameter markers
    pub fn reset_parameters(mut self) -> Statement<'con, 'static, 'col, S, A> {
        self.handle.reset_parameters().unwrap();
        self.transit()
    }

    /// Unbinds column buffers from result set.
    pub fn reset_columns(mut self) -> Statement<'con, 'param, 'static, S, A> {
        self.handle.reset_columns().unwrap();
        self.transit()
    }

    fn transit<'p, 'c, S2, A2>(self) -> Statement<'con, 'p, 'c, S2, A2> {
        Statement {
            handle: self.handle,
            parameters: PhantomData,
            columns: PhantomData,
            cursor: PhantomData,
            access_plan: PhantomData,
        }
    }
}

impl<'con, 'param, 'col, C, A> Statement<'con, 'param, 'col, C, A>
where
    C: CursorState,
{
    /// Returns the number of columns of the result set
    ///
    /// See [SQLNumResultCols][1]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlnumresultcols-function
    pub fn num_result_cols(&self) -> Return<SQLSMALLINT> {
        self.handle.num_result_cols()
    }

    /// Advances Cursor to next row
    ///
    /// See [SQLFetch][1]
    /// See [Fetching a Row of Data][2]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlfetch-function
    /// [2]: https://docs.microsoft.com/sql/odbc/reference/develop-app/fetching-a-row-of-data
    pub fn fetch(
        mut self,
    ) -> ReturnOption<
        Statement<'con, 'param, 'col, Positioned, A>,
        Statement<'con, 'param, 'col, NoCursor, A>,
    > {
        match self.handle.fetch() {
            ReturnOption::Success(()) => ReturnOption::Success(self.transit()),
            ReturnOption::Info(()) => ReturnOption::Info(self.transit()),
            ReturnOption::NoData(()) => ReturnOption::NoData(self.transit()),
            ReturnOption::Error(()) => ReturnOption::Error(self.transit()),
        }
    }

    /// Closes the cursor. Cursors only need to be closed explicitly if the
    /// Statement handle is
    /// intended to be reused, but a result set is not consumed.
    ///
    /// See [SQLCloseCursor][1]
    /// See [Closing the Cursor][2]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlclosecursor-function
    /// [2]: https://docs.microsoft.com/sql/odbc/reference/develop-app/closing-the-cursor
    pub fn close_cursor(
        mut self,
    ) -> Return<Statement<'con, 'param, 'col, NoCursor>, Statement<'con, 'param, 'col, C, A>> {
        match self.handle.close_cursor() {
            Success(()) => Success(self.transit()),
            Info(()) => Info(self.transit()),
            Error(()) => Error(self.transit()),
        }
    }

    /// Return information about result set column
    ///
    /// See [SQLDescribeCol Function][1]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqldescribecol-function
    pub fn describe_col<T>(
        &mut self,
        column_number: SQLUSMALLINT,
        column_name: &mut T,
        column_name_indicator: &mut SQLSMALLINT,
        nullable: &mut Nullable,
    ) -> Return<Option<DataType>>
    where
        T: OutputBuffer + ?Sized,
    {
        let mut data_type = SQL_UNKNOWN_TYPE;
        let mut column_size = 0;
        let mut decimal_digits = 0;
        self.handle.describe_col(
            column_number,
            column_name,
            column_name_indicator,
            &mut data_type,
            &mut column_size,
            &mut decimal_digits,
            nullable
        ).map(|()| DataType::new(data_type, column_size, decimal_digits))
    }
}

impl<'con, 'param, 'col> Statement<'con, 'param, 'col, NoCursor, Unprepared> {
    /// Allocates a new `Statement`
    pub fn with_parent(parent: &'con Connection) -> Return<Self> {
        HStmt::allocate(parent.as_hdbc()).map(|handle| {
            Statement {
                handle,
                parameters: PhantomData,
                cursor: PhantomData,
                columns: PhantomData,
                access_plan: PhantomData,
            }
        })
    }

    /// Prepares a `Statement` for execution by creating an Access Plan.
    ///
    /// See [SQLPrepare Function][1]
    /// See [Prepare and Execute a Statement (ODBC)][2]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlprepare-function
    /// [2]: https://docs.microsoft.com/sql/relational-databases/native-client-odbc-how-to/execute-queries/prepare-and-execute-a-statement-odbc
    pub fn prepare<T>(
        mut self,
        statement_text: &T,
    ) -> Return<
        Statement<'con, 'param, 'col, NoCursor, Prepared>,
        Statement<'con, 'param, 'col, NoCursor>,
    >
    where
        T: SqlStr + ?Sized,
    {
        // According to the state transition table preparing statements which are
        // already prepared
        // is possible. However we would need to check the status code in order to
        // decide which
        // state the `Statement` is in the case of an error. So for now we only support
        // preparing
        // freshly allocated statements until someone has a use case for 'repreparing'
        // a statement.
        match self.handle.prepare(statement_text) {
            Success(()) => Success(self.transit()),
            Info(()) => Info(self.transit()),
            Error(()) => Error(self.transit()),
        }
    }

    /// Executes a preparable statement, using the current values of the
    /// parametr marker variables.
    ///
    /// * See [SQLExecDirect][1]
    /// * See [Direct Execution][2]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlexecdirect-function
    /// [2]: https://docs.microsoft.com/sql/odbc/reference/develop-app/direct-execution-odbc
    pub fn exec_direct<T>(
        mut self,
        statement_text: &T,
    ) -> ReturnOption<
        ResultSet<'con, 'param, 'col, Unprepared>,
        Statement<'con, 'param, 'col, NoCursor>,
    >
    where
        T: SqlStr + ?Sized,
    {
        match self.handle.exec_direct(statement_text) {
            ReturnOption::Success(()) => ReturnOption::Success(self.transit()),
            ReturnOption::Info(()) => ReturnOption::Info(self.transit()),
            ReturnOption::NoData(()) => ReturnOption::NoData(self.transit()),
            ReturnOption::Error(()) => ReturnOption::Error(self.transit()),
        }
    }
}

impl<'con, 'param, 'col> Statement<'con, 'param, 'col, NoCursor, Prepared> {

    /// Return information about result set column
    ///
    /// See [SQLDescribeCol Function][1]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqldescribecol-function
    pub fn describe_col<T>(
        &mut self,
        column_number: SQLUSMALLINT,
        column_name: &mut T,
        column_name_indicator: &mut SQLSMALLINT,
        nullable: &mut Nullable,
    ) -> Return<Option<DataType>>
    where
        T: OutputBuffer + ?Sized,
    {
        let mut data_type = SQL_UNKNOWN_TYPE;
        let mut column_size = 0;
        let mut decimal_digits = 0;
        self.handle.describe_col(
            column_number,
            column_name,
            column_name_indicator,
            &mut data_type,
            &mut column_size,
            &mut decimal_digits,
            nullable
        ).map(|()| DataType::new(data_type, column_size, decimal_digits))
    }

    /// Executes a prepared statement, using the current values fo the
    /// parameter marker variables
    /// if any parameter markers exist in the statement.
    ///
    /// See [SQLExecute Function][1]
    /// See [Prepared Execution][2]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlexecute-function
    /// [2]: https://docs.microsoft.com/sql/odbc/reference/develop-app/prepared-execution-odbc
    pub fn execute(mut self) -> ReturnOption<ResultSet<'con, 'param, 'col, Prepared>, Self> {
        match self.handle.execute() {
            ReturnOption::Success(()) => ReturnOption::Success(self.transit()),
            ReturnOption::Info(()) => ReturnOption::Info(self.transit()),
            ReturnOption::Error(()) => ReturnOption::Error(self.transit()),
            ReturnOption::NoData(()) => ReturnOption::NoData(self.transit()),
        }
    }
}

impl<'con, 'param, 'col, A> Statement<'con, 'param, 'col, Positioned, A> {
    /// Retrieves data for a single column or output parameter.
    ///
    /// See [SQLGetData][1]
    /// [1]: https://docs.microsoft.com/sql/odbc/reference/syntax/sqlgetdata-function
    pub fn get_data<T>(
        &mut self,
        col_or_param_num: SQLUSMALLINT,
        target: &mut T,
    ) -> ReturnOption<Indicator>
    where
        T: CDataType + ?Sized,
    {
        self.handle.get_data(col_or_param_num, target)
    }
}

impl<'con, 'param, 'col, C> Diagnostics for Statement<'con, 'param, 'col, C> {
    fn diagnostics(
        &self,
        rec_number: SQLSMALLINT,
        message_text: &mut [SQLCHAR],
    ) -> ReturnOption<DiagResult> {
        self.handle.diagnostics(rec_number, message_text)
    }
}<|endoftext|>