<commit_before>extern crate gl_generator;
extern crate khronos_api;

use std::os;
use std::old_io::File;

fn main() {
    let dest = Path::new(os::getenv("OUT_DIR").unwrap());

    let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();

    gl_generator::generate_bindings(gl_generator::StructGenerator,
                                                   gl_generator::registry::Ns::Gl,
                                                   khronos_api::GL_XML,
                                                   vec!["GL_EXT_texture_filter_anisotropic".to_string()],
                                                   "4.5", "core",
                                                   &mut file).unwrap();
}
<commit_msg>fix generate_bindings<commit_after>extern crate gl_generator;
extern crate khronos_api;

use std::os;
use std::old_io::File;

fn main() {
    let dest = Path::new(os::getenv("OUT_DIR").unwrap());

    let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();

    gl_generator::generate_bindings(gl_generator::StructGenerator,
                                                   gl_generator::registry::Ns::Gl,
                                                   gl_generator::Fallbacks::All,
                                                   khronos_api::GL_XML,
                                                   vec!["GL_EXT_texture_filter_anisotropic".to_string()],
                                                   "4.5", "core",
                                                   &mut file).unwrap();
}
<|endoftext|>


<commit_before>extern crate serde_codegen;
extern crate serde_json;
extern crate glob;

use std::collections::BTreeMap;
use std::env;
use std::fs;
use std::fs::File;
use std::io::{Result, Read, Write};
use std::path::Path;

/// generate an enum of Events
fn main() {
     for entry in glob::glob("data/**/*.json").expect("Failed to read glob pattern") {
        println!("cargo:rerun-if-changed={}", entry.unwrap().display());
     }

    for entry in glob::glob("src/**/*.rs.in").expect("Failed to read glob pattern") {
        println!("cargo:rerun-if-changed={}", entry.unwrap().display());
    }

    let out_dir = env::var_os("OUT_DIR").unwrap();

    // Switch to our `src` directory so that we have the right base for our
    // globs, and so that we won't need to strip `src/` off every path.
    env::set_current_dir("src").unwrap();

    for entry in glob::glob("**/*.rs.in").expect("Failed to read glob pattern") {
        match entry {
            Ok(src) => {
                let mut dst = Path::new(&out_dir).join(&src);

                // Change ".rs.in" to ".rs".
                dst.set_file_name(src.file_stem().expect("Failed to get file stem"));
                dst.set_extension("rs");

                // Make sure our target directory exists.  We only need
                // this if there are extra nested sudirectories under src/.
                fs::create_dir_all(dst.parent().unwrap()).unwrap();

                // Process our source file.
                serde_codegen::expand(&src, &dst).unwrap();
            }
            Err(e) => {
                panic!("Error globbing: {}", e);
            }
        }
    }

    // let mut buf = String::new();
    // let mut event_list = File::open("events.txt").unwrap();
    // event_list.read_to_string(&mut buf).unwrap();
    // let events = buf.lines().collect::<Vec<&str>>();
    // println!("events {:#?}", events);
    // if let Ok(_) = env::var("FETCH_PAYLOAD_DATA") {
    // fetch_payload_data(&events).unwrap();
    // }
    // if let Ok(_) = env::var("SKIP_GENERATE") {
    // return;
    // }
    // generate_enum(&events).unwrap();
    //
    // let out_dir = env::var_os("OUT_DIR").unwrap();
    // let src = Path::new(&out_dir).join("events.rs.in");
    // let dst = Path::new(&out_dir).join("events.rs");
    // serde_codegen::expand(&src, &dst).unwrap();
}

/*fn fetch_payload_data(events: &Vec<&str>) -> Result<()> {
    println!("fetching payload data for events {:#?}", events);
    // let data_dir = Path::new("data");
    // let client = Client::new();
    // for event in events {
    // let src = format!("https://raw.githubusercontent.com/github/developer.github.\
    // com/master/lib/webhooks/{}.payload.json",
    // event);
    // let mut res = client.get(&src)
    // .send()
    // .unwrap();
    // let mut buf = String::new();
    // try!(res.read_to_string(&mut buf));
    // let outfile = data_dir.join(format!("{}.json", event));
    // let mut f = try!(File::create(outfile));
    // try!(f.write_all(buf.as_bytes()));
    // }
    Ok(())
}

fn generate_enum(events: &Vec<&str>) -> Result<()> {
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("events.rs.in");
    let mut f = try!(File::create(&dest_path));

    // synthensize a type that can represent arbitrary json in deployment payloads
    // as well has a type which we may implement a default value
    try!(f.write_all(b"#[derive(Debug, Deserialize)]
pub struct Value { pub json: serde_json::Value }

"));

    try!(f.write_all(b"#[derive(Debug, Deserialize)]
pub enum Event {
"));
    let mut defs = BTreeMap::new();
    for event in events {
        let mut data = try!(File::open(format!("data/{}.json", event)));
        let mut buf = String::new();
        try!(data.read_to_string(&mut buf));
        let parsed: serde_json::Value = serde_json::from_str(&buf).unwrap();
        let enum_name = container_name(event);
        try!(f.write_all(format!("  {} ", enum_name).as_bytes()));
        try!(f.write_all(b"{"));

        match parsed {
            serde_json::Value::Object(obj) => {
                for (k, v) in obj {
                    try!(f.write_all(format!(r#"
      #[serde(rename="{}")]
      {}: {},"#,
                                             k,
                                             field_name(&k),
                                             value(&enum_name, &mut defs, &k, &v))
                        .as_bytes()))
                }
            }
            _ => (),
        }
        try!(f.write_all(b"
  },
"));
    }
    try!(f.write_all(b"}

"));

    try!(print_structs(&mut f, defs, &mut vec![], 0));

    Ok(())
}

fn print_structs(f: &mut File,
                 defs: BTreeMap<String, serde_json::Value>,
                 generated: &mut Vec<String>,
                 depth: usize)
                 -> Result<()> {
    let mut aux = BTreeMap::new();
    for (struct_name, json) in defs.iter() {
        if generated.contains(&struct_name) {
            continue;
        }
        println!("struct {}", struct_name);
        try!(f.write_all(format!("
#[derive(Default, Debug, Deserialize)]
pub struct {} ",
                                 struct_name)
            .as_bytes()));
        try!(f.write_all(b"{"));
        match json {
            &serde_json::Value::Object(ref obj) => {
                for (k, v) in obj {
                    // fields are renamed to enable deserialization of fields
                    // that are also reserved works in rust
                    try!(f.write_all(format!(r#"
    #[serde(rename="{}")]
    pub {}: {},"#,
                                             k,
                                             field_name(&k),
                                             value(&struct_name, &mut aux, &k, &v))
                        .as_bytes()))
                }
            }
            _ => (),
        }

        try!(f.write_all(b"
}
"));
        generated.push(struct_name.clone());
    }
    if !aux.is_empty() {
        try!(print_structs(f, aux, generated, depth + 1));
    }
    Ok(())
}

fn value(container: &String,
         defs: &mut BTreeMap<String, serde_json::Value>,
         k: &str,
         j: &serde_json::Value)
         -> String {
    match j {
        &serde_json::Value::I64(_) => "i64".to_owned(),
        &serde_json::Value::U64(_) => "u64".to_owned(),
        &serde_json::Value::F64(_) => "f64".to_owned(),
        &serde_json::Value::String(_) => "String".to_owned(),
        &serde_json::Value::Bool(_) => "bool".to_owned(),
        &serde_json::Value::Array(ref jv) => {
            if jv.is_empty() {
                "Vec<String>".to_owned() // this is just a guess!
            } else {
                format!("Vec<{}>", value(&container, defs, k, &jv[0]))
            }
        }
        obj @ &serde_json::Value::Object(_) => {
            if "payload" == k {
                // payloads may contain any arbitrary json structure
                // it is unsafe to assume a fixed type of map, string, ect
                "Value".to_owned()
            } else {
                // avoid recusive types by compormising on an alternative name
                let struct_name = match container_name(k) {
                    ref recursive if recursive == container => format!("{}Inner", recursive),
                    ref exists if defs.contains_key(exists) && defs[exists] != *obj => {
                        format!("{}{}", container, exists)
                    }
                    valid => valid,
                };
                defs.insert(struct_name.clone(), obj.clone());
                struct_name
            }
        }
        &serde_json::Value::Null => "Option<String>".to_owned(),
    }
}

fn container_name(field: &str) -> String {
    if "self" == field {
        "SelfLink".to_owned()
    } else {
        field.to_camel()
    }
}

/// works around conflicts with reservied words
fn field_name(s: &str) -> String {
    // todo: this is only as robust as it needs to be
    // this list is not complete
    let reserved = vec!["ref", "self", "type"];
    if reserved.contains(&s) {
        format!("_{}", s)
    } else {
        s.to_owned()
    }
}
*/
<commit_msg>cleanup build<commit_after>extern crate serde_codegen;
extern crate serde_json;
extern crate glob;

