<commit_before>#![crate_name = "bindgen"]
#![crate_type = "dylib"]

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

// To avoid rather annoying warnings when matching with CXCursor_xxx as a
// constant.
#![allow(non_upper_case_globals)]

extern crate syntex_syntax as syntax;
extern crate aster;
extern crate quasi;
extern crate clang_sys;
extern crate libc;
extern crate regex;
#[macro_use]
extern crate log;

mod clangll;
mod clang;
mod ir;
mod parse;
mod regex_set;
mod codegen {
    include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
}

use std::borrow::Borrow;
use std::io::{self, Write};
use std::fs::OpenOptions;
use std::path::Path;
use std::marker;
use std::collections::HashSet;

use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::print::pprust;
use syntax::print::pp::eof;
use syntax::ptr::P;

use ir::context::BindgenContext;
use ir::item::{Item, ItemId};
use parse::{ClangItemParser, ParseError};
use regex_set::RegexSet;

#[derive(Debug)]
pub struct Builder<'a> {
    options: BindgenOptions,
    // TODO: Before the logger was here, do we still want the lifetime?
    phantom: marker::PhantomData<&'a ()>,
}

pub fn builder<'a>() -> Builder<'a> {
    Default::default()
}

impl<'a> Builder<'a> {
    pub fn header<T: Into<String>>(&mut self, header: T) -> &mut Self {
        self.clang_arg(header)
    }

    pub fn match_pat<T: Into<String>>(&mut self, arg: T) -> &mut Self {
        self.options.match_pat.insert(arg.into());
        self
    }

    pub fn hide_type<T: Into<String>>(&mut self, arg: T) -> &mut Self {
        self.options.hidden_types.insert(arg.into());
        self
    }

    pub fn opaque_type<T: Into<String>>(&mut self, arg: T) -> &mut Self {
        self.options.opaque_types.insert(arg.into());
        self
    }

    pub fn whitelisted_type<T: Borrow<str>>(&mut self, arg: &T) -> &mut Self {
        self.options.whitelisted_types.insert(arg);
        self
    }

    pub fn raw_line<T: Into<String>>(&mut self, arg: T) -> &mut Self {
        self.options.raw_lines.push(arg.into());
        self
    }

    pub fn clang_arg<T: Into<String>>(&mut self, arg: T) -> &mut Self {
        self.options.clang_args.push(arg.into());
        self
    }

    pub fn link<T: Into<String>>(&mut self, library: T) -> &mut Self {
        self.options.links.push((library.into(), LinkType::Default));
        self
    }

    pub fn link_static<T: Into<String>>(&mut self, library: T) -> &mut Self {
        self.options.links.push((library.into(), LinkType::Static));
        self
    }

    pub fn link_framework<T: Into<String>>(&mut self, library: T) -> &mut Self {
        self.options.links.push((library.into(), LinkType::Framework));
        self
    }

    pub fn dtor_attr<T: Into<String>>(&mut self, attr: T) -> &mut Self {
        self.options.dtor_attrs.push(attr.into());
        self
    }

    pub fn forbid_unknown_types(&mut self) -> &mut Self {
        self.options.fail_on_unknown_type = true;
        self
    }

    pub fn emit_builtins(&mut self) -> &mut Self {
        self.options.builtins = true;
        self
    }

    pub fn no_bitfield_methods(&mut self) -> &mut Self {
        self.options.gen_bitfield_methods = false;
        self
    }

    pub fn no_unstable_rust(&mut self) -> &mut Self {
        self.options.unstable_rust = false;
        self
    }
    pub fn rust_enums(&mut self, value: bool) -> &mut Self {
        self.options.rust_enums = value;
        self
    }

    pub fn rename_types(&mut self, value: bool) -> &mut Self {
        self.options.rename_types = value;
        self
    }

    pub fn disable_class_constants(&mut self) -> &mut Self {
        self.options.class_constants = false;
        self
    }

    pub fn generate(self) -> Result<Bindings, ()> {
        Bindings::generate(self.options, None)
    }
}

impl<'a> Default for Builder<'a> {
    fn default() -> Builder<'a> {
        Builder {
            options: Default::default(),
            phantom: marker::PhantomData,
        }
    }
}

/// Deprecated - use a `Builder` instead
#[derive(Debug)]
pub struct BindgenOptions {
    pub match_pat: HashSet<String>,
    pub hidden_types: HashSet<String>,
    pub opaque_types: HashSet<String>,
    pub whitelisted_types: RegexSet,
    pub whitelisted_functions: RegexSet,
    pub whitelisted_vars: RegexSet,
    pub builtins: bool,
    pub rust_enums: bool,
    pub links: Vec<(String, LinkType)>,
    pub emit_ast: bool,
    pub ignore_functions: bool,
    pub ignore_methods: bool,
    pub gen_bitfield_methods: bool,
    pub fail_on_unknown_type: bool,
    pub enable_cxx_namespaces: bool,
    pub rename_types: bool,
    pub derive_debug: bool,
    /// Generate or not only stable rust.
    pub unstable_rust: bool,
    /// Whether to generate C++ class constants.
    pub class_constants: bool,
    /// Wether to generate names that are **directly** under namespaces.
    pub namespaced_constants: bool,
    /// Whether to use msvc mangling rules
    pub msvc_mangling: bool,
    pub override_enum_ty: String,
    pub raw_lines: Vec<String>,
    /// Attributes for a type with destructor
    pub dtor_attrs: Vec<String>,
    pub clang_args: Vec<String>,
}

impl Default for BindgenOptions {
    fn default() -> BindgenOptions {
        BindgenOptions {
            match_pat: Default::default(),
            hidden_types: Default::default(),
            opaque_types: Default::default(),
            whitelisted_types: Default::default(),
            whitelisted_functions: Default::default(),
            whitelisted_vars: Default::default(),
            builtins: false,
            rust_enums: true,
            links: vec![],
            emit_ast: false,
            ignore_functions: false,
            ignore_methods: false,
            gen_bitfield_methods: true,
            fail_on_unknown_type: true,
            rename_types: true,
            derive_debug: true,
            enable_cxx_namespaces: false,
            override_enum_ty: "".to_string(),
            unstable_rust: true,
            class_constants: true,
            namespaced_constants: true,
            msvc_mangling: false,
            raw_lines: vec![],
            dtor_attrs: vec![],
            clang_args: vec![],
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum LinkType {
    Default,
    Static,
    Framework
}

#[derive(Debug, Clone)]
pub struct Bindings {
    module: ast::Mod,
    raw_lines: Vec<String>,
}

impl Bindings {
    /// Deprecated - use a `Builder` instead
    pub fn generate(options: BindgenOptions, span: Option<Span>) -> Result<Bindings, ()> {
        let span = span.unwrap_or(DUMMY_SP);

        let mut context = BindgenContext::new(options);
        parse(&mut context);

        let module = ast::Mod {
            inner: span,
            items: codegen::codegen(&mut context),
        };

        Ok(Bindings {
            module: module,
            raw_lines: context.options().raw_lines.clone(),
        })
    }

    pub fn into_ast(self) -> Vec<P<ast::Item>> {
        self.module.items
    }

    pub fn to_string(&self) -> String {
        let mut mod_str = vec![];
        {
            let ref_writer = Box::new(mod_str.by_ref()) as Box<Write>;
            self.write(ref_writer).expect("Could not write bindings to string");
        }
        String::from_utf8(mod_str).unwrap()
    }

    pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
        let file = try!(OpenOptions::new().write(true).truncate(true).create(true).open(path));
        self.write(Box::new(file))
    }

    // https://github.com/Manishearth/rust-clippy/issues/740
    #[cfg_attr(feature = "clippy", allow(needless_lifetimes))]
    pub fn write<'a>(&self, mut writer: Box<Write + 'a>) -> io::Result<()> {
        try!(writer.write("/* automatically generated by rust-bindgen */\n\n".as_bytes()));

        for line in self.raw_lines.iter() {
            try!(writer.write(line.as_bytes()));
            try!(writer.write("\n".as_bytes()));
        }
        if !self.raw_lines.is_empty() {
            try!(writer.write("\n".as_bytes()));
        }

        let mut ps = pprust::rust_printer(writer);
        try!(ps.print_mod(&self.module, &[]));
        try!(ps.print_remaining_comments());
        try!(eof(&mut ps.s));
        ps.s.out.flush()
    }
}

#[test]
fn builder_state() {
    let logger = DummyLogger;
    let mut build = builder();
    {
        build.header("example.h");
        build.link_static("m");
        build.log(&logger);
    }
    assert!(build.logger.is_some());
    assert!(build.options.clang_args.binary_search(&"example.h".to_owned()).is_ok());
    assert!(build.options.links.binary_search(&("m".to_owned(), LinkType::Static)).is_ok());
}

/// Determines whether the given cursor is in any of the files matched by the
/// options.
fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool {
    let (file, _, _, _) = cursor.location().location();

    match file.name() {
        None => ctx.options().builtins,
        Some(..) => true,
    }
}

pub fn parse_one(ctx: &mut BindgenContext,
                 cursor: clang::Cursor,
                 parent: Option<ItemId>,
                 children: &mut Vec<ItemId>) -> clangll::Enum_CXVisitorResult {
    if !filter_builtins(ctx, &cursor) {
        return CXChildVisit_Continue
    }

    use clangll::CXChildVisit_Continue;
    match Item::parse(cursor, parent, ctx) {
        Ok(id) => children.push(id),
        Err(ParseError::Continue) => {},
        Err(ParseError::Recurse) => {
            cursor.visit(|child, _| parse_one(ctx, *child, parent, children));
        }
    }
    CXChildVisit_Continue
}

fn parse(context: &mut BindgenContext) {
    use clang::Diagnostic;
    use clangll::*;

    for d in context.translation_unit().diags().iter() {
        let msg = d.format(Diagnostic::default_opts());
        let is_err = d.severity() >= CXDiagnostic_Error;
        println!("{}, err: {}", msg, is_err);
    }

    let cursor = context.translation_unit().cursor();
    if context.options().emit_ast {
        cursor.visit(|cur, _| clang::ast_dump(cur, 0));
    }

    let root = context.root_module();
    context.with_module(root, |context, children| {
        cursor.visit(|cursor, _| parse_one(context, *cursor, None, children))
    });

    assert!(context.current_module() == context.root_module(),
            "How did this happen?");
}
<commit_msg>Fix lifetime issues with buildgen::builder()<commit_after>#![crate_name = "bindgen"]
#![crate_type = "dylib"]

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

// To avoid rather annoying warnings when matching with CXCursor_xxx as a
// constant.
#![allow(non_upper_case_globals)]

extern crate syntex_syntax as syntax;
extern crate aster;
extern crate quasi;
extern crate clang_sys;
extern crate libc;
extern crate regex;
#[macro_use]
extern crate log;

mod clangll;
mod clang;
mod ir;
mod parse;
mod regex_set;
mod codegen {
    include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
}

use std::borrow::Borrow;
use std::io::{self, Write};
use std::fs::OpenOptions;
use std::path::Path;
use std::collections::HashSet;

use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::print::pprust;
use syntax::print::pp::eof;
use syntax::ptr::P;

use ir::context::BindgenContext;
use ir::item::{Item, ItemId};
use parse::{ClangItemParser, ParseError};
use regex_set::RegexSet;

#[derive(Debug,Default)]
pub struct Builder {
    options: BindgenOptions,
}

pub fn builder() -> Builder {
    Default::default()
}

impl Builder {
    pub fn header<T: Into<String>>(self, header: T) -> Builder {
        self.clang_arg(header)
    }

    pub fn match_pat<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.match_pat.insert(arg.into());
        self
    }

