<commit_before>// `impl Trait` is not required for this parser but we use to to show that it can be used to
// significantly simplify things

#![cfg(feature = "std")]

#[macro_use]
extern crate criterion;

#[macro_use]
extern crate combine;

use std::{collections::HashMap, fs::File, io::Read, path::Path};

use {
    combine::{
        error::{Commit, ParseError},
        parser::{
            char::{char, digit, spaces, string},
            choice::{choice, optional},
            function::parser,
            repeat::{many, many1, sep_by},
            sequence::between,
            token::{any, satisfy, satisfy_map},
        },
        stream::{
            buffered,
            position::{self, SourcePosition},
            IteratorStream,
        },
        EasyParser, Parser, Stream, StreamOnce,
    },
    criterion::{black_box, Bencher, Criterion},
};

#[derive(PartialEq, Debug)]
enum Value {
    Number(f64),
    String(String),
    Bool(bool),
    Null,
    Object(HashMap<String, Value>),
    Array(Vec<Value>),
}

fn lex<Input, P>(p: P) -> impl Parser<Input, Output = P::Output>
where
    P: Parser<Input>,
    Input: Stream<Token = char>,
    <Input as StreamOnce>::Error: ParseError<
        <Input as StreamOnce>::Token,
        <Input as StreamOnce>::Range,
        <Input as StreamOnce>::Position,
    >,
{
    p.skip(spaces())
}

fn integer<Input>() -> impl Parser<Input, Output = i64>
where
    Input: Stream<Token = char>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    lex(many1(digit()))
        .map(|s: String| {
            let mut n = 0;
            for c in s.chars() {
                n = n * 10 + (c as i64 - '0' as i64);
            }
            n
        })
        .expected("integer")
}

fn number<Input>() -> impl Parser<Input, Output = f64>
where
    Input: Stream<Token = char>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    let i = char('0').map(|_| 0.0).or(integer().map(|x| x as f64));
    let fractional = many(digit()).map(|digits: String| {
        let mut magnitude = 1.0;
        digits.chars().fold(0.0, |acc, d| {
            magnitude /= 10.0;
            match d.to_digit(10) {
                Some(d) => acc + (d as f64) * magnitude,
                None => panic!("Not a digit"),
            }
        })
    });

    let exp = satisfy(|c| c == 'e' || c == 'E').with(optional(char('-')).and(integer()));
    lex(optional(char('-'))
        .and(i)
        .map(|(sign, n)| if sign.is_some() { -n } else { n })
        .and(optional(char('.')).with(fractional))
        .map(|(x, y)| if x >= 0.0 { x + y } else { x - y })
        .and(optional(exp))
        .map(|(n, exp_option)| match exp_option {
            Some((sign, e)) => {
                let e = if sign.is_some() { -e } else { e };
                n * 10.0f64.powi(e as i32)
            }
            None => n,
        }))
    .expected("number")
}

fn json_char<Input>() -> impl Parser<Input, Output = char>
where
    Input: Stream<Token = char>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    parser(|input: &mut Input| {
        let (c, committed) = any().parse_lazy(input).into_result()?;
        let mut back_slash_char = satisfy_map(|c| {
            Some(match c {
                '"' => '"',
                '\\' => '\\',
                '/' => '/',
                'b' => '\u{0008}',
                'f' => '\u{000c}',
                'n' => '\n',
                'r' => '\r',
                't' => '\t',
                _ => return None,
            })
        });
        match c {
            '\\' => committed.combine(|_| back_slash_char.parse_stream(input).into_result()),
            '"' => Err(Commit::Peek(Input::Error::empty(input.position()).into())),
            _ => Ok((c, committed)),
        }
    })
}

fn json_string<Input>() -> impl Parser<Input, Output = String>
where
    Input: Stream<Token = char>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    between(char('"'), lex(char('"')), many(json_char())).expected("string")
}

fn object<Input>() -> impl Parser<Input, Output = Value>
where
    Input: Stream<Token = char>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    let field = (json_string(), lex(char(':')), json_value()).map(|t| (t.0, t.2));
    let fields = sep_by(field, lex(char(',')));
    between(lex(char('{')), lex(char('}')), fields)
        .map(Value::Object)
        .expected("object")
}

#[inline]
fn json_value<Input>() -> impl Parser<Input, Output = Value>
where
    Input: Stream<Token = char>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    json_value_()
}

// We need to use `parser!` to break the recursive use of `value` to prevent the returned parser
// from containing itself
parser! {
    #[inline]
    fn json_value_[Input]()(Input) -> Value
        where [ Input: Stream<Token = char> ]
    {
        let array = between(
            lex(char('[')),
            lex(char(']')),
            sep_by(json_value(), lex(char(','))),
        ).map(Value::Array);

        choice((
            json_string().map(Value::String),
            object(),
            array,
            number().map(Value::Number),
            lex(string("false").map(|_| Value::Bool(false))),
            lex(string("true").map(|_| Value::Bool(true))),
            lex(string("null").map(|_| Value::Null)),
        ))
    }
}

#[test]
fn json_test() {
    use self::Value::*;

    let input = r#"{
    "array": [1, ""],
    "object": {},
    "number": 3.14,
    "small_number": 0.59,
    "int": -100,
    "exp": -1e2,
    "exp_neg": 23e-2,
    "true": true,
    "false"  : false,
    "null" : null
}"#;
    let result = json_value().easy_parse(input);
    let expected = Object(
        vec![
            ("array", Array(vec![Number(1.0), String("".to_string())])),
            ("object", Object(HashMap::new())),
            ("number", Number(3.14)),
            ("small_number", Number(0.59)),
            ("int", Number(-100.)),
            ("exp", Number(-1e2)),
            ("exp_neg", Number(23E-2)),
            ("true", Bool(true)),
            ("false", Bool(false)),
            ("null", Null),
        ]
        .into_iter()
        .map(|(k, v)| (k.to_string(), v))
        .collect(),
    );
    match result {
        Ok(result) => assert_eq!(result, (expected, "")),
        Err(e) => {
            println!("{}", e);
            panic!();
        }
    }
}

fn test_data() -> String {
    let mut data = String::new();
    File::open(&Path::new(&"benches/data.json"))
        .and_then(|mut file| file.read_to_string(&mut data))
        .unwrap();
    data
}

fn bench_json(bencher: &mut Bencher<'_>) {
    let data = test_data();
    let mut parser = json_value();
    match parser.easy_parse(position::Stream::new(&data[..])) {
        Ok((Value::Array(_), _)) => (),
        Ok(_) => panic!(),
        Err(err) => {
            println!("{}", err);
            panic!();
        }
    }
    bencher.iter(|| {
        let result = parser.easy_parse(position::Stream::new(&data[..]));
        black_box(result)
    });
}

fn bench_json_core_error(bencher: &mut Bencher<'_>) {
    let data = test_data();
    let mut parser = json_value();
    match parser.parse(position::Stream::new(&data[..])) {
        Ok((Value::Array(_), _)) => (),
        Ok(_) => panic!(),
        Err(err) => {
            println!("{}", err);
            panic!();
        }
    }
    bencher.iter(|| {
        let result = parser.parse(position::Stream::new(&data[..]));
        black_box(result)
    });
}

fn bench_json_core_error_no_position(bencher: &mut Bencher<'_>) {
    let data = test_data();
    let mut parser = json_value();
    match parser.parse(&data[..]) {
        Ok((Value::Array(_), _)) => (),
        Ok(_) => panic!(),
        Err(err) => {
            println!("{}", err);
            panic!();
        }
    }
    bencher.iter(|| {
        let result = parser.parse(&data[..]);
        black_box(result)
    });
}

fn bench_buffered_json(bencher: &mut Bencher<'_>) {
    let data = test_data();
    bencher.iter(|| {
        let buffer =
            buffered::Stream::new(position::Stream::new(IteratorStream::new(data.chars())), 1);
        let mut parser = json_value();
        match parser.easy_parse(position::Stream::with_positioner(
            buffer,
            SourcePosition::default(),
        )) {
            Ok((Value::Array(v), _)) => {
                black_box(v);
            }
            Ok(_) => panic!(),
            Err(err) => {
                println!("{}", err);
                panic!();
            }
        }
    });
}

fn bench(c: &mut Criterion) {
    c.bench_function("json", bench_json);
    c.bench_function("json_core_error", bench_json_core_error);
    c.bench_function(
        "json_core_error_no_position",
        bench_json_core_error_no_position,
    );
    c.bench_function("buffered_json", bench_buffered_json);
}

criterion_group!(json, bench);
criterion_main!(json);
<commit_msg>chore: Remove outdated comment<commit_after>#![cfg(feature = "std")]

#[macro_use]
extern crate criterion;

#[macro_use]
extern crate combine;

use std::{collections::HashMap, fs::File, io::Read, path::Path};

use {
    combine::{
        error::{Commit, ParseError},
        parser::{
            char::{char, digit, spaces, string},
            choice::{choice, optional},
            function::parser,
            repeat::{many, many1, sep_by},
            sequence::between,
            token::{any, satisfy, satisfy_map},
        },
        stream::{
            buffered,
            position::{self, SourcePosition},
            IteratorStream,
        },
        EasyParser, Parser, Stream, StreamOnce,
    },
    criterion::{black_box, Bencher, Criterion},
};

#[derive(PartialEq, Debug)]
enum Value {
    Number(f64),
    String(String),
    Bool(bool),
    Null,
    Object(HashMap<String, Value>),
    Array(Vec<Value>),
}

fn lex<Input, P>(p: P) -> impl Parser<Input, Output = P::Output>
where
    P: Parser<Input>,
    Input: Stream<Token = char>,
    <Input as StreamOnce>::Error: ParseError<
        <Input as StreamOnce>::Token,
        <Input as StreamOnce>::Range,
        <Input as StreamOnce>::Position,
    >,
{
    p.skip(spaces())
}

fn integer<Input>() -> impl Parser<Input, Output = i64>
where
    Input: Stream<Token = char>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    lex(many1(digit()))
        .map(|s: String| {
            let mut n = 0;
            for c in s.chars() {
                n = n * 10 + (c as i64 - '0' as i64);
            }
            n
        })
        .expected("integer")
}

fn number<Input>() -> impl Parser<Input, Output = f64>
where
    Input: Stream<Token = char>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    let i = char('0').map(|_| 0.0).or(integer().map(|x| x as f64));
    let fractional = many(digit()).map(|digits: String| {
        let mut magnitude = 1.0;
        digits.chars().fold(0.0, |acc, d| {
            magnitude /= 10.0;
            match d.to_digit(10) {
                Some(d) => acc + (d as f64) * magnitude,
                None => panic!("Not a digit"),
            }
        })
    });

    let exp = satisfy(|c| c == 'e' || c == 'E').with(optional(char('-')).and(integer()));
    lex(optional(char('-'))
        .and(i)
        .map(|(sign, n)| if sign.is_some() { -n } else { n })
        .and(optional(char('.')).with(fractional))
        .map(|(x, y)| if x >= 0.0 { x + y } else { x - y })
        .and(optional(exp))
        .map(|(n, exp_option)| match exp_option {
            Some((sign, e)) => {
                let e = if sign.is_some() { -e } else { e };
                n * 10.0f64.powi(e as i32)
            }
            None => n,
        }))
    .expected("number")
}