use std::env;
use std::fs;
use std::path::Path;

/// generate an enum of Events
fn main() {
    for entry in glob::glob("src/**/*.rs.in").expect("Failed to read glob pattern") {
        println!("cargo:rerun-if-changed={}", entry.unwrap().display());
    }

    let out_dir = env::var_os("OUT_DIR").unwrap();

    // Switch to our `src` directory so that we have the right base for our
    // globs, and so that we won't need to strip `src/` off every path.
    env::set_current_dir("src").unwrap();

    for entry in glob::glob("**/*.rs.in").expect("Failed to read glob pattern") {
        match entry {
            Ok(src) => {
                let mut dst = Path::new(&out_dir).join(&src);

                // Change ".rs.in" to ".rs".
                dst.set_file_name(src.file_stem().expect("Failed to get file stem"));
                dst.set_extension("rs");

                // Make sure our target directory exists.  We only need
                // this if there are extra nested sudirectories under src/.
                fs::create_dir_all(dst.parent().unwrap()).unwrap();

                // Process our source file.
                serde_codegen::expand(&src, &dst).unwrap();
            }
            Err(e) => {
                panic!("Error globbing: {}", e);
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::str::FromStr;

fn main() {
    // OpenSSL >= 1.1.0 can be initialized concurrently and is initialized correctly by libcurl.
    // <= 1.0.2 need locking callbacks, which are provided by openssl_sys::init().
    let use_openssl = match env::var("DEP_OPENSSL_VERSION") {
        Ok(ver) => {
            let ver = u32::from_str(&ver).unwrap();
            if ver < 110 {
                println!("cargo:rustc-cfg=need_openssl_init");
            }
            true
        }
        Err(_) => false,
    };

    if use_openssl {
        // The system libcurl should have the default certificate paths configured.
        if env::var_os("DEP_CURL_STATIC").is_some() {
            println!("cargo:rustc-cfg=need_openssl_probe");
        }
    }
}
<commit_msg>Update OpenSSL initialization check (#419)<commit_after>use std::env;

fn main() {
    // OpenSSL >= 1.1.0 can be initialized concurrently and is initialized correctly by libcurl.
    // <= 1.0.2 need locking callbacks, which are provided by openssl_sys::init().
    let use_openssl = match env::var("DEP_OPENSSL_VERSION_NUMBER") {
        Ok(version) => {
            let version = u64::from_str_radix(&version, 16).unwrap();
            if version < 0x1_01_00_00_0 {
                println!("cargo:rustc-cfg=need_openssl_init");
            }
            true
        }
        Err(_) => false,
    };

    if use_openssl {
        // The system libcurl should have the default certificate paths configured.
        if env::var_os("DEP_CURL_STATIC").is_some() {
            println!("cargo:rustc-cfg=need_openssl_probe");
        }
    }
}
<|endoftext|>


<commit_before>#![allow(unstable)]
extern crate gl_generator;
extern crate khronos_api;

use std::os;
use std::fs::File;

fn main() {
    let target = os::getenv("TARGET").unwrap();
    let dest = Path::new(os::getenv("OUT_DIR").unwrap());

    if target.contains("windows") {
        let mut file = File::create(&dest.join("wgl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StaticGenerator,
                                        gl_generator::registry::Ns::Wgl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::WGL_XML, vec![],
                                        "1.0", "core", &mut file).unwrap();

        let mut file = File::create(&dest.join("wgl_extra_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Wgl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::WGL_XML,
                                        vec![
                                            "WGL_ARB_create_context".to_string(),
                                            "WGL_EXT_swap_control".to_string()
                                        ],
                                        "1.0", "core", &mut file).unwrap();
    }

    if target.contains("linux") {
        let mut file = File::create(&dest.join("glx_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StaticGenerator,
                                        gl_generator::registry::Ns::Glx,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GLX_XML, vec![],
                                        "1.4", "core", &mut file).unwrap();

        let mut file = File::create(&dest.join("glx_extra_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Glx,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GLX_XML,
                                        vec![
                                            "GLX_ARB_create_context".to_string(),
                                            "GLX_EXT_swap_control".to_string(),
                                            "GLX_SGI_swap_control".to_string()
                                        ],
                                        "1.4", "core", &mut file).unwrap();
    }

    if target.contains("android") {
        let mut file = File::create(&dest.join("egl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StaticGenerator,
                                        gl_generator::registry::Ns::Egl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::EGL_XML, vec![],
                                        "1.5", "core", &mut file).unwrap();
    }

    if target.contains("darwin") {
        let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::GlobalGenerator,
                                        gl_generator::registry::Ns::Gl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GL_XML,
                                        vec!["GL_EXT_framebuffer_object".to_string()],
                                        "3.2", "core", &mut file).unwrap();
    } else if target.contains("android") {
        let mut file = File::create(&dest.join("gles2_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Gles2,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GL_XML, vec![],
                                        "3.1", "core", &mut file).unwrap();
    } else {
        let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Gl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GL_XML, vec![],
                                        "4.1", "core", &mut file).unwrap();
    }
}
<commit_msg>Switch build.rs to new std APIs.<commit_after>extern crate gl_generator;
extern crate khronos_api;

use std::env;
use std::fs::File;
use std::path::PathBuf;

fn main() {
    let target = env::var("TARGET").unwrap();
    let dest = PathBuf::new(&env::var("OUT_DIR").unwrap());

    if target.contains("windows") {
        let mut file = File::create(&dest.join("wgl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StaticGenerator,
                                        gl_generator::registry::Ns::Wgl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::WGL_XML, vec![],
                                        "1.0", "core", &mut file).unwrap();

        let mut file = File::create(&dest.join("wgl_extra_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Wgl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::WGL_XML,
                                        vec![
                                            "WGL_ARB_create_context".to_string(),
                                            "WGL_EXT_swap_control".to_string()
                                        ],
                                        "1.0", "core", &mut file).unwrap();
    }

    if target.contains("linux") {
        let mut file = File::create(&dest.join("glx_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StaticGenerator,
                                        gl_generator::registry::Ns::Glx,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GLX_XML, vec![],
                                        "1.4", "core", &mut file).unwrap();

        let mut file = File::create(&dest.join("glx_extra_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Glx,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GLX_XML,
                                        vec![
                                            "GLX_ARB_create_context".to_string(),
                                            "GLX_EXT_swap_control".to_string(),
                                            "GLX_SGI_swap_control".to_string()
                                        ],
                                        "1.4", "core", &mut file).unwrap();
    }

    if target.contains("android") {
        let mut file = File::create(&dest.join("egl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StaticGenerator,
                                        gl_generator::registry::Ns::Egl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::EGL_XML, vec![],
                                        "1.5", "core", &mut file).unwrap();
    }

    if target.contains("darwin") {
        let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::GlobalGenerator,
                                        gl_generator::registry::Ns::Gl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GL_XML,
                                        vec!["GL_EXT_framebuffer_object".to_string()],
                                        "3.2", "core", &mut file).unwrap();
    } else if target.contains("android") {
        let mut file = File::create(&dest.join("gles2_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Gles2,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GL_XML, vec![],
                                        "3.1", "core", &mut file).unwrap();
    } else {
        let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();
        gl_generator::generate_bindings(gl_generator::StructGenerator,
                                        gl_generator::registry::Ns::Gl,
                                        gl_generator::Fallbacks::All,
                                        khronos_api::GL_XML, vec![],
                                        "4.1", "core", &mut file).unwrap();
    }
}
<|endoftext|>


<commit_before>#![macro_use]

pub enum CoResult<YieldT, CoroT, ReturnT> {
    Yield(YieldT, CoroT),
    Return(ReturnT),
}

pub trait Coroutine<Input>: Sized {
    type Yield;
    type Return;

    fn next(self, i: Input) -> CoResult<Self::Yield, Self, Self::Return>;
}

#[macro_export]
macro_rules! each {
    // full_each
    ($iter:expr => $elem:pat in
        $loop_body:block
     then with $then:pat in
        $then_body:block
     otherwise $else_body:block) => {{
        let mut iter_ = $iter;
        let fin;
        'outer: loop {
            loop {
                #[allow(unused_assignments)]
                match iter_.next(()) {
                    CoResult::Yield($elem, tail) => {
                        iter_ = tail;
                        $loop_body;
                    },
                    CoResult::Return($then) => {
                        fin = $then_body;
                        break 'outer;
                    }
                };
            }
            fin = $else_body;
            break;
        }
        fin
    }};

    // no_otherwise
    ($iter:expr => $elem:pat in
         $loop_body:block
     then with $then:pat in
         $then_body:block) => {{
        let mut iter_ = $iter;
        let fin;
        'outer: loop {
            #[allow(unused_assignments)]
            match iter_.next(()) {
                CoResult::Yield($elem, tail) => {
                    iter_ = tail;
                    $loop_body;
                },
                CoResult::Return($then) => {
                    fin = $then_body;
                    break 'outer;
                }
            };
        }
        fin
    }};

    // no_with
    ($iter:expr => $elem:pat in
         $loop_body:block
     then
         $then_body:block
     otherwise
         $else_body:block) => {{
        let mut iter_ = $iter;
        let fin;
        'outer: loop {
            loop {
                #[allow(unused_assignments)]
                match iter_.next(()) {
                    CoResult::Yield($elem, tail) => {
                        iter_ = tail;
                        $loop_body;
                    },
                    CoResult::Return(_) => {
                        fin = $then_body;
                        break 'outer;
                    }
                };
            }
            fin = $else_body;
            break;
        }
        fin
    }};

    // no_with_otherwise
    ($iter:expr => $elem:pat in
         $loop_body:block
     then
         $then_body:block) => {{
        let mut iter_ = $iter;
        let fin;
        'outer: loop {
            #[allow(unused_assignments)]
            match iter_.next(()) {
                CoResult::Yield($elem, tail) => {
                    iter_ = tail;
                    $loop_body;
                },
                CoResult::Return(_) => {
                    fin = $then_body;
                    break 'outer;
                }
            };
        }
        fin
    }};

    // no_then
    ($iter:expr => $elem:pat in
         $loop_body:block
     otherwise
         $else_body:block) => {{
        let mut iter_ = $iter;
        let fin;
        'outer: loop {
            loop {
                #[allow(unused_assignments, unreachable_patterns, unreachable_code)]
                match iter_.next(()) {
                    CoResult::Yield($elem, tail) => {
                        iter_ = tail;
                        $loop_body;
                    },
                    CoResult::Return(ret) => {
                        fin = ret;
                        break 'outer;
                    }
                };
            }
            fin = $else_body;
            break;
        }
        fin
    }};

    // no_then_otherwise
    ($iter:expr => $elem:pat in
         $loop_body:block) => {{
        let mut iter_ = $iter;
        let fin;
        loop {
            #[allow(unused_assignments)]
            match iter_.next(()) {
                CoResult::Yield($elem, tail) => {
                    iter_ = tail;
                    $loop_body;
                },
                CoResult::Return(ret) => {
                    fin = ret;
                    break;
                }
            };
        }
        fin
    }};
}

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

    struct Counter<T> {
        i: T,
        lim: T,
    }

    impl Coroutine<()> for Counter<i64> {
        type Yield = i64;
        type Return = &'static str;

        fn next(self, _: ()) -> CoResult<Self::Yield, Self, Self::Return> {
            if self.i < self.lim {
                CoResult::Yield(self.i,
                                Counter {
                                    i: self.i + 1,
                                    lim: self.lim,
                                })
            } else {
                CoResult::Return("I'm done!")
            }
        }
    }

    struct InfiniteCounter<T> {
        i: T,
    }

    impl Coroutine<()> for InfiniteCounter<i64> {
        type Yield = i64;
        type Return = !;

        fn next(self, _: ()) -> CoResult<Self::Yield, Self, Self::Return> {
            CoResult::Yield(self.i, InfiniteCounter { i: self.i + 1 })
        }
    }

    #[test]
    fn full_each() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let large_num = 1000;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
            if large_num < 5 { break; }
        } then with msg in {
            String::from(msg) + " Yayy!"
        } otherwise {
            String::from("I got broken!")
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, String::from("I'm done! Yayy!"));
    }

    #[test]
    fn full_each_with_break() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
            break;
        } then with msg in {
            msg
        } otherwise {
            "I got broken!"
        });
        assert_eq!(cnt, 4);
        assert_eq!(message, "I got broken!");
    }

    #[test]
    fn full_each_with_capture_patterns() {

        struct Blabber<T> {
            i: T,
            lim: T,
        }

        impl Coroutine<()> for Blabber<i64> {
            type Yield = (i64, i64);
            type Return = (&'static str, i64);

            fn next(self, _: ()) -> CoResult<Self::Yield, Self, Self::Return> {
                if self.i < self.lim {
                    CoResult::Yield((self.i, self.lim),
                                    Blabber {
                                        i: self.i + 1,
                                        lim: self.lim,
                                    })
                } else {
                    CoResult::Return(("I'm done!", self.lim))
                }
            }
        }

        let bart = Blabber::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let large_num = 1000;
        let (message, lim) = each!(bart => (i, lim) in {
            assert_eq!(i, cnt);
            assert_eq!(lim, 10);
            cnt += 1;
            if large_num < 5 { break; }
        } then with (msg, lim) in {
            (String::from(msg) + " Yayy!", lim)
        } otherwise {
            (String::from("I got broken!"), -1)
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, String::from("I'm done! Yayy!"));
        assert_eq!(lim, 10);
    }

    #[test]
    fn no_with() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let large_number = 1000;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
            if large_number < 5 { break; }
        } then {
            "At last!"
        } otherwise {
            "I got broken!"
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, "At last!");
    }

    #[test]
    fn no_otherwise() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
        } then with msg in {
            String::from(msg) + " Yayy!"
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, String::from("I'm done! Yayy!"));
    }

    #[test]
    fn no_with_otherwise() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
        } then {
            "At last!"
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, "At last!");
    }

    #[test]
    fn no_then() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        #[allow(unreachable_code)]
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
        } otherwise {
            "bogus"
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, "I'm done!");
    }

    #[test]
    fn no_then_with_break() {
        let bart = InfiniteCounter::<i64> { i: 3 };
        let mut cnt = 3;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
            if cnt >= 20 { break; }
        } otherwise {
            "I got broken!"
        });
        assert_eq!(cnt, 20);
        assert_eq!(message, "I got broken!");
    }

    #[test]
    fn no_then_otherwise() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, "I'm done!");
    }
}
<commit_msg>Move #[allow(unreachable_code)] near code in cause<commit_after>#![macro_use]