    pub fn hide_type<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.hidden_types.insert(arg.into());
        self
    }

    pub fn opaque_type<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.opaque_types.insert(arg.into());
        self
    }

    pub fn whitelisted_type<T: Borrow<str>>(mut self, arg: &T) -> Builder {
        self.options.whitelisted_types.insert(arg);
        self
    }

    pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.raw_lines.push(arg.into());
        self
    }

    pub fn clang_arg<T: Into<String>>(mut self, arg: T) -> Builder {
        self.options.clang_args.push(arg.into());
        self
    }

    pub fn link<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Default));
        self
    }

    pub fn link_static<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Static));
        self
    }

    pub fn link_framework<T: Into<String>>(mut self, library: T) -> Builder {
        self.options.links.push((library.into(), LinkType::Framework));
        self
    }

    pub fn dtor_attr<T: Into<String>>(mut self, attr: T) -> Builder {
        self.options.dtor_attrs.push(attr.into());
        self
    }

    pub fn forbid_unknown_types(mut self) -> Builder {
        self.options.fail_on_unknown_type = true;
        self
    }

    pub fn emit_builtins(mut self) -> Builder {
        self.options.builtins = true;
        self
    }

    pub fn no_bitfield_methods(mut self) -> Builder {
        self.options.gen_bitfield_methods = false;
        self
    }

    pub fn no_unstable_rust(mut self) -> Builder {
        self.options.unstable_rust = false;
        self
    }
    pub fn rust_enums(mut self, value: bool) -> Builder {
        self.options.rust_enums = value;
        self
    }

    pub fn rename_types(mut self, value: bool) -> Builder {
        self.options.rename_types = value;
        self
    }

    pub fn disable_class_constants(mut self) -> Builder {
        self.options.class_constants = false;
        self
    }

    pub fn generate(self) -> Result<Bindings, ()> {
        Bindings::generate(self.options, None)
    }
}

/// Deprecated - use a `Builder` instead
#[derive(Debug)]
pub struct BindgenOptions {
    pub match_pat: HashSet<String>,
    pub hidden_types: HashSet<String>,
    pub opaque_types: HashSet<String>,
    pub whitelisted_types: RegexSet,
    pub whitelisted_functions: RegexSet,
    pub whitelisted_vars: RegexSet,
    pub builtins: bool,
    pub rust_enums: bool,
    pub links: Vec<(String, LinkType)>,
    pub emit_ast: bool,
    pub ignore_functions: bool,
    pub ignore_methods: bool,
    pub gen_bitfield_methods: bool,
    pub fail_on_unknown_type: bool,
    pub enable_cxx_namespaces: bool,
    pub rename_types: bool,
    pub derive_debug: bool,
    /// Generate or not only stable rust.
    pub unstable_rust: bool,
    /// Whether to generate C++ class constants.
    pub class_constants: bool,
    /// Wether to generate names that are **directly** under namespaces.
    pub namespaced_constants: bool,
    /// Whether to use msvc mangling rules
    pub msvc_mangling: bool,
    pub override_enum_ty: String,
    pub raw_lines: Vec<String>,
    /// Attributes for a type with destructor
    pub dtor_attrs: Vec<String>,
    pub clang_args: Vec<String>,
}

impl Default for BindgenOptions {
    fn default() -> BindgenOptions {
        BindgenOptions {
            match_pat: Default::default(),
            hidden_types: Default::default(),
            opaque_types: Default::default(),
            whitelisted_types: Default::default(),
            whitelisted_functions: Default::default(),
            whitelisted_vars: Default::default(),
            builtins: false,
            rust_enums: true,
            links: vec![],
            emit_ast: false,
            ignore_functions: false,
            ignore_methods: false,
            gen_bitfield_methods: true,
            fail_on_unknown_type: true,
            rename_types: true,
            derive_debug: true,
            enable_cxx_namespaces: false,
            override_enum_ty: "".to_string(),
            unstable_rust: true,
            class_constants: true,
            namespaced_constants: true,
            msvc_mangling: false,
            raw_lines: vec![],
            dtor_attrs: vec![],
            clang_args: vec![],
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum LinkType {
    Default,
    Static,
    Framework
}

#[derive(Debug, Clone)]
pub struct Bindings {
    module: ast::Mod,
    raw_lines: Vec<String>,
}

impl Bindings {
    /// Deprecated - use a `Builder` instead
    pub fn generate(options: BindgenOptions, span: Option<Span>) -> Result<Bindings, ()> {
        let span = span.unwrap_or(DUMMY_SP);

        let mut context = BindgenContext::new(options);
        parse(&mut context);

        let module = ast::Mod {
            inner: span,
            items: codegen::codegen(&mut context),
        };

        Ok(Bindings {
            module: module,
            raw_lines: context.options().raw_lines.clone(),
        })
    }

    pub fn into_ast(self) -> Vec<P<ast::Item>> {
        self.module.items
    }

    pub fn to_string(&self) -> String {
        let mut mod_str = vec![];
        {
            let ref_writer = Box::new(mod_str.by_ref()) as Box<Write>;
            self.write(ref_writer).expect("Could not write bindings to string");
        }
        String::from_utf8(mod_str).unwrap()
    }

    pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
        let file = try!(OpenOptions::new().write(true).truncate(true).create(true).open(path));
        self.write(Box::new(file))
    }

    // https://github.com/Manishearth/rust-clippy/issues/740
    #[cfg_attr(feature = "clippy", allow(needless_lifetimes))]
    pub fn write<'a>(&self, mut writer: Box<Write + 'a>) -> io::Result<()> {
        try!(writer.write("/* automatically generated by rust-bindgen */\n\n".as_bytes()));

        for line in self.raw_lines.iter() {
            try!(writer.write(line.as_bytes()));
            try!(writer.write("\n".as_bytes()));
        }
        if !self.raw_lines.is_empty() {
            try!(writer.write("\n".as_bytes()));
        }

        let mut ps = pprust::rust_printer(writer);
        try!(ps.print_mod(&self.module, &[]));
        try!(ps.print_remaining_comments());
        try!(eof(&mut ps.s));
        ps.s.out.flush()
    }
}

#[test]
fn builder_state() {
    let logger = DummyLogger;
    let mut build = builder();
    {
        build.header("example.h");
        build.link_static("m");
        build.log(&logger);
    }
    assert!(build.logger.is_some());
    assert!(build.options.clang_args.binary_search(&"example.h".to_owned()).is_ok());
    assert!(build.options.links.binary_search(&("m".to_owned(), LinkType::Static)).is_ok());
}

/// Determines whether the given cursor is in any of the files matched by the
/// options.
fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool {
    let (file, _, _, _) = cursor.location().location();

    match file.name() {
        None => ctx.options().builtins,
        Some(..) => true,
    }
}

pub fn parse_one(ctx: &mut BindgenContext,
                 cursor: clang::Cursor,
                 parent: Option<ItemId>,
                 children: &mut Vec<ItemId>) -> clangll::Enum_CXVisitorResult {
    if !filter_builtins(ctx, &cursor) {
        return CXChildVisit_Continue
    }

    use clangll::CXChildVisit_Continue;
    match Item::parse(cursor, parent, ctx) {
        Ok(id) => children.push(id),
        Err(ParseError::Continue) => {},
        Err(ParseError::Recurse) => {
            cursor.visit(|child, _| parse_one(ctx, *child, parent, children));
        }
    }
    CXChildVisit_Continue
}

fn parse(context: &mut BindgenContext) {
    use clang::Diagnostic;
    use clangll::*;

    for d in context.translation_unit().diags().iter() {
        let msg = d.format(Diagnostic::default_opts());
        let is_err = d.severity() >= CXDiagnostic_Error;
        println!("{}, err: {}", msg, is_err);
    }

    let cursor = context.translation_unit().cursor();
    if context.options().emit_ast {
        cursor.visit(|cur, _| clang::ast_dump(cur, 0));
    }

    let root = context.root_module();
    context.with_module(root, |context, children| {
        cursor.visit(|cursor, _| parse_one(context, *cursor, None, children))
    });

    assert!(context.current_module() == context.root_module(),
            "How did this happen?");
}
<|endoftext|>


<commit_before>//! Openapi provides structures and support for serializing and deserializing [openapi](https://github.com/OAI/OpenAPI-Specification) specifications
//!
//! # Examples
//!
//! Typical use deserialing an existing to a persisted spec to rust form or
//! visa versa
//!
//! The hyper client should be configured with tls.
//!
//! ```no_run
//! extern crate openapi;
//!
//! fn main() {
//!   match openapi::from_path("path/to/openapi.yaml") {
//!     Ok(spec) => println!("spec: {:?}", spec),
//!     Err(err) => println!("error: {}", err)
//!   }
//! }
//! ```
//!
//! # Errors
//!
//! Operations typically result in a `openapi::Result` Type which is an alias
//! for Rust's
//! built-in Result with the Err Type fixed to the
//! [openapi::errors::Error](errors/struct.Error.html) enum type. These are
//! provided
//! using [error_chain](https://github.com/brson/error-chain) crate so their
//! shape and behavior should be consistent and familiar to existing
//! error_chain users.
//!
use serde::{Deserialize, Serialize};
use std::{fs::File, io::Read, path::Path, result::Result as StdResult};

pub mod error;
pub mod v2;
pub mod v3_0;

pub use error::Error;

const MINIMUM_OPENAPI30_VERSION: &str = ">= 3.0";

pub type Result<T> = StdResult<T, Error>;

/// Supported versions of the OpenApi.
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
#[serde(untagged)]
pub enum OpenApi {
    /// Version 2.0 of the OpenApi specification.
    ///
    /// Refer to the official
    /// [specification](https://github.com/OAI/OpenAPI-Specification/blob/0dd79f6/versions/2.0.md)
    /// for more information.
    V2(v2::Spec),

    /// Version 3.0.1 of the OpenApi specification.
    ///
    /// Refer to the official
    /// [specification](https://github.com/OAI/OpenAPI-Specification/blob/0dd79f6/versions/3.0.1.md)
    /// for more information.
    #[allow(non_camel_case_types)]
    V3_0(v3_0::Spec),
}

/// deserialize an open api spec from a path
pub fn from_path<P>(path: P) -> Result<OpenApi>
where
    P: AsRef<Path>,
{
    from_reader(File::open(path)?)
}

/// deserialize an open api spec from type which implements Read
pub fn from_reader<R>(read: R) -> Result<OpenApi>
where
    R: Read,
{
    Ok(serde_yaml::from_reader::<R, OpenApi>(read)?)
}

/// serialize to a yaml string
pub fn to_yaml(spec: &OpenApi) -> Result<String> {
    Ok(serde_yaml::to_string(spec)?)
}

/// serialize to a json string
pub fn to_json(spec: &OpenApi) -> Result<String> {
    Ok(serde_json::to_string_pretty(spec)?)
}

#[cfg(test)]
mod tests {
    use super::*;
    use pretty_assertions::assert_eq;
    use std::{
        fs::{self, read_to_string, File},
        io::Write,
    };

    /// Helper function to write string to file.
    fn write_to_file<P>(
        path: P,
        filename: &str,
        data: &str,
    ) where
        P: AsRef<Path> + std::fmt::Debug,
    {
        println!("    Saving string to {:?}...", path);
        std::fs::create_dir_all(&path).unwrap();
        let full_filename = path.as_ref().to_path_buf().join(filename);
        let mut f = File::create(&full_filename).unwrap();
        f.write_all(data.as_bytes()).unwrap();
    }

    /// Convert a YAML `&str` to a JSON `String`.
    fn convert_yaml_str_to_json(yaml_str: &str) -> String {
        let yaml: serde_yaml::Value = serde_yaml::from_str(yaml_str).unwrap();
        let json: serde_json::Value = serde_yaml::from_value(yaml).unwrap();
        serde_json::to_string_pretty(&json).unwrap()
    }