fn json_char<Input>() -> impl Parser<Input, Output = char>
where
    Input: Stream<Token = char>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    parser(|input: &mut Input| {
        let (c, committed) = any().parse_lazy(input).into_result()?;
        let mut back_slash_char = satisfy_map(|c| {
            Some(match c {
                '"' => '"',
                '\\' => '\\',
                '/' => '/',
                'b' => '\u{0008}',
                'f' => '\u{000c}',
                'n' => '\n',
                'r' => '\r',
                't' => '\t',
                _ => return None,
            })
        });
        match c {
            '\\' => committed.combine(|_| back_slash_char.parse_stream(input).into_result()),
            '"' => Err(Commit::Peek(Input::Error::empty(input.position()).into())),
            _ => Ok((c, committed)),
        }
    })
}

fn json_string<Input>() -> impl Parser<Input, Output = String>
where
    Input: Stream<Token = char>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    between(char('"'), lex(char('"')), many(json_char())).expected("string")
}

fn object<Input>() -> impl Parser<Input, Output = Value>
where
    Input: Stream<Token = char>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    let field = (json_string(), lex(char(':')), json_value()).map(|t| (t.0, t.2));
    let fields = sep_by(field, lex(char(',')));
    between(lex(char('{')), lex(char('}')), fields)
        .map(Value::Object)
        .expected("object")
}

#[inline]
fn json_value<Input>() -> impl Parser<Input, Output = Value>
where
    Input: Stream<Token = char>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    json_value_()
}

// We need to use `parser!` to break the recursive use of `value` to prevent the returned parser
// from containing itself
parser! {
    #[inline]
    fn json_value_[Input]()(Input) -> Value
        where [ Input: Stream<Token = char> ]
    {
        let array = between(
            lex(char('[')),
            lex(char(']')),
            sep_by(json_value(), lex(char(','))),
        ).map(Value::Array);

        choice((
            json_string().map(Value::String),
            object(),
            array,
            number().map(Value::Number),
            lex(string("false").map(|_| Value::Bool(false))),
            lex(string("true").map(|_| Value::Bool(true))),
            lex(string("null").map(|_| Value::Null)),
        ))
    }
}

#[test]
fn json_test() {
    use self::Value::*;

    let input = r#"{
    "array": [1, ""],
    "object": {},
    "number": 3.14,
    "small_number": 0.59,
    "int": -100,
    "exp": -1e2,
    "exp_neg": 23e-2,
    "true": true,
    "false"  : false,
    "null" : null
}"#;
    let result = json_value().easy_parse(input);
    let expected = Object(
        vec![
            ("array", Array(vec![Number(1.0), String("".to_string())])),
            ("object", Object(HashMap::new())),
            ("number", Number(3.14)),
            ("small_number", Number(0.59)),
            ("int", Number(-100.)),
            ("exp", Number(-1e2)),
            ("exp_neg", Number(23E-2)),
            ("true", Bool(true)),
            ("false", Bool(false)),
            ("null", Null),
        ]
        .into_iter()
        .map(|(k, v)| (k.to_string(), v))
        .collect(),
    );
    match result {
        Ok(result) => assert_eq!(result, (expected, "")),
        Err(e) => {
            println!("{}", e);
            panic!();
        }
    }
}

fn test_data() -> String {
    let mut data = String::new();
    File::open(&Path::new(&"benches/data.json"))
        .and_then(|mut file| file.read_to_string(&mut data))
        .unwrap();
    data
}

fn bench_json(bencher: &mut Bencher<'_>) {
    let data = test_data();
    let mut parser = json_value();
    match parser.easy_parse(position::Stream::new(&data[..])) {
        Ok((Value::Array(_), _)) => (),
        Ok(_) => panic!(),
        Err(err) => {
            println!("{}", err);
            panic!();
        }
    }
    bencher.iter(|| {
        let result = parser.easy_parse(position::Stream::new(&data[..]));
        black_box(result)
    });
}

fn bench_json_core_error(bencher: &mut Bencher<'_>) {
    let data = test_data();
    let mut parser = json_value();
    match parser.parse(position::Stream::new(&data[..])) {
        Ok((Value::Array(_), _)) => (),
        Ok(_) => panic!(),
        Err(err) => {
            println!("{}", err);
            panic!();
        }
    }
    bencher.iter(|| {
        let result = parser.parse(position::Stream::new(&data[..]));
        black_box(result)
    });
}

fn bench_json_core_error_no_position(bencher: &mut Bencher<'_>) {
    let data = test_data();
    let mut parser = json_value();
    match parser.parse(&data[..]) {
        Ok((Value::Array(_), _)) => (),
        Ok(_) => panic!(),
        Err(err) => {
            println!("{}", err);
            panic!();
        }
    }
    bencher.iter(|| {
        let result = parser.parse(&data[..]);
        black_box(result)
    });
}

fn bench_buffered_json(bencher: &mut Bencher<'_>) {
    let data = test_data();
    bencher.iter(|| {
        let buffer =
            buffered::Stream::new(position::Stream::new(IteratorStream::new(data.chars())), 1);
        let mut parser = json_value();
        match parser.easy_parse(position::Stream::with_positioner(
            buffer,
            SourcePosition::default(),
        )) {
            Ok((Value::Array(v), _)) => {
                black_box(v);
            }
            Ok(_) => panic!(),
            Err(err) => {
                println!("{}", err);
                panic!();
            }
        }
    });
}

fn bench(c: &mut Criterion) {
    c.bench_function("json", bench_json);
    c.bench_function("json_core_error", bench_json_core_error);
    c.bench_function(
        "json_core_error_no_position",
        bench_json_core_error_no_position,
    );
    c.bench_function("buffered_json", bench_buffered_json);
}

criterion_group!(json, bench);
criterion_main!(json);
<|endoftext|>


<commit_before>#![feature(test)]

#[cfg(feature = "enable_logging")]
extern crate env_logger;
extern crate lzma_rs;
extern crate test;

use std::io::Read;
use test::Bencher;

fn compress_bench(x: &[u8], b: &mut Bencher) {
    b.iter(|| {
        let mut compressed: Vec<u8> = Vec::new();
        lzma_rs::lzma_compress(&mut std::io::BufReader::new(x), &mut compressed).unwrap();
    });
}

fn decompress_after_compress_bench(x: &[u8], b: &mut Bencher) {
    let mut compressed: Vec<u8> = Vec::new();
    lzma_rs::lzma_compress(&mut std::io::BufReader::new(x), &mut compressed).unwrap();

    b.iter(|| {
        let mut bf = std::io::BufReader::new(compressed.as_slice());
        let mut decomp: Vec<u8> = Vec::new();
        lzma_rs::lzma_decompress(&mut bf, &mut decomp).unwrap();
    });
}

fn decompress_bench(compressed: &[u8], b: &mut Bencher) {
    b.iter(|| {
        let mut bf = std::io::BufReader::new(compressed);
        let mut decomp: Vec<u8> = Vec::new();
        lzma_rs::lzma_decompress(&mut bf, &mut decomp).unwrap();
    });
}

fn decompress_bench_file(compfile: &str, b: &mut Bencher) {
    let mut f = std::fs::File::open(compfile).unwrap();
    let mut compressed = Vec::new();
    f.read_to_end(&mut compressed).unwrap();
    decompress_bench(&compressed, b);
}

#[bench]
fn compress_empty(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    compress_bench(b"", b);
}

#[bench]
fn decompress_after_compress_empty(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    decompress_after_compress_bench(b"", b);
}

#[bench]
fn compress_hello(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    compress_bench(b"Hello world", b);
}

#[bench]
fn decompress_after_compress_hello(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    decompress_after_compress_bench(b"Hello world", b);
}

#[bench]
fn compress_65536(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    compress_bench(&[0; 0x10000], b);
}

#[bench]
fn decompress_after_compress_65536(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    decompress_after_compress_bench(&[0; 0x10000], b);
}

#[bench]
fn decompress_big_file(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    decompress_bench_file("tests/files/foo.txt.lzma", b);
}

#[bench]
fn decompress_huge_dict(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    let compressed: &[u8] = b"\x5d\x7f\x7f\x7f\x7f\xff\xff\xff\
                              \xff\xff\xff\xff\xff\x00\x24\x19\
                              \x49\x98\x6f\x10\x19\xc6\xd7\x31\
                              \xeb\x36\x50\xb2\x98\x48\xff\xfe\
                              \xa5\xb0\x00";
    decompress_bench(&compressed, b);
}
<commit_msg>Remove unused extern statements from benchmarks.<commit_after>#![feature(test)]

extern crate test;

use std::io::Read;
use test::Bencher;

fn compress_bench(x: &[u8], b: &mut Bencher) {
    b.iter(|| {
        let mut compressed: Vec<u8> = Vec::new();
        lzma_rs::lzma_compress(&mut std::io::BufReader::new(x), &mut compressed).unwrap();
    });
}

fn decompress_after_compress_bench(x: &[u8], b: &mut Bencher) {
    let mut compressed: Vec<u8> = Vec::new();
    lzma_rs::lzma_compress(&mut std::io::BufReader::new(x), &mut compressed).unwrap();

    b.iter(|| {
        let mut bf = std::io::BufReader::new(compressed.as_slice());
        let mut decomp: Vec<u8> = Vec::new();
        lzma_rs::lzma_decompress(&mut bf, &mut decomp).unwrap();
    });
}

fn decompress_bench(compressed: &[u8], b: &mut Bencher) {
    b.iter(|| {
        let mut bf = std::io::BufReader::new(compressed);
        let mut decomp: Vec<u8> = Vec::new();
        lzma_rs::lzma_decompress(&mut bf, &mut decomp).unwrap();
    });
}

fn decompress_bench_file(compfile: &str, b: &mut Bencher) {
    let mut f = std::fs::File::open(compfile).unwrap();
    let mut compressed = Vec::new();
    f.read_to_end(&mut compressed).unwrap();
    decompress_bench(&compressed, b);
}

#[bench]
fn compress_empty(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    compress_bench(b"", b);
}

#[bench]
fn decompress_after_compress_empty(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    decompress_after_compress_bench(b"", b);
}

#[bench]
fn compress_hello(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    compress_bench(b"Hello world", b);
}

