<commit_before>//! # Handlebars
//!
//! [Handlebars](http://handlebarsjs.com/) is a modern and extensible templating solution originally created in the JavaScript world. It's used by many popular frameworks like [Ember.js](http://emberjs.com) and Chaplin. It's also ported to some other platforms such as [Java](https://github.com/jknack/handlebars.java).
//!
//! And this is handlebars Rust implementation, designed for general purpose text generation.
//!
//! ## Quick Start
//!
//! ```
//! extern crate handlebars;
//!
//! use std::collections::BTreeMap;
//! use handlebars::Handlebars;
//!
//! fn main() {
//!   // create the handlebars registry
//!   let mut handlebars = Handlebars::new();
//!
//!   // register the template. The template string will be verified and compiled.
//!   let source = "hello {{world}}";
//!   assert!(handlebars.register_template_string("t1", source).is_ok());
//!
//!   // Prepare some data.
//!   //
//!   // The data type should implements `rustc_serialize::json::ToJson` or
//!   // `serde::Serialize`
//!   let mut data = BTreeMap::new();
//!   data.insert("world".to_string(), "世界!".to_string());
//!   assert_eq!(handlebars.render("t1", &data).unwrap(), "hello 世界!");
//! }
//! ```
//!
//! In this example, we created a template registry and registered a template named `t1`.
//! Then we rendered a `BTreeMap` with an entry of key `world`, the result is just what
//! we expected.
//!
//! I recommend you to walk through handlebars.js' [intro page](http://handlebarsjs.com)
//! if you are not quite familiar with the template language itself.
//!
//! ## Rational: Why (this) Handlebars?
//!
//! Handlebars is a real-world templating system that you can use to build
//! your application without pain.
//!
//! ### Features
//!
//! #### Isolation of Rust and HTML
//!
//! This library doesn't attempt to use some macro magic to allow you to
//! write your template within your rust code. I admit that it's fun (and feel cool) to do
//! that but it doesn't fit real-world use case in my opinion.
//!
//! #### Limited but essential control structure built-in
//!
//! Only essential control directive `if` and `each` were built-in. This
//! prevents you to put too much application logic into your template.
//!
//! #### Extensible helper system
//!
//! You can write your own helper with Rust! It can be a block helper or
//! inline helper. Put you logic into the helper and don't repeat
//! yourself.
//!
//! #### Template inheritance
//!
//! Every time I look into a templating system, I will investigate its
//! support for [template
//! inheritance](https://docs.djangoproject.com/en/1.9/ref/templates/language/#template-inh
//! eritance).
//!
//! Template include is not enough. In most case you will need a skeleton
//! of page as parent (header, footer, etc.), and embed you page into this
//! parent.
//!
//! You can find a real example for template inheritance in
//! `examples/partials.rs`, and templates used by this file.
//!
//! ### Limitations
//!
//! #### Compatibility with JavaScript version
//!
//! This implementation is **not fully compatible** with the original javascript version.
//!
//! First of all, mustache block is not supported. I suggest you to use `#if` and `#each` for
//! same functionality.
//!
//! There are some other minor features missing:
//!
//! * Chained else [#12](https://github.com/sunng87/handlebars-rust/issues/12)
//!
//! Feel free to fire an issue on [github](https://github.com/sunng87/handlebars-rust/issues) if
//! you find missing features.
//!
//! #### Static typed
//!
//! As a static typed language, it's a little verbose to use handlebars.
//! You will have to make your data `ToJson`-able, so we can render
//! it. If you are on nightly channel, we have [a syntax
//! extension](https://github.com/sunng87/tojson_macros) to generate
//! default `ToJson` implementation for you. If you prefer
//! [serde](https://github.com/serde-rs/serde), you can enable `serde_type` feature
//! of handlebars-rust and add `#[Serialize]` for your types.
//!
//! ## Usage
//!
//! ### Template Creation and Registration
//!
//! Templates are created from String and registered to `Handlebars` with a name.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use handlebars::Handlebars;
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   let source = "hello {{world}}";
//!
//!   assert!(handlebars.register_template_string("t1", source).is_ok())
//! }
//! ```
//!
//! On registeration, the template is parsed, compiled and cached in the registry. So further
//! usage will benifite from the one-time work. Also features like include, inheritance
//! that involves template reference requires you to register those template first with
//! a name so the registry can find it.
//!
//! If you template is small or just to expirement, you can use `template_render` API
//! without registration.
//!
//! ```
//! extern crate handlebars;
//!
//! use handlebars::Handlebars;
//! use std::collections::BTreeMap;
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   let source = "hello {{world}}";
//!
//!   let mut data = BTreeMap::new();
//!   data.insert("world".to_string(), "世界!".to_string());
//!   assert_eq!(handlebars.template_render(source, &data).unwrap(),"hello 世界!".to_owned());
//! }
//! ```
//!
//! ### Rendering Something
//!
//! Since handlebars is originally based on JavaScript type system. It supports dynamic features like duck-typing, truthy/falsey values. But for a static language like Rust, this is a little difficult. As a solution, we are using the `serialize::json::Json` internally for data rendering.
//!
//! That means, if you want to render something, you have to ensure the data type implements the `rustc_serialize::json::ToJson` trait (or serde's `Serialize`). Luckily, most rust internal types already have that trait. However, if you want to render your custom struct, you need to implement it manually, or use [tojson_macros](https://github.com/sunng87/tojson_macros) to generate default `ToJson` implementation.
//!
//! You can use default `render` function to render a template into `String`. From 0.9, there's `renderw` to render text into anything of `std::io::Write`.
//!
//! ```ignore
//! extern crate rustc_serialize;
//! extern crate handlebars;
//!
//! use rustc_serialize::json::{Json, ToJson};
//! use std::collections::BTreeMap;
//!
//! use handlebars::Handlebars;
//!
//! struct Person {
//!   name: String,
//!   age: i16,
//! }
//!
//! impl ToJson for Person {
//!   fn to_json(&self) -> Json {
//!     let mut m: BTreeMap<String, Json> = BTreeMap::new();
//!     m.insert("name".to_string(), self.name.to_json());
//!     m.insert("age".to_string(), self.age.to_json());
//!     m.to_json()
//!   }
//! }
//!
//! fn main() {
//!   let source = "Hello, {{name}}";
//!
//!   let mut handlebars = Handlebars::new();
//!   assert!(handlebars.register_template_string("hello", source).is_ok());
//!
//!
//!   let data = Person {
//!       name: "Ning Sun".to_string(),
//!       age: 27
//!   };
//!   assert_eq!(handlebars.render("hello", &data).unwrap(), "Hello, Ning Sun".to_owned());
//! }
//! ```
//!
//! Or if you don't need the template to be cached or referenced by other ones, you can
//! simply render it without registering.
//!
//! ```ignore
//! fn main() {
//!   let source = "Hello, {{name}}";
//!
//!   let mut handlebars = Handlebars::new();
//!
//!   let data = Person {
//!       name: "Ning Sun".to_string(),
//!       age: 27
//!   };
//!   assert_eq!(handlebars.template_render("Hello, {{name}}", &data).unwrap(),
//!       "Hello, Ning Sun".to_owned());
//! }
//! ```
//!
//! #### Escaping
//!
//! As per the handlebars spec, output using `{{expression}}` is escaped by default (to be precise, the characters `&"<>` are replaced by their respective html / xml entities). However, since the use cases of a rust template engine are probably a bit more diverse than those of a JavaScript one, this implementation allows the user to supply a custom escape function to be used instead. For more information see the `EscapeFn` type and `Handlebars::register_escape_fn()` method.
//!
//! ### Custom Helper
//!
//! Handlebars is nothing without helpers. You can also create your own helpers with rust. Helpers in handlebars-rust are custom struct implements the `HelperDef` trait, concretely, the `call` function. For your convenience, most of stateless helpers can be implemented as bare functions.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use std::io::Write;
//! use handlebars::{Handlebars, HelperDef, RenderError, RenderContext, Helper, Context, JsonRender};
//!
//! // implement by a structure impls HelperDef
//! #[derive(Clone, Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn call(&self, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
//!     let param = h.param(0).unwrap();
//!
//!     try!(rc.writer.write("1st helper: ".as_bytes()));
//!     try!(rc.writer.write(param.value().render().into_bytes().as_ref()));
//!     Ok(())
//!   }
//! }
//!
//! // implement via bare function
//! fn another_simple_helper (h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
//!     let param = h.param(0).unwrap();
//!
//!     try!(rc.writer.write("2nd helper: ".as_bytes()));
//!     try!(rc.writer.write(param.value().render().into_bytes().as_ref()));
//!     Ok(())
//! }
//!
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_helper("simple-helper", Box::new(SimpleHelper));
//!   handlebars.register_helper("another-simple-helper", Box::new(another_simple_helper));
//!   // via closure
//!   handlebars.register_helper("closure-helper",
//!       Box::new(|h: &Helper, r: &Handlebars, rc: &mut RenderContext| -> Result<(), RenderError>{
//!           let param = h.param(0).unwrap();
//!
//!           try!(rc.writer.write("3rd helper: ".as_bytes()));
//!           try!(rc.writer.write(param.value().render().into_bytes().as_ref()));
//!           Ok(())
//!       }));
//!
//!   let tpl = "{{simple-helper 1}}\n{{another-simple-helper 2}}\n{{closure-helper 3}}";
//!   assert_eq!(handlebars.template_render(tpl, &()).unwrap(),
//!       "1st helper: 1\n2nd helper: 2\n3rd helper: 3".to_owned());
//! }
//! ```
//!
//! #### Arguments of HelpDef
//!
//! You can get data from the `Helper` argument about the template information:
//!
//! * `name()` for the helper name. This is known to you for most situation but if you are defining `helperMissing` or `blockHelperMissing`, this is important.
//! * `params()` is a vector of parameter value in helper, like `{{#somehelper param1 param2 param3}}`.
//! * `param(n)` returns value of the index
//! * `hash()` is a map of String key and Json value, defined in helper as `{{@somehelper a=1 b="2" c=true}}`.
//! * `hash_get(key)` returns value of the key
//! * `template()` gives you the nested template of block helper.
//! * `inverse()` gives you the inversed template of it, inversed template is the template behind `{{else}}`.
//!
//! You can learn more about helpers by looking into source code of built-in helpers.
//!
//! #### Built-in Helpers
//!
//! * `{{#raw}} ... {{/raw}}` escape handlebars expression within the block
//! * `{{#if ...}} ... {{else}} ... {{/if}}` if-else block
//! * `{{#unless ...}} ... {{else}} .. {{/unless}}` if-not-else block
//! * `{{#each ...}} ... {{/each}}` iterates over an array or object. Handlebar-rust doesn't support mustach iteration syntax so use this instead.
//! * `{{#with ...}} ... {{/with}}` change current context. Similar to {{#each}}, used for replace corresponding mustach syntax.
//! * `{{lookup ... ...}}` get value from array by `@index` or `@key`
//! * `{{> ...}}` include template with name
//! * `{{log ...}}` log value with rust logger, default level: INFO. Currently you cannot change the level.
//!
//! ### Template inheritance
//!
//! Handlebarsjs partial system is fully supported in this implementation.
//! Check [example](https://github.com/sunng87/handlebars-rust/blob/master/examples/partials.rs#L49) for detail.
//!
//!