pub enum CoResult<YieldT, CoroT, ReturnT> {
    Yield(YieldT, CoroT),
    Return(ReturnT),
}

pub trait Coroutine<Input>: Sized {
    type Yield;
    type Return;

    fn next(self, i: Input) -> CoResult<Self::Yield, Self, Self::Return>;
}

#[macro_export]
macro_rules! each {
    // full_each
    ($iter:expr => $elem:pat in
         $loop_body:block
     then with $then:pat in
         $then_body:block
     otherwise
         $else_body:block) => {{
        let mut iter_ = $iter;
        let fin;
        'outer: loop {
            loop {
                match iter_.next(()) {
                    CoResult::Yield($elem, tail) => {
                        #[allow(unused_assignments)] // if $loop_body contains a `break` statement
                        {
                            iter_ = tail;
                        }
                        $loop_body;
                    },
                    CoResult::Return($then) => {
                        fin = $then_body;
                        break 'outer;
                    }
                };
            }
            fin = $else_body;
            break;
        }
        fin
    }};

    // no_otherwise
    ($iter:expr => $elem:pat in
         $loop_body:block
     then with $then:pat in
         $then_body:block) => {{
        let mut iter_ = $iter;
        let fin;
        'outer: loop {
            loop {
                match iter_.next(()) {
                    CoResult::Yield($elem, tail) => {
                        #[allow(unused_assignments)] // if $loop_body contains a `break` statement
                        {
                            iter_ = tail;
                        }
                        $loop_body;
                    },
                    CoResult::Return($then) => {
                        fin = $then_body;
                        break 'outer;
                    }
                };
            }
            #[allow(unreachable_code)] // if $loop_body contains a `break` statement
            {
                break;
            }
        }
        fin
    }};

    // no_with
    ($iter:expr => $elem:pat in
         $loop_body:block
     then
         $then_body:block
     otherwise
         $else_body:block) => {{
        let mut iter_ = $iter;
        let fin;
        'outer: loop {
            loop {
                match iter_.next(()) {
                    CoResult::Yield($elem, tail) => {
                        #[allow(unused_assignments)] // if $loop_body contains a `break` statement
                        {
                            iter_ = tail;
                        }
                        $loop_body;
                    },
                    CoResult::Return(_) => {
                        fin = $then_body;
                        break 'outer;
                    }
                };
            }
            fin = $else_body;
            break;
        }
        fin
    }};

    // no_with_otherwise
    ($iter:expr => $elem:pat in
         $loop_body:block
     then
         $then_body:block) => {{
        let mut iter_ = $iter;
        let fin;
        'outer: loop {
            loop {
                match iter_.next(()) {
                    CoResult::Yield($elem, tail) => {
                        #[allow(unused_assignments)] // if $loop_body contains a `break` statement
                        {
                            iter_ = tail;
                        }
                        $loop_body;
                    },
                    CoResult::Return(_) => {
                        fin = $then_body;
                        break 'outer;
                    }
                };
            }
            #[allow(unreachable_code)] // if $loop_body contains a `break` statement
            {
                break;
            }
        }
        fin
    }};

    // no_then
    ($iter:expr => $elem:pat in
         $loop_body:block
     otherwise
         $else_body:block) => {{
        let mut iter_ = $iter;
        let fin;
        'outer: loop {
            loop {
                #[allow(unreachable_patterns, unreachable_code)] // if $iter::Return is !
                match iter_.next(()) {
                    CoResult::Yield($elem, tail) => {
                        #[allow(unused_assignments)] // if $loop_body contains a `break` statement
                        {
                            iter_ = tail;
                        }
                        $loop_body;
                    },
                    CoResult::Return(ret) => {
                        fin = ret;
                        break 'outer;
                    }
                };
            }
            fin = $else_body;
            break;
        }
        fin
    }};

    // no_then_otherwise
    ($iter:expr => $elem:pat in
         $loop_body:block) => {{
        let mut iter_ = $iter;
        let fin;
        loop {
            match iter_.next(()) {
                CoResult::Yield($elem, tail) => {
                        #[allow(unused_assignments)] // if $loop_body contains a `break` statement
                        {
                            iter_ = tail;
                        }
                    $loop_body;
                },
                CoResult::Return(ret) => {
                    fin = ret;
                    break;
                }
            };
        }
        fin
    }};
}

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

    struct Counter<T> {
        i: T,
        lim: T,
    }

    impl Coroutine<()> for Counter<i64> {
        type Yield = i64;
        type Return = &'static str;

        fn next(self, _: ()) -> CoResult<Self::Yield, Self, Self::Return> {
            if self.i < self.lim {
                CoResult::Yield(self.i,
                                Counter {
                                    i: self.i + 1,
                                    lim: self.lim,
                                })
            } else {
                CoResult::Return("I'm done!")
            }
        }
    }

    struct InfiniteCounter<T> {
        i: T,
    }

    impl Coroutine<()> for InfiniteCounter<i64> {
        type Yield = i64;
        type Return = !;

        fn next(self, _: ()) -> CoResult<Self::Yield, Self, Self::Return> {
            CoResult::Yield(self.i, InfiniteCounter { i: self.i + 1 })
        }
    }

    #[test]
    fn full_each() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let large_num = 1000;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
            if large_num < 5 { break; }
        } then with msg in {
            String::from(msg) + " Yayy!"
        } otherwise {
            String::from("I got broken!")
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, String::from("I'm done! Yayy!"));
    }

    #[test]
    fn full_each_with_break() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
            break;
        } then with msg in {
            msg
        } otherwise {
            "I got broken!"
        });
        assert_eq!(cnt, 4);
        assert_eq!(message, "I got broken!");
    }

    #[test]
    fn full_each_with_capture_patterns() {

        struct Blabber<T> {
            i: T,
            lim: T,
        }

        impl Coroutine<()> for Blabber<i64> {
            type Yield = (i64, i64);
            type Return = (&'static str, i64);

            fn next(self, _: ()) -> CoResult<Self::Yield, Self, Self::Return> {
                if self.i < self.lim {
                    CoResult::Yield((self.i, self.lim),
                                    Blabber {
                                        i: self.i + 1,
                                        lim: self.lim,
                                    })
                } else {
                    CoResult::Return(("I'm done!", self.lim))
                }
            }
        }

        let bart = Blabber::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let large_num = 1000;
        let (message, lim) = each!(bart => (i, lim) in {
            assert_eq!(i, cnt);
            assert_eq!(lim, 10);
            cnt += 1;
            if large_num < 5 { break; }
        } then with (msg, lim) in {
            (String::from(msg) + " Yayy!", lim)
        } otherwise {
            (String::from("I got broken!"), -1)
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, String::from("I'm done! Yayy!"));
        assert_eq!(lim, 10);
    }

    #[test]
    fn no_with() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let large_number = 1000;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
            if large_number < 5 { break; }
        } then {
            "At last!"
        } otherwise {
            "I got broken!"
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, "At last!");
    }

    #[test]
    fn no_otherwise() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
        } then with msg in {
            String::from(msg) + " Yayy!"
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, String::from("I'm done! Yayy!"));
    }

    #[test]
    fn no_with_otherwise() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
        } then {
            "At last!"
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, "At last!");
    }

    #[test]
    fn no_then() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
            if cnt > 100 { break; }
        } otherwise {
            "bogus"
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, "I'm done!");
    }

    #[test]
    fn no_then_with_break() {
        let bart = InfiniteCounter::<i64> { i: 3 };
        let mut cnt = 3;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
            if cnt >= 20 { break; }
        } otherwise {
            "I got broken!"
        });
        assert_eq!(cnt, 20);
        assert_eq!(message, "I got broken!");
    }

    #[test]
    fn no_then_otherwise() {
        let bart = Counter::<i64> { i: 3, lim: 10 };
        let mut cnt = 3;
        let message = each!(bart => i in {
            assert_eq!(i, cnt);
            cnt += 1;
        });
        assert_eq!(cnt, 10);
        assert_eq!(message, "I'm done!");
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::str;
use serde::de;
use error::{Error, Result};

pub struct BencodeAccess<'a, R: 'a + Read> {
    de: &'a mut Deserializer<R>,
}

impl<'a, R: 'a + Read> BencodeAccess<'a, R> {
    fn new(de: &'a mut Deserializer<R>) -> BencodeAccess<'a, R> {
        BencodeAccess { de: de }
    }
}

impl<'de, 'a, R: 'a + Read> de::VariantAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;

    fn unit_variant(self) -> Result<()> {
        Ok(())
    }

    fn newtype_variant_seed<T: de::DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value> {
        let res = seed.deserialize(&mut *self.de)?;
        if ParseResult::End != self.de.parse()? {
            return Err(Error::InvalidType("expected `d`".to_string()));
        }
        Ok(res)
    }

    fn tuple_variant<V: de::Visitor<'de>>(self, _: usize, visitor: V) -> Result<V::Value> {
        let res = de::Deserializer::deserialize_any(&mut *self.de, visitor)?;
        if ParseResult::End != self.de.parse()? {
            return Err(Error::InvalidType("expected `d`".to_string()));
        }
        Ok(res)
    }

    fn struct_variant<V: de::Visitor<'de>>(self,
                                           _: &'static [&'static str],
                                           visitor: V)
                                           -> Result<V::Value> {
        let res = de::Deserializer::deserialize_any(&mut *self.de, visitor)?;
        if ParseResult::End != self.de.parse()? {
            return Err(Error::InvalidType("expected `d`".to_string()));
        }
        Ok(res)
    }
}