    /// Deserialize and re-serialize the input file to a JSON string through two different
    /// paths, comparing the result.
    /// 1. File -> `String` -> `serde_yaml::Value` -> `serde_json::Value` -> `String`
    /// 2. File -> `Spec` -> `serde_json::Value` -> `String`
    /// Both conversion of `serde_json::Value` -> `String` are done
    /// using `serde_json::to_string_pretty`.
    /// Since the first conversion is independant of the current crate (and only
    /// uses serde's json and yaml support), no information should be lost in the final
    /// JSON string. The second conversion goes through our `OpenApi`, so the final JSON
    /// string is a representation of _our_ implementation.
    /// By comparing those two JSON conversions, we can validate our implementation.
    fn compare_spec_through_json(
        input_file: &Path,
        save_path_base: &Path,
    ) -> (String, String, String) {
        // First conversion:
        //     File -> `String` -> `serde_yaml::Value` -> `serde_json::Value` -> `String`

        // Read the original file to string
        let spec_yaml_str = read_to_string(&input_file)
            .unwrap_or_else(|e| panic!("failed to read contents of {:?}: {}", input_file, e));
        // Convert YAML string to JSON string
        let spec_json_str = convert_yaml_str_to_json(&spec_yaml_str);

        // Second conversion:
        //     File -> `Spec` -> `serde_json::Value` -> `String`

        // Parse the input file
        let parsed_spec = from_path(&input_file).unwrap();
        // Convert to serde_json::Value
        let parsed_spec_json = serde_json::to_value(parsed_spec).unwrap();
        // Convert to a JSON string
        let parsed_spec_json_str: String = serde_json::to_string_pretty(&parsed_spec_json).unwrap();

        // Save JSON strings to file
        let api_filename = input_file
            .file_name()
            .unwrap()
            .to_str()
            .unwrap()
            .replace(".yaml", ".json");

        let mut save_path = save_path_base.to_path_buf();
        save_path.push("yaml_to_json");
        write_to_file(&save_path, &api_filename, &spec_json_str);

        let mut save_path = save_path_base.to_path_buf();
        save_path.push("yaml_to_spec_to_json");
        write_to_file(&save_path, &api_filename, &parsed_spec_json_str);

        // Return the JSON filename and the two JSON strings
        (api_filename, parsed_spec_json_str, spec_json_str)
    }

    // Just tests if the deserialization does not blow up. But does not test correctness
    #[test]
    fn can_deserialize() {
        for entry in fs::read_dir("data/v2").unwrap() {
            let entry = entry.unwrap();
            let path = entry.path();
            // cargo test -- --nocapture to see this message
            println!("Testing if {:?} is deserializable", path);
            from_path(path).unwrap();
        }
    }

    #[test]
    fn can_deserialize_and_reserialize_v2() {
        let save_path_base: std::path::PathBuf =
            ["target", "tests", "can_deserialize_and_reserialize_v2"]
                .iter()
                .collect();

        for entry in fs::read_dir("data/v2").unwrap() {
            let entry = entry.unwrap();
            let path = entry.path();

            println!("Testing if {:?} is deserializable", path);

            let (api_filename, parsed_spec_json_str, spec_json_str) =
                compare_spec_through_json(&path, &save_path_base);

            assert_eq!(
                parsed_spec_json_str.lines().collect::<Vec<_>>(),
                spec_json_str.lines().collect::<Vec<_>>(),
                "contents did not match for api {}",
                api_filename
            );
        }
    }

    #[test]
    fn can_deserialize_and_reserialize_v3() {
        let save_path_base: std::path::PathBuf =
            ["target", "tests", "can_deserialize_and_reserialize_v3"]
                .iter()
                .collect();

        for entry in fs::read_dir("data/v3.0").unwrap() {
            let entry = entry.unwrap();
            let path = entry.path();

            println!("Testing if {:?} is deserializable", path);

            let (api_filename, parsed_spec_json_str, spec_json_str) =
                compare_spec_through_json(&path, &save_path_base);

            assert_eq!(
                parsed_spec_json_str.lines().collect::<Vec<_>>(),
                spec_json_str.lines().collect::<Vec<_>>(),
                "contents did not match for api {}",
                api_filename
            );
        }
    }
}
<commit_msg>simplify<commit_after>//! Openapi provides structures and support for serializing and deserializing [openapi](https://github.com/OAI/OpenAPI-Specification) specifications
//!
//! # Examples
//!
//! Typical use deserialing an existing to a persisted spec to rust form or
//! visa versa
//!
//! The hyper client should be configured with tls.
//!
//! ```no_run
//! extern crate openapi;
//!
//! fn main() {
//!   match openapi::from_path("path/to/openapi.yaml") {
//!     Ok(spec) => println!("spec: {:?}", spec),
//!     Err(err) => println!("error: {}", err)
//!   }
//! }
//! ```
//!
//! # Errors
//!
//! Operations typically result in a `openapi::Result` Type which is an alias
//! for Rust's
//! built-in Result with the Err Type fixed to the
//! [openapi::errors::Error](errors/struct.Error.html) enum type. These are
//! provided
//! using [error_chain](https://github.com/brson/error-chain) crate so their
//! shape and behavior should be consistent and familiar to existing
//! error_chain users.
//!
use serde::{Deserialize, Serialize};
use std::{fs::File, io::Read, path::Path, result::Result as StdResult};

pub mod error;
pub mod v2;
pub mod v3_0;

pub use error::Error;

const MINIMUM_OPENAPI30_VERSION: &str = ">= 3.0";

pub type Result<T> = StdResult<T, Error>;

/// Supported versions of the OpenApi.
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
#[serde(untagged)]
pub enum OpenApi {
    /// Version 2.0 of the OpenApi specification.
    ///
    /// Refer to the official
    /// [specification](https://github.com/OAI/OpenAPI-Specification/blob/0dd79f6/versions/2.0.md)
    /// for more information.
    V2(v2::Spec),

    /// Version 3.0.1 of the OpenApi specification.
    ///
    /// Refer to the official
    /// [specification](https://github.com/OAI/OpenAPI-Specification/blob/0dd79f6/versions/3.0.1.md)
    /// for more information.
    #[allow(non_camel_case_types)]
    V3_0(v3_0::Spec),
}

/// deserialize an open api spec from a path
pub fn from_path<P>(path: P) -> Result<OpenApi>
where
    P: AsRef<Path>,
{
    from_reader(File::open(path)?)
}

/// deserialize an open api spec from type which implements Read
pub fn from_reader<R>(read: R) -> Result<OpenApi>
where
    R: Read,
{
    Ok(serde_yaml::from_reader::<R, OpenApi>(read)?)
}

/// serialize to a yaml string
pub fn to_yaml(spec: &OpenApi) -> Result<String> {
    Ok(serde_yaml::to_string(spec)?)
}

/// serialize to a json string
pub fn to_json(spec: &OpenApi) -> Result<String> {
    Ok(serde_json::to_string_pretty(spec)?)
}

#[cfg(test)]
mod tests {
    use super::*;
    use pretty_assertions::assert_eq;
    use std::{
        fs::{self, read_to_string, File},
        io::Write,
    };

    /// Helper function to write string to file.
    fn write_to_file<P>(
        path: P,
        filename: &str,
        data: &str,
    ) where
        P: AsRef<Path> + std::fmt::Debug,
    {
        println!("    Saving string to {:?}...", path);
        std::fs::create_dir_all(&path).unwrap();
        let full_filename = path.as_ref().to_path_buf().join(filename);
        let mut f = File::create(&full_filename).unwrap();
        f.write_all(data.as_bytes()).unwrap();
    }

    /// Convert a YAML `&str` to a JSON `String`.
    fn convert_yaml_str_to_json(yaml_str: &str) -> String {
        let yaml: serde_yaml::Value = serde_yaml::from_str(yaml_str).unwrap();
        let json: serde_json::Value = serde_yaml::from_value(yaml).unwrap();
        serde_json::to_string_pretty(&json).unwrap()
    }

    /// Deserialize and re-serialize the input file to a JSON string through two different
    /// paths, comparing the result.
    /// 1. File -> `String` -> `serde_yaml::Value` -> `serde_json::Value` -> `String`
    /// 2. File -> `Spec` -> `serde_json::Value` -> `String`
    /// Both conversion of `serde_json::Value` -> `String` are done
    /// using `serde_json::to_string_pretty`.
    /// Since the first conversion is independant of the current crate (and only
    /// uses serde's json and yaml support), no information should be lost in the final
    /// JSON string. The second conversion goes through our `OpenApi`, so the final JSON
    /// string is a representation of _our_ implementation.
    /// By comparing those two JSON conversions, we can validate our implementation.
    fn compare_spec_through_json(
        input_file: &Path,
        save_path_base: &Path,
    ) -> (String, String, String) {
        // First conversion:
        //     File -> `String` -> `serde_yaml::Value` -> `serde_json::Value` -> `String`

        // Read the original file to string
        let spec_yaml_str = read_to_string(&input_file)
            .unwrap_or_else(|e| panic!("failed to read contents of {:?}: {}", input_file, e));
        // Convert YAML string to JSON string
        let spec_json_str = convert_yaml_str_to_json(&spec_yaml_str);

        // Second conversion:
        //     File -> `Spec` -> `serde_json::Value` -> `String`

        // Parse the input file
        let parsed_spec = from_path(&input_file).unwrap();
        // Convert to serde_json::Value
        let parsed_spec_json = serde_json::to_value(parsed_spec).unwrap();
        // Convert to a JSON string
        let parsed_spec_json_str: String = serde_json::to_string_pretty(&parsed_spec_json).unwrap();

        // Save JSON strings to file
        let api_filename = input_file
            .file_name()
            .unwrap()
            .to_str()
            .unwrap()
            .replace(".yaml", ".json");

        let mut save_path = save_path_base.to_path_buf();
        save_path.push("yaml_to_json");
        write_to_file(&save_path, &api_filename, &spec_json_str);

        let mut save_path = save_path_base.to_path_buf();
        save_path.push("yaml_to_spec_to_json");
        write_to_file(&save_path, &api_filename, &parsed_spec_json_str);

        // Return the JSON filename and the two JSON strings
        (api_filename, parsed_spec_json_str, spec_json_str)
    }

    // Just tests if the deserialization does not blow up. But does not test correctness
    #[test]
    fn can_deserialize() {
        for entry in fs::read_dir("data/v2").unwrap() {
            let path = entry.unwrap().path();
            // cargo test -- --nocapture to see this message
            println!("Testing if {:?} is deserializable", path);
            from_path(path).unwrap();
        }
    }

    #[test]
    fn can_deserialize_and_reserialize_v2() {
        let save_path_base: std::path::PathBuf =
            ["target", "tests", "can_deserialize_and_reserialize_v2"]
                .iter()
                .collect();

        for entry in fs::read_dir("data/v2").unwrap() {
            let path = entry.unwrap().path();

            println!("Testing if {:?} is deserializable", path);

            let (api_filename, parsed_spec_json_str, spec_json_str) =
                compare_spec_through_json(&path, &save_path_base);

            assert_eq!(
                parsed_spec_json_str.lines().collect::<Vec<_>>(),
                spec_json_str.lines().collect::<Vec<_>>(),
                "contents did not match for api {}",
                api_filename
            );
        }
    }

    #[test]
    fn can_deserialize_and_reserialize_v3() {
        let save_path_base: std::path::PathBuf =
            ["target", "tests", "can_deserialize_and_reserialize_v3"]
                .iter()
                .collect();

        for entry in fs::read_dir("data/v3.0").unwrap() {
            let entry = entry.unwrap();
            let path = entry.path();

            println!("Testing if {:?} is deserializable", path);

            let (api_filename, parsed_spec_json_str, spec_json_str) =
                compare_spec_through_json(&path, &save_path_base);

            assert_eq!(
                parsed_spec_json_str.lines().collect::<Vec<_>>(),
                spec_json_str.lines().collect::<Vec<_>>(),
                "contents did not match for api {}",
                api_filename
            );
        }
    }
}
<|endoftext|>


<commit_before>#![feature(catch_panic)]
#[macro_use]
extern crate lazy_static;
use std::string::ToString;
use std::thread::{JoinHandle, spawn, catch_panic};
use std::sync::*;
use std::any::{Any};
use std::io::{self, Write};

pub struct ExampleGroup {
    description: String,
    running_examples: Vec<JoinHandle<Result<(), Box<Any + Send>>>>,
}

pub struct ExampleGroupAndBlock {
    group: ExampleGroup,
    block: Box<Fn(&mut ExampleGroup) + Sync + Send + 'static>,
}

pub struct Example {
    description: String,
}

impl ExampleGroup {
    pub fn it<F>(&mut self, description: &str, example_definition_block: F) where F: Fn() + Sync + Send + 'static {
        self.running_examples.push(spawn(move || {
            let result = catch_panic(move || {
                example_definition_block();
            });

            with_world(|world| {
                if result.is_err() {
                    world.reporter.example_failed();
                } else {
                    world.reporter.example_passed();
                }
            });

            return result;
        }));
    }