#![allow(dead_code)]
#![recursion_limit = "200"]

#[macro_use]
extern crate log;
#[macro_use]
extern crate quick_error;
#[macro_use]
extern crate pest;
#[macro_use]
extern crate lazy_static;

extern crate regex;

#[cfg(test)]
#[macro_use]
extern crate maplit;

#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))]
extern crate rustc_serialize as serialize;

#[cfg(feature = "serde_type")]
extern crate serde_json;

pub use self::template::Template;
pub use self::error::{TemplateError, TemplateFileError, TemplateRenderError};
pub use self::registry::{EscapeFn, no_escape, html_escape, Registry as Handlebars};
pub use self::render::{RenderError, RenderContext, Helper, ContextJson, Directive as Decorator};
pub use self::helpers::HelperDef;
pub use self::directives::DirectiveDef as DecoratorDef;
pub use self::context::{Context, JsonRender, JsonTruthy};

mod grammar;
mod template;
mod error;
mod registry;
mod render;
mod helpers;
mod context;
mod support;
mod directives;
#[cfg(feature="partial4")]
mod partial;
<commit_msg>Revert "(feat) do not export Renderable trait"<commit_after>//! # Handlebars
//!
//! [Handlebars](http://handlebarsjs.com/) is a modern and extensible templating solution originally created in the JavaScript world. It's used by many popular frameworks like [Ember.js](http://emberjs.com) and Chaplin. It's also ported to some other platforms such as [Java](https://github.com/jknack/handlebars.java).
//!
//! And this is handlebars Rust implementation, designed for general purpose text generation.
//!
//! ## Quick Start
//!
//! ```
//! extern crate handlebars;
//!
//! use std::collections::BTreeMap;
//! use handlebars::Handlebars;
//!
//! fn main() {
//!   // create the handlebars registry
//!   let mut handlebars = Handlebars::new();
//!
//!   // register the template. The template string will be verified and compiled.
//!   let source = "hello {{world}}";
//!   assert!(handlebars.register_template_string("t1", source).is_ok());
//!
//!   // Prepare some data.
//!   //
//!   // The data type should implements `rustc_serialize::json::ToJson` or
//!   // `serde::Serialize`
//!   let mut data = BTreeMap::new();
//!   data.insert("world".to_string(), "世界!".to_string());
//!   assert_eq!(handlebars.render("t1", &data).unwrap(), "hello 世界!");
//! }
//! ```
//!
//! In this example, we created a template registry and registered a template named `t1`.
//! Then we rendered a `BTreeMap` with an entry of key `world`, the result is just what
//! we expected.
//!
//! I recommend you to walk through handlebars.js' [intro page](http://handlebarsjs.com)
//! if you are not quite familiar with the template language itself.
//!
//! ## Rational: Why (this) Handlebars?
//!
//! Handlebars is a real-world templating system that you can use to build
//! your application without pain.
//!
//! ### Features
//!
//! #### Isolation of Rust and HTML
//!
//! This library doesn't attempt to use some macro magic to allow you to
//! write your template within your rust code. I admit that it's fun (and feel cool) to do
//! that but it doesn't fit real-world use case in my opinion.
//!
//! #### Limited but essential control structure built-in
//!
//! Only essential control directive `if` and `each` were built-in. This
//! prevents you to put too much application logic into your template.
//!
//! #### Extensible helper system
//!
//! You can write your own helper with Rust! It can be a block helper or
//! inline helper. Put you logic into the helper and don't repeat
//! yourself.
//!
//! #### Template inheritance
//!
//! Every time I look into a templating system, I will investigate its
//! support for [template
//! inheritance](https://docs.djangoproject.com/en/1.9/ref/templates/language/#template-inh
//! eritance).
//!
//! Template include is not enough. In most case you will need a skeleton
//! of page as parent (header, footer, etc.), and embed you page into this
//! parent.
//!
//! You can find a real example for template inheritance in
//! `examples/partials.rs`, and templates used by this file.
//!
//! ### Limitations
//!
//! #### Compatibility with JavaScript version
//!
//! This implementation is **not fully compatible** with the original javascript version.
//!
//! First of all, mustache block is not supported. I suggest you to use `#if` and `#each` for
//! same functionality.
//!
//! There are some other minor features missing:
//!
//! * Chained else [#12](https://github.com/sunng87/handlebars-rust/issues/12)
//!
//! Feel free to fire an issue on [github](https://github.com/sunng87/handlebars-rust/issues) if
//! you find missing features.
//!
//! #### Static typed
//!
//! As a static typed language, it's a little verbose to use handlebars.
//! You will have to make your data `ToJson`-able, so we can render
//! it. If you are on nightly channel, we have [a syntax
//! extension](https://github.com/sunng87/tojson_macros) to generate
//! default `ToJson` implementation for you. If you prefer
//! [serde](https://github.com/serde-rs/serde), you can enable `serde_type` feature
//! of handlebars-rust and add `#[Serialize]` for your types.
//!
//! ## Usage
//!
//! ### Template Creation and Registration
//!
//! Templates are created from String and registered to `Handlebars` with a name.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use handlebars::Handlebars;
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   let source = "hello {{world}}";
//!
//!   assert!(handlebars.register_template_string("t1", source).is_ok())
//! }
//! ```
//!
//! On registeration, the template is parsed, compiled and cached in the registry. So further
//! usage will benifite from the one-time work. Also features like include, inheritance
//! that involves template reference requires you to register those template first with
//! a name so the registry can find it.
//!
//! If you template is small or just to expirement, you can use `template_render` API
//! without registration.
//!
//! ```
//! extern crate handlebars;
//!
//! use handlebars::Handlebars;
//! use std::collections::BTreeMap;
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   let source = "hello {{world}}";
//!
//!   let mut data = BTreeMap::new();
//!   data.insert("world".to_string(), "世界!".to_string());
//!   assert_eq!(handlebars.template_render(source, &data).unwrap(),"hello 世界!".to_owned());
//! }
//! ```
//!
//! ### Rendering Something
//!
//! Since handlebars is originally based on JavaScript type system. It supports dynamic features like duck-typing, truthy/falsey values. But for a static language like Rust, this is a little difficult. As a solution, we are using the `serialize::json::Json` internally for data rendering.
//!
//! That means, if you want to render something, you have to ensure the data type implements the `rustc_serialize::json::ToJson` trait (or serde's `Serialize`). Luckily, most rust internal types already have that trait. However, if you want to render your custom struct, you need to implement it manually, or use [tojson_macros](https://github.com/sunng87/tojson_macros) to generate default `ToJson` implementation.
//!
//! You can use default `render` function to render a template into `String`. From 0.9, there's `renderw` to render text into anything of `std::io::Write`.
//!
//! ```ignore
//! extern crate rustc_serialize;
//! extern crate handlebars;
//!
//! use rustc_serialize::json::{Json, ToJson};
//! use std::collections::BTreeMap;
//!
//! use handlebars::Handlebars;
//!
//! struct Person {
//!   name: String,
//!   age: i16,
//! }
//!
//! impl ToJson for Person {
//!   fn to_json(&self) -> Json {
//!     let mut m: BTreeMap<String, Json> = BTreeMap::new();
//!     m.insert("name".to_string(), self.name.to_json());
//!     m.insert("age".to_string(), self.age.to_json());
//!     m.to_json()
//!   }
//! }
//!
//! fn main() {
//!   let source = "Hello, {{name}}";
//!
//!   let mut handlebars = Handlebars::new();
//!   assert!(handlebars.register_template_string("hello", source).is_ok());
//!
//!
//!   let data = Person {
//!       name: "Ning Sun".to_string(),
//!       age: 27
//!   };
//!   assert_eq!(handlebars.render("hello", &data).unwrap(), "Hello, Ning Sun".to_owned());
//! }
//! ```
//!
//! Or if you don't need the template to be cached or referenced by other ones, you can
//! simply render it without registering.
//!
//! ```ignore
//! fn main() {
//!   let source = "Hello, {{name}}";
//!
//!   let mut handlebars = Handlebars::new();
//!
//!   let data = Person {
//!       name: "Ning Sun".to_string(),
//!       age: 27
//!   };
//!   assert_eq!(handlebars.template_render("Hello, {{name}}", &data).unwrap(),
//!       "Hello, Ning Sun".to_owned());
//! }
//! ```
//!
//! #### Escaping
//!
//! As per the handlebars spec, output using `{{expression}}` is escaped by default (to be precise, the characters `&"<>` are replaced by their respective html / xml entities). However, since the use cases of a rust template engine are probably a bit more diverse than those of a JavaScript one, this implementation allows the user to supply a custom escape function to be used instead. For more information see the `EscapeFn` type and `Handlebars::register_escape_fn()` method.
//!
//! ### Custom Helper
//!
//! Handlebars is nothing without helpers. You can also create your own helpers with rust. Helpers in handlebars-rust are custom struct implements the `HelperDef` trait, concretely, the `call` function. For your convenience, most of stateless helpers can be implemented as bare functions.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use std::io::Write;
//! use handlebars::{Handlebars, HelperDef, RenderError, RenderContext, Helper, Context, JsonRender};
//!
//! // implement by a structure impls HelperDef
//! #[derive(Clone, Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn call(&self, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
//!     let param = h.param(0).unwrap();
//!
//!     try!(rc.writer.write("1st helper: ".as_bytes()));
//!     try!(rc.writer.write(param.value().render().into_bytes().as_ref()));
//!     Ok(())
//!   }
//! }
//!
//! // implement via bare function
//! fn another_simple_helper (h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
//!     let param = h.param(0).unwrap();
//!
//!     try!(rc.writer.write("2nd helper: ".as_bytes()));
//!     try!(rc.writer.write(param.value().render().into_bytes().as_ref()));
//!     Ok(())
//! }
//!
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_helper("simple-helper", Box::new(SimpleHelper));
//!   handlebars.register_helper("another-simple-helper", Box::new(another_simple_helper));
//!   // via closure
//!   handlebars.register_helper("closure-helper",
//!       Box::new(|h: &Helper, r: &Handlebars, rc: &mut RenderContext| -> Result<(), RenderError>{
//!           let param = h.param(0).unwrap();
//!
//!           try!(rc.writer.write("3rd helper: ".as_bytes()));
//!           try!(rc.writer.write(param.value().render().into_bytes().as_ref()));
//!           Ok(())
//!       }));
//!
//!   let tpl = "{{simple-helper 1}}\n{{another-simple-helper 2}}\n{{closure-helper 3}}";
//!   assert_eq!(handlebars.template_render(tpl, &()).unwrap(),
//!       "1st helper: 1\n2nd helper: 2\n3rd helper: 3".to_owned());
//! }
//! ```
//!
//! #### Arguments of HelpDef
//!
//! You can get data from the `Helper` argument about the template information:
//!
//! * `name()` for the helper name. This is known to you for most situation but if you are defining `helperMissing` or `blockHelperMissing`, this is important.
//! * `params()` is a vector of parameter value in helper, like `{{#somehelper param1 param2 param3}}`.
//! * `param(n)` returns value of the index
//! * `hash()` is a map of String key and Json value, defined in helper as `{{@somehelper a=1 b="2" c=true}}`.
//! * `hash_get(key)` returns value of the key
//! * `template()` gives you the nested template of block helper.
//! * `inverse()` gives you the inversed template of it, inversed template is the template behind `{{else}}`.
//!
//! You can learn more about helpers by looking into source code of built-in helpers.
//!
//! #### Built-in Helpers
//!
//! * `{{#raw}} ... {{/raw}}` escape handlebars expression within the block
//! * `{{#if ...}} ... {{else}} ... {{/if}}` if-else block
//! * `{{#unless ...}} ... {{else}} .. {{/unless}}` if-not-else block
//! * `{{#each ...}} ... {{/each}}` iterates over an array or object. Handlebar-rust doesn't support mustach iteration syntax so use this instead.
//! * `{{#with ...}} ... {{/with}}` change current context. Similar to {{#each}}, used for replace corresponding mustach syntax.
//! * `{{lookup ... ...}}` get value from array by `@index` or `@key`
//! * `{{> ...}}` include template with name
//! * `{{log ...}}` log value with rust logger, default level: INFO. Currently you cannot change the level.
//!
//! ### Template inheritance
//!
//! Handlebarsjs partial system is fully supported in this implementation.
//! Check [example](https://github.com/sunng87/handlebars-rust/blob/master/examples/partials.rs#L49) for detail.
//!
//!