impl<'de, 'a, R: 'a + Read> de::SeqAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;

    fn next_element_seed<T: de::DeserializeSeed<'de>>(&mut self,
                                                      seed: T)
                                                      -> Result<Option<T::Value>> {
        match self.de.parse()? {
            ParseResult::End => Ok(None),
            r @ _ => {
                self.de.next = Some(r);
                Ok(Some(seed.deserialize(&mut *self.de)?))
            }
        }
    }
}

impl<'de, 'a, R: 'a + Read> de::MapAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;
    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
        where K: de::DeserializeSeed<'de>
    {
        match self.de.parse()? {
            ParseResult::End => Ok(None),
            r @ _ => {
                self.de.next = Some(r);
                Ok(Some(seed.deserialize(&mut *self.de)?))
            }
        }
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
        where V: de::DeserializeSeed<'de>
    {
        seed.deserialize(&mut *self.de)
    }
}

impl<'de, 'a, R: 'a + Read> de::EnumAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;
    type Variant = Self;
    fn variant_seed<V: de::DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self)> {
        match self.de.parse()? {
            t @ ParseResult::Bytes(_) => {
                self.de.next = Some(t);
                Ok((seed.deserialize(&mut *self.de)?, self))
            }
            ParseResult::Map => Ok((seed.deserialize(&mut *self.de)?, self)),
            t @ _ => Err(Error::InvalidValue(format!("Expected bytes or map; got `{:?}`", t))),
        }
    }
}