#[bench]
fn decompress_after_compress_hello(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    decompress_after_compress_bench(b"Hello world", b);
}

#[bench]
fn compress_65536(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    compress_bench(&[0; 0x10000], b);
}

#[bench]
fn decompress_after_compress_65536(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    decompress_after_compress_bench(&[0; 0x10000], b);
}

#[bench]
fn decompress_big_file(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    decompress_bench_file("tests/files/foo.txt.lzma", b);
}

#[bench]
fn decompress_huge_dict(b: &mut Bencher) {
    #[cfg(feature = "enable_logging")]
    let _ = env_logger::try_init();
    let compressed: &[u8] = b"\x5d\x7f\x7f\x7f\x7f\xff\xff\xff\
                              \xff\xff\xff\xff\xff\x00\x24\x19\
                              \x49\x98\x6f\x10\x19\xc6\xd7\x31\
                              \xeb\x36\x50\xb2\x98\x48\xff\xfe\
                              \xa5\xb0\x00";
    decompress_bench(&compressed, b);
}
<|endoftext|>


<commit_before>#![feature(custom_derive)]
#![feature(proc_macro)]

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

extern crate bitcoin;
extern crate secp256k1;
extern crate rand;
extern crate futures;
extern crate env_logger;
extern crate tokio_minihttp;
extern crate tokio_proto;
extern crate tokio_service;
extern crate time;

use secp256k1::{Secp256k1, ContextFlag};
use secp256k1::key::{PublicKey, SecretKey};
use bitcoin::blockdata::block::{Block};
use bitcoin::util::address::{Address, Privkey};
use bitcoin::util::hash::{Hash160};
use bitcoin::network::constants::Network;
use bitcoin::network::serialize::{deserialize, serialize};
use bitcoin::util::base58::{ToBase58, FromBase58};
use rand::{thread_rng, Rng};
use std::io;
use futures::future;
use tokio_minihttp::{Request, Response, Http};
use tokio_proto::TcpServer;
use tokio_service::Service;

#[derive(Serialize, Deserialize, Debug)]
pub struct WeddingRequest {
    alice_pk : String,
    bob_pk : String,
    public_message : String
}

//#[derive(Serialize, Deserialize, Debug)]
pub struct WeddingEvent {
    priest_pk : String,
    timestamp : time::Tm,
}

struct WeddingService;

impl Service for WeddingService {
    type Request = Request;
    type Response = Response;
    type Error = io::Error;
    type Future = future::Ok<Response, io::Error>;

    fn call(&self, _request: Request) -> Self::Future {
        // Deserialize request and get addresses of participants
        //let deserialized_request: WeddingRequest = serde_json::from_str(&_request.data).unwrap();
        let pk_alice: Address =
        FromBase58::from_base58check("2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr").unwrap();
        let pk_bob: Address =
        FromBase58::from_base58check("2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr").unwrap();

        let wedding_request = WeddingRequest{
            alice_pk : pk_alice.to_base58check(),
            bob_pk : pk_bob.to_base58check(),
            public_message : "MyFirstWedding".to_string()
         };

        // Create new wedding event
        // Hardcode addresses of priest for now
        let compressed = false;
        let pk_priest = "1Er1kCVPzyXxhogYr7biLSPQ9ZC4nL1gNw".to_string();
        let sk_priest: Privkey =
        FromBase58::from_base58check("5KMDBYFxRfi4MzgLDyA2wcq3hzqjnPmWw14gve5bJ77e3KLuUHe").unwrap();
        let wedding = WeddingEvent{ priest_pk : pk_priest, timestamp : time::now_utc() };

        // Prepare response
        let mut resp = Response::new();
        //let serialized_response = serde_json::to_string(&wedding).unwrap();
        let serialized_response = r#"{ priest_address:"1Er1kCVPzyXxhogYr7biLSPQ9ZC4nL1gNw", expiration_timestamp:"0" }"#.to_string();
        resp.body(&serialized_response);
        future::ok(resp)
    }
}

fn main() {
    //Get latest block from bitcoind service

    //Start HTTP-service
    drop(env_logger::init());
    let addr = "0.0.0.0:3000".parse().unwrap();
    TcpServer::new(Http, addr).serve(|| Ok(WeddingService));
}
<commit_msg>Removed hardcode.<commit_after>#![feature(custom_derive)]
#![feature(proc_macro)]

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

extern crate bitcoin;
extern crate secp256k1;
extern crate rand;
extern crate futures;
extern crate env_logger;
extern crate tokio_minihttp;
extern crate tokio_proto;
extern crate tokio_service;
extern crate time;

use secp256k1::{Secp256k1, ContextFlag};
use secp256k1::key::{PublicKey, SecretKey};
use bitcoin::blockdata::block::{Block};
use bitcoin::util::address::{Address, Privkey};
use bitcoin::util::hash::{Hash160};
use bitcoin::network::constants::Network;
use bitcoin::network::serialize::{deserialize, serialize};
use bitcoin::util::base58::{ToBase58, FromBase58};
use rand::{thread_rng, Rng};
use std::io;
use futures::future;
use tokio_minihttp::{Request, Response, Http};
use tokio_proto::TcpServer;
use tokio_service::Service;

#[derive(Serialize, Deserialize, Debug)]
pub struct WeddingRequest {
    alice_pk : String,
    bob_pk : String,
    public_message : String
}

#[derive(Serialize, Deserialize, Debug)]
pub struct WeddingEvent {
    priest_address : String,
    //timestamp : time::Tm,
}

struct WeddingService;

impl Service for WeddingService {
    type Request = Request;
    type Response = Response;
    type Error = io::Error;
    type Future = future::Ok<Response, io::Error>;

    fn call(&self, _request: Request) -> Self::Future {
        // Deserialize request and get addresses of participants
        //let deserialized_request: WeddingRequest = serde_json::from_str(&_request.data).unwrap();
        let pk_alice: Address =
        FromBase58::from_base58check("2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr").unwrap();
        let pk_bob: Address =
        FromBase58::from_base58check("2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr").unwrap();

        let wedding_request = WeddingRequest{
            alice_pk : pk_alice.to_base58check(),
            bob_pk : pk_bob.to_base58check(),
            public_message : "MyFirstOne".to_string()
         };

        // Create new wedding event and priest credentials
        // generate keypair from secp256k1 elliptic curve
        let secp = Secp256k1::with_caps(ContextFlag::SignOnly);
        let network = Network::Bitcoin;
        let compressed = false;
        let sk = SecretKey::new(&secp, &mut thread_rng());
        let pk = PublicKey::from_secret_key(&secp, &sk).expect("Failed to create public key");

        // convert public key to Bitcoin address and private key to base58
        let address = Address::from_key(network, &pk, compressed);
        let privkey = Privkey::from_key(network, sk, compressed);
        let wedding = WeddingEvent{
            priest_address : address.to_base58check(),
            //timestamp : time::now_utc()
        };

        // Prepare response
        let mut resp = Response::new();
        let serialized_response = serde_json::to_string(&wedding).unwrap();
        //let serialized_response = r#"{ priest_address:"1Er1kCVPzyXxhogYr7biLSPQ9ZC4nL1gNw", expiration_timestamp:"0" }"#.to_string();
        resp.body(&serialized_response);
        future::ok(resp)
    }
}