#![allow(dead_code)]
#![recursion_limit = "200"]

#[macro_use]
extern crate log;
#[macro_use]
extern crate quick_error;
#[macro_use]
extern crate pest;
#[macro_use]
extern crate lazy_static;

extern crate regex;

#[cfg(test)]
#[macro_use]
extern crate maplit;

#[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))]
extern crate rustc_serialize as serialize;

#[cfg(feature = "serde_type")]
extern crate serde_json;

pub use self::template::Template;
pub use self::error::{TemplateError, TemplateFileError, TemplateRenderError};
pub use self::registry::{EscapeFn, no_escape, html_escape, Registry as Handlebars};
pub use self::render::{Renderable, RenderError, RenderContext, Helper, ContextJson,
                       Directive as Decorator};
pub use self::helpers::HelperDef;
pub use self::directives::DirectiveDef as DecoratorDef;
pub use self::context::{Context, JsonRender, JsonTruthy};

mod grammar;
mod template;
mod error;
mod registry;
mod render;
mod helpers;
mod context;
mod support;
mod directives;
#[cfg(feature="partial4")]
mod partial;
<|endoftext|>


<commit_before>#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
extern crate core;

extern crate byteorder;
pub mod chacha20;
pub mod curve25519;
pub mod gcm;
pub mod hkdf;
pub mod hmac;
pub mod poly1305;
pub mod sha2;
pub mod util;
pub(crate) mod aes;
pub(crate) mod const_curve25519;
pub(crate) mod ghash;

#[cfg(not(feature = "std"))]
#[macro_use]
pub(crate) extern crate std;

#[cfg(test)]
pub mod test_helpers {
    use std::str;
    use std::vec::Vec;

    // ew
    pub fn h2b(s: &str) -> Vec<u8> {
        s.as_bytes()
            .chunks(2)
            .map(|x| {
                u8::from_str_radix(str::from_utf8(x).unwrap(), 16).unwrap()
            })
            .collect()
    }
}
<commit_msg>aes: make public<commit_after>#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
extern crate core;

extern crate byteorder;
pub mod aes;
pub mod chacha20;
pub mod curve25519;
pub mod gcm;
pub mod hkdf;
pub mod hmac;
pub mod poly1305;
pub mod sha2;
pub mod util;
pub(crate) mod const_curve25519;
pub(crate) mod ghash;

#[cfg(not(feature = "std"))]
#[macro_use]
pub(crate) extern crate std;

#[cfg(test)]
pub mod test_helpers {
    use std::str;
    use std::vec::Vec;