#[derive(Debug, Eq, PartialEq)]
enum ParseResult {
    Int(i64),
    Bytes(Vec<u8>),
    /// list start
    List,
    /// map start
    Map,
    /// list or map end
    End,
}

#[derive(Debug)]
pub struct Deserializer<R: Read> {
    reader: R,
    next: Option<ParseResult>,
}

impl<'de, R: Read> Deserializer<R> {
    pub fn new(reader: R) -> Deserializer<R> {
        Deserializer {
            reader: reader,
            next: None,
        }
    }

    fn parse_int(&mut self) -> Result<i64> {
        let mut buf = [0; 1];
        let mut result = Vec::new();
        loop {
            if 1 != self.reader.read(&mut buf).map_err(Error::IoError)? {
                return Err(Error::EndOfStream);
            }
            match buf[0] {
                b'e' => {
                    let len_str =
                        String::from_utf8(result)
                            .map_err(|_| {
                                         Error::InvalidValue("Non UTF-8 integer encoding"
                                                                 .to_string())
                                     })?;
                    let len_int = len_str
                        .parse()
                        .map_err(|_| {
                                     Error::InvalidValue(format!("Can't parse `{}` as integer",
                                                                 len_str))
                                 })?;
                    return Ok(len_int);
                }
                n => result.push(n),
            }
        }
    }

    fn parse_bytes_len(&mut self, len_char: u8) -> Result<usize> {
        let mut buf = [0; 1];
        let mut len = Vec::new();
        len.push(len_char);
        loop {
            if 1 != self.reader.read(&mut buf).map_err(Error::IoError)? {
                return Err(Error::EndOfStream);
            }
            match buf[0] {
                b':' => {
                    let len_str =
                        String::from_utf8(len)
                            .map_err(|_| {
                                         Error::InvalidValue("Non UTF-8 integer encoding"
                                                                 .to_string())
                                     })?;
                    let len_int = len_str.parse()
                        .map_err(|_| Error::InvalidValue(format!("Can't parse `{}` as string length", len_str)))?;
                    return Ok(len_int);
                }
                n => len.push(n),
            }
        }
    }

    fn parse_bytes(&mut self, len_char: u8) -> Result<Vec<u8>> {
        let len = self.parse_bytes_len(len_char)?;
        let mut buf = vec![0u8; len];
        let actual_len = self.reader
            .read(buf.as_mut_slice())
            .map_err(Error::IoError)?;
        if len != actual_len {
            return Err(Error::EndOfStream);
        }
        Ok(buf)
    }

    fn parse(&mut self) -> Result<ParseResult> {
        let mut buf = [0; 1];
        if 1 != self.reader.read(&mut buf).map_err(Error::IoError)? {
            return Err(Error::EndOfStream);
        }
        match buf[0] {
            b'i' => Ok(ParseResult::Int(self.parse_int()?)),
            n @ b'0'...b'9' => Ok(ParseResult::Bytes(self.parse_bytes(n)?)),
            b'l' => Ok(ParseResult::List),
            b'd' => Ok(ParseResult::Map),
            b'e' => Ok(ParseResult::End),
            c @ _ => Err(Error::InvalidValue(format!("Invalid charackter `{}`", c as char))),
        }
    }
}

impl<'de, 'a, R: Read> de::Deserializer<'de> for &'a mut Deserializer<R> {
    type Error = Error;

    #[inline]
    fn deserialize_any<V: de::Visitor<'de>>(mut self, visitor: V) -> Result<V::Value> {
        let parser_res = match self.next.take() {
            Some(v) => v,
            None => self.parse()?,
        };
        match parser_res {
            ParseResult::Int(i) => visitor.visit_i64(i),
            ParseResult::Bytes(s) => visitor.visit_bytes(s.as_ref()),
            ParseResult::List => visitor.visit_seq(BencodeAccess::new(&mut self)),
            ParseResult::Map => visitor.visit_map(BencodeAccess::new(&mut self)),
            ParseResult::End => Err(Error::EndOfStream),
        }
    }

    forward_to_deserialize_any! {
        i64 string seq bool i8 i16 i32 u8 u16 u32
        u64 f32 f64 char str unit bytes byte_buf map unit_struct tuple_struct tuple
        newtype_struct ignored_any identifier struct
    }

    #[inline]
    fn deserialize_option<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_some(self)
    }

    #[inline]
    fn deserialize_enum<V>(self,
                           _name: &str,
                           _variants: &'static [&'static str],
                           visitor: V)
                           -> Result<V::Value>
        where V: de::Visitor<'de>
    {
        visitor.visit_enum(BencodeAccess::new(self))
    }
}

pub fn from_str<'de, T>(s: &'de str) -> Result<T>
    where T: de::Deserialize<'de>
{
    from_bytes(s.as_bytes())
}

pub fn from_bytes<'de, T>(b: &'de [u8]) -> Result<T>
    where T: de::Deserialize<'de>
{
    de::Deserialize::deserialize(&mut Deserializer::new(b))
}
<commit_msg>fix typo<commit_after>use std::io::Read;
use std::str;
use serde::de;
use error::{Error, Result};

pub struct BencodeAccess<'a, R: 'a + Read> {
    de: &'a mut Deserializer<R>,
}

impl<'a, R: 'a + Read> BencodeAccess<'a, R> {
    fn new(de: &'a mut Deserializer<R>) -> BencodeAccess<'a, R> {
        BencodeAccess { de: de }
    }
}