    fn block_on_all_examples(self) -> Result<(), ()> {
        let mut failed = false;
        for jh in self.running_examples.into_iter() {
            if jh.join().unwrap().is_err() {
                failed = true;
            }
        }

        if failed {
            return Err(());
        } else {
            return Ok(());
        }
    }

    fn run(mut self, block: Box<Fn(&mut ExampleGroup) + Send + Sync + 'static>) -> bool {
        block(&mut self);

        let result = self.block_on_all_examples();
        return result.is_ok();
    }
}

pub struct Reporter;

impl Reporter {
    pub fn example_failed(&self) {
        print!("F");
        io::stdout().flush();
    }

    pub fn example_passed(&self) {
        print!(".");
        io::stdout().flush();
    }
}

struct World {
    reporter: Reporter,
    failed: bool,
    example_groups: Vec<ExampleGroupAndBlock>,
}

fn with_world<F, T>(blk: F) -> T where F: FnOnce(&mut World) -> T {
    let c = WORLD.clone();
    let mut guard = c.lock().unwrap();
    blk(&mut guard)
}

impl World {
    fn describe<F>(&mut self, description: &str, example_group_definition_block: F) where F: Fn(&mut ExampleGroup) + Sync + Send + 'static {
        self.example_groups.push(
            ExampleGroupAndBlock {
                group: ExampleGroup {
                    description: description.to_string(),
                    running_examples: Vec::new(),
                },
                block: Box::new(example_group_definition_block)
            }
        );
    }
}

lazy_static! {
    static ref WORLD: Arc<Mutex<World>> = Arc::new(Mutex::new(World { failed: false, reporter: Reporter, example_groups: Vec::new() }));
}

pub fn describe<F>(description: &str, example_group_definition_block: F) where F: Fn(&mut ExampleGroup) + Sync + Send + 'static {
    with_world(|world| {
        world.describe(description, example_group_definition_block);
    });
}

fn get_examples_from_world() -> Vec<ExampleGroupAndBlock> {
    let mut result = Vec::new();

    with_world(|world| {
        ::std::mem::replace(&mut world.example_groups, result)
    })
}

pub fn descriptor_main() {
    let mut example_groups = get_examples_from_world();
    let join_handles: Vec<JoinHandle<Result<(), ()>>> = example_groups.into_iter().map({ |ExampleGroupAndBlock { group: example_group, block: block }|
        spawn(|| -> Result<(), ()> {
            if example_group.run(block) {
                Ok(())
            } else {
                Err(())
            }
        })
    }).collect();

    let results = join_handles.into_iter().map(|jh| { jh.join().unwrap() });
    let failed = results.into_iter().any(|r| { r.is_err() });

    with_world(|world| {
        world.failed = failed;
        println!("{}", world.failed);
    });
}
<commit_msg>Lift the remainder of with_world calls out of core descriptor methods.<commit_after>#![feature(catch_panic)]
#[macro_use]
extern crate lazy_static;
use std::string::ToString;
use std::thread::{JoinHandle, spawn, catch_panic};
use std::sync::*;
use std::any::{Any};
use std::io::{self, Write};

pub struct ExampleGroup {
    description: String,
    running_examples: Vec<JoinHandle<Result<(), Box<Any + Send>>>>,
    state: Arc<Mutex<WorldState>>,
}

pub struct ExampleGroupAndBlock {
    group: ExampleGroup,
    block: Box<Fn(&mut ExampleGroup) + Sync + Send + 'static>,
}

pub struct Example {
    description: String,
}

struct World {
    state: Arc<Mutex<WorldState>>,
    example_groups: Vec<ExampleGroupAndBlock>,
}

struct WorldState {
    reporter: Reporter,
    failed: bool,
}

impl ExampleGroup {
    pub fn it<F>(&mut self, description: &str, example_definition_block: F) where F: Fn() + Sync + Send + 'static {
        let state: Arc<Mutex<WorldState>> = self.state.clone();
        self.running_examples.push(spawn(move || {
            let result = catch_panic(move || {
                example_definition_block();
            });

            if result.is_err() {
                state.lock().unwrap().reporter.example_failed();
            } else {
                state.lock().unwrap().reporter.example_passed();
            }

            return result;
        }));
    }

    fn block_on_all_examples(self) -> Result<(), ()> {
        let mut failed = false;
        for jh in self.running_examples.into_iter() {
            if jh.join().unwrap().is_err() {
                failed = true;
            }
        }

        if failed {
            return Err(());
        } else {
            return Ok(());
        }
    }

    fn run(mut self, block: Box<Fn(&mut ExampleGroup) + Send + Sync + 'static>) -> bool {
        block(&mut self);

        let result = self.block_on_all_examples();
        return result.is_ok();
    }
}

pub struct Reporter;

impl Reporter {
    pub fn example_failed(&self) {
        print!("F");
        io::stdout().flush();
    }

    pub fn example_passed(&self) {
        print!(".");
        io::stdout().flush();
    }
}

fn with_world<F, T>(blk: F) -> T where F: FnOnce(&mut World) -> T {
    let c = WORLD.clone();
    let mut guard = c.lock().unwrap();
    blk(&mut guard)
}

impl World {
    fn describe<F>(&mut self, description: &str, example_group_definition_block: F) where F: Fn(&mut ExampleGroup) + Sync + Send + 'static {
        self.example_groups.push(
            ExampleGroupAndBlock {
                group: ExampleGroup {
                    description: description.to_string(),
                    running_examples: Vec::new(),
                    state: self.state.clone(),
                },
                block: Box::new(example_group_definition_block)
            }
        );
    }

    fn new() -> World {
        World {
            state: Arc::new(Mutex::new(WorldState {
                failed: false,
                reporter: Reporter,
            })),
            example_groups: Vec::new(),
        }
    }
}

lazy_static! {
    static ref WORLD: Arc<Mutex<World>> = Arc::new(Mutex::new(World::new()));
}

pub fn describe<F>(description: &str, example_group_definition_block: F) where F: Fn(&mut ExampleGroup) + Sync + Send + 'static {
    with_world(|world| {
        world.describe(description, example_group_definition_block);
    });
}

fn get_examples_from_world() -> Vec<ExampleGroupAndBlock> {
    let mut result = Vec::new();

    with_world(|world| {
        ::std::mem::replace(&mut world.example_groups, result)
    })
}

pub fn descriptor_main() {
    let mut example_groups = get_examples_from_world();
    let join_handles: Vec<JoinHandle<Result<(), ()>>> = example_groups.into_iter().map({ |ExampleGroupAndBlock { group: example_group, block: block }|
        spawn(|| -> Result<(), ()> {
            if example_group.run(block) {
                Ok(())
            } else {
                Err(())
            }
        })
    }).collect();

    let results = join_handles.into_iter().map(|jh| { jh.join().unwrap() });
    let failed = results.into_iter().any(|r| { r.is_err() });

    with_world(|world| {
        let state = world.state.clone();
        state.lock().unwrap().failed = failed;
        println!("{}", state.lock().unwrap().failed);
    });
}
<|endoftext|>


<commit_before>#![warn(rust_2018_idioms)]

//! lapin
//!
//! This project follows the AMQP 0.9.1 specifications, targetting especially RabbitMQ.
//!
//! ## Example
//!
//! ```rust,no_run
//! use env_logger;
//! use log::info;
//!
//! use crate::lapin::{
//!   BasicProperties, Channel, Connection, ConnectionProperties, ConsumerDelegate,
//!   message::Delivery,
//!   options::*,
//!   types::FieldTable,
//! };
//!
//! #[derive(Clone,Debug)]
//! struct Subscriber {
//!   channel: Channel,
//! }
//!
//! impl ConsumerDelegate for Subscriber {
//!   fn on_new_delivery(&self, delivery: Delivery) {
//!     self.channel.basic_ack(delivery.delivery_tag, BasicAckOptions::default()).wait().expect("basic_ack");
//!   }
//! }
//!
//! fn main() {
//!   env_logger::init();
//!
//!   let addr = std::env::var("AMQP_ADDR").unwrap_or_else(|_| "amqp://127.0.0.1:5672/%2f".into());
//!   let conn = Connection::connect(&addr, ConnectionProperties::default()).wait().expect("connection error");
//!
//!   info!("CONNECTED");
//!
//!   let channel_a = conn.create_channel().wait().expect("create_channel");
//!   let channel_b = conn.create_channel().wait().expect("create_channel");
//!
//!   channel_a.queue_declare("hello", QueueDeclareOptions::default(), FieldTable::default()).wait().expect("queue_declare");
//!   let queue = channel_b.queue_declare("hello", QueueDeclareOptions::default(), FieldTable::default()).wait().expect("queue_declare");
//!
//!   info!("will consume");
//!   channel_b.clone().basic_consume(&queue, "my_consumer", BasicConsumeOptions::default(), FieldTable::default()).wait().expect("basic_consume").set_delegate(Box::new(Subscriber { channel: channel_b }));
//!
//!   let payload = b"Hello world!";
//!
//!   loop {
//!     channel_a.basic_publish("", "hello", BasicPublishOptions::default(), payload.to_vec(), BasicProperties::default()).wait().expect("basic_publish");
//!   }
//! }
//! ```

pub use amq_protocol::{
    auth,
    protocol::{self, BasicProperties},
    tcp, types, uri,
};

pub use channel::{options, Channel};
pub use channel_status::{ChannelState, ChannelStatus};
pub use configuration::Configuration;
pub use connection::{Connect, Connection};
pub use connection_properties::ConnectionProperties;
pub use connection_status::{ConnectionState, ConnectionStatus};
pub use consumer::{Consumer, ConsumerDelegate};
pub use error::{Error, Result};
pub use exchange::ExchangeKind;
pub use queue::Queue;

pub mod confirmation;
pub mod executor;
pub mod message;

mod acknowledgement;
mod buffer;
mod channel;
mod channel_status;
mod channels;
mod configuration;
mod connection;
mod connection_properties;
mod connection_status;
mod consumer;
mod error;
mod error_handler;
mod exchange;
mod frames;
mod id_sequence;
mod io_loop;
mod queue;
mod queues;
mod registration;
mod returned_messages;
mod wait;
<commit_msg>lapin: fix rustdoc<commit_after>#![warn(rust_2018_idioms)]

//! lapin
//!
//! This project follows the AMQP 0.9.1 specifications, targetting especially RabbitMQ.
//!
//! ## Example
//!
//! ```rust,no_run
//! use env_logger;
//! use log::info;
//!
//! use crate::lapin::{
//!   BasicProperties, Channel, Connection, ConnectionProperties, ConsumerDelegate,
//!   message::DeliveryResult,
//!   options::*,
//!   types::FieldTable,
//! };
//!
//! #[derive(Clone,Debug)]
//! struct Subscriber {
//!   channel: Channel,
//! }
//!
//! impl ConsumerDelegate for Subscriber {
//!   fn on_new_delivery(&self, delivery: DeliveryResult) {
//!     if let Some(delivery) = delivery.unwrap() {
//!       self.channel.basic_ack(delivery.delivery_tag, BasicAckOptions::default()).wait().expect("basic_ack");
//!     }
//!   }
//! }
//!
//! fn main() {
//!   env_logger::init();
//!
//!   let addr = std::env::var("AMQP_ADDR").unwrap_or_else(|_| "amqp://127.0.0.1:5672/%2f".into());
//!   let conn = Connection::connect(&addr, ConnectionProperties::default()).wait().expect("connection error");
//!
//!   info!("CONNECTED");
//!
//!   let channel_a = conn.create_channel().wait().expect("create_channel");
//!   let channel_b = conn.create_channel().wait().expect("create_channel");
//!
//!   channel_a.queue_declare("hello", QueueDeclareOptions::default(), FieldTable::default()).wait().expect("queue_declare");
//!   let queue = channel_b.queue_declare("hello", QueueDeclareOptions::default(), FieldTable::default()).wait().expect("queue_declare");
//!
//!   info!("will consume");
//!   channel_b.clone().basic_consume(&queue, "my_consumer", BasicConsumeOptions::default(), FieldTable::default()).wait().expect("basic_consume").set_delegate(Box::new(Subscriber { channel: channel_b }));
//!
//!   let payload = b"Hello world!";
//!
//!   loop {
//!     channel_a.basic_publish("", "hello", BasicPublishOptions::default(), payload.to_vec(), BasicProperties::default()).wait().expect("basic_publish");
//!   }
//! }
//! ```