    // ew
    pub fn h2b(s: &str) -> Vec<u8> {
        s.as_bytes()
            .chunks(2)
            .map(|x| {
                u8::from_str_radix(str::from_utf8(x).unwrap(), 16).unwrap()
            })
            .collect()
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use unique::Unique;
use std::ptr::{self};
use std::ffi::{CStr,CString};
use std::default::Default;
use std::path::Path;
use std::slice;
use std::ops::Deref;
use std::str;
use std::fmt;
use std::convert::From;
mod raw;
mod unique;

use self::Error::*;

const PCAP_ERROR_NOT_ACTIVATED: i32 = -3;

/// An error received from pcap
#[derive(Debug)]
pub enum Error {
    MalformedError(str::Utf8Error),
    PcapError(String)
}

impl Error {
    fn new<T>(ptr: *const libc::c_char) -> Result<T, Error> {
        Err(PcapError(try!(cstr_to_string(ptr))))
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            MalformedError(e) => {
                write!(f, "pcap returned an error that was not encoded properly: {}", e)
            },
            PcapError(ref e) => {
                write!(f, "pcap error: {}", e)
            }
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            MalformedError(..) => "error message from pcap is invalid",
            PcapError(..) => "pcap FFI error"
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            MalformedError(ref e) => Some(e),
            _ => None
        }
    }
}

impl From<str::Utf8Error> for Error {
    fn from(obj: str::Utf8Error) -> Error {
        MalformedError(obj)
    }
}

/// An iterator over devices that pcap is aware about on the system.
pub struct Devices {
    orig: Unique<raw::Struct_pcap_if>,
    device: Unique<raw::Struct_pcap_if>
}

impl Devices {
    /// Construct a new `Devices` iterator by internally using `pcap_findalldevs()`
    pub fn list_all() -> Result<Devices, Error> {
        unsafe {
            let mut errbuf = [0i8; 256];
            let mut dev_buf: *mut raw::Struct_pcap_if = ptr::null_mut();

            match raw::pcap_findalldevs(&mut dev_buf, errbuf.as_mut_ptr()) {
                0 => {
                    Ok(Devices {
                        orig: Unique::new(dev_buf),
                        device: Unique::new(dev_buf)
                    })
                },
                _ => {
                    Error::new(errbuf.as_ptr())
                }
            }
        }
    }
}

impl Iterator for Devices {
    type Item = Device;

    fn next(&mut self) -> Option<Device> {
        if self.device.is_null() {
            None
        } else {
            unsafe {
                let ret = Device {
                    name: cstr_to_string(self.device.get().name).unwrap(),
                    desc: {
                        if !self.device.get().description.is_null() {
                            Some(cstr_to_string(self.device.get().description).unwrap())
                        } else {
                            None
                        }
                    }
                };
                self.device = Unique::new(self.device.get().next);

                Some(ret)
            }
        }
    }
}

impl Drop for Devices {
    fn drop(&mut self) {
        unsafe {
            raw::pcap_freealldevs(*self.orig);
        }
    }
}

#[derive(Debug)]
/// A network device as returned from `Devices::list_all()`.
pub struct Device {
    pub name: String,
    pub desc: Option<String>
}

impl Device {
    /// Returns the default Device suitable for captures according to pcap_lookupdev,
    /// or an error from pcap.
    pub fn lookup() -> Result<Device, Error> {
        let mut errbuf = [0i8; 256];

        unsafe {
            let default_name = raw::pcap_lookupdev(errbuf.as_mut_ptr());

            if default_name.is_null() {
                return Error::new(errbuf.as_ptr());
            }

            Ok(Device {
                name: try!(cstr_to_string(default_name)),
                desc: None
            })
        }
    }
}

impl AsRef<str> for Device {
    fn as_ref(&self) -> &str {
        &*self.name
    }
}

/// This is a datalink link type returned from pcap.
#[derive(Debug)]
pub struct Linktype(pub i32);

impl Linktype {
    /// Gets the name of the link type, such as EN10MB
    pub fn get_name(&self) -> Result<String, Error> {
        unsafe {
            Ok(try!(cstr_to_string(raw::pcap_datalink_val_to_name(self.0))))
        }
    }

    /// Gets the description of a link type.
    pub fn get_description(&self) -> Result<String, Error> {
        unsafe {
            Ok(try!(cstr_to_string(raw::pcap_datalink_val_to_description(self.0))))
        }
    }
}

/// This is a builder for a `Capture` handle. It's useful when you want to specify certain
/// parameters, like promiscuous mode, or buffer length, before opening.
///
/// You can use `Capture::from_device()` instead of this builder, with less flexibility.
pub struct CaptureBuilder {
    buffer_size: i32,
    snaplen: i32,
    promisc: i32,
    rfmon: Option<i32>,
    timeout: i32,
}

impl CaptureBuilder {
    /// Creates a `CaptureBuilder` with sensible defaults.
    pub fn new() -> CaptureBuilder {
        CaptureBuilder {
            buffer_size: 1000000,
            snaplen: 65535,
            promisc: 0,
            rfmon: None,
            timeout: 0
        }
    }

    /// Open a `Capture` with this `CaptureBuilder` with the given device. You can
    /// provide a `Device` or an &str name of the device/source you would like to open.
    pub fn open<D: AsRef<str>>(&self, device: D) -> Result<Capture, Error> {
        let name = CString::new(device.as_ref()).unwrap();
        // TODO: handle errors better throughout this library
        let mut errbuf = [0i8; 256];

        unsafe {
            let handle = raw::pcap_create(name.as_ptr(), errbuf.as_mut_ptr());
            if handle.is_null() {
                return Error::new(errbuf.as_ptr());
            }

            let cap = Capture {
                handle: Unique::new(handle)
            };

            raw::pcap_set_snaplen(handle, self.snaplen);
            raw::pcap_set_buffer_size(handle, self.buffer_size);
            raw::pcap_set_promisc(handle, self.promisc);
            match self.rfmon {
                Some(rfmon) => {
                    raw::pcap_set_rfmon(handle, rfmon);
                },
                None => {}
            };
            raw::pcap_set_timeout(handle, self.timeout);

            if 0 != raw::pcap_activate(handle) {
                return Error::new(raw::pcap_geterr(handle));
            }

            Ok(cap)
        }
    }

    /// Set the read timeout for the Capture. By default, this is 0, so it will block
    /// indefinitely.
    pub fn timeout(&mut self, ms: i32) -> &mut CaptureBuilder {
        self.timeout = ms;
        self
    }

    /// Set promiscuous mode on or off. By default, this is off.
    pub fn promisc(&mut self, to: bool) -> &mut CaptureBuilder {
        self.promisc = if to {1} else {0};
        self
    }

    /// Set rfmon mode on or off. The default is maintained by pcap.
    pub fn rfmon(&mut self, to: bool) -> &mut CaptureBuilder {
        self.rfmon = Some(if to {1} else {0});
        self
    }

    /// Set the buffer size for incoming packet data.
    ///
    /// The default is 1000000. This should always be larger than the snaplen.
    pub fn buffer_size(&mut self, to: i32) -> &mut CaptureBuilder {
        self.buffer_size = to;
        self
    }

    /// Set the snaplen size (the maximum length of a packet captured into the buffer).
    /// Useful if you only want certain headers, but not the entire packet.
    ///
    /// The default is 65535
    pub fn snaplen(&mut self, to: i32) -> &mut CaptureBuilder {
        self.snaplen = to;
        self
    }
}

/// Represents a packet returned from pcap. This can be dereferenced to access
/// the underlying packet `[u8]` slice.
pub struct Packet<'a> {
    header: &'a raw::Struct_pcap_pkthdr,
    data: &'a libc::c_uchar
}

impl<'b> Deref for Packet<'b> {
    type Target = [u8];

    fn deref<'a>(&'a self) -> &'a [u8] {
        unsafe {
            slice::from_raw_parts(self.data, self.header.caplen as usize)
        }
    }
}

impl<'a> std::fmt::Debug for Packet<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        self.deref().fmt(f)
    }
}

/// This represents an open capture handle attached to a device or file.
///
/// Internally it represents a `pcap_t`.
pub struct Capture {
    handle: Unique<raw::pcap_t>
}

impl Capture {
    /// Creates a capture handle from the specified device, or an error from pcap.
    ///
    /// You can provide this a `Device` from `Devices::list_all()` or an `&str` name of
    /// the device such as "any" on Linux.
    pub fn from_device<D: AsRef<str>>(device: D) -> Result<Capture, Error> {
        CaptureBuilder::new().open(device)
    }

    /// Creates a capture handle from the specified file, or an error from pcap.
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Capture, Error> {
        let name = CString::new(path.as_ref().to_str().unwrap()).unwrap();
        let mut errbuf = [0i8; 256];

        unsafe {
            let handle = raw::pcap_open_offline(name.as_ptr(), errbuf.as_mut_ptr());
            if handle.is_null() {
                return Error::new(errbuf.as_ptr());
            }

            let cap = Capture {
                handle: Unique::new(handle)
            };

            Ok(cap)
        }
    }