impl<'de, 'a, R: 'a + Read> de::VariantAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;

    fn unit_variant(self) -> Result<()> {
        Ok(())
    }

    fn newtype_variant_seed<T: de::DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value> {
        let res = seed.deserialize(&mut *self.de)?;
        if ParseResult::End != self.de.parse()? {
            return Err(Error::InvalidType("expected `d`".to_string()));
        }
        Ok(res)
    }

    fn tuple_variant<V: de::Visitor<'de>>(self, _: usize, visitor: V) -> Result<V::Value> {
        let res = de::Deserializer::deserialize_any(&mut *self.de, visitor)?;
        if ParseResult::End != self.de.parse()? {
            return Err(Error::InvalidType("expected `d`".to_string()));
        }
        Ok(res)
    }

    fn struct_variant<V: de::Visitor<'de>>(self,
                                           _: &'static [&'static str],
                                           visitor: V)
                                           -> Result<V::Value> {
        let res = de::Deserializer::deserialize_any(&mut *self.de, visitor)?;
        if ParseResult::End != self.de.parse()? {
            return Err(Error::InvalidType("expected `d`".to_string()));
        }
        Ok(res)
    }
}

impl<'de, 'a, R: 'a + Read> de::SeqAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;

    fn next_element_seed<T: de::DeserializeSeed<'de>>(&mut self,
                                                      seed: T)
                                                      -> Result<Option<T::Value>> {
        match self.de.parse()? {
            ParseResult::End => Ok(None),
            r @ _ => {
                self.de.next = Some(r);
                Ok(Some(seed.deserialize(&mut *self.de)?))
            }
        }
    }
}

impl<'de, 'a, R: 'a + Read> de::MapAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;
    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
        where K: de::DeserializeSeed<'de>
    {
        match self.de.parse()? {
            ParseResult::End => Ok(None),
            r @ _ => {
                self.de.next = Some(r);
                Ok(Some(seed.deserialize(&mut *self.de)?))
            }
        }
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
        where V: de::DeserializeSeed<'de>
    {
        seed.deserialize(&mut *self.de)
    }
}

impl<'de, 'a, R: 'a + Read> de::EnumAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;
    type Variant = Self;
    fn variant_seed<V: de::DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self)> {
        match self.de.parse()? {
            t @ ParseResult::Bytes(_) => {
                self.de.next = Some(t);
                Ok((seed.deserialize(&mut *self.de)?, self))
            }
            ParseResult::Map => Ok((seed.deserialize(&mut *self.de)?, self)),
            t @ _ => Err(Error::InvalidValue(format!("Expected bytes or map; got `{:?}`", t))),
        }
    }
}

#[derive(Debug, Eq, PartialEq)]
enum ParseResult {
    Int(i64),
    Bytes(Vec<u8>),
    /// list start
    List,
    /// map start
    Map,
    /// list or map end
    End,
}

#[derive(Debug)]
pub struct Deserializer<R: Read> {
    reader: R,
    next: Option<ParseResult>,
}

impl<'de, R: Read> Deserializer<R> {
    pub fn new(reader: R) -> Deserializer<R> {
        Deserializer {
            reader: reader,
            next: None,
        }
    }

    fn parse_int(&mut self) -> Result<i64> {
        let mut buf = [0; 1];
        let mut result = Vec::new();
        loop {
            if 1 != self.reader.read(&mut buf).map_err(Error::IoError)? {
                return Err(Error::EndOfStream);
            }
            match buf[0] {
                b'e' => {
                    let len_str =
                        String::from_utf8(result)
                            .map_err(|_| {
                                         Error::InvalidValue("Non UTF-8 integer encoding"
                                                                 .to_string())
                                     })?;
                    let len_int = len_str
                        .parse()
                        .map_err(|_| {
                                     Error::InvalidValue(format!("Can't parse `{}` as integer",
                                                                 len_str))
                                 })?;
                    return Ok(len_int);
                }
                n => result.push(n),
            }
        }
    }

    fn parse_bytes_len(&mut self, len_char: u8) -> Result<usize> {
        let mut buf = [0; 1];
        let mut len = Vec::new();
        len.push(len_char);
        loop {
            if 1 != self.reader.read(&mut buf).map_err(Error::IoError)? {
                return Err(Error::EndOfStream);
            }
            match buf[0] {
                b':' => {
                    let len_str =
                        String::from_utf8(len)
                            .map_err(|_| {
                                         Error::InvalidValue("Non UTF-8 integer encoding"
                                                                 .to_string())
                                     })?;
                    let len_int = len_str.parse()
                        .map_err(|_| Error::InvalidValue(format!("Can't parse `{}` as string length", len_str)))?;
                    return Ok(len_int);
                }
                n => len.push(n),
            }
        }
    }

    fn parse_bytes(&mut self, len_char: u8) -> Result<Vec<u8>> {
        let len = self.parse_bytes_len(len_char)?;
        let mut buf = vec![0u8; len];
        let actual_len = self.reader
            .read(buf.as_mut_slice())
            .map_err(Error::IoError)?;
        if len != actual_len {
            return Err(Error::EndOfStream);
        }
        Ok(buf)
    }

    fn parse(&mut self) -> Result<ParseResult> {
        let mut buf = [0; 1];
        if 1 != self.reader.read(&mut buf).map_err(Error::IoError)? {
            return Err(Error::EndOfStream);
        }
        match buf[0] {
            b'i' => Ok(ParseResult::Int(self.parse_int()?)),
            n @ b'0'...b'9' => Ok(ParseResult::Bytes(self.parse_bytes(n)?)),
            b'l' => Ok(ParseResult::List),
            b'd' => Ok(ParseResult::Map),
            b'e' => Ok(ParseResult::End),
            c @ _ => Err(Error::InvalidValue(format!("Invalid character `{}`", c as char))),
        }
    }
}

impl<'de, 'a, R: Read> de::Deserializer<'de> for &'a mut Deserializer<R> {
    type Error = Error;

    #[inline]
    fn deserialize_any<V: de::Visitor<'de>>(mut self, visitor: V) -> Result<V::Value> {
        let parser_res = match self.next.take() {
            Some(v) => v,
            None => self.parse()?,
        };
        match parser_res {
            ParseResult::Int(i) => visitor.visit_i64(i),
            ParseResult::Bytes(s) => visitor.visit_bytes(s.as_ref()),
            ParseResult::List => visitor.visit_seq(BencodeAccess::new(&mut self)),
            ParseResult::Map => visitor.visit_map(BencodeAccess::new(&mut self)),
            ParseResult::End => Err(Error::EndOfStream),
        }
    }

    forward_to_deserialize_any! {
        i64 string seq bool i8 i16 i32 u8 u16 u32
        u64 f32 f64 char str unit bytes byte_buf map unit_struct tuple_struct tuple
        newtype_struct ignored_any identifier struct
    }

    #[inline]
    fn deserialize_option<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_some(self)
    }

    #[inline]
    fn deserialize_enum<V>(self,
                           _name: &str,
                           _variants: &'static [&'static str],
                           visitor: V)
                           -> Result<V::Value>
        where V: de::Visitor<'de>
    {
        visitor.visit_enum(BencodeAccess::new(self))
    }
}

pub fn from_str<'de, T>(s: &'de str) -> Result<T>
    where T: de::Deserialize<'de>
{
    from_bytes(s.as_bytes())
}