pub use amq_protocol::{
    auth,
    protocol::{self, BasicProperties},
    tcp, types, uri,
};

pub use channel::{options, Channel};
pub use channel_status::{ChannelState, ChannelStatus};
pub use configuration::Configuration;
pub use connection::{Connect, Connection};
pub use connection_properties::ConnectionProperties;
pub use connection_status::{ConnectionState, ConnectionStatus};
pub use consumer::{Consumer, ConsumerDelegate};
pub use error::{Error, Result};
pub use exchange::ExchangeKind;
pub use queue::Queue;

pub mod confirmation;
pub mod executor;
pub mod message;

mod acknowledgement;
mod buffer;
mod channel;
mod channel_status;
mod channels;
mod configuration;
mod connection;
mod connection_properties;
mod connection_status;
mod consumer;
mod error;
mod error_handler;
mod exchange;
mod frames;
mod id_sequence;
mod io_loop;
mod queue;
mod queues;
mod registration;
mod returned_messages;
mod wait;
<|endoftext|>


<commit_before>//! Actix web is a small, pragmatic, and extremely fast web framework
//! for Rust.
//!
//! ```rust,ignore
//! use actix_web::{server, App, Path, Responder};
//! # use std::thread;
//!
//! fn index(info: Path<(String, u32)>) -> impl Responder {
//!     format!("Hello {}! id:{}", info.0, info.1)
//! }
//!
//! fn main() {
//!     # thread::spawn(|| {
//!     server::new(|| {
//!         App::new().resource("/{name}/{id}/index.html", |r| r.with(index))
//!     }).bind("127.0.0.1:8080")
//!         .unwrap()
//!         .run();
//!     # });
//! }
//! ```
//!
//! ## Documentation & community resources
//!
//! Besides the API documentation (which you are currently looking
//! at!), several other resources are available:
//!
//! * [User Guide](https://actix.rs/docs/)
//! * [Chat on gitter](https://gitter.im/actix/actix)
//! * [GitHub repository](https://github.com/actix/actix-web)
//! * [Cargo package](https://crates.io/crates/actix-web)
//!
//! To get started navigating the API documentation you may want to
//! consider looking at the following pages:
//!
//! * [App](struct.App.html): This struct represents an actix-web
//!   application and is used to configure routes and other common
//!   settings.
//!
//! * [HttpServer](server/struct.HttpServer.html): This struct
//!   represents an HTTP server instance and is used to instantiate and
//!   configure servers.
//!
//! * [Request](struct.Request.html) and
//!   [Response](struct.Response.html): These structs
//!   represent HTTP requests and responses and expose various methods
//!   for inspecting, creating and otherwise utilizing them.
//!
//! ## Features
//!
//! * Supported *HTTP/1.x* protocol
//! * Streaming and pipelining
//! * Keep-alive and slow requests handling
//! * `WebSockets` server/client
//! * Supported Rust version: 1.26 or later
//!
//! ## Package feature
//!
//! * `session` - enables session support, includes `ring` crate as
//!   dependency
//!
#![allow(
    clippy::type_complexity,
    clippy::new_without_default,
    clippy::new_without_default_derive
)]

#[macro_use]
extern crate log;

pub mod body;
pub mod client;
mod config;
mod extensions;
mod header;
mod helpers;
mod httpcodes;
pub mod httpmessage;
mod json;
mod message;
mod request;
mod response;
mod service;

pub mod error;
pub mod h1;
pub mod h2;
pub mod payload;
pub mod test;
pub mod ws;

pub use self::body::{Body, MessageBody};
pub use self::config::{KeepAlive, ServiceConfig, ServiceConfigBuilder};
pub use self::error::{Error, ResponseError, Result};
pub use self::extensions::Extensions;
pub use self::httpmessage::HttpMessage;
pub use self::message::{Message, RequestHead, ResponseHead};
pub use self::request::Request;
pub use self::response::Response;
pub use self::service::{SendError, SendResponse};

pub mod dev {
    //! The `actix-web` prelude for library developers
    //!
    //! The purpose of this module is to alleviate imports of many common actix
    //! traits by adding a glob import to the top of actix heavy modules:
    //!
    //! ```
    //! # #![allow(unused_imports)]
    //! use actix_http::dev::*;
    //! ```

    pub use crate::httpmessage::{MessageBody, Readlines, UrlEncoded};
    pub use crate::json::JsonBody;
    pub use crate::response::ResponseBuilder;
}

pub mod http {
    //! Various HTTP related types

    // re-exports
    pub use http::header::{HeaderName, HeaderValue};
    pub use http::{Method, StatusCode, Version};

    #[doc(hidden)]
    pub use http::{uri, Error, HeaderMap, HttpTryFrom, Uri};

    #[doc(hidden)]
    pub use http::uri::PathAndQuery;

    pub use cookie::{Cookie, CookieBuilder};

    /// Various http headers
    pub mod header {
        pub use crate::header::*;
    }
    pub use crate::header::ContentEncoding;
    pub use crate::message::ConnectionType;
}
<commit_msg>export Payload type<commit_after>//! Actix web is a small, pragmatic, and extremely fast web framework
//! for Rust.
//!
//! ```rust,ignore
//! use actix_web::{server, App, Path, Responder};
//! # use std::thread;
//!
//! fn index(info: Path<(String, u32)>) -> impl Responder {
//!     format!("Hello {}! id:{}", info.0, info.1)
//! }
//!
//! fn main() {
//!     # thread::spawn(|| {
//!     server::new(|| {
//!         App::new().resource("/{name}/{id}/index.html", |r| r.with(index))
//!     }).bind("127.0.0.1:8080")
//!         .unwrap()
//!         .run();
//!     # });
//! }
//! ```
//!
//! ## Documentation & community resources
//!
//! Besides the API documentation (which you are currently looking
//! at!), several other resources are available:
//!
//! * [User Guide](https://actix.rs/docs/)
//! * [Chat on gitter](https://gitter.im/actix/actix)
//! * [GitHub repository](https://github.com/actix/actix-web)
//! * [Cargo package](https://crates.io/crates/actix-web)
//!
//! To get started navigating the API documentation you may want to
//! consider looking at the following pages:
//!
//! * [App](struct.App.html): This struct represents an actix-web
//!   application and is used to configure routes and other common
//!   settings.
//!
//! * [HttpServer](server/struct.HttpServer.html): This struct
//!   represents an HTTP server instance and is used to instantiate and
//!   configure servers.
//!
//! * [Request](struct.Request.html) and
//!   [Response](struct.Response.html): These structs
//!   represent HTTP requests and responses and expose various methods
//!   for inspecting, creating and otherwise utilizing them.
//!
//! ## Features
//!
//! * Supported *HTTP/1.x* protocol
//! * Streaming and pipelining
//! * Keep-alive and slow requests handling
//! * `WebSockets` server/client
//! * Supported Rust version: 1.26 or later
//!
//! ## Package feature
//!
//! * `session` - enables session support, includes `ring` crate as
//!   dependency
//!
#![allow(
    clippy::type_complexity,
    clippy::new_without_default,
    clippy::new_without_default_derive
)]

#[macro_use]
extern crate log;

pub mod body;
pub mod client;
mod config;
mod extensions;
mod header;
mod helpers;
mod httpcodes;
pub mod httpmessage;
mod json;
mod message;
mod payload;
mod request;
mod response;
mod service;

pub mod error;
pub mod h1;
pub mod h2;
pub mod test;
pub mod ws;

pub use self::body::{Body, MessageBody};
pub use self::config::{KeepAlive, ServiceConfig, ServiceConfigBuilder};
pub use self::error::{Error, ResponseError, Result};
pub use self::extensions::Extensions;
pub use self::httpmessage::HttpMessage;
pub use self::message::{Message, RequestHead, ResponseHead};
pub use self::payload::Payload;
pub use self::request::Request;
pub use self::response::Response;
pub use self::service::{SendError, SendResponse};

pub mod dev {
    //! The `actix-web` prelude for library developers
    //!
    //! The purpose of this module is to alleviate imports of many common actix
    //! traits by adding a glob import to the top of actix heavy modules:
    //!
    //! ```
    //! # #![allow(unused_imports)]
    //! use actix_http::dev::*;
    //! ```

    pub use crate::httpmessage::{MessageBody, Readlines, UrlEncoded};
    pub use crate::json::JsonBody;
    pub use crate::response::ResponseBuilder;
}

pub mod http {
    //! Various HTTP related types

    // re-exports
    pub use http::header::{HeaderName, HeaderValue};
    pub use http::{Method, StatusCode, Version};

    #[doc(hidden)]
    pub use http::{uri, Error, HeaderMap, HttpTryFrom, Uri};

    #[doc(hidden)]
    pub use http::uri::PathAndQuery;

    pub use cookie::{Cookie, CookieBuilder};

    /// Various http headers
    pub mod header {
        pub use crate::header::*;
    }
    pub use crate::header::ContentEncoding;
    pub use crate::message::ConnectionType;
}
<|endoftext|>


<commit_before>//! This crate allows one-liners to read from a terminal
//! A minimal example to get an i32 from the command line is
//!
//! ```rust,no_run
//! #[macro_use] extern crate text_io;
//! fn main() {
//!     let i: i32 = read!();
//! }
//! ```
//!
//! The `read!()` macro will always read until the next ascii whitespace character
//! (`\n`, `\r`, `\t` or space).
//!
//! Any type that implements the `FromStr` trait can be read with the `read!` macro.
//!
//! # Advanced
//! Text parsing can be done similar to `println!` by adding a format string
//! to the macro:
//!
//! ```rust,no_run
//! # #[macro_use]
//! # extern crate text_io;
//! # fn main() {
//! let i: i32 = read!("The answer: {}!");
//! # }
//! ```
//!
//! This will read `"The answer: "`, then an integer, then an exclamation mark. Any deviation from
//! the format string will result in a panic.
//!
//! Note: only a single value can be read per `read!` invocation.

use std::error;
use std::fmt;