    /// List the datalink types that this captured device supports.
    pub fn list_datalinks(&mut self) -> Result<Vec<Linktype>, Error> {
        unsafe {
            let mut links: *mut i32 = ptr::null_mut();

            let num = raw::pcap_list_datalinks(*self.handle, &mut links);

            if num == PCAP_ERROR_NOT_ACTIVATED {
                raw::pcap_free_datalinks(links);
                panic!("It should not be possible to run list_datalinks on a Capture that is not activated, please report this bug!")
            } else if num < 0 {
                raw::pcap_free_datalinks(links);
                Error::new(raw::pcap_geterr(*self.handle))
            } else {
                let slice = slice::from_raw_parts(links, num as usize).iter().map(|&a| Linktype(a)).collect();
                raw::pcap_free_datalinks(links);

                Ok(slice)
            }
        }
    }

    /// Set the datalink type for the current capture handle.
    pub fn set_datalink(&mut self, linktype: Linktype) -> Result<(), Error> {
        unsafe {
            match raw::pcap_set_datalink(*self.handle, linktype.0) {
                0 => {
                    Ok(())
                },
                _ => {
                    Error::new(raw::pcap_geterr(*self.handle))
                }
            }
        }
    }

    /// Get the current datalink type for this capture handle.
    pub fn get_datalink(&mut self) -> Linktype {
        unsafe {
            match raw::pcap_datalink(*self.handle) {
                PCAP_ERROR_NOT_ACTIVATED => {
                    panic!("It should not be possible to run get_datalink on a Capture that is not activated, please report this bug!");
                },
                lt => {
                    Linktype(lt)
                }
            }
        }
    }

    /// Blocks until a packet is returned from the capture handle or an error occurs.
    ///
    /// pcap captures packets and places them into a buffer which this function reads
    /// from. This buffer has a finite length, so if the buffer fills completely new
    /// packets will be discarded temporarily. This means that in realtime situations,
    /// you probably want to minimize the time between calls of this next() method.
    pub fn next<'a>(&'a mut self) -> Option<Packet<'a>> {
        unsafe {
            let mut header: *mut raw::Struct_pcap_pkthdr = ptr::null_mut();
            let mut packet: *const libc::c_uchar = ptr::null();
            match raw::pcap_next_ex(*self.handle, &mut header, &mut packet) {
                1 => {
                    // packet was read without issue
                    Some(Packet {
                        header: &*header,
                        data: &*packet
                    })
                },
                _ => {
                    None
                }
            }
        }
    }

    /// Adds a filter to the capture using the given BPF program string. Internally
    /// this is compiled using `pcap_compile()`.
    ///
    /// See http://biot.com/capstats/bpf.html for more information about this syntax.
    pub fn filter(&mut self, program: &str) -> Result<(), Error> {
        let program = CString::new(program).unwrap();

        unsafe {
            let mut bpf_program: raw::Struct_bpf_program = Default::default();

            if -1 == raw::pcap_compile(*self.handle, &mut bpf_program, program.as_ptr(), 0, 0) {
                return Error::new(raw::pcap_geterr(*self.handle));
            }

            if -1 == raw::pcap_setfilter(*self.handle, &mut bpf_program) {
                raw::pcap_freecode(&mut bpf_program);
                return Error::new(raw::pcap_geterr(*self.handle));
            }

            raw::pcap_freecode(&mut bpf_program);
            Ok(())
        }
    }
}

impl Drop for Capture {
    fn drop(&mut self) {
        unsafe {
            raw::pcap_close(*self.handle)
        }
    }
}

fn cstr_to_string(ptr: *const libc::c_char) -> Result<String, str::Utf8Error> {
    Ok(try!(str::from_utf8(unsafe{CStr::from_ptr(ptr)}.to_bytes())).to_string())
}
<commit_msg>Change uses of AsRef<str> to Into<Device> (I feel like it's more ergonomic).<commit_after>extern crate libc;

use unique::Unique;
use std::ptr::{self};
use std::ffi::{CStr,CString};
use std::default::Default;
use std::path::Path;
use std::slice;
use std::ops::Deref;
use std::str;
use std::fmt;
use std::convert::From;
mod raw;
mod unique;

use self::Error::*;

const PCAP_ERROR_NOT_ACTIVATED: i32 = -3;

/// An error received from pcap
#[derive(Debug)]
pub enum Error {
    MalformedError(str::Utf8Error),
    PcapError(String)
}

impl Error {
    fn new<T>(ptr: *const libc::c_char) -> Result<T, Error> {
        Err(PcapError(try!(cstr_to_string(ptr))))
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            MalformedError(e) => {
                write!(f, "pcap returned an error that was not encoded properly: {}", e)
            },
            PcapError(ref e) => {
                write!(f, "pcap error: {}", e)
            }
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            MalformedError(..) => "error message from pcap is invalid",
            PcapError(..) => "pcap FFI error"
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            MalformedError(ref e) => Some(e),
            _ => None
        }
    }
}

impl From<str::Utf8Error> for Error {
    fn from(obj: str::Utf8Error) -> Error {
        MalformedError(obj)
    }
}

/// An iterator over devices that pcap is aware about on the system.
pub struct Devices {
    orig: Unique<raw::Struct_pcap_if>,
    device: Unique<raw::Struct_pcap_if>
}

impl Devices {
    /// Construct a new `Devices` iterator by internally using `pcap_findalldevs()`
    pub fn list_all() -> Result<Devices, Error> {
        unsafe {
            let mut errbuf = [0i8; 256];
            let mut dev_buf: *mut raw::Struct_pcap_if = ptr::null_mut();

            match raw::pcap_findalldevs(&mut dev_buf, errbuf.as_mut_ptr()) {
                0 => {
                    Ok(Devices {
                        orig: Unique::new(dev_buf),
                        device: Unique::new(dev_buf)
                    })
                },
                _ => {
                    Error::new(errbuf.as_ptr())
                }
            }
        }
    }
}

impl Iterator for Devices {
    type Item = Device;

    fn next(&mut self) -> Option<Device> {
        if self.device.is_null() {
            None
        } else {
            unsafe {
                let ret = Device {
                    name: cstr_to_string(self.device.get().name).unwrap(),
                    desc: {
                        if !self.device.get().description.is_null() {
                            Some(cstr_to_string(self.device.get().description).unwrap())
                        } else {
                            None
                        }
                    }
                };
                self.device = Unique::new(self.device.get().next);

                Some(ret)
            }
        }
    }
}

impl Drop for Devices {
    fn drop(&mut self) {
        unsafe {
            raw::pcap_freealldevs(*self.orig);
        }
    }
}

#[derive(Debug)]
/// A network device as returned from `Devices::list_all()`.
pub struct Device {
    pub name: String,
    pub desc: Option<String>
}

impl Device {
    /// Returns the default Device suitable for captures according to pcap_lookupdev,
    /// or an error from pcap.
    pub fn lookup() -> Result<Device, Error> {
        let mut errbuf = [0i8; 256];

        unsafe {
            let default_name = raw::pcap_lookupdev(errbuf.as_mut_ptr());

            if default_name.is_null() {
                return Error::new(errbuf.as_ptr());
            }

            Ok(Device {
                name: try!(cstr_to_string(default_name)),
                desc: None
            })
        }
    }
}

impl<'a> Into<Device> for &'a str {
    fn into(self) -> Device {
        Device {
            name: self.into(),
            desc: None
        }
    }
}

/// This is a datalink link type returned from pcap.
#[derive(Debug)]
pub struct Linktype(pub i32);

impl Linktype {
    /// Gets the name of the link type, such as EN10MB
    pub fn get_name(&self) -> Result<String, Error> {
        unsafe {
            Ok(try!(cstr_to_string(raw::pcap_datalink_val_to_name(self.0))))
        }
    }

    /// Gets the description of a link type.
    pub fn get_description(&self) -> Result<String, Error> {
        unsafe {
            Ok(try!(cstr_to_string(raw::pcap_datalink_val_to_description(self.0))))
        }
    }
}

/// This is a builder for a `Capture` handle. It's useful when you want to specify certain
/// parameters, like promiscuous mode, or buffer length, before opening.
///
/// You can use `Capture::from_device()` instead of this builder, with less flexibility.
pub struct CaptureBuilder {
    buffer_size: i32,
    snaplen: i32,
    promisc: i32,
    rfmon: Option<i32>,
    timeout: i32,
}

impl CaptureBuilder {
    /// Creates a `CaptureBuilder` with sensible defaults.
    pub fn new() -> CaptureBuilder {
        CaptureBuilder {
            buffer_size: 1000000,
            snaplen: 65535,
            promisc: 0,
            rfmon: None,
            timeout: 0
        }
    }