pub fn from_bytes<'de, T>(b: &'de [u8]) -> Result<T>
    where T: de::Deserialize<'de>
{
    de::Deserialize::deserialize(&mut Deserializer::new(b))
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::str;
use serde::de;
use error::{Error, Result};

pub struct BencodeAccess<'a, R: 'a + Read> {
    de: &'a mut Deserializer<R>,
}

impl<'a, R: 'a + Read> BencodeAccess<'a, R> {
    fn new(de: &'a mut Deserializer<R>) -> BencodeAccess<'a, R> {
        BencodeAccess { de: de }
    }
}

impl<'de, 'a, R: 'a + Read> de::VariantAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;

    fn unit_variant(self) -> Result<()> {
        Ok(())
    }

    fn newtype_variant_seed<T: de::DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value> {
        let res = seed.deserialize(&mut *self.de)?;
        if ParseResult::End != self.de.parse()? {
            return Err(Error::InvalidType("expected `d`".to_string()));
        }
        Ok(res)
    }

    fn tuple_variant<V: de::Visitor<'de>>(self, _: usize, visitor: V) -> Result<V::Value> {
        let res = de::Deserializer::deserialize_any(&mut *self.de, visitor)?;
        if ParseResult::End != self.de.parse()? {
            return Err(Error::InvalidType("expected `d`".to_string()));
        }
        Ok(res)
    }

    fn struct_variant<V: de::Visitor<'de>>(self,
                                           _: &'static [&'static str],
                                           visitor: V)
                                           -> Result<V::Value> {
        let res = de::Deserializer::deserialize_any(&mut *self.de, visitor)?;
        if ParseResult::End != self.de.parse()? {
            return Err(Error::InvalidType("expected `d`".to_string()));
        }
        Ok(res)
    }
}

impl<'de, 'a, R: 'a + Read> de::SeqAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;

    fn next_element_seed<T: de::DeserializeSeed<'de>>(&mut self,
                                                      seed: T)
                                                      -> Result<Option<T::Value>> {
        match self.de.parse()? {
            ParseResult::End => Ok(None),
            r @ _ => {
                self.de.next = Some(r);
                Ok(Some(seed.deserialize(&mut *self.de)?))
            }
        }
    }
}

impl<'de, 'a, R: 'a + Read> de::MapAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;
    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
        where K: de::DeserializeSeed<'de>
    {
        match self.de.parse()? {
            ParseResult::End => Ok(None),
            r @ _ => {
                self.de.next = Some(r);
                Ok(Some(seed.deserialize(&mut *self.de)?))
            }
        }
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
        where V: de::DeserializeSeed<'de>
    {
        seed.deserialize(&mut *self.de)
    }
}

impl<'de, 'a, R: 'a + Read> de::EnumAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;
    type Variant = Self;
    fn variant_seed<V: de::DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self)> {
        match self.de.parse()? {
            t @ ParseResult::Bytes(_) => {
                self.de.next = Some(t);
                Ok((seed.deserialize(&mut *self.de)?, self))
            }
            ParseResult::Map => Ok((seed.deserialize(&mut *self.de)?, self)),
            t @ _ => Err(Error::InvalidValue(format!("Expected bytes or map; got `{:?}`", t))),
        }
    }
}

#[derive(Debug, Eq, PartialEq)]
enum ParseResult {
    Int(i64),
    Bytes(Vec<u8>),
    /// list start
    List,
    /// map start
    Map,
    /// list or map end
    End,
}

#[derive(Debug)]
pub struct Deserializer<R: Read> {
    reader: R,
    next: Option<ParseResult>,
}

impl<'de, R: Read> Deserializer<R> {
    pub fn new(reader: R) -> Deserializer<R> {
        Deserializer {
            reader: reader,
            next: None,
        }
    }

    fn parse_int(&mut self) -> Result<i64> {
        let mut buf = [0; 1];
        let mut result = Vec::new();
        loop {
            if 1 != self.reader.read(&mut buf).map_err(Error::IoError)? {
                return Err(Error::EndOfStream);
            }
            match buf[0] {
                b'e' => {
                    let len_str =
                        String::from_utf8(result)
                            .map_err(|_| {
                                         Error::InvalidValue("Non UTF-8 integer encoding"
                                                                 .to_string())
                                     })?;
                    let len_int = len_str
                        .parse()
                        .map_err(|_| {
                                     Error::InvalidValue(format!("Can't parse `{}` as integer",
                                                                 len_str))
                                 })?;
                    return Ok(len_int);
                }
                n => result.push(n),
            }
        }
    }

    fn parse_bytes_len(&mut self, len_char: u8) -> Result<usize> {
        let mut buf = [0; 1];
        let mut len = Vec::new();
        len.push(len_char);
        loop {
            if 1 != self.reader.read(&mut buf).map_err(Error::IoError)? {
                return Err(Error::EndOfStream);
            }
            match buf[0] {
                b':' => {
                    let len_str =
                        String::from_utf8(len)
                            .map_err(|_| {
                                         Error::InvalidValue("Non UTF-8 integer encoding"
                                                                 .to_string())
                                     })?;
                    let len_int = len_str.parse()
                        .map_err(|_| Error::InvalidValue(format!("Can't parse `{}` as string length", len_str)))?;
                    return Ok(len_int);
                }
                n => len.push(n),
            }
        }
    }

    fn parse_bytes(&mut self, len_char: u8) -> Result<Vec<u8>> {
        let len = self.parse_bytes_len(len_char)?;
        let mut buf = vec![0u8; len];
        let actual_len = self.reader
            .read(buf.as_mut_slice())
            .map_err(Error::IoError)?;
        if len != actual_len {
            return Err(Error::EndOfStream);
        }
        Ok(buf)
    }

    fn parse(&mut self) -> Result<ParseResult> {
        let mut buf = [0; 1];
        if 1 != self.reader.read(&mut buf).map_err(Error::IoError)? {
            return Err(Error::EndOfStream);
        }
        match buf[0] {
            b'i' => Ok(ParseResult::Int(self.parse_int()?)),
            n @ b'0'...b'9' => Ok(ParseResult::Bytes(self.parse_bytes(n)?)),
            b'l' => Ok(ParseResult::List),
            b'd' => Ok(ParseResult::Map),
            b'e' => Ok(ParseResult::End),
            c @ _ => Err(Error::InvalidValue(format!("Invalid character `{}`", c as char))),
        }
    }
}

impl<'de, 'a, R: Read> de::Deserializer<'de> for &'a mut Deserializer<R> {
    type Error = Error;

    #[inline]
    fn deserialize_any<V: de::Visitor<'de>>(mut self, visitor: V) -> Result<V::Value> {
        let parser_res = match self.next.take() {
            Some(v) => v,
            None => self.parse()?,
        };
        match parser_res {
            ParseResult::Int(i) => visitor.visit_i64(i),
            ParseResult::Bytes(s) => visitor.visit_bytes(s.as_ref()),
            ParseResult::List => visitor.visit_seq(BencodeAccess::new(&mut self)),
            ParseResult::Map => visitor.visit_map(BencodeAccess::new(&mut self)),
            ParseResult::End => Err(Error::EndOfStream),
        }
    }

    forward_to_deserialize_any! {
        i64 string seq bool i8 i16 i32 u8 u16 u32
        u64 f32 f64 char str unit bytes byte_buf map unit_struct tuple_struct tuple
        newtype_struct ignored_any identifier struct
    }

    #[inline]
    fn deserialize_option<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_some(self)
    }

    #[inline]
    fn deserialize_enum<V>(self,
                           _name: &str,
                           _variants: &'static [&'static str],
                           visitor: V)
                           -> Result<V::Value>
        where V: de::Visitor<'de>
    {
        visitor.visit_enum(BencodeAccess::new(self))
    }
}

pub fn from_str<'de, T>(s: &'de str) -> Result<T>
    where T: de::Deserialize<'de>
{
    from_bytes(s.as_bytes())
}

pub fn from_bytes<'de, T>(b: &'de [u8]) -> Result<T>
    where T: de::Deserialize<'de>
{
    de::Deserialize::deserialize(&mut Deserializer::new(b))
}
<commit_msg>fix variants<commit_after>use std::io::Read;
use std::str;
use serde::de;
use error::{Error, Result};

pub struct BencodeAccess<'a, R: 'a + Read> {
    de: &'a mut Deserializer<R>,
    len: Option<usize>,
}

impl<'a, R: 'a + Read> BencodeAccess<'a, R> {
    fn new(de: &'a mut Deserializer<R>, len: Option<usize>) -> BencodeAccess<'a, R> {
        BencodeAccess { de: de, len: len }
    }
}