#[derive(Debug, PartialEq)]
pub enum Error {
    MissingMatch,
    MissingClosingBrace,
    UnexpectedValue(u8, Option<u8>),
    InvalidUtf8(Vec<u8>),
    PartialUtf8(usize, Vec<u8>),
    Parse(String, &'static str),
    #[doc(hidden)]
    __NonExhaustive__,
}

impl error::Error for Error {
    fn description(&self) -> &str {
        use Error::*;

        match *self {
            MissingMatch => "Bad read! format string: did not contain {{}}",
            MissingClosingBrace => "found single open curly brace at the end of the format string",
            UnexpectedValue(..) => "found value not matching the pattern",
            InvalidUtf8(..) => "input was not valid utf8",
            PartialUtf8(..) => "input was only partially valid utf8",
            Parse(..) => "could not parse input as target type",
            __NonExhaustive__ => unreachable!(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Error::*;
        use std::str::from_utf8;

        match *self {
            InvalidUtf8(ref raw) => write!(f, "input was not valid utf8: {:?}", raw),
            Parse(ref s, arg) => write!(f, "could not parse {} as target type of {}", s, arg),
            UnexpectedValue(exp, act) => write!(
                f,
                "found value {:?} not matching the pattern value {}",
                act.map(|b| b as char),
                exp as char
            ),
            PartialUtf8(n, ref raw) => write!(
                f,
                "input was only partially valid utf8: \"{}\" followed by {:?}",
                from_utf8(&raw[..n]).unwrap(),
                &raw[n..]
            ),
            _ => write!(f, "{}", <Error as error::Error>::description(self)),
        }
    }
}

/// ```rust,no_run
/// # #[macro_use]
/// # extern crate text_io;
/// # fn main() {
/// let i: i32 = try_read!("The answer: {}!").unwrap();
/// let i: Result<i32, _> = try_read!("The {}{{}}!", "The answer is 42!".bytes());
/// assert!(i.is_err());
/// # }
/// ```
///
/// ```rust
/// # #[macro_use]
/// # extern crate text_io;
/// # fn main() {
/// let i: Result<i32, _> = try_read!("The answer is {}!", "The answer is 42!".bytes());
/// assert!(i.is_ok());
///
/// let i: Result<i32, _> = try_read!("The {}{{}}!", "The answer is 42!".bytes());
/// assert!(i.is_err());
/// # }
/// ```
#[macro_export]
macro_rules! try_read(
    () => { try_read!("{}") };
    ($text:expr) => {{
        (|| -> Result<_, $crate::Error> {
            let __try_read_var__;
            try_scan!($text, __try_read_var__);
            Ok(__try_read_var__)
        })()
    }};
    ($text:expr, $input:expr) => {{
        (|| -> Result<_, $crate::Error> {
            let __try_read_var__;
            try_scan!($input => $text, __try_read_var__);
            Ok(__try_read_var__)
        })()
    }};
);

/// ```rust,no_run
/// # #[macro_use]
/// # extern crate text_io;
/// # use std::error::Error;
/// # fn main() {}
/// fn parser() -> Result<i32, Box<Error>> {
///     let i: i32;
///     let text = "The answer is 42!";
///
///     try_scan!(text.bytes() => "The answer is {}!", i);
///
///     assert_eq!(i, 1);
///     Ok(i)
/// }
/// ```
#[macro_export]
macro_rules! try_scan(
    ($pattern:expr, $($arg:expr),*) => {
        use ::std::io::Read;
        try_scan!(::std::io::stdin().bytes().map(|c| c.unwrap()) => $pattern, $($arg),*) ;
        format_args!($pattern, $($arg),*);
    };
    ($input:expr => $pattern:expr, $($arg:expr),*) => {{
        use ::std::str::FromStr;
        use $crate::Error;

        fn match_next(expected: u8, iter: &mut Iterator<Item = u8>) -> Result<(), $crate::Error> {
            let next = iter.next();
            if next != Some(expected) {
                return Err(Error::UnexpectedValue(expected, next))?
            }
            Ok(())
        }

        fn parse_capture<T>(name: &'static str, next: Option<u8>, iter: &mut Iterator<Item = u8>)
        -> Result<T, $crate::Error>
        where
            T: FromStr,
            <T as FromStr>::Err: ::std::fmt::Debug
        {
            static WHITESPACES: &'static [u8] = b"\t\r\n ";
            let raw: Vec<u8> = match next {
                Some(c) => iter.take_while(|&ch| ch != c).collect(),
                None => iter
                    .skip_while(|ch| WHITESPACES.contains(ch))
                    .take_while(|ch| !WHITESPACES.contains(ch))
                    .collect(),
            };
            match String::from_utf8(raw) {
                Ok(s) => FromStr::from_str(&s).map_err(|_| Error::Parse(s, name)),
                Err(e) => {
                    let n = e.utf8_error().valid_up_to();
                    let raw = e.into_bytes();
                    if n == 0 {
                        Err(Error::InvalidUtf8(raw))
                    } else {
                        Err(Error::PartialUtf8(n, raw))
                    }
                }
            }
        }

        // typesafe macros :)
        let pattern: &'static str = $pattern;
        let stdin: &mut Iterator<Item = u8> = &mut ($input);

        let mut pattern = pattern.bytes();

        $(
            $arg = loop {
                match pattern.next().ok_or(Error::MissingMatch)? {
                    b'{' => match pattern.next().ok_or(Error::MissingClosingBrace)? {
                        b'{' => match_next(b'{', stdin)?,
                        b'}' => break parse_capture(stringify!($arg), pattern.next(), stdin)?,
                        _ => return Err(Error::MissingClosingBrace)?,
                    },
                    c => match_next(c, stdin)?,
                }
            };
        )*

        for c in pattern {
            match_next(c, stdin)?
        }

        format_args!($pattern, $($arg),*);
    }};
);

/// All text input is handled through this macro
#[macro_export]
macro_rules! read(
    () => { read!("{}") };
    ($text:expr) => {{
        let value;
        scan!($text, value);
        value
    }};
    ($text:expr, $input:expr) => {{
        let value;
        scan!($input => $text, value);
        value
    }};
);

/// This macro allows to pass several variables so multiple values can be read
#[macro_export]
macro_rules! scan(
    ($text:expr, $($arg:expr),*) => {
        use ::std::io::Read;
        scan!(::std::io::stdin().bytes().map(|c| c.unwrap()) => $text, $($arg),*) ;
        format_args!($text, $($arg),*);
    };
    ($input:expr => $text:expr, $($arg:expr),*) => {{
        use ::std::str::FromStr;
        // typesafe macros :)
        let text: &'static str = $text;
        let stdin: &mut Iterator<Item = u8> = &mut ($input);

        let mut text = text.bytes();
        $(
        loop { match text.next() {
            Some(b'{') => match text.next() {
                Some(b'{') => assert_eq!(Some(b'{'), stdin.next()),
                Some(b'}') => {
                    static WHITESPACES: &'static [u8] = b"\t\r\n ";
                    let s: Vec<u8> = match text.next() {
                        Some(c) => stdin.take_while(|&ch| ch != c).collect(),
                        None => stdin
                            .skip_while(|ch| WHITESPACES.contains(ch))
                            .take_while(|ch| !WHITESPACES.contains(ch))
                            .collect(),
                    };
                    let s = match ::std::str::from_utf8(&s) {
                        Ok(s) => s,
                        Err(e) => {
                            let n = e.valid_up_to();
                            if n == 0 {
                                panic!("input was not valid utf8: {:?}", s);
                            } else {
                                panic!("input was only partially valid utf8: \"{}\" followed by {:?}",
                                       ::std::str::from_utf8(&s[..n]).unwrap(), &s[n..]);
                            }
                        }
                    };
                    $arg = FromStr::from_str(s).expect(&format!("could not parse {} as target type of {}", s, stringify!($arg)));
                    break;
                }
                Some(_) => panic!("found bad curly brace"),
                None => panic!("found single open curly brace at the end of the format string"),
            },
            Some(c) => assert_eq!(Some(c), stdin.next()),
            None => panic!("Bad read! format string: did not contain {{}}"),
        } }
        )*
        for c in text {
            assert_eq!(Some(c), stdin.next());
        }
        format_args!($text, $($arg),*);
    }};
);
<commit_msg>Extract function definitions to crate to reduce code bloat<commit_after>//! This crate allows one-liners to read from a terminal
//! A minimal example to get an i32 from the command line is
//!
//! ```rust,no_run
//! #[macro_use] extern crate text_io;
//! fn main() {
//!     let i: i32 = read!();
//! }
//! ```
//!
//! The `read!()` macro will always read until the next ascii whitespace character
//! (`\n`, `\r`, `\t` or space).
//!
//! Any type that implements the `FromStr` trait can be read with the `read!` macro.
//!
//! # Advanced
//! Text parsing can be done similar to `println!` by adding a format string
//! to the macro:
//!
//! ```rust,no_run
//! # #[macro_use]
//! # extern crate text_io;
//! # fn main() {
//! let i: i32 = read!("The answer: {}!");
//! # }
//! ```
//!
//! This will read `"The answer: "`, then an integer, then an exclamation mark. Any deviation from
//! the format string will result in a panic.
//!
//! Note: only a single value can be read per `read!` invocation.

use std::error;
use std::fmt;
use std::str::FromStr;

#[derive(Debug, PartialEq)]
pub enum Error {
    MissingMatch,
    MissingClosingBrace,
    UnexpectedValue(u8, Option<u8>),
    InvalidUtf8(Vec<u8>),
    PartialUtf8(usize, Vec<u8>),
    Parse(String, &'static str),
    #[doc(hidden)]
    __NonExhaustive__,
}

impl error::Error for Error {
    fn description(&self) -> &str {
        use Error::*;

        match *self {
            MissingMatch => "Bad read! format string: did not contain {{}}",
            MissingClosingBrace => "found single open curly brace at the end of the format string",
            UnexpectedValue(..) => "found value not matching the pattern",
            InvalidUtf8(..) => "input was not valid utf8",
            PartialUtf8(..) => "input was only partially valid utf8",
            Parse(..) => "could not parse input as target type",
            __NonExhaustive__ => unreachable!(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Error::*;
        use std::str::from_utf8;

        match *self {
            InvalidUtf8(ref raw) => write!(f, "input was not valid utf8: {:?}", raw),
            Parse(ref s, arg) => write!(f, "could not parse {} as target type of {}", s, arg),
            UnexpectedValue(exp, act) => write!(
                f,
                "found value {:?} not matching the pattern value {}",
                act.map(|b| b as char),
                exp as char
            ),
            PartialUtf8(n, ref raw) => write!(
                f,
                "input was only partially valid utf8: \"{}\" followed by {:?}",
                from_utf8(&raw[..n]).unwrap(),
                &raw[n..]
            ),
            _ => write!(f, "{}", <Error as error::Error>::description(self)),
        }
    }
}

pub fn match_next(expected: u8, iter: &mut Iterator<Item = u8>) -> Result<(), Error> {
    let next = iter.next();
    if next != Some(expected) {
        return Err(Error::UnexpectedValue(expected, next))?
    }
    Ok(())
}

pub fn parse_capture<T>(name: &'static str, next: Option<u8>, iter: &mut Iterator<Item = u8>)
-> Result<T, Error>
where
    T: FromStr,
    <T as FromStr>::Err: ::std::fmt::Debug
{
    static WHITESPACES: &'static [u8] = b"\t\r\n ";
    let raw: Vec<u8> = match next {
        Some(c) => iter.take_while(|&ch| ch != c).collect(),
        None => iter
            .skip_while(|ch| WHITESPACES.contains(ch))
            .take_while(|ch| !WHITESPACES.contains(ch))
            .collect(),
    };
    match String::from_utf8(raw) {
        Ok(s) => FromStr::from_str(&s).map_err(|_| Error::Parse(s, name)),
        Err(e) => {
            let n = e.utf8_error().valid_up_to();
            let raw = e.into_bytes();
            if n == 0 {
                Err(Error::InvalidUtf8(raw))
            } else {
                Err(Error::PartialUtf8(n, raw))
            }
        }
    }
}

/// ```rust,no_run
/// # #[macro_use]
/// # extern crate text_io;
/// # fn main() {
/// let i: i32 = try_read!("The answer: {}!").unwrap();
/// let i: Result<i32, _> = try_read!("The {}{{}}!", "The answer is 42!".bytes());
/// assert!(i.is_err());
/// # }
/// ```
///
/// ```rust
/// # #[macro_use]
/// # extern crate text_io;
/// # fn main() {
/// let i: Result<i32, _> = try_read!("The answer is {}!", "The answer is 42!".bytes());
/// assert!(i.is_ok());
///
/// let i: Result<i32, _> = try_read!("The {}{{}}!", "The answer is 42!".bytes());
/// assert!(i.is_err());
/// # }
/// ```
#[macro_export]
macro_rules! try_read(
    () => { try_read!("{}") };
    ($text:expr) => {{
        (|| -> Result<_, $crate::Error> {
            let __try_read_var__;
            try_scan!($text, __try_read_var__);
            Ok(__try_read_var__)
        })()
    }};
    ($text:expr, $input:expr) => {{
        (|| -> Result<_, $crate::Error> {
            let __try_read_var__;
            try_scan!($input => $text, __try_read_var__);
            Ok(__try_read_var__)
        })()
    }};
);

/// ```rust,no_run
/// # #[macro_use]
/// # extern crate text_io;
/// # use std::error::Error;
/// # fn main() {}
/// fn parser() -> Result<i32, Box<Error>> {
///     let i: i32;
///     let text = "The answer is 42!";
///
///     try_scan!(text.bytes() => "The answer is {}!", i);
///
///     assert_eq!(i, 1);
///     Ok(i)
/// }
/// ```
#[macro_export]
macro_rules! try_scan(
    ($pattern:expr, $($arg:expr),*) => {
        use ::std::io::Read;
        try_scan!(::std::io::stdin().bytes().map(|c| c.unwrap()) => $pattern, $($arg),*) ;
        format_args!($pattern, $($arg),*);
    };
    ($input:expr => $pattern:expr, $($arg:expr),*) => {{
        use $crate::{Error, match_next, parse_capture};

        // typesafe macros :)
        let pattern: &'static str = $pattern;
        let stdin: &mut Iterator<Item = u8> = &mut ($input);

        let mut pattern = pattern.bytes();

        $(
            $arg = loop {
                match pattern.next().ok_or(Error::MissingMatch)? {
                    b'{' => match pattern.next().ok_or(Error::MissingClosingBrace)? {
                        b'{' => match_next(b'{', stdin)?,
                        b'}' => break parse_capture(stringify!($arg), pattern.next(), stdin)?,
                        _ => return Err(Error::MissingClosingBrace)?,
                    },
                    c => match_next(c, stdin)?,
                }
            };
        )*

        for c in pattern {
            match_next(c, stdin)?
        }

        format_args!($pattern, $($arg),*);
    }};
);

/// All text input is handled through this macro
#[macro_export]
macro_rules! read(
    () => { read!("{}") };
    ($text:expr) => {{
        let value;
        scan!($text, value);
        value
    }};
    ($text:expr, $input:expr) => {{
        let value;
        scan!($input => $text, value);
        value
    }};
);

/// This macro allows to pass several variables so multiple values can be read
#[macro_export]
macro_rules! scan(
    ($text:expr, $($arg:expr),*) => {
        use ::std::io::Read;
        scan!(::std::io::stdin().bytes().map(|c| c.unwrap()) => $text, $($arg),*) ;
        format_args!($text, $($arg),*);
    };
    ($input:expr => $text:expr, $($arg:expr),*) => {{
        use ::std::str::FromStr;
        // typesafe macros :)
        let text: &'static str = $text;
        let stdin: &mut Iterator<Item = u8> = &mut ($input);

        let mut text = text.bytes();
        $(
        loop { match text.next() {
            Some(b'{') => match text.next() {
                Some(b'{') => assert_eq!(Some(b'{'), stdin.next()),
                Some(b'}') => {
                    static WHITESPACES: &'static [u8] = b"\t\r\n ";
                    let s: Vec<u8> = match text.next() {
                        Some(c) => stdin.take_while(|&ch| ch != c).collect(),
                        None => stdin
                            .skip_while(|ch| WHITESPACES.contains(ch))
                            .take_while(|ch| !WHITESPACES.contains(ch))
                            .collect(),
                    };
                    let s = match ::std::str::from_utf8(&s) {
                        Ok(s) => s,
                        Err(e) => {
                            let n = e.valid_up_to();
                            if n == 0 {
                                panic!("input was not valid utf8: {:?}", s);
                            } else {
                                panic!("input was only partially valid utf8: \"{}\" followed by {:?}",
                                       ::std::str::from_utf8(&s[..n]).unwrap(), &s[n..]);
                            }
                        }
                    };
                    $arg = FromStr::from_str(s).expect(&format!("could not parse {} as target type of {}", s, stringify!($arg)));
                    break;
                }
                Some(_) => panic!("found bad curly brace"),
                None => panic!("found single open curly brace at the end of the format string"),
            },
            Some(c) => assert_eq!(Some(c), stdin.next()),
            None => panic!("Bad read! format string: did not contain {{}}"),
        } }
        )*
        for c in text {
            assert_eq!(Some(c), stdin.next());
        }
        format_args!($text, $($arg),*);
    }};
);
<|endoftext|>


<commit_before>// (c) 2016 Productize SPRL <joost@productize.be>

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

extern crate rustc_serialize;
extern crate symbolic_expressions;

use std::fmt;

pub use symbolic_expressions::Sexp;
pub use error::*;

pub trait FromSexp {
    fn from_sexp(&Sexp) -> Self;
}

use util::read_file;

pub fn parse_split_quote_aware(s:&str) -> Vec<String> {
    let mut v:Vec<String> = vec![];
    let mut in_q:bool = false;
    let mut q_seen:bool = false;
    let mut s2:String = String::from("");
    for c in s.chars() {
        if !in_q && c == '\"' {
            in_q = true;
            //s2.push(c);
            continue
        }
        if in_q && c == '\"' {
            in_q = false;
            //s2.push(c);
            q_seen = true;
            continue
        }
        if !in_q && c == ' ' {
            if !s2.is_empty() || q_seen {
                v.push(s2.clone());
                s2.clear();
            }
            q_seen = false;
            continue;
        }
        s2.push(c);
    }
    if !s2.is_empty() || q_seen {
        v.push(s2.clone())
    }
    v
}

pub fn parse_split_quote_aware_n(n:usize, s:&str) -> Result<Vec<String>> {
    let mut i = 0;
    let mut v:Vec<String> = vec![];
    let mut in_q:bool = false;
    let mut q_seen:bool = false;
    let mut s2:String = String::from("");
    for c in s.chars() {
        if i == n { // if we're in the nth. just keep collecting in current string
            s2.push(c);
            continue;
        }
        if !in_q && c == '\"' {
            in_q = true;
            //s2.push(c);
            continue
        }
        if in_q && c == '\"' {
            in_q = false;
            //s2.push(c);
            q_seen = true;
            continue
        }
        if !in_q && c == ' ' {
            if !s2.is_empty() || q_seen {
                i += 1;
                v.push(s2.clone());
                s2.clear();
            }
            q_seen = false;
            continue;
        }
        s2.push(c);
    }
    if !s2.is_empty() || q_seen {
        v.push(s2.clone())
    }
    if v.len() < n {
        return str_error(format!("expecting {} elements in {}", n, s))
    }
    Ok(v)
}

#[derive(Debug)]
pub enum KicadFile {
    Unknown(String),
    Module(footprint::Module),
    Schematic(schematic::Schematic),
    Layout(layout::Layout),
    SymbolLib(symbol_lib::SymbolLib),
    Project(project::Project),
}

#[derive(PartialEq)]
pub enum Expected {
    Module,
    Schematic,
    Layout,
    SymbolLib,
    Project,
    Any,
}

impl fmt::Display for KicadFile {
    fn fmt(&self, f: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> {
        match *self {
            KicadFile::Unknown(ref x)   => write!(f, "unknown: {}", x),
            KicadFile::Module(_)    => write!(f, "module"),
            KicadFile::Schematic(_) => write!(f, "schematic"),
            KicadFile::Layout(_)    => write!(f, "layout"),
            KicadFile::SymbolLib(_) => write!(f, "symbollib"),
            KicadFile::Project(_)   => write!(f, "project"),
        }
    }
}

pub fn read_kicad_file(name: &str, expected:Expected) -> Result<KicadFile> {
    let pb = std::path::PathBuf::from(name);
    let data = try!(read_file(name));
    let mut msg = String::new();
    match footprint::parse(&data) {
        Ok(module) => return Ok(KicadFile::Module(module)),
        Err(x) => { if expected == Expected::Module { msg = format!("{}", x) } },
    }
    match schematic::parse(Some(pb), &data) {
        Ok(sch) => return Ok(KicadFile::Schematic(sch)),
        Err(x) => { if expected == Expected::Schematic { msg = format!("{}", x) } },
    }
    match layout::parse(&data) {
        Ok(layout) => return Ok(KicadFile::Layout(layout)),
        Err(x) => { if expected == Expected::Layout { msg = format!("{}", x) } },
    }
    match symbol_lib::parse_str(&data) {
        Ok(sl) => return Ok(KicadFile::SymbolLib(sl)),
        Err(x) => { if expected == Expected::SymbolLib { msg = format!("{}", x) } },
    }
    match project::parse_str(&data) {
        Ok(p) => return Ok(KicadFile::Project(p)),
        Err(x) => { if expected == Expected::Project { msg = format!("{}", x) } },
    }
    Ok(KicadFile::Unknown(format!("{}: {}", name, msg)))
}

pub fn read_module(name: &str) -> Result<footprint::Module> {
    match try!(read_kicad_file(name, Expected::Module)) {
        KicadFile::Module(mo) => Ok(mo),
        x => str_error(format!("unexpected {} in {}", x, name)),
    }
}

pub fn read_schematic(name: &str) -> Result<schematic::Schematic> {
    match try!(read_kicad_file(name, Expected::Schematic)) {
        KicadFile::Schematic(mo) => Ok(mo),
        x => str_error(format!("unexpected {} in {}", x, name)),
    }
}

pub fn read_layout(name: &str) -> Result<layout::Layout> {
    match try!(read_kicad_file(name, Expected::Layout)) {
        KicadFile::Layout(mo) => Ok(mo),
        x => str_error(format!("unexpected {} in {}", x, name)),
    }
}

pub fn read_symbol_lib(name: &str) -> Result<symbol_lib::SymbolLib> {
    match try!(read_kicad_file(name, Expected::SymbolLib)) {
        KicadFile::SymbolLib(mo) => Ok(mo),
        x => str_error(format!("unexpected {} in {}", x, name)),
    }
}

pub fn read_project(name: &str) -> Result<project::Project> {
    match try!(read_kicad_file(name, Expected::Project)) {
        KicadFile::Project(mo) => Ok(mo),
        x => str_error(format!("unexpected {} in {}", x, name)),
    }
}

pub mod error;
pub mod footprint;
pub mod schematic;
pub mod layout;
pub mod symbol_lib;
pub mod project;
pub mod util;
mod formatter;
<commit_msg>make read_file public<commit_after>// (c) 2016 Productize SPRL <joost@productize.be>

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

extern crate rustc_serialize;
extern crate symbolic_expressions;

use std::fmt;

pub use symbolic_expressions::Sexp;
pub use error::*;

pub trait FromSexp {
    fn from_sexp(&Sexp) -> Self;
}

pub use util::read_file;

pub fn parse_split_quote_aware(s:&str) -> Vec<String> {
    let mut v:Vec<String> = vec![];
    let mut in_q:bool = false;
    let mut q_seen:bool = false;
    let mut s2:String = String::from("");
    for c in s.chars() {
        if !in_q && c == '\"' {
            in_q = true;
            //s2.push(c);
            continue
        }
        if in_q && c == '\"' {
            in_q = false;
            //s2.push(c);
            q_seen = true;
            continue
        }
        if !in_q && c == ' ' {
            if !s2.is_empty() || q_seen {
                v.push(s2.clone());
                s2.clear();
            }
            q_seen = false;
            continue;
        }
        s2.push(c);
    }
    if !s2.is_empty() || q_seen {
        v.push(s2.clone())
    }
    v
}

pub fn parse_split_quote_aware_n(n:usize, s:&str) -> Result<Vec<String>> {
    let mut i = 0;
    let mut v:Vec<String> = vec![];
    let mut in_q:bool = false;
    let mut q_seen:bool = false;
    let mut s2:String = String::from("");
    for c in s.chars() {
        if i == n { // if we're in the nth. just keep collecting in current string
            s2.push(c);
            continue;
        }
        if !in_q && c == '\"' {
            in_q = true;
            //s2.push(c);
            continue
        }
        if in_q && c == '\"' {
            in_q = false;
            //s2.push(c);
            q_seen = true;
            continue
        }
        if !in_q && c == ' ' {
            if !s2.is_empty() || q_seen {
                i += 1;
                v.push(s2.clone());
                s2.clear();
            }
            q_seen = false;
            continue;
        }
        s2.push(c);
    }
    if !s2.is_empty() || q_seen {
        v.push(s2.clone())
    }
    if v.len() < n {
        return str_error(format!("expecting {} elements in {}", n, s))
    }
    Ok(v)
}

#[derive(Debug)]
pub enum KicadFile {
    Unknown(String),
    Module(footprint::Module),
    Schematic(schematic::Schematic),
    Layout(layout::Layout),
    SymbolLib(symbol_lib::SymbolLib),
    Project(project::Project),
}

#[derive(PartialEq)]
pub enum Expected {
    Module,
    Schematic,
    Layout,
    SymbolLib,
    Project,
    Any,
}

impl fmt::Display for KicadFile {
    fn fmt(&self, f: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> {
        match *self {
            KicadFile::Unknown(ref x)   => write!(f, "unknown: {}", x),
            KicadFile::Module(_)    => write!(f, "module"),
            KicadFile::Schematic(_) => write!(f, "schematic"),
            KicadFile::Layout(_)    => write!(f, "layout"),
            KicadFile::SymbolLib(_) => write!(f, "symbollib"),
            KicadFile::Project(_)   => write!(f, "project"),
        }
    }
}

pub fn read_kicad_file(name: &str, expected:Expected) -> Result<KicadFile> {
    let pb = std::path::PathBuf::from(name);
    let data = try!(read_file(name));
    let mut msg = String::new();
    match footprint::parse(&data) {
        Ok(module) => return Ok(KicadFile::Module(module)),
        Err(x) => { if expected == Expected::Module { msg = format!("{}", x) } },
    }
    match schematic::parse(Some(pb), &data) {
        Ok(sch) => return Ok(KicadFile::Schematic(sch)),
        Err(x) => { if expected == Expected::Schematic { msg = format!("{}", x) } },
    }
    match layout::parse(&data) {
        Ok(layout) => return Ok(KicadFile::Layout(layout)),
        Err(x) => { if expected == Expected::Layout { msg = format!("{}", x) } },
    }
    match symbol_lib::parse_str(&data) {
        Ok(sl) => return Ok(KicadFile::SymbolLib(sl)),
        Err(x) => { if expected == Expected::SymbolLib { msg = format!("{}", x) } },
    }
    match project::parse_str(&data) {
        Ok(p) => return Ok(KicadFile::Project(p)),
        Err(x) => { if expected == Expected::Project { msg = format!("{}", x) } },
    }
    Ok(KicadFile::Unknown(format!("{}: {}", name, msg)))
}

pub fn read_module(name: &str) -> Result<footprint::Module> {
    match try!(read_kicad_file(name, Expected::Module)) {
        KicadFile::Module(mo) => Ok(mo),
        x => str_error(format!("unexpected {} in {}", x, name)),
    }
}

pub fn read_schematic(name: &str) -> Result<schematic::Schematic> {
    match try!(read_kicad_file(name, Expected::Schematic)) {
        KicadFile::Schematic(mo) => Ok(mo),
        x => str_error(format!("unexpected {} in {}", x, name)),
    }
}

pub fn read_layout(name: &str) -> Result<layout::Layout> {
    match try!(read_kicad_file(name, Expected::Layout)) {
        KicadFile::Layout(mo) => Ok(mo),
        x => str_error(format!("unexpected {} in {}", x, name)),
    }
}

pub fn read_symbol_lib(name: &str) -> Result<symbol_lib::SymbolLib> {
    match try!(read_kicad_file(name, Expected::SymbolLib)) {
        KicadFile::SymbolLib(mo) => Ok(mo),
        x => str_error(format!("unexpected {} in {}", x, name)),
    }
}

pub fn read_project(name: &str) -> Result<project::Project> {
    match try!(read_kicad_file(name, Expected::Project)) {
        KicadFile::Project(mo) => Ok(mo),
        x => str_error(format!("unexpected {} in {}", x, name)),
    }
}

pub mod error;
pub mod footprint;
pub mod schematic;
pub mod layout;
pub mod symbol_lib;
pub mod project;
pub mod util;
mod formatter;
<|endoftext|>


<commit_before>use std::io::{IoResult};

struct Triangle {
    normal: [f32, ..3],
    v1: [f32, ..3],
    v2: [f32, ..3],
    v3: [f32, ..3],
    attr_byte_count: u16
}

static EMPTY_TRIANGLE : Triangle = Triangle {
    normal: [0f32, 0f32, 0f32],
    v1: [0f32, 0f32, 0f32],
    v2: [0f32, 0f32, 0f32],
    v3: [0f32, 0f32, 0f32],
    attr_byte_count: 0
};

struct BinaryStlHeader {
    header: [u8, ..80],
    num_triangles: u32
}

pub struct BinaryStlFile {
    header: BinaryStlHeader,
    triangles: Vec<Triangle>
}

fn read_point<T: Reader>(input: &mut T) -> IoResult<[f32, ..3]> {
    let x1 = try!(input.read_le_f32());
    let x2 = try!(input.read_le_f32());
    let x3 = try!(input.read_le_f32());

    Ok([x1, x2, x3])
}

fn read_triangle<T: Reader>(input: &mut T) -> IoResult<Triangle> {
    let normal = try!(read_point(input));
    let v1 = try!(read_point(input));
    let v2 = try!(read_point(input));
    let v3 = try!(read_point(input));
    let attr_count = try!(input.read_le_u16());

    Ok(Triangle { normal: normal,
                  v1: v1, v2: v2, v3: v3,
                  attr_byte_count: attr_count })
}

pub fn read_stl<T: Reader>(input: &mut T) -> IoResult<BinaryStlFile> {
    let mut header = BinaryStlHeader { header: [0u8, ..80],
                                       num_triangles: 0 };

    // read the header
    try!(input.read_at_least(header.header.len(), &mut header.header));

    // TODO: check the header to make sure whether this is a binary
    // STL file.

    header.num_triangles = try!(input.read_le_u32());

    let mut triangles = Vec::new();
    for _ in range(0, header.num_triangles) {
        triangles.push(try!(read_triangle(input)));
    }

    Ok(BinaryStlFile {
        header: header,
        triangles: triangles
    })
}

#[test]
fn it_works() {
}
<commit_msg>STL Write support, with a simple round trip test.<commit_after>use std::io::{BufReader, IoResult};

struct Triangle {
    normal: [f32, ..3],
    v1: [f32, ..3],
    v2: [f32, ..3],
    v3: [f32, ..3],
    attr_byte_count: u16
}

fn point_eq(lhs: [f32, ..3], rhs: [f32, ..3]) -> bool {
    lhs[0] == rhs[0] && lhs[1] == rhs[1] && lhs[2] == rhs[2]
}

impl PartialEq for Triangle {
    fn eq(&self, rhs: &Triangle) -> bool {
        point_eq(self.normal, rhs.normal)
            && point_eq(self.v1, rhs.v1)
            && point_eq(self.v2, rhs.v2)
            && point_eq(self.v3, rhs.v3)
            && self.attr_byte_count == rhs.attr_byte_count
    }
}

impl Eq for Triangle {}

struct BinaryStlHeader {
    header: [u8, ..80],
    num_triangles: u32
}

pub struct BinaryStlFile {
    header: BinaryStlHeader,
    triangles: Vec<Triangle>
}

fn read_point<T: Reader>(input: &mut T) -> IoResult<[f32, ..3]> {
    let x1 = try!(input.read_le_f32());
    let x2 = try!(input.read_le_f32());
    let x3 = try!(input.read_le_f32());

    Ok([x1, x2, x3])
}

fn read_triangle<T: Reader>(input: &mut T) -> IoResult<Triangle> {
    let normal = try!(read_point(input));
    let v1 = try!(read_point(input));
    let v2 = try!(read_point(input));
    let v3 = try!(read_point(input));
    let attr_count = try!(input.read_le_u16());

    Ok(Triangle { normal: normal,
                  v1: v1, v2: v2, v3: v3,
                  attr_byte_count: attr_count })
}

pub fn read_stl<T: Reader>(input: &mut T) -> IoResult<BinaryStlFile> {
    let mut header = BinaryStlHeader { header: [0u8, ..80],
                                       num_triangles: 0 };

    // read the header
    try!(input.read_at_least(header.header.len(), &mut header.header));

    // TODO: check the header to make sure whether this is a binary
    // STL file.

    header.num_triangles = try!(input.read_le_u32());

    let mut triangles = Vec::new();
    for _ in range(0, header.num_triangles) {
        triangles.push(try!(read_triangle(input)));
    }

    Ok(BinaryStlFile {
        header: header,
        triangles: triangles
    })
}

fn write_point<T: Writer>(out: &mut T, p: [f32, ..3]) -> IoResult<()> {
    for x in p.iter() {
        try!(out.write_le_f32(*x));
    }
    Ok(())
}

pub fn write_stl<T: Writer>(out: &mut T, stl: &BinaryStlFile) -> IoResult<()> {
    assert!(stl.header.num_triangles as uint == stl.triangles.len());

    //write the header.
    try!(out.write(&stl.header.header));
    try!(out.write_le_u32(stl.header.num_triangles));

    // write all the triangles
    for t in stl.triangles.iter() {
        try!(write_point(out, t.normal));
        try!(write_point(out, t.v1));
        try!(write_point(out, t.v2));
        try!(write_point(out, t.v3));
        try!(out.write_le_u16(t.attr_byte_count));
    }

    Ok(())
}

#[test]
fn write_read() {
    // Make sure we can write and read a simple file.
    let file = BinaryStlFile {
        header: BinaryStlHeader { header: [0u8, ..80],
                                  num_triangles: 1 },
        triangles: vec![Triangle { normal: [0f32, 1f32, 0f32],
                                   v1: [0f32, 0f32, 0f32],
                                   v2: [0f32, 0f32, 1f32],
                                   v3: [1f32, 0f32, 1f32],
                                   attr_byte_count: 0 }]
    };

    let mut buffer = Vec::new();

    match write_stl(&mut buffer, &file) {
        Ok(_) => (),
        Err(_) => panic!()
    }

    match read_stl(&mut BufReader::new(buffer.as_slice())) {
        Ok(stl) => {
            assert!(stl.header.num_triangles == file.header.num_triangles);
            assert!(stl.triangles.len() == 1);
            assert!(stl.triangles[0] == file.triangles[0])
        },
        Err(_) => panic!()
    }
}
<|endoftext|>


<commit_before>

macro_rules! dbg {
    () => {
        dbg!("");
    };
    ($format:expr) => {
        dbg!(concat!($format,"{}"), "");
    };
    //($blk:block) => {
    //    dbg!("{:?}", $blk);
    //};
    ($format:expr, $($tail:expr),*) => {
        if cfg!(debug_assertions) {
            println!(concat!("{}:{}:{} ",$format),
                    cfg!(crate_name), file!(), line!(), $($tail),*);
        }
    };
}

#[test]
fn test_dbg() {
    dbg!();
    dbg!("");
    dbg!("non-format string");
    dbg!("format: {}", 42);
    dbg!("format: {} {}", 42, 43);
    dbg!("format: {}", 42+42);
    dbg!("format: {}", {42+42});
    //dbg!(42);
    //dbg!(42+42);
    //dbg!({ 42+42 });
}
<commit_msg>export the macro<commit_after>
#[macro_export]
macro_rules! dbg {
    () => {
        dbg!("");
    };
    ($format:expr) => {
        dbg!(concat!($format,"{}"), "");
    };
    //($blk:block) => {
    //    dbg!("{:?}", $blk);
    //};
    ($format:expr, $($tail:expr),*) => {
        if cfg!(debug_assertions) {
            println!(concat!("{}:{}:{} ",$format),
                    cfg!(crate_name), file!(), line!(), $($tail),*);
        }
    };
}

#[test]
fn test_dbg() {
    dbg!();
    dbg!("");
    dbg!("non-format string");
    dbg!("format: {}", 42);
    dbg!("format: {} {}", 42, 43);
    dbg!("format: {}", 42+42);
    dbg!("format: {}", {42+42});
    //dbg!(42);
    //dbg!(42+42);
    //dbg!({ 42+42 });
}
<|endoftext|>