    /// Open a `Capture` with this `CaptureBuilder` with the given device. You can
    /// provide a `Device` or an &str name of the device/source you would like to open.
    pub fn open<D: Into<Device>>(&self, device: D) -> Result<Capture, Error> {
        let device: Device = device.into();
        let name = CString::new(device.name).unwrap();
        // TODO: handle errors better throughout this library
        let mut errbuf = [0i8; 256];

        unsafe {
            let handle = raw::pcap_create(name.as_ptr(), errbuf.as_mut_ptr());
            if handle.is_null() {
                return Error::new(errbuf.as_ptr());
            }

            let cap = Capture {
                handle: Unique::new(handle)
            };

            raw::pcap_set_snaplen(handle, self.snaplen);
            raw::pcap_set_buffer_size(handle, self.buffer_size);
            raw::pcap_set_promisc(handle, self.promisc);
            match self.rfmon {
                Some(rfmon) => {
                    raw::pcap_set_rfmon(handle, rfmon);
                },
                None => {}
            };
            raw::pcap_set_timeout(handle, self.timeout);

            if 0 != raw::pcap_activate(handle) {
                return Error::new(raw::pcap_geterr(handle));
            }

            Ok(cap)
        }
    }

    /// Set the read timeout for the Capture. By default, this is 0, so it will block
    /// indefinitely.
    pub fn timeout(&mut self, ms: i32) -> &mut CaptureBuilder {
        self.timeout = ms;
        self
    }

    /// Set promiscuous mode on or off. By default, this is off.
    pub fn promisc(&mut self, to: bool) -> &mut CaptureBuilder {
        self.promisc = if to {1} else {0};
        self
    }

    /// Set rfmon mode on or off. The default is maintained by pcap.
    pub fn rfmon(&mut self, to: bool) -> &mut CaptureBuilder {
        self.rfmon = Some(if to {1} else {0});
        self
    }

    /// Set the buffer size for incoming packet data.
    ///
    /// The default is 1000000. This should always be larger than the snaplen.
    pub fn buffer_size(&mut self, to: i32) -> &mut CaptureBuilder {
        self.buffer_size = to;
        self
    }

    /// Set the snaplen size (the maximum length of a packet captured into the buffer).
    /// Useful if you only want certain headers, but not the entire packet.
    ///
    /// The default is 65535
    pub fn snaplen(&mut self, to: i32) -> &mut CaptureBuilder {
        self.snaplen = to;
        self
    }
}

/// Represents a packet returned from pcap. This can be dereferenced to access
/// the underlying packet `[u8]` slice.
pub struct Packet<'a> {
    header: &'a raw::Struct_pcap_pkthdr,
    data: &'a libc::c_uchar
}

impl<'b> Deref for Packet<'b> {
    type Target = [u8];

    fn deref<'a>(&'a self) -> &'a [u8] {
        unsafe {
            slice::from_raw_parts(self.data, self.header.caplen as usize)
        }
    }
}

impl<'a> std::fmt::Debug for Packet<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        self.deref().fmt(f)
    }
}

/// This represents an open capture handle attached to a device or file.
///
/// Internally it represents a `pcap_t`.
pub struct Capture {
    handle: Unique<raw::pcap_t>
}

impl Capture {
    /// Creates a capture handle from the specified device, or an error from pcap.
    ///
    /// You can provide this a `Device` from `Devices::list_all()` or an `&str` name of
    /// the device such as "any" on Linux.
    pub fn from_device<D: Into<Device>>(device: D) -> Result<Capture, Error> {
        CaptureBuilder::new().open(device)
    }

    /// Creates a capture handle from the specified file, or an error from pcap.
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Capture, Error> {
        let name = CString::new(path.as_ref().to_str().unwrap()).unwrap();
        let mut errbuf = [0i8; 256];

        unsafe {
            let handle = raw::pcap_open_offline(name.as_ptr(), errbuf.as_mut_ptr());
            if handle.is_null() {
                return Error::new(errbuf.as_ptr());
            }

            let cap = Capture {
                handle: Unique::new(handle)
            };

            Ok(cap)
        }
    }

    /// List the datalink types that this captured device supports.
    pub fn list_datalinks(&mut self) -> Result<Vec<Linktype>, Error> {
        unsafe {
            let mut links: *mut i32 = ptr::null_mut();

            let num = raw::pcap_list_datalinks(*self.handle, &mut links);

            if num == PCAP_ERROR_NOT_ACTIVATED {
                raw::pcap_free_datalinks(links);
                panic!("It should not be possible to run list_datalinks on a Capture that is not activated, please report this bug!")
            } else if num < 0 {
                raw::pcap_free_datalinks(links);
                Error::new(raw::pcap_geterr(*self.handle))
            } else {
                let slice = slice::from_raw_parts(links, num as usize).iter().map(|&a| Linktype(a)).collect();
                raw::pcap_free_datalinks(links);

                Ok(slice)
            }
        }
    }

    /// Set the datalink type for the current capture handle.
    pub fn set_datalink(&mut self, linktype: Linktype) -> Result<(), Error> {
        unsafe {
            match raw::pcap_set_datalink(*self.handle, linktype.0) {
                0 => {
                    Ok(())
                },
                _ => {
                    Error::new(raw::pcap_geterr(*self.handle))
                }
            }
        }
    }

    /// Get the current datalink type for this capture handle.
    pub fn get_datalink(&mut self) -> Linktype {
        unsafe {
            match raw::pcap_datalink(*self.handle) {
                PCAP_ERROR_NOT_ACTIVATED => {
                    panic!("It should not be possible to run get_datalink on a Capture that is not activated, please report this bug!");
                },
                lt => {
                    Linktype(lt)
                }
            }
        }
    }

    /// Blocks until a packet is returned from the capture handle or an error occurs.
    ///
    /// pcap captures packets and places them into a buffer which this function reads
    /// from. This buffer has a finite length, so if the buffer fills completely new
    /// packets will be discarded temporarily. This means that in realtime situations,
    /// you probably want to minimize the time between calls of this next() method.
    pub fn next<'a>(&'a mut self) -> Option<Packet<'a>> {
        unsafe {
            let mut header: *mut raw::Struct_pcap_pkthdr = ptr::null_mut();
            let mut packet: *const libc::c_uchar = ptr::null();
            match raw::pcap_next_ex(*self.handle, &mut header, &mut packet) {
                1 => {
                    // packet was read without issue
                    Some(Packet {
                        header: &*header,
                        data: &*packet
                    })
                },
                _ => {
                    None
                }
            }
        }
    }

    /// Adds a filter to the capture using the given BPF program string. Internally
    /// this is compiled using `pcap_compile()`.
    ///
    /// See http://biot.com/capstats/bpf.html for more information about this syntax.
    pub fn filter(&mut self, program: &str) -> Result<(), Error> {
        let program = CString::new(program).unwrap();

        unsafe {
            let mut bpf_program: raw::Struct_bpf_program = Default::default();

            if -1 == raw::pcap_compile(*self.handle, &mut bpf_program, program.as_ptr(), 0, 0) {
                return Error::new(raw::pcap_geterr(*self.handle));
            }

            if -1 == raw::pcap_setfilter(*self.handle, &mut bpf_program) {
                raw::pcap_freecode(&mut bpf_program);
                return Error::new(raw::pcap_geterr(*self.handle));
            }

            raw::pcap_freecode(&mut bpf_program);
            Ok(())
        }
    }
}

impl Drop for Capture {
    fn drop(&mut self) {
        unsafe {
            raw::pcap_close(*self.handle)
        }
    }
}