fn main() {
    //Start HTTP-service
    drop(env_logger::init());
    let addr = "0.0.0.0:3000".parse().unwrap();
    TcpServer::new(Http, addr).serve(|| Ok(WeddingService));
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use bytecode_source_map::source_map::{ModuleSourceMap, SourceMap};
use bytecode_to_boogie::translator::BoogieTranslator;
use bytecode_verifier::VerifiedModule;
use goldenfile;
use ir_to_bytecode::{compiler::compile_module, parser::ast::Loc, parser::parse_module};
use libra_tools::tempdir::TempPath;
use libra_types::account_address::AccountAddress;
use prettydiff::{basic::DiffOp, diff_lines};
use std::{env, fs, fs::File, io::Error, io::Read, io::Write, path::Path, process::Command};
use stdlib::{stdlib_modules, stdlib_source_map};

fn compile_files(file_names: Vec<&str>) -> (Vec<VerifiedModule>, SourceMap<Loc>) {
    let mut verified_modules = stdlib_modules().to_vec();
    let mut source_maps = stdlib_source_map().to_vec();
    let files_len = file_names.len();
    let dep_files = &file_names[0..files_len];

    // assuming the last file is a program that might contain a script
    let address = AccountAddress::default();
    for file_name in dep_files {
        let code = fs::read_to_string(file_name).unwrap();
        let module = parse_module(&code).unwrap();
        let (compiled_module, source_map) =
            compile_module(address, module, &verified_modules).expect("module failed to compile");
        let verified_module_res = VerifiedModule::new(compiled_module);

        match verified_module_res {
            Err(e) => {
                println!("vm verification errors!");
                for s in &e.1 {
                    println!("status: {:?}", s);
                }
                panic!("{:?}", e.0);
            }
            Ok(verified_module) => {
                verified_modules.push(verified_module);
                source_maps.push(source_map);
            }
        }
    }
    (verified_modules, source_maps)
}

#[allow(unused_variables)]
pub fn generate_boogie(file_name: &str, target_modules: &[&str]) -> String {
    let mut file_names = vec![];
    file_names.push(file_name);
    let (modules, source_maps) = compile_files(file_names.to_vec());

    if option_env!("VERIFY_BPL_GOLDEN").unwrap_or("0") == "1" {
        // Verify or update golden files. This will run its own translate focused to the target
        // test, so no need to pass in generated content.
        verify_or_update_golden(&modules, &source_maps, file_name, target_modules);
    }

    // Run regular translation producing output for execution with boogie.
    let mut ts = BoogieTranslator::new(&modules, &source_maps);
    let mut res = String::new();

    // handwritten boogie code
    let written_code = fs::read_to_string("src/bytecode_instrs.bpl").unwrap();
    res.push_str(&written_code);
    res.push_str(&ts.translate());

    res
}

pub fn run_boogie(boogie_str: &str) {
    let temp_path = TempPath::new();
    temp_path.create_as_dir().unwrap();
    let boogie_file_path = temp_path.path().join("output.bpl");
    // In order to debug errors in the output, one may uncomment below to find the output
    // file at a stable location.
    //    let mut boogie_file_path = std::path::PathBuf::new();
    //    boogie_file_path.push("/tmp/output.bpl");
    fs::write(&boogie_file_path, boogie_str).unwrap();
    if let Ok(boogie_path) = env::var("BOOGIE_EXE") {
        if let Ok(z3_path) = env::var("Z3_EXE") {
            let status = Command::new(boogie_path)
                .args(&[
                    &format!("{}{}", "-z3exe:", z3_path).as_str(),
                    "-doModSetAnalysis",
                    "-noinfer",
                    "-noVerify",
                    boogie_file_path.to_str().unwrap(),
                ])
                .status()
                .expect("failed to execute Boogie");
            assert!(status.success());
        }
    }
}

/// Verifies or updates golden file for the given generated boogie source.
///
/// This re-generates the source based on the module targeted by this test.
fn verify_or_update_golden(
    modules: &[VerifiedModule],
    source_maps: &[ModuleSourceMap<Loc>],
    file_name: &str,
    target_modules: &[&str],
) {
    // Translate targeted to the given set of modules, if not empty.
    let mut ts = BoogieTranslator::new(&modules, &source_maps);
    if !target_modules.is_empty() {
        ts = ts.set_target_modules(target_modules);
    }
    let source = ts.translate();

    // The mint created here will automatically verify/update the
    // file once it is dropped.
    let mut mint = goldenfile::Mint::new("tests/goldenfiles");
    let goldenfile_name = format!(
        "{}.bpl",
        Path::new(file_name).file_stem().unwrap().to_str().unwrap()
    );
    let mut goldenfile = mint
        .new_goldenfile_with_differ(goldenfile_name, Box::new(file_diff))
        .unwrap();
    write!(goldenfile, "{}", clean_for_golden(&source)).unwrap();
}

/// Clean a content to be usable as a golden file. Currently, we ensure there are no
/// trailing whitespaces and no empty last line, because this is required by git-checks.sh.
fn clean_for_golden(content: &str) -> String {
    let mut res = String::new();
    for line in content.lines() {
        res.push_str(line.trim_end());
        res.push_str("\n");
    }
    res = res.trim_end().to_string(); // removes empty lines at end
    res.push_str("\n"); // adds back a single newline
    res
}

/// Implements a custom differ for golden tests. The existing differ prints the full
/// text (also unchanged lines) which is infeasible for large sources. The diff output
/// is rather rudimentary, but this is fine because the diff is best analyzed anyway
/// using the users standard diff tools.
fn file_diff(old: &Path, new: &Path) {
    let print_lines = |lines: &[&str], prefix: &str| {
        for line in lines {
            println!("{}{}", prefix, line);
        }
    };

    let print_context = |lines: &[&str]| {
        if lines.len() <= 3 {
            print_lines(lines, "= ");
        } else {
            print_lines(&lines[..1], "= ");
            println!("= ... ({} lines)", lines.len() - 2);
            print_lines(&lines[lines.len() - 1..], "= ");
        }
    };

    let read_file = |path: &Path| -> Result<String, Error> {
        let mut file = File::open(path)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        Ok(contents)
    };

    let old_content = match read_file(old) {
        Ok(c) => c,
        _ => {
            panic!(
                "
Cannot read golden file at {}. In order to create initial golden files,
run the test with env variable REGENERATE_GOLDENFILES=1 set.
",
                old.display()
            );
        }
    };
    let new_content = read_file(new).unwrap();
    if old_content == new_content {
        return;
    }
    let diff = diff_lines(&new_content, &old_content);
    for d in diff.diff() {
        match d {
            DiffOp::Equal(lines) => print_context(lines),
            DiffOp::Insert(lines) => print_lines(lines, "+ "),
            DiffOp::Remove(lines) => print_lines(lines, "- "),
            DiffOp::Replace(old, new) => {
                print_lines(old, "- ");
                print_lines(new, "+ ");
            }
        }
    }
    panic!(
        "
Old and new differ!
Use env variable REGENERATE_GOLDENFILES=1 to regenerate golden files.
Then use your favorite diff tool to verify you are good with the changes.
"
    );
}
<commit_msg>Add support for CVC4<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use bytecode_source_map::source_map::{ModuleSourceMap, SourceMap};
use bytecode_to_boogie::translator::BoogieTranslator;
use bytecode_verifier::VerifiedModule;
use goldenfile;
use ir_to_bytecode::{compiler::compile_module, parser::ast::Loc, parser::parse_module};
use libra_tools::tempdir::TempPath;
use libra_types::account_address::AccountAddress;
use prettydiff::{basic::DiffOp, diff_lines};
use std::{env, fs, fs::File, io::Error, io::Read, io::Write, path::Path, process::Command};
use stdlib::{stdlib_modules, stdlib_source_map};

fn compile_files(file_names: Vec<&str>) -> (Vec<VerifiedModule>, SourceMap<Loc>) {
    let mut verified_modules = stdlib_modules().to_vec();
    let mut source_maps = stdlib_source_map().to_vec();
    let files_len = file_names.len();
    let dep_files = &file_names[0..files_len];

    // assuming the last file is a program that might contain a script
    let address = AccountAddress::default();
    for file_name in dep_files {
        let code = fs::read_to_string(file_name).unwrap();
        let module = parse_module(&code).unwrap();
        let (compiled_module, source_map) =
            compile_module(address, module, &verified_modules).expect("module failed to compile");
        let verified_module_res = VerifiedModule::new(compiled_module);

        match verified_module_res {
            Err(e) => {
                println!("vm verification errors!");
                for s in &e.1 {
                    println!("status: {:?}", s);
                }
                panic!("{:?}", e.0);
            }
            Ok(verified_module) => {
                verified_modules.push(verified_module);
                source_maps.push(source_map);
            }
        }
    }
    (verified_modules, source_maps)
}

#[allow(unused_variables)]
pub fn generate_boogie(file_name: &str, target_modules: &[&str]) -> String {
    let mut file_names = vec![];
    file_names.push(file_name);
    let (modules, source_maps) = compile_files(file_names.to_vec());

    if option_env!("VERIFY_BPL_GOLDEN").unwrap_or("0") == "1" {
        // Verify or update golden files. This will run its own translate focused to the target
        // test, so no need to pass in generated content.
        verify_or_update_golden(&modules, &source_maps, file_name, target_modules);
    }

    // Run regular translation producing output for execution with boogie.
    let mut ts = BoogieTranslator::new(&modules, &source_maps);
    let mut res = String::new();

    // handwritten boogie code
    let written_code = fs::read_to_string("src/bytecode_instrs.bpl").unwrap();
    res.push_str(&written_code);
    res.push_str(&ts.translate());

    res
}

pub fn run_boogie(boogie_str: &str) {
    let temp_path = TempPath::new();
    temp_path.create_as_dir().unwrap();
    let boogie_file_path = temp_path.path().join("output.bpl");
    // In order to debug errors in the output, one may uncomment below to find the output
    // file at a stable location.
    //    let mut boogie_file_path = std::path::PathBuf::new();
    //    boogie_file_path.push("/tmp/output.bpl");
    fs::write(&boogie_file_path, boogie_str).unwrap();
    if let Ok(boogie_path) = env::var("BOOGIE_EXE") {
        if let Ok(cvc4_path) = env::var("CVC4_EXE") {
            let status = Command::new(boogie_path)
                .args(&[
                    &format!("{}{}", "-cvc4exe:", cvc4_path).as_str(),
                    "-proverOpt:SOLVER=CVC4",
                    "-doModSetAnalysis",
                    "-useArrayTheory",
                    "-noinfer",
                    "-noVerify",
                    boogie_file_path.to_str().unwrap(),
                ])
                .status()
                .expect("failed to execute Boogie");
            assert!(status.success());
        } else if let Ok(z3_path) = env::var("Z3_EXE") {
            let status = Command::new(boogie_path)
                .args(&[
                    &format!("{}{}", "-z3exe:", z3_path).as_str(),
                    "-doModSetAnalysis",
                    "-noinfer",
                    "-noVerify",
                    boogie_file_path.to_str().unwrap(),
                ])
                .status()
                .expect("failed to execute Boogie");
            assert!(status.success());
        }
    }
}

/// Verifies or updates golden file for the given generated boogie source.
///
/// This re-generates the source based on the module targeted by this test.
fn verify_or_update_golden(
    modules: &[VerifiedModule],
    source_maps: &[ModuleSourceMap<Loc>],
    file_name: &str,
    target_modules: &[&str],
) {
    // Translate targeted to the given set of modules, if not empty.
    let mut ts = BoogieTranslator::new(&modules, &source_maps);
    if !target_modules.is_empty() {
        ts = ts.set_target_modules(target_modules);
    }
    let source = ts.translate();

    // The mint created here will automatically verify/update the
    // file once it is dropped.
    let mut mint = goldenfile::Mint::new("tests/goldenfiles");
    let goldenfile_name = format!(
        "{}.bpl",
        Path::new(file_name).file_stem().unwrap().to_str().unwrap()
    );
    let mut goldenfile = mint
        .new_goldenfile_with_differ(goldenfile_name, Box::new(file_diff))
        .unwrap();
    write!(goldenfile, "{}", clean_for_golden(&source)).unwrap();
}

/// Clean a content to be usable as a golden file. Currently, we ensure there are no
/// trailing whitespaces and no empty last line, because this is required by git-checks.sh.
fn clean_for_golden(content: &str) -> String {
    let mut res = String::new();
    for line in content.lines() {
        res.push_str(line.trim_end());
        res.push_str("\n");
    }
    res = res.trim_end().to_string(); // removes empty lines at end
    res.push_str("\n"); // adds back a single newline
    res
}

/// Implements a custom differ for golden tests. The existing differ prints the full
/// text (also unchanged lines) which is infeasible for large sources. The diff output
/// is rather rudimentary, but this is fine because the diff is best analyzed anyway
/// using the users standard diff tools.
fn file_diff(old: &Path, new: &Path) {
    let print_lines = |lines: &[&str], prefix: &str| {
        for line in lines {
            println!("{}{}", prefix, line);
        }
    };

    let print_context = |lines: &[&str]| {
        if lines.len() <= 3 {
            print_lines(lines, "= ");
        } else {
            print_lines(&lines[..1], "= ");
            println!("= ... ({} lines)", lines.len() - 2);
            print_lines(&lines[lines.len() - 1..], "= ");
        }
    };

    let read_file = |path: &Path| -> Result<String, Error> {
        let mut file = File::open(path)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        Ok(contents)
    };

    let old_content = match read_file(old) {
        Ok(c) => c,
        _ => {
            panic!(
                "
Cannot read golden file at {}. In order to create initial golden files,
run the test with env variable REGENERATE_GOLDENFILES=1 set.
",
                old.display()
            );
        }
    };
    let new_content = read_file(new).unwrap();
    if old_content == new_content {
        return;
    }
    let diff = diff_lines(&new_content, &old_content);
    for d in diff.diff() {
        match d {
            DiffOp::Equal(lines) => print_context(lines),
            DiffOp::Insert(lines) => print_lines(lines, "+ "),
            DiffOp::Remove(lines) => print_lines(lines, "- "),
            DiffOp::Replace(old, new) => {
                print_lines(old, "- ");
                print_lines(new, "+ ");
            }
        }
    }
    panic!(
        "
Old and new differ!
Use env variable REGENERATE_GOLDENFILES=1 to regenerate golden files.
Then use your favorite diff tool to verify you are good with the changes.
"
    );
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate handlebars;
#[macro_use]
extern crate serde_json;

use handlebars::Handlebars;

handlebars_helper!(lower: |s: str| s.to_lowercase());
handlebars_helper!(upper: |s: str| s.to_uppercase());
handlebars_helper!(hex: |v: i64| format!("0x{:x}", v));
handlebars_helper!(money: |v: i64, {cur: str="$"}| format!("{}{}.00", cur, v));
handlebars_helper!(all_hash: |{cur: str="$"}| cur);

#[test]
fn test_macro_helper() {
    let mut hbs = Handlebars::new();

    hbs.register_helper("lower", Box::new(lower));
    hbs.register_helper("upper", Box::new(upper));
    hbs.register_helper("hex", Box::new(hex));
    hbs.register_helper("money", Box::new(money));

    let data = json!("Teixeira");

    assert_eq!(
        hbs.render_template("{{lower this}}", &data).unwrap(),
        "teixeira"
    );
    assert_eq!(
        hbs.render_template("{{upper this}}", &data).unwrap(),
        "TEIXEIRA"
    );
    assert_eq!(hbs.render_template("{{hex 16}}", &()).unwrap(), "0x10");

    assert_eq!(
        hbs.render_template("{{money 5000}}", &()).unwrap(),
        "$5000.00"
    );
    assert_eq!(
        hbs.render_template("{{money 5000 cur=\"£\"}}", &())
            .unwrap(),
        "£5000.00"
    );
}
<commit_msg>(test) added test for arg list and kwargs map<commit_after>#[macro_use]
extern crate handlebars;
#[macro_use]
extern crate serde_json;

use handlebars::Handlebars;

handlebars_helper!(lower: |s: str| s.to_lowercase());
handlebars_helper!(upper: |s: str| s.to_uppercase());
handlebars_helper!(hex: |v: i64| format!("0x{:x}", v));
handlebars_helper!(money: |v: i64, {cur: str="$"}| format!("{}{}.00", cur, v));
handlebars_helper!(all_hash: |{cur: str="$"}| cur);
handlebars_helper!(nargs: |*args| args.len());
handlebars_helper!(has_a: |{a:i64 = 99}, **kwargs|
                   format!("{}, {}", a, kwargs.get("a").is_some()));

#[test]
fn test_macro_helper() {
    let mut hbs = Handlebars::new();

    hbs.register_helper("lower", Box::new(lower));
    hbs.register_helper("upper", Box::new(upper));
    hbs.register_helper("hex", Box::new(hex));
    hbs.register_helper("money", Box::new(money));
    hbs.register_helper("nargs", Box::new(nargs));
    hbs.register_helper("has_a", Box::new(has_a));

    let data = json!("Teixeira");

    assert_eq!(
        hbs.render_template("{{lower this}}", &data).unwrap(),
        "teixeira"
    );
    assert_eq!(
        hbs.render_template("{{upper this}}", &data).unwrap(),
        "TEIXEIRA"
    );
    assert_eq!(hbs.render_template("{{hex 16}}", &()).unwrap(), "0x10");

    assert_eq!(
        hbs.render_template("{{money 5000}}", &()).unwrap(),
        "$5000.00"
    );
    assert_eq!(
        hbs.render_template("{{money 5000 cur=\"£\"}}", &())
            .unwrap(),
        "£5000.00"
    );
    assert_eq!(
        hbs.render_template("{{nargs 1 1 1 1 1}}", &()).unwrap(),
        "5"
    );
    assert_eq!(hbs.render_template("{{nargs}}", &()).unwrap(), "0");

    assert_eq!(
        hbs.render_template("{{has_a a=1 b=2}}", &()).unwrap(),
        "1, true"
    );

    assert_eq!(
        hbs.render_template("{{has_a x=1 b=2}}", &()).unwrap(),
        "99, false"
    );
}
<|endoftext|>


<commit_before>use pyo3::ffi::{Py_hash_t, Py_intptr_t, Py_uintptr_t};
use std::os::raw::*;

pub type npy_intp = Py_intptr_t;
pub type npy_uintp = Py_uintptr_t;
pub type npy_longlong = c_longlong;
pub type npy_ulonglong = c_ulonglong;
pub type npy_bool = c_uchar;
pub type npy_longdouble = f64;
pub type npy_byte = c_char;
pub type npy_ubyte = c_uchar;
pub type npy_ushort = c_ushort;
pub type npy_uint = c_uint;
pub type npy_ulong = c_ulong;
pub type npy_char = c_char;
pub type npy_short = c_short;
pub type npy_int = c_int;
pub type npy_long = c_long;
pub type npy_float = f32;
pub type npy_double = f64;
pub type npy_hash_t = Py_hash_t;
pub type npy_int64 = c_long;
pub type npy_uint64 = c_ulong;
pub type npy_int32 = c_int;
pub type npy_uint32 = c_uint;
pub type npy_ucs4 = c_uint;
pub type npy_int16 = c_short;
pub type npy_uint16 = c_ushort;
pub type npy_int8 = c_char;
pub type npy_uint8 = c_uchar;
pub type npy_float64 = f64;
pub type npy_complex128 = npy_cdouble;
pub type npy_float32 = f32;
pub type npy_complex64 = npy_cfloat;
pub type npy_half = npy_uint16;
pub type npy_float16 = npy_half;
pub type npy_float128 = npy_longdouble;
pub type npy_complex256 = npy_clongdouble;
pub type npy_timedelta = npy_int64;
pub type npy_datetime = npy_int64;

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_cdouble {
    pub real: f64,
    pub imag: f64,
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_cfloat {
    pub real: f32,
    pub imag: f32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_clongdouble {
    pub real: npy_longdouble,
    pub imag: npy_longdouble,
}

#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_ORDER {
    NPY_ANYORDER = -1,
    NPY_CORDER = 0,
    NPY_FORTRANORDER = 1,
    NPY_KEEPORDER = 2,
}

#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SCALARKIND {
    NPY_NOSCALAR = -1,
    NPY_BOOL_SCALAR = 0,
    NPY_INTPOS_SCALAR = 1,
    NPY_INTNEG_SCALAR = 2,
    NPY_FLOAT_SCALAR = 3,
    NPY_COMPLEX_SCALAR = 4,
    NPY_OBJECT_SCALAR = 5,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SORTKIND {
    NPY_QUICKSORT = 0,
    NPY_HEAPSORT = 1,
    NPY_MERGESORT = 2,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SEARCHSIDE {
    NPY_SEARCHLEFT = 0,
    NPY_SEARCHRIGHT = 1,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_DATETIMEUNIT {
    NPY_FR_Y = 0,
    NPY_FR_M = 1,
    NPY_FR_W = 2,
    NPY_FR_D = 4,
    NPY_FR_h = 5,
    NPY_FR_m = 6,
    NPY_FR_s = 7,
    NPY_FR_ms = 8,
    NPY_FR_us = 9,
    NPY_FR_ns = 10,
    NPY_FR_ps = 11,
    NPY_FR_fs = 12,
    NPY_FR_as = 13,
    NPY_FR_GENERIC = 14,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum NPY_TYPES {
    NPY_BOOL = 0,
    NPY_BYTE = 1,
    NPY_UBYTE = 2,
    NPY_SHORT = 3,
    NPY_USHORT = 4,
    NPY_INT = 5,
    NPY_UINT = 6,
    NPY_LONG = 7,
    NPY_ULONG = 8,
    NPY_LONGLONG = 9,
    NPY_ULONGLONG = 10,
    NPY_FLOAT = 11,
    NPY_DOUBLE = 12,
    NPY_LONGDOUBLE = 13,
    NPY_CFLOAT = 14,
    NPY_CDOUBLE = 15,
    NPY_CLONGDOUBLE = 16,
    NPY_OBJECT = 17,
    NPY_STRING = 18,
    NPY_UNICODE = 19,
    NPY_VOID = 20,
    NPY_DATETIME = 21,
    NPY_TIMEDELTA = 22,
    NPY_HALF = 23,
    NPY_NTYPES = 24,
    NPY_NOTYPE = 25,
    NPY_CHAR = 26,
    NPY_USERDEF = 256,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SELECTKIND {
    NPY_INTROSELECT = 0,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_CASTING {
    NPY_NO_CASTING = 0,
    NPY_EQUIV_CASTING = 1,
    NPY_SAFE_CASTING = 2,
    NPY_SAME_KIND_CASTING = 3,
    NPY_UNSAFE_CASTING = 4,
}

#[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_CLIPMODE {
    NPY_CLIP = 0,
    NPY_WRAP = 1,
    NPY_RAISE = 2,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_datetimestruct {
    pub year: npy_int64,
    pub month: npy_int32,
    pub day: npy_int32,
    pub hour: npy_int32,
    pub min: npy_int32,
    pub sec: npy_int32,
    pub us: npy_int32,
    pub ps: npy_int32,
    pub as_: npy_int32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_timedeltastruct {
    pub day: npy_int64,
    pub sec: npy_int32,
    pub us: npy_int32,
    pub ps: npy_int32,
    pub as_: npy_int32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_stride_sort_item {
    pub perm: npy_intp,
    pub stride: npy_intp,
}

#[repr(u8)]
#[derive(Debug, Clone, Copy)]
pub enum NPY_TYPECHAR {
    NPY_BOOLLTR = b'?',
    NPY_BYTELTR = b'b',
    NPY_UBYTELTR = b'B',
    NPY_SHORTLTR = b'h',
    NPY_USHORTLTR = b'H',
    NPY_INTLTR = b'i',
    NPY_UINTLTR = b'I',
    NPY_LONGLTR = b'l',
    NPY_ULONGLTR = b'L',
    NPY_LONGLONGLTR = b'q',
    NPY_ULONGLONGLTR = b'Q',
    NPY_HALFLTR = b'e',
    NPY_FLOATLTR = b'f',
    NPY_DOUBLELTR = b'd',
    NPY_LONGDOUBLELTR = b'g',
    NPY_CFLOATLTR = b'F',
    NPY_CDOUBLELTR = b'D',
    NPY_CLONGDOUBLELTR = b'G',
    NPY_OBJECTLTR = b'O',
    NPY_STRINGLTR = b'S',
    NPY_STRINGLTR2 = b'a',
    NPY_UNICODELTR = b'U',
    NPY_VOIDLTR = b'V',
    NPY_DATETIMELTR = b'M',
    NPY_TIMEDELTALTR = b'm',
    NPY_CHARLTR = b'c',
    NPY_INTPLTR = b'p',
    NPY_UINTPLTR = b'P',
}

#[repr(u8)]
#[derive(Debug, Clone, Copy)]
// NPY_TYPEKINDCHAR doesn't exist in the header, but these enum values are not
// related to NPY_TYPECHAR although being stuffed into it (type kinds, not type codes)
pub enum NPY_TYPEKINDCHAR {
    NPY_GENBOOLLTR = b'b',
    NPY_SIGNEDLTR = b'i',
    NPY_UNSIGNEDLTR = b'u',
    NPY_FLOATINGLTR = b'f',
    NPY_COMPLEXLTR = b'c',
}

#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_BYTEORDER_CHAR {
    NPY_LITTLE = b'<',
    NPY_BIG = b'>',
    NPY_NATIVE = b'=',
    NPY_SWAP = b's',
    NPY_IGNORE = b'|',
}

impl NPY_BYTEORDER_CHAR {
    #[cfg(target_endian = "little")]
    pub const NPY_NATBYTE: Self = Self::NPY_LITTLE;
    #[cfg(target_endian = "little")]
    pub const NPY_OPPBYTE: Self = Self::NPY_BIG;

    #[cfg(target_endian = "big")]
    pub const NPY_NATBYTE: Self = Self::NPY_BIG;
    #[cfg(target_endian = "big")]
    pub const NPY_OPPBYTE: Self = Self::NPY_LITTLE;
}
<commit_msg>(Clarify why `NPY_TYPEKINDCHAR` had to be created)<commit_after>use pyo3::ffi::{Py_hash_t, Py_intptr_t, Py_uintptr_t};
use std::os::raw::*;

pub type npy_intp = Py_intptr_t;
pub type npy_uintp = Py_uintptr_t;
pub type npy_longlong = c_longlong;
pub type npy_ulonglong = c_ulonglong;
pub type npy_bool = c_uchar;
pub type npy_longdouble = f64;
pub type npy_byte = c_char;
pub type npy_ubyte = c_uchar;
pub type npy_ushort = c_ushort;
pub type npy_uint = c_uint;
pub type npy_ulong = c_ulong;
pub type npy_char = c_char;
pub type npy_short = c_short;
pub type npy_int = c_int;
pub type npy_long = c_long;
pub type npy_float = f32;
pub type npy_double = f64;
pub type npy_hash_t = Py_hash_t;
pub type npy_int64 = c_long;
pub type npy_uint64 = c_ulong;
pub type npy_int32 = c_int;
pub type npy_uint32 = c_uint;
pub type npy_ucs4 = c_uint;
pub type npy_int16 = c_short;
pub type npy_uint16 = c_ushort;
pub type npy_int8 = c_char;
pub type npy_uint8 = c_uchar;
pub type npy_float64 = f64;
pub type npy_complex128 = npy_cdouble;
pub type npy_float32 = f32;
pub type npy_complex64 = npy_cfloat;
pub type npy_half = npy_uint16;
pub type npy_float16 = npy_half;
pub type npy_float128 = npy_longdouble;
pub type npy_complex256 = npy_clongdouble;
pub type npy_timedelta = npy_int64;
pub type npy_datetime = npy_int64;

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_cdouble {
    pub real: f64,
    pub imag: f64,
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_cfloat {
    pub real: f32,
    pub imag: f32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_clongdouble {
    pub real: npy_longdouble,
    pub imag: npy_longdouble,
}

#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_ORDER {
    NPY_ANYORDER = -1,
    NPY_CORDER = 0,
    NPY_FORTRANORDER = 1,
    NPY_KEEPORDER = 2,
}

#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SCALARKIND {
    NPY_NOSCALAR = -1,
    NPY_BOOL_SCALAR = 0,
    NPY_INTPOS_SCALAR = 1,
    NPY_INTNEG_SCALAR = 2,
    NPY_FLOAT_SCALAR = 3,
    NPY_COMPLEX_SCALAR = 4,
    NPY_OBJECT_SCALAR = 5,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SORTKIND {
    NPY_QUICKSORT = 0,
    NPY_HEAPSORT = 1,
    NPY_MERGESORT = 2,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SEARCHSIDE {
    NPY_SEARCHLEFT = 0,
    NPY_SEARCHRIGHT = 1,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_DATETIMEUNIT {
    NPY_FR_Y = 0,
    NPY_FR_M = 1,
    NPY_FR_W = 2,
    NPY_FR_D = 4,
    NPY_FR_h = 5,
    NPY_FR_m = 6,
    NPY_FR_s = 7,
    NPY_FR_ms = 8,
    NPY_FR_us = 9,
    NPY_FR_ns = 10,
    NPY_FR_ps = 11,
    NPY_FR_fs = 12,
    NPY_FR_as = 13,
    NPY_FR_GENERIC = 14,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum NPY_TYPES {
    NPY_BOOL = 0,
    NPY_BYTE = 1,
    NPY_UBYTE = 2,
    NPY_SHORT = 3,
    NPY_USHORT = 4,
    NPY_INT = 5,
    NPY_UINT = 6,
    NPY_LONG = 7,
    NPY_ULONG = 8,
    NPY_LONGLONG = 9,
    NPY_ULONGLONG = 10,
    NPY_FLOAT = 11,
    NPY_DOUBLE = 12,
    NPY_LONGDOUBLE = 13,
    NPY_CFLOAT = 14,
    NPY_CDOUBLE = 15,
    NPY_CLONGDOUBLE = 16,
    NPY_OBJECT = 17,
    NPY_STRING = 18,
    NPY_UNICODE = 19,
    NPY_VOID = 20,
    NPY_DATETIME = 21,
    NPY_TIMEDELTA = 22,
    NPY_HALF = 23,
    NPY_NTYPES = 24,
    NPY_NOTYPE = 25,
    NPY_CHAR = 26,
    NPY_USERDEF = 256,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SELECTKIND {
    NPY_INTROSELECT = 0,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_CASTING {
    NPY_NO_CASTING = 0,
    NPY_EQUIV_CASTING = 1,
    NPY_SAFE_CASTING = 2,
    NPY_SAME_KIND_CASTING = 3,
    NPY_UNSAFE_CASTING = 4,
}

#[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_CLIPMODE {
    NPY_CLIP = 0,
    NPY_WRAP = 1,
    NPY_RAISE = 2,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_datetimestruct {
    pub year: npy_int64,
    pub month: npy_int32,
    pub day: npy_int32,
    pub hour: npy_int32,
    pub min: npy_int32,
    pub sec: npy_int32,
    pub us: npy_int32,
    pub ps: npy_int32,
    pub as_: npy_int32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_timedeltastruct {
    pub day: npy_int64,
    pub sec: npy_int32,
    pub us: npy_int32,
    pub ps: npy_int32,
    pub as_: npy_int32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_stride_sort_item {
    pub perm: npy_intp,
    pub stride: npy_intp,
}

#[repr(u8)]
#[derive(Debug, Clone, Copy)]
pub enum NPY_TYPECHAR {
    NPY_BOOLLTR = b'?',
    NPY_BYTELTR = b'b',
    NPY_UBYTELTR = b'B',
    NPY_SHORTLTR = b'h',
    NPY_USHORTLTR = b'H',
    NPY_INTLTR = b'i',
    NPY_UINTLTR = b'I',
    NPY_LONGLTR = b'l',
    NPY_ULONGLTR = b'L',
    NPY_LONGLONGLTR = b'q',
    NPY_ULONGLONGLTR = b'Q',
    NPY_HALFLTR = b'e',
    NPY_FLOATLTR = b'f',
    NPY_DOUBLELTR = b'd',
    NPY_LONGDOUBLELTR = b'g',
    NPY_CFLOATLTR = b'F',
    NPY_CDOUBLELTR = b'D',
    NPY_CLONGDOUBLELTR = b'G',
    NPY_OBJECTLTR = b'O',
    NPY_STRINGLTR = b'S',
    NPY_STRINGLTR2 = b'a',
    NPY_UNICODELTR = b'U',
    NPY_VOIDLTR = b'V',
    NPY_DATETIMELTR = b'M',
    NPY_TIMEDELTALTR = b'm',
    NPY_CHARLTR = b'c',
    NPY_INTPLTR = b'p',
    NPY_UINTPLTR = b'P',
}

// Note: NPY_TYPEKINDCHAR doesn't exist in the header and has been created here artificially
// because the original C enum contained duplicate values - namely, those related to type kinds.
// There's also a comment in the C code preceding this block of values and stating that they are
// related to type kind chars and not type codes.
#[repr(u8)]
#[derive(Debug, Clone, Copy)]
pub enum NPY_TYPEKINDCHAR {
    NPY_GENBOOLLTR = b'b',
    NPY_SIGNEDLTR = b'i',
    NPY_UNSIGNEDLTR = b'u',
    NPY_FLOATINGLTR = b'f',
    NPY_COMPLEXLTR = b'c',
}

#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_BYTEORDER_CHAR {
    NPY_LITTLE = b'<',
    NPY_BIG = b'>',
    NPY_NATIVE = b'=',
    NPY_SWAP = b's',
    NPY_IGNORE = b'|',
}

impl NPY_BYTEORDER_CHAR {
    #[cfg(target_endian = "little")]
    pub const NPY_NATBYTE: Self = Self::NPY_LITTLE;
    #[cfg(target_endian = "little")]
    pub const NPY_OPPBYTE: Self = Self::NPY_BIG;

    #[cfg(target_endian = "big")]
    pub const NPY_NATBYTE: Self = Self::NPY_BIG;
    #[cfg(target_endian = "big")]
    pub const NPY_OPPBYTE: Self = Self::NPY_LITTLE;
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::io::BufRead;

use error::{Error, Result};

#[derive(Debug, Deserialize, Serialize)]
pub struct Plan {
    pub name: String,
    pub origin: String,
    pub version: Option<String>,
}

impl Plan {
    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
        let mut name: Option<String> = None;
        let mut origin: Option<String> = None;
        let mut version: Option<String> = None;
        for line in bytes.lines() {
            if let Ok(line) = line {
                let parts: Vec<&str> = line.splitn(2, "=").collect();
                match parts[0] {
                    "pkg_name" => name = Some(parts[1].to_string()),
                    "pkg_origin" => origin = Some(parts[1].to_string()),
                    "pkg_version" => version = Some(parts[1].to_string()),
                    _ => (),
                }
            }
        }

        if name.is_none() || origin.is_none() {
            return Err(Error::PlanMalformed);
        }

        Ok(Plan {
            name: name.unwrap(),
            origin: origin.unwrap(),
            version: version,
        })
    }
}
<commit_msg>Make plan parsing a little more robust.<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::io::BufRead;

use error::{Error, Result};

#[derive(Debug, Deserialize, Serialize)]
pub struct Plan {
    pub name: String,
    pub origin: String,
    pub version: Option<String>,
}

impl Plan {
    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
        let mut name: Option<String> = None;
        let mut origin: Option<String> = None;
        let mut version: Option<String> = None;
        for line in bytes.lines() {
            if let Ok(line) = line {
                // Rather than just blindly accepting values, let's trim all the
                // whitespace first, verify that we actually have 2 things separated
                // by an equal sign, and strip out quotes of any kind.
                //
                // To do this properly, we probably need some kind of bash parser,
                // or a plan file syntax that's in a different language that we do
                // have a parser for (LUA!), but both of those things are beyond the
                // scope of this task.
                let parts: Vec<&str> = line.splitn(2, "=").map(|x| x.trim()).collect();

                if parts.len() != 2 {
                    continue;
                }

                let mut val = parts[1].replace("\"", "");
                val = val.replace("'", "");

                match parts[0] {
                    "pkg_name" => name = Some(val),
                    "pkg_origin" => origin = Some(val),
                    "pkg_version" => version = Some(val),
                    _ => (),
                }
            }
        }

        if name.is_none() || origin.is_none() {
            return Err(Error::PlanMalformed);
        }

        Ok(Plan {
            name: name.unwrap(),
            origin: origin.unwrap(),
            version: version,
        })
    }
}

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

    #[test]
    fn parsing_plan_with_no_quotes_works() {
        let content = r#"
        pkg_origin=neurosis
        pkg_name=testapp
        pkg_version=0.1.3
        pkg_maintainer="The Habitat Maintainers <humans@habitat.sh>"
        pkg_license=()
        pkg_upstream_url=https://github.com/habitat-sh/habitat-example-plans
        pkg_source=nosuchfile.tar.gz
        pkg_deps=()
        pkg_expose=()

        do_download() {
          return 0
        }

        do_verify() {
          return 0
        }

        do_unpack() {
          return 0
        }

        do_build() {
          return 0
        }

        do_install() {
          return 0
        }
        "#;
        let plan = Plan::from_bytes(content.as_bytes()).unwrap();
        assert_eq!(plan.origin, "neurosis".to_string());
        assert_eq!(plan.name, "testapp".to_string());
        assert_eq!(plan.version, Some("0.1.3".to_string()));
    }

    #[test]
    fn parsing_plan_with_double_quotes_works() {
        let content = r#"
        pkg_origin="neurosis"
        pkg_name="testapp"
        pkg_version="0.1.3"
        pkg_maintainer="The Habitat Maintainers <humans@habitat.sh>"
        pkg_license=()
        pkg_upstream_url=https://github.com/habitat-sh/habitat-example-plans
        pkg_source=nosuchfile.tar.gz
        pkg_deps=()
        pkg_expose=()

        do_download() {
          return 0
        }

        do_verify() {
          return 0
        }

        do_unpack() {
          return 0
        }

        do_build() {
          return 0
        }

        do_install() {
          return 0
        }
        "#;
        let plan = Plan::from_bytes(content.as_bytes()).unwrap();
        assert_eq!(plan.origin, "neurosis".to_string());
        assert_eq!(plan.name, "testapp".to_string());
        assert_eq!(plan.version, Some("0.1.3".to_string()));
    }

    #[test]
    fn parsing_plan_with_single_quotes_works() {
        let content = r#"
        pkg_origin='neurosis'
        pkg_name='testapp'
        pkg_version='0.1.3'
        pkg_maintainer="The Habitat Maintainers <humans@habitat.sh>"
        pkg_license=()
        pkg_upstream_url=https://github.com/habitat-sh/habitat-example-plans
        pkg_source=nosuchfile.tar.gz
        pkg_deps=()
        pkg_expose=()

        do_download() {
          return 0
        }

        do_verify() {
          return 0
        }

        do_unpack() {
          return 0
        }

        do_build() {
          return 0
        }

        do_install() {
          return 0
        }
        "#;
        let plan = Plan::from_bytes(content.as_bytes()).unwrap();
        assert_eq!(plan.origin, "neurosis".to_string());
        assert_eq!(plan.name, "testapp".to_string());
        assert_eq!(plan.version, Some("0.1.3".to_string()));
    }
}
<|endoftext|>


<commit_before>/* Copyright (C) 2015 Yutaka Kamei */

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use unquote::unquote_plus;

/// An alias type of `Vec<String>`.
///
pub type QueryValue = Vec<String>;

/// An alias type of `HashMap<String, QueryValue>`.
///
pub type Query = HashMap<String, QueryValue>;

pub trait GetQuery {
    /// Gets first value from Vec<String> via HashMap.get().
    ///
    fn get_first(&self, k: &String) -> Option<&String>;

    /// Gets value from `Vec<String>` via `HashMap.get()`.
    /// This requires one &str argument and returns `Option<QueryValue>`
    /// instead of `Option<&QueryValue>`.
    ///
    fn get_from_str(&self, k: &str) -> Option<QueryValue>;

    /// Gets first value from `Vec<String>` via `HashMap.get()`.
    /// This requires one &str argument and returns `Option<String>`
    /// instead of `Option<&String>`.
    ///
    fn get_first_from_str(&self, k: &str) -> Option<String>;
}

impl GetQuery for Query {
    fn get_first(&self, k: &String) -> Option<&String> {
        match self.get(k) {
            Some(value) => value.get(0),
            None        => None,
        }
    }

    fn get_from_str(&self, k: &str) -> Option<QueryValue> {
        match self.get(&k.to_string()) {
            Some(value) => Some(value.iter().map(|e| e.to_string()).collect()),
            None        => None,
        }
    }

    fn get_first_from_str(&self, k: &str) -> Option<String> {
        match self.get(&k.to_string()) {
            Some(value) => match value.get(0) {
                Some(string) => Some(string.to_string()),
                None         => None,
            },
            None        => None,
        }
    }
}

/// Parses a query given as a string argument.
///
/// # Examples
///
/// ```
/// use urlparse::parse_qs;
///
/// let map = parse_qs("a=123&a=90&a=%E4%BA%80%E4%BA%95&b=0;n1;n2");
/// let a = map.get(&"a".to_string()).unwrap();
/// let b = map.get(&"b".to_string()).unwrap();
/// assert_eq!(a.len(), 3);
/// assert_eq!(b.len(), 1);
/// assert_eq!(*a.get(2).unwrap(), "亀井");
/// ```
///
pub fn parse_qs(s: &str) -> Query {
    let mut map : Query = Query::new();
    for item in s.split(|c| c == '&' || c == ';') {
        match item.find('=') {
            Some(index) => {
                let (key, value) = item.split_at(index);
                let _key = match unquote_plus(key) {
                    Ok(k)  => k,
                    Err(_) => continue,  // FIXME: This is not strict mode.
                };
                let _value = match unquote_plus(value.trim_left_matches('=')) {
                    Ok(v)  => v,
                    Err(_) => continue,  // FIXME: This is not strict mode.
                };
                if _value.is_empty() {
                    continue;
                }
                let mut result = match map.entry(_key) {
                    Vacant(entry)   => entry.insert(Vec::new()),
                    Occupied(entry) => entry.into_mut(),
                };
                result.push(_value);
            },
            None        => continue,
        }
    }
    return map;
}
<commit_msg>Update comments<commit_after>/* Copyright (C) 2015 Yutaka Kamei */

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use unquote::unquote_plus;

/// An alias type of `Vec<String>`.
///
pub type QueryValue = Vec<String>;

/// An alias type of `HashMap<String, QueryValue>`.
///
pub type Query = HashMap<String, QueryValue>;

pub trait GetQuery {
    /// Gets first value from Vec<String> via HashMap.get().
    ///
    fn get_first(&self, k: &String) -> Option<&String>;

    /// Gets value from `Vec<String>` via `HashMap.get()`.
    /// This requires one &str argument and returns `Option<QueryValue>`
    /// instead of `Option<&QueryValue>`.
    ///
    fn get_from_str(&self, k: &str) -> Option<QueryValue>;

    /// Gets first value from `Vec<String>` via `HashMap.get()`.
    /// This requires one &str argument and returns `Option<String>`
    /// instead of `Option<&String>`.
    ///
    fn get_first_from_str(&self, k: &str) -> Option<String>;
}

impl GetQuery for Query {
    fn get_first(&self, k: &String) -> Option<&String> {
        match self.get(k) {
            Some(value) => value.get(0),
            None        => None,
        }
    }

    fn get_from_str(&self, k: &str) -> Option<QueryValue> {
        match self.get(&k.to_string()) {
            Some(value) => Some(value.iter().map(|e| e.to_string()).collect()),
            None        => None,
        }
    }

    fn get_first_from_str(&self, k: &str) -> Option<String> {
        match self.get(&k.to_string()) {
            Some(value) => match value.get(0) {
                Some(string) => Some(string.to_string()),
                None         => None,
            },
            None        => None,
        }
    }
}

/// Parses a query given as a string argument.
///
/// # Examples
///
/// ```
/// use urlparse::parse_qs;
///
/// let map = parse_qs("a=123&a=90&a=%E4%BA%80%E4%BA%95&b=0;n1;n2");
/// let a = map.get(&"a".to_string()).unwrap();
/// let b = map.get(&"b".to_string()).unwrap();
/// assert_eq!(a.len(), 3);
/// assert_eq!(b.len(), 1);
/// assert_eq!(*a.get(2).unwrap(), "亀井");
/// ```
///
pub fn parse_qs(s: &str) -> Query {
    let mut map : Query = Query::new();
    for item in s.split(|c| c == '&' || c == ';') {
        match item.find('=') {
            Some(index) => {
                let (key, value) = item.split_at(index);
                let _key = match unquote_plus(key) {
                    Ok(k)  => k,
                    Err(_) => continue,  // NOTE: We ignore error when doing unquote_plus()
                };
                let _value = match unquote_plus(value.trim_left_matches('=')) {
                    Ok(v)  => v,
                    Err(_) => continue,  // NOTE: We ignore error when doing unquote_plus()
                };
                if _value.is_empty() {
                    continue;
                }
                let mut result = match map.entry(_key) {
                    Vacant(entry)   => entry.insert(Vec::new()),
                    Occupied(entry) => entry.into_mut(),
                };
                result.push(_value);
            },
            None        => continue,
        }
    }
    return map;
}
<|endoftext|>


<commit_before>
use std::io;
use std::borrow::Cow;
use std::fmt;
use std::error;
use std::str;

use util;
use common::{Position, TextPosition};

#[derive(Debug)]
pub enum ErrorKind {
    Syntax(Cow<'static, str>),
    Io(io::Error),
    Utf8(str::Utf8Error),
    UnexpectedEof,
}

/// An XML parsing error.
///
/// Consists of a 2D position in a document and a textual message describing the error.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Error {
    pos: TextPosition,
    kind: ErrorKind,
}

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

impl Position for Error {
    #[inline]
    fn position(&self) -> TextPosition { self.pos }
}

impl Error {
    /// Returns a reference to a message which is contained inside this error.
    #[inline]
    pub fn msg(&self) -> &str {
        use self::ErrorKind::*;
        match self.kind {
            UnexpectedEof => &"Unexpected EOF",
            Utf8(ref reason) => error_description(reason),
            Io(ref io_error) => error_description(io_error),
            Syntax(ref msg) => msg.as_ref(),
        }
    }

    pub fn kind(&self) -> &ErrorKind { &self.kind }
}

impl error::Error for Error {
    #[inline]
    fn description(&self) -> &str { self.msg() }
}

impl<'a, P, M> From<(&'a P, M)> for Error where P: Position, M: Into<Cow<'static, str>> {
    fn from(orig: (&'a P, M)) -> Self {
        Error{
            pos: orig.0.position(),
            kind: ErrorKind::Syntax(orig.1.into())
        }
    }
}

impl From<util::CharReadError> for Error {
    fn from(e: util::CharReadError) -> Self {
        use util::CharReadError::*;
        Error{
            pos: TextPosition::new(),
            kind: match e {
                UnexpectedEof => ErrorKind::UnexpectedEof,
                Utf8(ref reason) => ErrorKind::Utf8(reason.clone()),
                Io(ref io_error) =>
                    ErrorKind::Io(
                        io::Error::new(
                            io_error.kind(),
                            error_description(io_error)
                        )
                    ),
            }
        }
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error {
            pos: TextPosition::new(),
            kind: ErrorKind::Io(e),
        }
    }
}

impl Clone for ErrorKind {
    fn clone(&self) -> Self {
        use self::ErrorKind::*;
        match *self {
            UnexpectedEof => UnexpectedEof,
            Utf8(ref reason) => Utf8(reason.clone()),
            Io(ref io_error) => Io(io::Error::new(io_error.kind(), error_description(io_error))),
            Syntax(ref msg) => Syntax(msg.clone()),
        }
    }
}
impl PartialEq for ErrorKind {
    fn eq(&self, other: &ErrorKind) -> bool {
        use self::ErrorKind::*;
        match (self, other) {
            (&UnexpectedEof, &UnexpectedEof) => true,
            (&Utf8(ref left), &Utf8(ref right)) => left == right,
            (&Io(ref left), &Io(ref right)) =>
                left.kind() == right.kind() &&
                error_description(left) == error_description(right),
            (&Syntax(ref left), &Syntax(ref right)) =>
                left == right,

            (_, _) => false,
        }
    }
}
impl Eq for ErrorKind {}

fn error_description(e: &error::Error) -> &str { e.description() }
<commit_msg>Don’t clone/recreate in `impl From<util::CharReadError> for Error`<commit_after>
use std::io;
use std::borrow::Cow;
use std::fmt;
use std::error;
use std::str;

use util;
use common::{Position, TextPosition};

#[derive(Debug)]
pub enum ErrorKind {
    Syntax(Cow<'static, str>),
    Io(io::Error),
    Utf8(str::Utf8Error),
    UnexpectedEof,
}

/// An XML parsing error.
///
/// Consists of a 2D position in a document and a textual message describing the error.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Error {
    pos: TextPosition,
    kind: ErrorKind,
}

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

impl Position for Error {
    #[inline]
    fn position(&self) -> TextPosition { self.pos }
}

impl Error {
    /// Returns a reference to a message which is contained inside this error.
    #[inline]
    pub fn msg(&self) -> &str {
        use self::ErrorKind::*;
        match self.kind {
            UnexpectedEof => &"Unexpected EOF",
            Utf8(ref reason) => error_description(reason),
            Io(ref io_error) => error_description(io_error),
            Syntax(ref msg) => msg.as_ref(),
        }
    }

    pub fn kind(&self) -> &ErrorKind { &self.kind }
}

impl error::Error for Error {
    #[inline]
    fn description(&self) -> &str { self.msg() }
}

impl<'a, P, M> From<(&'a P, M)> for Error where P: Position, M: Into<Cow<'static, str>> {
    fn from(orig: (&'a P, M)) -> Self {
        Error{
            pos: orig.0.position(),
            kind: ErrorKind::Syntax(orig.1.into())
        }
    }
}

impl From<util::CharReadError> for Error {
    fn from(e: util::CharReadError) -> Self {
        use util::CharReadError::*;
        Error{
            pos: TextPosition::new(),
            kind: match e {
                UnexpectedEof => ErrorKind::UnexpectedEof,
                Utf8(reason) => ErrorKind::Utf8(reason),
                Io(io_error) => ErrorKind::Io(io_error),
            }
        }
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error {
            pos: TextPosition::new(),
            kind: ErrorKind::Io(e),
        }
    }
}

impl Clone for ErrorKind {
    fn clone(&self) -> Self {
        use self::ErrorKind::*;
        match *self {
            UnexpectedEof => UnexpectedEof,
            Utf8(ref reason) => Utf8(reason.clone()),
            Io(ref io_error) => Io(io::Error::new(io_error.kind(), error_description(io_error))),
            Syntax(ref msg) => Syntax(msg.clone()),
        }
    }
}
impl PartialEq for ErrorKind {
    fn eq(&self, other: &ErrorKind) -> bool {
        use self::ErrorKind::*;
        match (self, other) {
            (&UnexpectedEof, &UnexpectedEof) => true,
            (&Utf8(ref left), &Utf8(ref right)) => left == right,
            (&Io(ref left), &Io(ref right)) =>
                left.kind() == right.kind() &&
                error_description(left) == error_description(right),
            (&Syntax(ref left), &Syntax(ref right)) =>
                left == right,

            (_, _) => false,
        }
    }
}
impl Eq for ErrorKind {}

fn error_description(e: &error::Error) -> &str { e.description() }
<|endoftext|>


<commit_before>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate gfx;
extern crate gfx_app;

pub use gfx_app::ColorFormat;

gfx_vertex_struct!( Vertex {
    pos: [f32; 2] = "a_Pos",
    color: [f32; 3] = "a_Color",
});

gfx_pipeline!(pipe {
    vbuf: gfx::VertexBuffer<Vertex> = (),
    out: gfx::RenderTarget<ColorFormat> = "Target0",
});

struct App<R: gfx::Resources> {
    pso: gfx::PipelineState<R, pipe::Meta>,
    data: pipe::Data<R>,
    slice: gfx::Slice<R>,
}

impl<R: gfx::Resources> gfx_app::Application<R> for App<R> {
    fn new<F: gfx::Factory<R>>(mut factory: F, init: gfx_app::Init<R>) -> Self {
        use gfx::traits::FactoryExt;

        let vs = gfx_app::shade::Source {
            glsl_120: include_bytes!("shader/triangle_120.glslv"),
            glsl_150: include_bytes!("shader/triangle_150.glslv"),
            hlsl_40:  include_bytes!("data/vertex.fx"),
            .. gfx_app::shade::Source::empty()
        };
        let fs = gfx_app::shade::Source {
            glsl_120: include_bytes!("shader/triangle_120.glslf"),
            glsl_150: include_bytes!("shader/triangle_150.glslf"),
            hlsl_40:  include_bytes!("data/pixel.fx"),
            .. gfx_app::shade::Source::empty()
        };

        let vertex_data = [
            Vertex { pos: [ -0.5, -0.5 ], color: [1.0, 0.0, 0.0] },
            Vertex { pos: [  0.5, -0.5 ], color: [0.0, 1.0, 0.0] },
            Vertex { pos: [  0.0,  0.5 ], color: [0.0, 0.0, 1.0] },
        ];
        let (vbuf, slice) = factory.create_vertex_buffer(&vertex_data);

        App {
            pso: factory.create_pipeline_simple(
                vs.select(init.backend).unwrap(),
                fs.select(init.backend).unwrap(),
                gfx::state::CullFace::Nothing,
                pipe::new()
                ).unwrap(),
            data: pipe::Data {
                vbuf: vbuf,
                out: init.color,
            },
            slice: slice,
        }
    }

    fn render<C: gfx::CommandBuffer<R>>(&mut self, encoder: &mut gfx::Encoder<R, C>) {
        encoder.clear(&self.data.out, [0.1, 0.2, 0.3, 1.0]);
        encoder.draw(&self.slice, &self.pso, &self.data);
    }
}

pub fn main() {
    use gfx_app::Application;
    App::launch_default("Triangle example");
}
<commit_msg>Remove gfx_app dependency from triangle example<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate gfx_device_gl;
extern crate glutin;

use gfx::traits::FactoryExt;
use gfx::Device;

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

gfx_vertex_struct!(Vertex {
    pos: [f32; 2] = "a_Pos",
    color: [f32; 3] = "a_Color",
});

gfx_pipeline!(pipe {
    vbuf: gfx::VertexBuffer<Vertex> = (),
    out: gfx::RenderTarget<ColorFormat> = "Target0",
});

fn triangle() -> [Vertex; 3] { [
    Vertex { pos: [ -0.5, -0.5 ], color: [1.0, 0.0, 0.0] },
    Vertex { pos: [  0.5, -0.5 ], color: [0.0, 1.0, 0.0] },
    Vertex { pos: [  0.0,  0.5 ], color: [0.0, 0.0, 1.0] },
] }

fn clear_color() -> [f32; 4] {
    [0.1, 0.2, 0.3, 1.0]
}

pub fn main() {
    let builder = glutin::WindowBuilder::new()
        .with_title("Triangle example".to_string())
        .with_dimensions(1024, 768)
        .with_vsync();
    let (window, mut device, mut factory, main_color, _main_depth) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder);
    let command_buffer = factory.create_command_buffer();
    let mut encoder: gfx::Encoder<_, _> = command_buffer.into();
    let pso = factory.create_pipeline_simple(
        include_bytes!("shader/triangle_150.glslv"),
        include_bytes!("shader/triangle_150.glslf"),
        gfx::state::CullFace::Nothing,
        pipe::new()
    ).unwrap();
    let (vertex_buffer, slice) = factory.create_vertex_buffer(&triangle());
    let data = pipe::Data {
        vbuf: vertex_buffer,
        out: main_color
    };

    'main: loop {
        // loop over events
        for event in window.poll_events() {
            match event {
                glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) |
                glutin::Event::Closed => break 'main,
                _ => {},
            }
        }
        // draw a frame
        encoder.clear(&data.out, clear_color());
        encoder.draw(&slice, &pso, &data);
        window.swap_buffers().unwrap();
        device.cleanup();
        encoder.flush(&mut device);
    }
}
<|endoftext|>