impl<'de, 'a, R: 'a + Read> de::SeqAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;

    fn next_element_seed<T: de::DeserializeSeed<'de>>(&mut self,
                                                      seed: T)
                                                      -> Result<Option<T::Value>> {
        let res = match self.de.parse()? {
            ParseResult::End => Ok(None),
            r @ _ => {
                self.de.next = Some(r);
                Ok(Some(seed.deserialize(&mut *self.de)?))
            }
        };
        match self.len {
            Some(l) => {
                let l = l - 1;
                self.len = Some(l);
                if l == 0 && ParseResult::End != self.de.parse()? {
                    return Err(Error::InvalidType("expected `e`".to_string()));
                }
            }
            None => (),
        }
        res
    }
}

impl<'de, 'a, R: 'a + Read> de::MapAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;
    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
        where K: de::DeserializeSeed<'de>
    {
        match self.de.parse()? {
            ParseResult::End => Ok(None),
            r @ _ => {
                self.de.next = Some(r);
                Ok(Some(seed.deserialize(&mut *self.de)?))
            }
        }
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
        where V: de::DeserializeSeed<'de>
    {
        seed.deserialize(&mut *self.de)
    }
}

impl<'de, 'a, R: 'a + Read> de::VariantAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;

    fn unit_variant(self) -> Result<()> {
        Ok(())
    }

    fn newtype_variant_seed<T: de::DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value> {
        let res = seed.deserialize(&mut *self.de)?;
        if ParseResult::End != self.de.parse()? {
            return Err(Error::InvalidType("expected `e`".to_string()));
        }
        Ok(res)
    }

    fn tuple_variant<V: de::Visitor<'de>>(self, len: usize, visitor: V) -> Result<V::Value> {
        let res = match self.de.parse()? {
            ParseResult::List => {
                visitor
                    .visit_seq(BencodeAccess::new(&mut *self.de, Some(len)))?
            }
            _ => return Err(Error::InvalidType("expected list".to_string())),
        };
        if ParseResult::End != self.de.parse()? {
            return Err(Error::InvalidType("expected `e`".to_string()));
        }
        Ok(res)
    }

    fn struct_variant<V: de::Visitor<'de>>(self,
                                           _: &'static [&'static str],
                                           visitor: V)
                                           -> Result<V::Value> {
        let res = de::Deserializer::deserialize_any(&mut *self.de, visitor)?;
        if ParseResult::End != self.de.parse()? {
            return Err(Error::InvalidType("expected `e`".to_string()));
        }
        Ok(res)
    }
}

impl<'de, 'a, R: 'a + Read> de::EnumAccess<'de> for BencodeAccess<'a, R> {
    type Error = Error;
    type Variant = Self;
    fn variant_seed<V: de::DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self)> {
        match self.de.parse()? {
            t @ ParseResult::Bytes(_) => {
                self.de.next = Some(t);
                Ok((seed.deserialize(&mut *self.de)?, self))
            }
            ParseResult::Map => Ok((seed.deserialize(&mut *self.de)?, self)),
            t @ _ => Err(Error::InvalidValue(format!("Expected bytes or map; got `{:?}`", t))),
        }
    }
}

#[derive(Debug, Eq, PartialEq)]
enum ParseResult {
    Int(i64),
    Bytes(Vec<u8>),
    /// list start
    List,
    /// map start
    Map,
    /// list or map end
    End,
}

#[derive(Debug)]
pub struct Deserializer<R: Read> {
    reader: R,
    next: Option<ParseResult>,
}

impl<'de, R: Read> Deserializer<R> {
    pub fn new(reader: R) -> Deserializer<R> {
        Deserializer {
            reader: reader,
            next: None,
        }
    }

    fn parse_int(&mut self) -> Result<i64> {
        let mut buf = [0; 1];
        let mut result = Vec::new();
        loop {
            if 1 != self.reader.read(&mut buf).map_err(Error::IoError)? {
                return Err(Error::EndOfStream);
            }
            match buf[0] {
                b'e' => {
                    let len_str =
                        String::from_utf8(result)
                            .map_err(|_| {
                                         Error::InvalidValue("Non UTF-8 integer encoding"
                                                                 .to_string())
                                     })?;
                    let len_int = len_str
                        .parse()
                        .map_err(|_| {
                                     Error::InvalidValue(format!("Can't parse `{}` as integer",
                                                                 len_str))
                                 })?;
                    return Ok(len_int);
                }
                n => result.push(n),
            }
        }
    }

    fn parse_bytes_len(&mut self, len_char: u8) -> Result<usize> {
        let mut buf = [0; 1];
        let mut len = Vec::new();
        len.push(len_char);
        loop {
            if 1 != self.reader.read(&mut buf).map_err(Error::IoError)? {
                return Err(Error::EndOfStream);
            }
            match buf[0] {
                b':' => {
                    let len_str =
                        String::from_utf8(len)
                            .map_err(|_| {
                                         Error::InvalidValue("Non UTF-8 integer encoding"
                                                                 .to_string())
                                     })?;
                    let len_int = len_str.parse()
                        .map_err(|_| Error::InvalidValue(format!("Can't parse `{}` as string length", len_str)))?;
                    return Ok(len_int);
                }
                n => len.push(n),
            }
        }
    }

    fn parse_bytes(&mut self, len_char: u8) -> Result<Vec<u8>> {
        let len = self.parse_bytes_len(len_char)?;
        let mut buf = vec![0u8; len];
        let actual_len = self.reader
            .read(buf.as_mut_slice())
            .map_err(Error::IoError)?;
        if len != actual_len {
            return Err(Error::EndOfStream);
        }
        Ok(buf)
    }

    fn parse(&mut self) -> Result<ParseResult> {
        if let Some(t) = self.next.take() {
            return Ok(t);
        }
        let mut buf = [0; 1];
        if 1 != self.reader.read(&mut buf).map_err(Error::IoError)? {
            return Err(Error::EndOfStream);
        }
        match buf[0] {
            b'i' => Ok(ParseResult::Int(self.parse_int()?)),
            n @ b'0'...b'9' => Ok(ParseResult::Bytes(self.parse_bytes(n)?)),
            b'l' => Ok(ParseResult::List),
            b'd' => Ok(ParseResult::Map),
            b'e' => Ok(ParseResult::End),
            c @ _ => Err(Error::InvalidValue(format!("Invalid character `{}`", c as char))),
        }
    }
}

impl<'de, 'a, R: Read> de::Deserializer<'de> for &'a mut Deserializer<R> {
    type Error = Error;

    #[inline]
    fn deserialize_any<V: de::Visitor<'de>>(mut self, visitor: V) -> Result<V::Value> {
        match self.parse()? {
            ParseResult::Int(i) => visitor.visit_i64(i),
            ParseResult::Bytes(s) => visitor.visit_bytes(s.as_ref()),
            ParseResult::List => visitor.visit_seq(BencodeAccess::new(&mut self, None)),
            ParseResult::Map => visitor.visit_map(BencodeAccess::new(&mut self, None)),
            ParseResult::End => Err(Error::EndOfStream),
        }
    }

    forward_to_deserialize_any! {
        i64 string seq bool i8 i16 i32 u8 u16 u32
        u64 f32 f64 char str unit bytes byte_buf map unit_struct tuple_struct tuple
        newtype_struct ignored_any identifier struct
    }

    #[inline]
    fn deserialize_option<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
        visitor.visit_some(self)
    }

    #[inline]
    fn deserialize_enum<V>(self,
                           _name: &str,
                           _variants: &'static [&'static str],
                           visitor: V)
                           -> Result<V::Value>
        where V: de::Visitor<'de>
    {
        visitor.visit_enum(BencodeAccess::new(self, None))
    }
}

pub fn from_str<'de, T>(s: &'de str) -> Result<T>
    where T: de::Deserialize<'de>
{
    from_bytes(s.as_bytes())
}

pub fn from_bytes<'de, T>(b: &'de [u8]) -> Result<T>
    where T: de::Deserialize<'de>
{
    de::Deserialize::deserialize(&mut Deserializer::new(b))
}
<|endoftext|>