fn cstr_to_string(ptr: *const libc::c_char) -> Result<String, str::Utf8Error> {
    Ok(try!(str::from_utf8(unsafe{CStr::from_ptr(ptr)}.to_bytes())).to_string())
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate url;
extern crate serde;
extern crate serde_json;

use hyper::client::{Client};
use hyper::header::{ContentType};
use hyper::client::response::{Response};
use hyper::error::Error as HyperError;
use url::form_urlencoded::{serialize};
use std::io::Read;
use std::io::Error;
use std::collections::BTreeMap;

pub struct Cleverbot {
    user: String,
    key: String,
    pub nick: String,
}

#[derive(Debug)]
pub enum CleverbotError {
    IncorrectCredentials,
    DuplicatedReferenceNames,
    Io(HyperError),
    Api(String),
    Std(Error),
}

impl From<HyperError> for CleverbotError {
    fn from(err: HyperError) -> CleverbotError {
        CleverbotError::Io(err)
    }
}

impl From<Error> for CleverbotError {
    fn from(err: Error) -> CleverbotError {
        CleverbotError::Std(err)
    }
}

impl Cleverbot {
    /// Creates a new Cleverbot instance.
    /// * `user` - The API User.
    /// * `key` - The API Key.
    pub fn new(user: String, key: String, nick: Option<String>) -> Result<Cleverbot, CleverbotError> {
        let mut response = {
            let mut args = vec![
                ("user", &*user),
                ("key", &*key),
            ];
            if let Some(ref nick) = nick { args.push(("nick", &*nick)) }
            match request("https://cleverbot.io/1.0/create", &*args) {
                Ok(response) => response,
                Err(err) => return Err(CleverbotError::Io(err)),
            }
        };
        let mut body = String::new();
        try!(response.read_to_string(&mut body));
        let json: BTreeMap<String, String> = serde_json::from_str(&body).unwrap();
        let result = json.get("status").unwrap();
        match result.as_ref() {
            "success" => Ok(Cleverbot {
                    user: user,
                    key: key,
                    nick: json.get("nick").unwrap().to_string(),
                }),
            "Error: API credentials incorrect" => Err(CleverbotError::IncorrectCredentials),
            "Error: reference name already exists" => Err(CleverbotError::DuplicatedReferenceNames),
            _ => Err(CleverbotError::Api(result.to_owned()))
        }
    }

    /// Sends the bot a message and returns its response. If the nick is not set, it will
    /// set it randomly through set_nick_randomly. Returns its response or error string.
    /// * `message` - The message to send to the bot.
    pub fn say(&mut self, message: &str) -> Result<String, CleverbotError> {
        let args = vec![
            ("user", &*self.user),
            ("key", &*self.key),
            ("nick", &*self.nick),
            ("text", message),
        ];
        let mut response = {
            match request("https://cleverbot.io/1.0/ask", &*args) {
                Ok(response) => response,
                Err(err) => return Err(CleverbotError::Io(err)),
            }
        };
        let mut body = String::new();
        try!(response.read_to_string(&mut body));
        let json: BTreeMap<String, String> = serde_json::from_str(&body).unwrap();
        let result = json.get("status").unwrap();
        match result.as_ref() {
            "success" => Ok(json.get("response").unwrap().to_string()),
            "Error: API credentials incorrect" => Err(CleverbotError::IncorrectCredentials),
            "Error: reference name already exists" => Err(CleverbotError::DuplicatedReferenceNames),
            _ => Err(CleverbotError::Api(result.to_owned()))
        }
    }
}

/// Submits a POST request to the URL with the given vec body.
/// * `base` - The URL
/// * `args` - A vector representing the request body.
fn request(base: &str, args: &[(&str, &str)]) -> Result<Response, HyperError> {
    let client = Client::new();
    let body = serialize(args.into_iter());
    client.post(base)
        .body(&body)
        .header(ContentType::form_url_encoded())
        .send()
}
<commit_msg>:lock: Remove all unwrap() calls.<commit_after>extern crate hyper;
extern crate url;
extern crate serde;
extern crate serde_json;

use hyper::client::{Client};
use hyper::header::{ContentType};
use hyper::client::response::{Response};
use hyper::error::Error as HyperError;
use url::form_urlencoded::{serialize};
use std::io::Read;
use std::io::Error;
use std::collections::BTreeMap;
use serde_json::error::Error as JsonError;

#[derive(Debug)]
pub enum CleverbotError {
    IncorrectCredentials,
    DuplicatedReferenceNames,
    Io(HyperError),
    Api(String),
    Std(Error),
    Json(JsonError),
    MissingValue(String)
}

impl From<HyperError> for CleverbotError {
    fn from(err: HyperError) -> CleverbotError {
        CleverbotError::Io(err)
    }
}

impl From<Error> for CleverbotError {
    fn from(err: Error) -> CleverbotError {
        CleverbotError::Std(err)
    }
}

impl From<JsonError> for CleverbotError {
    fn from(err: JsonError) -> CleverbotError {
        CleverbotError::Json(err)
    }
}

pub struct Cleverbot {
    user: String,
    key: String,
    pub nick: String,
}

impl Cleverbot {
    /// Creates a new Cleverbot instance.
    /// * `user` - The API User.
    /// * `key` - The API Key.
    pub fn new(user: String, key: String, nick: Option<String>) -> Result<Cleverbot, CleverbotError> {
        let mut response = {
            let mut args = vec![
                ("user", &*user),
                ("key", &*key),
            ];
            if let Some(ref nick) = nick { args.push(("nick", &*nick)) }
            match request("https://cleverbot.io/1.0/create", &*args) {
                Ok(response) => response,
                Err(err) => return Err(CleverbotError::Io(err)),
            }
        };
        let mut body = String::new();
        try!(response.read_to_string(&mut body));
        let json: BTreeMap<String, String> = try!(serde_json::from_str(&body));
        let opt_result = json.get("status");
        let result = {
            if let Some(opt_result) = opt_result {
                opt_result.to_owned()
            } else {
                return Err(CleverbotError::MissingValue(String::from("status")));
            }
        };
        match result.as_ref() {
            "success" => {
                let json_nick = json.get("nick");
                let nick = {
                    if let Some(ref json_nick) = json_nick {
                        json_nick
                    } else {
                        return Err(CleverbotError::MissingValue(String::from("nick")));
                    }
                };
                Ok(Cleverbot {
                    user: user,
                    key: key,
                    nick: nick.to_string(),
                })
            },
            "Error: API credentials incorrect" => Err(CleverbotError::IncorrectCredentials),
            "Error: reference name already exists" => Err(CleverbotError::DuplicatedReferenceNames),
            _ => Err(CleverbotError::Api(result))
        }
    }

    /// Sends the bot a message and returns its response. If the nick is not set, it will
    /// set it randomly through set_nick_randomly. Returns its response or error string.
    /// * `message` - The message to send to the bot.
    pub fn say(&mut self, message: &str) -> Result<String, CleverbotError> {
        let args = vec![
            ("user", &*self.user),
            ("key", &*self.key),
            ("nick", &*self.nick),
            ("text", message),
        ];
        let mut response = {
            match request("https://cleverbot.io/1.0/ask", &*args) {
                Ok(response) => response,
                Err(err) => return Err(CleverbotError::Io(err)),
            }
        };
        let mut body = String::new();
        try!(response.read_to_string(&mut body));
        let json: BTreeMap<String, String> = try!(serde_json::from_str(&body));
        let opt_result = json.get("status");
        let result = {
            if let Some(opt_result) = opt_result {
                opt_result.to_owned()
            } else {
                return Err(CleverbotError::MissingValue(String::from("status")));
            }
        };
        match result.as_ref() {
            "success" => {
                let json_response = json.get("response");
                let response = {
                    if let Some(ref json_response) = json_response {
                        json_response
                    } else {
                        return Err(CleverbotError::MissingValue(String::from("nick")));
                    }
                };
                Ok(response.to_string())
            },
            "Error: API credentials incorrect" => Err(CleverbotError::IncorrectCredentials),
            "Error: reference name already exists" => Err(CleverbotError::DuplicatedReferenceNames),
            _ => Err(CleverbotError::Api(result.to_owned()))
        }
    }
}

/// Submits a POST request to the URL with the given vec body.
/// * `base` - The URL
/// * `args` - A vector representing the request body.
fn request(base: &str, args: &[(&str, &str)]) -> Result<Response, HyperError> {
    let client = Client::new();
    let body = serialize(args.into_iter());
    client.post(base)
        .body(&body)
        .header(ContentType::form_url_encoded())
        .send()
}
<|endoftext|>


<commit_before>#![feature(core, Hash)]

extern crate semver;

use std::collections::HashMap;
use std::error::Error;
use std::old_io::net::ip::IpAddr;

pub use self::typemap::TypeMap;
mod typemap;

#[derive(PartialEq, Show, Clone, Copy)]
pub enum Scheme {
    Http,
    Https
}

#[derive(PartialEq, Show, Clone, Copy)]
pub enum Host<'a> {
    Name(&'a str),
    Ip(IpAddr)
}

#[derive(PartialEq, Hash, Eq, Show, Clone, Copy)]
pub enum Method {
    Get,
    Post,
    Put,
    Delete,
    Head,
    Connect,
    Options,
    Trace,

    // RFC-5789
    Patch,
    Purge,

    // WebDAV, Subversion, UPNP
    Other(&'static str)
}

/// A Dictionary for extensions provided by the server or middleware
pub type Extensions = TypeMap;

pub trait Request {
    /// The version of HTTP being used
    fn http_version(&self) -> semver::Version;

    /// The version of the conduit spec being used
    fn conduit_version(&self) -> semver::Version;

    /// The request method, such as GET, POST, PUT, DELETE or PATCH
    fn method(&self) -> Method;

    /// The scheme part of the request URL
    fn scheme(&self) -> Scheme;

    /// The host part of the requested URL
    fn host<'a>(&'a self) -> Host<'a>;

    /// The initial part of the request URL's path that corresponds
    /// to a virtual root. This allows an application to have a
    /// virtual location that consumes part of the path.
    fn virtual_root<'a>(&'a self) -> Option<&'a str>;

    /// The remainder of the path.
    fn path<'a>(&'a self) -> &'a str;

    /// The portion of the request URL that follows the "?"
    fn query_string<'a>(&'a self) -> Option<&'a str>;

    /// The remote IP address of the client or the last proxy that
    /// sent the request.
    fn remote_ip(&self) -> IpAddr;

    /// The byte-size of the body, if any
    fn content_length(&self) -> Option<u64>;

    /// The request's headers, as conduit::Headers.
    fn headers<'a>(&'a self) -> &'a Headers;

    /// A Reader for the body of the request
    fn body<'a>(&'a mut self) -> &'a mut Reader;

    /// A readable map of extensions
    fn extensions<'a>(&'a self) -> &'a Extensions;

    /// A mutable map of extensions
    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions;
}

pub trait Headers {
    /// Find the value of a given header. Multi-line headers are represented
    /// as an array.
    fn find(&self, key: &str) -> Option<Vec<&str>>;

    /// Returns true if a particular header exists
    fn has(&self, key: &str) -> bool;

    /// Iterate over all of the available headers.
    fn all(&self) -> Vec<(&str, Vec<&str>)>;
}

pub struct Response {
    /// The status code as a tuple of the return code and status string
    pub status: (u32, &'static str),

    /// A Map of the headers
    pub headers: HashMap<String, Vec<String>>,

    /// A Writer for body of the response
    pub body: Box<Reader + Send>
}

/// A Handler takes a request and returns a response or an error.
/// By default, a bare function implements `Handler`.
pub trait Handler : Sync + Send {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Error+Send>>;
}

impl<F> Handler for F
    where F: Fn(&mut Request) -> Result<Response, Box<Error+Send>> + Sync + Send,
{
    fn call(&self, request: &mut Request) -> Result<Response, Box<Error+Send>> {
        (*self)(request)
    }
}
<commit_msg>Fix a feature name<commit_after>#![feature(core, hash)]

extern crate semver;

use std::collections::HashMap;
use std::error::Error;
use std::old_io::net::ip::IpAddr;

pub use self::typemap::TypeMap;
mod typemap;

#[derive(PartialEq, Show, Clone, Copy)]
pub enum Scheme {
    Http,
    Https
}

#[derive(PartialEq, Show, Clone, Copy)]
pub enum Host<'a> {
    Name(&'a str),
    Ip(IpAddr)
}

#[derive(PartialEq, Hash, Eq, Show, Clone, Copy)]
pub enum Method {
    Get,
    Post,
    Put,
    Delete,
    Head,
    Connect,
    Options,
    Trace,

    // RFC-5789
    Patch,
    Purge,

    // WebDAV, Subversion, UPNP
    Other(&'static str)
}

/// A Dictionary for extensions provided by the server or middleware
pub type Extensions = TypeMap;

pub trait Request {
    /// The version of HTTP being used
    fn http_version(&self) -> semver::Version;

    /// The version of the conduit spec being used
    fn conduit_version(&self) -> semver::Version;

    /// The request method, such as GET, POST, PUT, DELETE or PATCH
    fn method(&self) -> Method;

    /// The scheme part of the request URL
    fn scheme(&self) -> Scheme;

    /// The host part of the requested URL
    fn host<'a>(&'a self) -> Host<'a>;

    /// The initial part of the request URL's path that corresponds
    /// to a virtual root. This allows an application to have a
    /// virtual location that consumes part of the path.
    fn virtual_root<'a>(&'a self) -> Option<&'a str>;

    /// The remainder of the path.
    fn path<'a>(&'a self) -> &'a str;

    /// The portion of the request URL that follows the "?"
    fn query_string<'a>(&'a self) -> Option<&'a str>;

    /// The remote IP address of the client or the last proxy that
    /// sent the request.
    fn remote_ip(&self) -> IpAddr;

    /// The byte-size of the body, if any
    fn content_length(&self) -> Option<u64>;

    /// The request's headers, as conduit::Headers.
    fn headers<'a>(&'a self) -> &'a Headers;

    /// A Reader for the body of the request
    fn body<'a>(&'a mut self) -> &'a mut Reader;

    /// A readable map of extensions
    fn extensions<'a>(&'a self) -> &'a Extensions;

    /// A mutable map of extensions
    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions;
}

pub trait Headers {
    /// Find the value of a given header. Multi-line headers are represented
    /// as an array.
    fn find(&self, key: &str) -> Option<Vec<&str>>;

    /// Returns true if a particular header exists
    fn has(&self, key: &str) -> bool;

    /// Iterate over all of the available headers.
    fn all(&self) -> Vec<(&str, Vec<&str>)>;
}

pub struct Response {
    /// The status code as a tuple of the return code and status string
    pub status: (u32, &'static str),

    /// A Map of the headers
    pub headers: HashMap<String, Vec<String>>,

    /// A Writer for body of the response
    pub body: Box<Reader + Send>
}

/// A Handler takes a request and returns a response or an error.
/// By default, a bare function implements `Handler`.
pub trait Handler : Sync + Send {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Error+Send>>;
}

impl<F> Handler for F
    where F: Fn(&mut Request) -> Result<Response, Box<Error+Send>> + Sync + Send,
{
    fn call(&self, request: &mut Request) -> Result<Response, Box<Error+Send>> {
        (*self)(request)
    }
}
<|endoftext|>


<commit_before>#![crate_type="lib"]
#![feature(str_char)]

pub use sys::Window;

pub use button::Button;
pub use cell::{CopyCell, CloneCell};
pub use click::Click;
pub use color::Color;
pub use event::Event;
pub use label::Label;
pub use place::Place;
pub use point::Point;
pub use progress_bar::ProgressBar;
pub use rect::Rect;
pub use renderer::Renderer;
pub use text_box::TextBox;
pub use widget::Widget;

pub mod button;
pub mod cell;
pub mod click;
pub mod color;
pub mod event;
pub mod label;
pub mod place;
pub mod point;
pub mod progress_bar;
pub mod rect;
pub mod renderer;
pub mod text_box;
pub mod widget;

#[cfg(target_os = "redox")]
#[path="orbital/mod.rs"]
pub mod sys;

#[cfg(not(target_os = "redox"))]
#[path="sdl2/mod.rs"]
pub mod sys;

pub fn example() {
    let mut window = Window::new(Rect::new(100, 100, 400, 400), "OrbTK");

    let x = 20;
    let mut y = 20;

    let label = Label::new()
        .text("Test Label")
        .position(x, y)
        .size(80, 16)
        .place(&mut window);

    y += 16 + 10;

    Button::new()
        .text("Test Button")
        .position(x, y)
        .size(88, 16)
        .on_click(move |_button: &Button, point: Point| {
            let text = format!("{:?}", point);

            let mut rect = label.rect.get();
            rect.width = text.chars().count() * 8;
            label.rect.set(rect);

            label.text.set(text);
        })
        .place(&mut window);

    y += 16 + 10;

    ProgressBar::new()
        .value(50)
        .position(x, y)
        .size(300, 16)
        .on_click(|progress_bar: &ProgressBar, point: Point| {
            progress_bar.value.set(point.x * 100 / progress_bar.rect.get().width as isize);
        })
        .place(&mut window);

    y += 16 + 10;

    Label::new()
        .text("Test Input")
        .position(x, y)
        .size(80, 16)
        .place(&mut window);

    TextBox::new()
        .position(x + 80 + 10, y)
        .size(210, 16)
        .place(&mut window);

    window.exec();
}
<commit_msg>Reorganize example<commit_after>#![crate_type="lib"]
#![feature(str_char)]

pub use sys::Window;

pub use button::Button;
pub use cell::{CopyCell, CloneCell};
pub use click::Click;
pub use color::Color;
pub use event::Event;
pub use label::Label;
pub use place::Place;
pub use point::Point;
pub use progress_bar::ProgressBar;
pub use rect::Rect;
pub use renderer::Renderer;
pub use text_box::TextBox;
pub use widget::Widget;

pub mod button;
pub mod cell;
pub mod click;
pub mod color;
pub mod event;
pub mod label;
pub mod place;
pub mod point;
pub mod progress_bar;
pub mod rect;
pub mod renderer;
pub mod text_box;
pub mod widget;

#[cfg(target_os = "redox")]
#[path="orbital/mod.rs"]
pub mod sys;

#[cfg(not(target_os = "redox"))]
#[path="sdl2/mod.rs"]
pub mod sys;

pub fn example() {
    let mut window = Window::new(Rect::new(100, 100, 420, 420), "OrbTK");

    let x = 10;
    let mut y = 10;

    let label = Label::new()
        .text("Test Label")
        .position(x, y)
        .size(400, 16)
        .place(&mut window);

    y += 16 + 10;

    let text_box = TextBox::new()
        .position(x, y)
        .size(302, 16)
        .place(&mut window);

    Button::new()
        .text("Test Button")
        .position(x + 302 + 10, y)
        .size(88, 16)
        .on_click(move |_button: &Button, _point: Point| {
            label.text.set(format!("Input: {}", text_box.text.get()));
        })
        .place(&mut window);

    y += 16 + 10;

    let progress_label = Label::new()
        .text("Progress: 0%")
        .position(x, y)
        .size(400, 16)
        .place(&mut window);

    y += 16 + 10;

    ProgressBar::new()
        .position(x, y)
        .size(400, 16)
        .on_click(move |progress_bar: &ProgressBar, point: Point| {
            let progress = point.x * 100 / progress_bar.rect.get().width as isize;
            progress_label.text.set(format!("Progress: {}%", progress));
            progress_bar.value.set(progress);
        })
        .place(&mut window);

    window.exec();
}
<|endoftext|>


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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