<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
//!
//! ```
//! 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 `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.
//! Handlebars templating language is designed against JSON data type. In rust,
//! we will convert user's structs, vectors or maps to JSON type in order to use
//! in template. You have to make sure your data implements the `Serialize` trait
//! from the [Serde](https://serde.rs) project.
//!
//! ## 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.
//!
//! ```
//! 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 `serde_json::value::Value` internally for data rendering.
//!
//! That means, if you want to render something, you have to ensure the data type implements the `serde::Serialize` trait. Most rust internal types already have that trait. Use `#derive[Serialize]` for your types to generate default 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
//! use std::collections::BTreeMap;
//!
//! use handlebars::Handlebars;
//!
//! #[derive(Serialize)]
//! struct Person {
//!   name: String,
//!   age: i16,
//! }
//!
//! 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.
//!
//! ```
//! use std::io::Write;
//! use handlebars::{Handlebars, HelperDef, RenderContext, Helper, Context, JsonRender, HelperResult};
//!
//! // implement by a structure impls HelperDef
//! #[derive(Clone, Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn call(&self, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> HelperResult {
//!     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) -> HelperResult {
//!     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| -> HelperResult {
//!           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());
//! }
//! ```
//! Data available to helper can be found in [Helper](struct.Helper.html). And there are more
//! examples in [HelperDef](trait.HelperDef.html) page.
//!
//! 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;
extern crate pest;
#[macro_use]
extern crate pest_derive;
#[macro_use]
extern crate lazy_static;
#[cfg(test)]
#[macro_use]
extern crate maplit;
#[cfg(test)]
#[macro_use]
extern crate serde_derive;

extern crate regex;
extern crate serde;
#[allow(unused_imports)]
#[macro_use]
extern crate serde_json;

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

mod grammar;
mod template;
mod error;
mod registry;
mod render;
mod helpers;
mod context;
mod support;
mod directives;
mod partial;
<commit_msg>(feat) expose StringWriter<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
//!
//! ```
//! 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 `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.
//! Handlebars templating language is designed against JSON data type. In rust,
//! we will convert user's structs, vectors or maps to JSON type in order to use
//! in template. You have to make sure your data implements the `Serialize` trait
//! from the [Serde](https://serde.rs) project.
//!
//! ## 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.
//!
//! ```
//! 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 `serde_json::value::Value` internally for data rendering.
//!
//! That means, if you want to render something, you have to ensure the data type implements the `serde::Serialize` trait. Most rust internal types already have that trait. Use `#derive[Serialize]` for your types to generate default 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
//! use std::collections::BTreeMap;
//!
//! use handlebars::Handlebars;
//!
//! #[derive(Serialize)]
//! struct Person {
//!   name: String,
//!   age: i16,
//! }
//!
//! 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.
//!
//! ```
//! use std::io::Write;
//! use handlebars::{Handlebars, HelperDef, RenderContext, Helper, Context, JsonRender, HelperResult};
//!
//! // implement by a structure impls HelperDef
//! #[derive(Clone, Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn call(&self, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> HelperResult {
//!     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) -> HelperResult {
//!     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| -> HelperResult {
//!           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());
//! }
//! ```
//! Data available to helper can be found in [Helper](struct.Helper.html). And there are more
//! examples in [HelperDef](trait.HelperDef.html) page.
//!
//! 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;
extern crate pest;
#[macro_use]
extern crate pest_derive;
#[macro_use]
extern crate lazy_static;
#[cfg(test)]
#[macro_use]
extern crate maplit;
#[cfg(test)]
#[macro_use]
extern crate serde_derive;

extern crate regex;
extern crate serde;
#[allow(unused_imports)]
#[macro_use]
extern crate serde_json;

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

mod grammar;
mod template;
mod error;
mod registry;
mod render;
mod helpers;
mod context;
mod support;
mod directives;
mod partial;
<|endoftext|>


<commit_before>extern crate libc;

use libc::c_char;

use std::str::from_utf8;
use std::ffi::CStr;

/// External interface for the scoring algorithm
#[no_mangle]
pub extern "C" fn selecta_score(choice: *const c_char, query: *const c_char) -> f64 {
    let slice = unsafe { CStr::from_ptr(choice).to_bytes() };
    let choice = from_utf8(slice).unwrap();

    let slice = unsafe { CStr::from_ptr(query).to_bytes() };
    let query = from_utf8(slice).unwrap();

    score(choice, query)
}

/// Given a chosen word, score how well a substring matches.
///
/// Example:
///
/// ```rust
/// use selecta_score::score;
///
/// assert_eq!(0.0, score("selecta", "sell"));
/// assert!(0.0 < score("selecta", "sela"));
/// assert!(score("selecta", "select") > score("selecta", "sela"));
/// ```
pub fn score(choice: &str, query: &str) -> f64 {
    if query.len() == 0 {
        return 1.0;
    }

    if choice.len() == 0 {
        return 0.0;
    }

    // TODO: use UTF-8 versions of `to_lowercase()` when stable.
    let lower_choice = choice.to_lowercase();
    let lower_query = query.to_lowercase();
    let lower_choice_len = lower_choice.len() as f64;

    let match_length = compute_match_length(lower_choice.as_ref(), lower_query.chars().collect());

    match match_length {
        Some(match_length) => {
            let score = lower_query.len() as f64 / match_length as f64;
            score / lower_choice_len
        },
        None => { 0.0 },
    }

}

/// Find the length of the shortest substring matching the given characters.
fn compute_match_length(haystack: &str, needles: Vec<char>) -> Option<usize> {
    let first_char = needles.first().expect("Unable to get first char of needle");
    let rest = &needles[1..];

    let first_indexes = find_char_in_string(haystack, first_char);

    first_indexes.iter().map(|&first_index|
        match find_end_of_match(haystack, rest, first_index) {
            Some(index) => {
                Some(index - first_index + 1)
            },
            None => { None }
        }
    ).filter(|&m|
        m.is_some()
    ).map(|m|
        m.unwrap()
    ).min()
}

/// Find all occurrences of the character in the string, returning their indexes.
fn find_char_in_string(haystack: &str, needle: &char) -> Vec<usize> {
    let mut index: usize = 0;
    let mut indexes = Vec::new();

    loop {
        index = match find_from_offset(haystack, *needle, index) {
            Some(i) => {
                indexes.push(i);
                i + 1
            },
            None => { break; },
        };
    }

    indexes
}

/// Find each of the characters in the string, moving strictly left to right.
fn find_end_of_match(haystack: &str, needles: &[char], first_index: usize) -> Option<usize> {
    let mut last_index = first_index;
    for needle in needles.iter() {
        last_index = match find_from_offset(haystack, *needle, last_index + 1) {
            Some(i) => i,
            None => { return None; },
        };
    }

    Some(last_index)
}

/// Implements Ruby's `#index` method
fn find_from_offset(haystack: &str, needle: char, offset: usize) -> Option<usize> {
    let h = &haystack[offset..];

    let index = h.find(needle);

    match index {
        Some(i) => Some(i + offset),
        None => None,
    }
}

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

    #[test]
    fn test_scores_zero_when_choice_is_empty() {
        assert!(score("", "a") == 0.0);
    }

    #[test]
    fn test_scores_one_when_query_is_empty() {
        assert!(score("a", "") == 1.0);
    }

    #[test]
    fn test_scores_zero_when_the_query_longer_than_choice() {
        assert!(score("short", "longer") == 0.0);
    }

    #[test]
    fn test_scores_zero_when_query_does_not_match_at_all() {
        assert!(score("a", "b") == 0.0);
    }

    #[test]
    fn test_scores_zero_when_only_prefix_of_query_matches() {
        assert!(score("ab", "ac") == 0.0);
    }

    #[test]
    fn test_scores_greater_than_zero_when_matches() {
        let given_choices: Vec<&str> = vec!("a", "ab", "ba", "bab");

        for choice in given_choices.iter() {
            assert!(score(*choice, "a") > 0.0);
        }

        assert!(score("babababab", "aaaa") > 0.0);
    }

    #[test]
    fn test_scores_1_normalized_to_length_when_the_query_equals_choice() {
        assert!(score("a", "a") == 1.0);
        assert!(score("ab", "ab") == 0.5);
        assert!(score("a long string", "a long string") == 1.0 / "a long string".len() as f64);
        assert!(score("spec/search_spec.rb", "sear") == 1.0 / "spec/search_spec.rb".len() as f64);
    }

    #[test]
    fn test_matches_punctuation() {
        assert!(score("/! symbols $^", "/!$^") > 0.0);
    }

    #[test]
    fn test_is_case_insensitive() {
        assert!(score("a", "A") == 1.0);
        assert!(score("A", "a") == 1.0);
    }

    #[test]
    fn test_does_not_match_when_same_letter_is_repeated_in_choice() {
        assert!(score("a", "aa") == 0.0);
    }

    #[test]
    fn test_scores_higher_for_better_matches() {
        assert!(score("selecta.gemspec", "asp") > score("algorithm4_spec.rb", "asp"));
        assert!(score("README.md", "em") > score("benchmark.rb", "em"));
        assert!(score("search.rb", "sear") > score("spec/search_spec.rb", "sear"));
    }

    #[test]
    fn test_scores_shorter_matches_higher() {
        assert!(score("fbb", "fbb") > score("foo bar baz", "fbb"));
        assert!(score("foo", "foo") > score("longer foo", "foo"));
        assert!(score("foo", "foo") > score("foo longer", "foo"));
        assert!(score("1/2/3/4", "1/2/3") > score("1/9/2/3/4", "1/2/3"));
    }

    #[test]
    fn test_sometimes_score_longer_strings_higher_if_better_match() {
        assert!(score("long 12 long", "12") > score("1 long 2", "12"));
    }

    #[test]
    fn test_scores_higher_of_two_matches_regardless_of_order() {
        let tight = "12";
        let loose = "1padding2";
        let expect1 = tight.to_string() + loose;
        let expect2 = loose.to_string() + tight;

        assert!(score(expect1.as_ref(), "12") == 1.0 / expect1.len() as f64);
        assert!(score(expect2.as_ref(), "12") == 1.0 / expect2.len() as f64);
    }
}
<commit_msg>Apply rustfmt changes<commit_after>extern crate libc;

use libc::c_char;

use std::str::from_utf8;
use std::ffi::CStr;

/// External interface for the scoring algorithm
#[no_mangle]
pub extern "C" fn selecta_score(choice: *const c_char, query: *const c_char) -> f64 {
    let slice = unsafe { CStr::from_ptr(choice).to_bytes() };
    let choice = from_utf8(slice).unwrap();

    let slice = unsafe { CStr::from_ptr(query).to_bytes() };
    let query = from_utf8(slice).unwrap();

    score(choice, query)
}

/// Given a chosen word, score how well a substring matches.
///
/// Example:
///
/// ```rust
/// use selecta_score::score;
///
/// assert_eq!(0.0, score("selecta", "sell"));
/// assert!(0.0 < score("selecta", "sela"));
/// assert!(score("selecta", "select") > score("selecta", "sela"));
/// ```
pub fn score(choice: &str, query: &str) -> f64 {
    if query.len() == 0 {
        return 1.0;
    }

    if choice.len() == 0 {
        return 0.0;
    }

    // TODO: use UTF-8 versions of `to_lowercase()` when stable.
    let lower_choice = choice.to_lowercase();
    let lower_query = query.to_lowercase();
    let lower_choice_len = lower_choice.len() as f64;

    let match_length = compute_match_length(lower_choice.as_ref(), lower_query.chars().collect());

    match match_length {
        Some(match_length) => {
            let score = lower_query.len() as f64 / match_length as f64;
            score / lower_choice_len
        }
        None => 0.0,
    }

}

/// Find the length of the shortest substring matching the given characters.
fn compute_match_length(haystack: &str, needles: Vec<char>) -> Option<usize> {
    let first_char = needles.first().expect("Unable to get first char of needle");
    let rest = &needles[1..];

    let first_indexes = find_char_in_string(haystack, first_char);

    first_indexes.iter()
                 .map(|&first_index| {
                     match find_end_of_match(haystack, rest, first_index) {
                         Some(index) => Some(index - first_index + 1),
                         None => None,
                     }
                 })
                 .filter(|&m| m.is_some())
                 .map(|m| m.unwrap())
                 .min()
}

/// Find all occurrences of the character in the string, returning their indexes.
fn find_char_in_string(haystack: &str, needle: &char) -> Vec<usize> {
    let mut index: usize = 0;
    let mut indexes = Vec::new();

    loop {
        index = match find_from_offset(haystack, *needle, index) {
            Some(i) => {
                indexes.push(i);
                i + 1
            }
            None => {
                break;
            }
        };
    }

    indexes
}

/// Find each of the characters in the string, moving strictly left to right.
fn find_end_of_match(haystack: &str, needles: &[char], first_index: usize) -> Option<usize> {
    let mut last_index = first_index;
    for needle in needles.iter() {
        last_index = match find_from_offset(haystack, *needle, last_index + 1) {
            Some(i) => i,
            None => {
                return None;
            }
        };
    }

    Some(last_index)
}

/// Implements Ruby's `#index` method
fn find_from_offset(haystack: &str, needle: char, offset: usize) -> Option<usize> {
    let h = &haystack[offset..];

    let index = h.find(needle);

    match index {
        Some(i) => Some(i + offset),
        None => None,
    }
}

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

    #[test]
    fn test_scores_zero_when_choice_is_empty() {
        assert!(score("", "a") == 0.0);
    }

    #[test]
    fn test_scores_one_when_query_is_empty() {
        assert!(score("a", "") == 1.0);
    }

    #[test]
    fn test_scores_zero_when_the_query_longer_than_choice() {
        assert!(score("short", "longer") == 0.0);
    }

    #[test]
    fn test_scores_zero_when_query_does_not_match_at_all() {
        assert!(score("a", "b") == 0.0);
    }

    #[test]
    fn test_scores_zero_when_only_prefix_of_query_matches() {
        assert!(score("ab", "ac") == 0.0);
    }

    #[test]
    fn test_scores_greater_than_zero_when_matches() {
        let given_choices: Vec<&str> = vec!["a", "ab", "ba", "bab"];

        for choice in given_choices.iter() {
            assert!(score(*choice, "a") > 0.0);
        }

        assert!(score("babababab", "aaaa") > 0.0);
    }

    #[test]
    fn test_scores_1_normalized_to_length_when_the_query_equals_choice() {
        assert!(score("a", "a") == 1.0);
        assert!(score("ab", "ab") == 0.5);
        assert!(score("a long string", "a long string") == 1.0 / "a long string".len() as f64);
        assert!(score("spec/search_spec.rb", "sear") == 1.0 / "spec/search_spec.rb".len() as f64);
    }

    #[test]
    fn test_matches_punctuation() {
        assert!(score("/! symbols $^", "/!$^") > 0.0);
    }

    #[test]
    fn test_is_case_insensitive() {
        assert!(score("a", "A") == 1.0);
        assert!(score("A", "a") == 1.0);
    }

    #[test]
    fn test_does_not_match_when_same_letter_is_repeated_in_choice() {
        assert!(score("a", "aa") == 0.0);
    }

    #[test]
    fn test_scores_higher_for_better_matches() {
        assert!(score("selecta.gemspec", "asp") > score("algorithm4_spec.rb", "asp"));
        assert!(score("README.md", "em") > score("benchmark.rb", "em"));
        assert!(score("search.rb", "sear") > score("spec/search_spec.rb", "sear"));
    }

    #[test]
    fn test_scores_shorter_matches_higher() {
        assert!(score("fbb", "fbb") > score("foo bar baz", "fbb"));
        assert!(score("foo", "foo") > score("longer foo", "foo"));
        assert!(score("foo", "foo") > score("foo longer", "foo"));
        assert!(score("1/2/3/4", "1/2/3") > score("1/9/2/3/4", "1/2/3"));
    }

    #[test]
    fn test_sometimes_score_longer_strings_higher_if_better_match() {
        assert!(score("long 12 long", "12") > score("1 long 2", "12"));
    }

    #[test]
    fn test_scores_higher_of_two_matches_regardless_of_order() {
        let tight = "12";
        let loose = "1padding2";
        let expect1 = tight.to_string() + loose;
        let expect2 = loose.to_string() + tight;

        assert!(score(expect1.as_ref(), "12") == 1.0 / expect1.len() as f64);
        assert!(score(expect2.as_ref(), "12") == 1.0 / expect2.len() as f64);
    }
}
<|endoftext|>


<commit_before>//! [Special functions][1].
//!
//! [1]: https://en.wikipedia.org/wiki/Special_functions

#[cfg(test)]
extern crate assert;

extern crate libc;
extern crate num;

pub use beta::{ln_beta, inc_beta, inv_inc_beta};

mod beta;

#[link_name = "m"]
mod m {
    use libc::{c_double, c_int};

    extern {
        pub fn erf(x: c_double) -> c_double;
        pub fn erfc(x: c_double) -> c_double;
        pub fn lgamma_r(x: c_double, sign: &mut c_int) -> c_double;
    }
}

// Use Horner’s method to evaluate polynomials.
macro_rules! eval_poly(
    ($x0:expr, $coefs:expr) => ($coefs.iter().rev().fold(0.0, |sum, &c| $x0 * sum + c));
);

/// Compute the real-valued digamma function.
///
/// The digamma function is defined by
///
/// ```math
///        d ln(Γ(x))
/// ψ(x) = ----------
///            dx
/// ```
///
/// where Γ is the Gamma function. The computation is based on an approximation
/// as described in the reference below.
///
/// * M. J. Beal, “Variational Algorithms for Approximate Bayesian Inference.”
/// The Gatsby Computational Neuroscience Unit, University College London, 2003,
/// pp. 265–266.
///
/// # Examples
///
/// ```
/// use special::digamma;
///
/// let euler_mascheroni = 0.5772156649015325;
/// assert_eq!(-euler_mascheroni, digamma(1.0));
/// ```
#[inline]
pub fn digamma(x: f64)-> f64 {
    if x > 8.0 {
        let inv_x = x.recip();
        let inv_x_e2 = inv_x * inv_x;
        x.ln() - 0.5*inv_x - inv_x_e2 * eval_poly!(inv_x_e2, [
            // Coefficients are `Bernoulli[2n] / 2n`
            1.0/12.0, -1.0/120.0, 1.0/252.0, -1.0/240.0,
            5.0/660.0, -691.0/32760.0, 1.0/12.0, -3617.0/8160.0
        ])
    } else {
        // Shift by recurrence
        digamma(x + 1.0) - x.recip()
    }
}

/// Compute the error function.
#[inline]
pub fn erf(x: f64) -> f64 {
    unsafe { m::erf(x) }
}

/// Compute the complementary error function.
#[inline]
pub fn erfc(x: f64) -> f64 {
    unsafe { m::erfc(x) }
}

/// Compute the natural logarithm of the gamma function.
#[inline]
pub fn ln_gamma(x: f64) -> (f64, i32) {
    let mut sign: i32 = 0;
    let value = unsafe { m::lgamma_r(x, &mut sign) };
    (value, sign)
}

#[cfg(test)]
mod tests {
    #[test]
    fn digamma() {
        use std::f64::consts::{FRAC_PI_2, LN_2};
        let euler_mascheroni = 0.577215664901533;

        assert_eq!(-FRAC_PI_2 - 3.0 * LN_2 - euler_mascheroni, super::digamma(0.25));
    }
}
<commit_msg>Cosmetic adjustments<commit_after>//! [Special functions][1].
//!
//! [1]: https://en.wikipedia.org/wiki/Special_functions

#[cfg(test)]
extern crate assert;

extern crate libc;
extern crate num;

pub use beta::{ln_beta, inc_beta, inv_inc_beta};

mod beta;

#[link_name = "m"]
mod m {
    use libc::{c_double, c_int};

    extern {
        pub fn erf(x: c_double) -> c_double;
        pub fn erfc(x: c_double) -> c_double;
        pub fn lgamma_r(x: c_double, sign: &mut c_int) -> c_double;
    }
}

/// Compute the real-valued digamma function.
///
/// The digamma function is defined by
///
/// ```math
///        d ln(Γ(x))
/// ψ(x) = ----------
///            dx
/// ```
///
/// where Γ is the Gamma function. The computation is based on an approximation
/// as described in the reference below.
///
/// * M. J. Beal, “Variational Algorithms for Approximate Bayesian Inference.”
/// The Gatsby Computational Neuroscience Unit, University College London, 2003,
/// pp. 265–266.
///
/// # Examples
///
/// ```
/// use special::digamma;
///
/// let euler_mascheroni = 0.5772156649015325;
/// assert_eq!(-euler_mascheroni, digamma(1.0));
/// ```
#[inline]
pub fn digamma(x: f64)-> f64 {
    // Use Horner’s method to evaluate polynomials.
    macro_rules! eval_poly(
        ($x0:expr, $coefs:expr) => (
            $coefs.iter().rev().fold(0.0, |sum, &c| $x0 * sum + c)
        );
    );

    if x > 8.0 {
        let inv_x = x.recip();
        let inv_x_e2 = inv_x * inv_x;
        x.ln() - 0.5*inv_x - inv_x_e2 * eval_poly!(inv_x_e2, [
            // The coefficients are `Bernoulli[2n] / 2n`.
            1.0/12.0, -1.0/120.0, 1.0/252.0, -1.0/240.0,
            5.0/660.0, -691.0/32760.0, 1.0/12.0, -3617.0/8160.0,
        ])
    } else {
        // Shift by recurrence.
        digamma(x + 1.0) - x.recip()
    }
}

/// Compute the error function.
#[inline]
pub fn erf(x: f64) -> f64 {
    unsafe { m::erf(x) }
}

/// Compute the complementary error function.
#[inline]
pub fn erfc(x: f64) -> f64 {
    unsafe { m::erfc(x) }
}

/// Compute the natural logarithm of the gamma function.
#[inline]
pub fn ln_gamma(x: f64) -> (f64, i32) {
    let mut sign: i32 = 0;
    let value = unsafe { m::lgamma_r(x, &mut sign) };
    (value, sign)
}

#[cfg(test)]
mod tests {
    #[test]
    fn digamma() {
        use std::f64::consts::{FRAC_PI_2, LN_2};
        let euler_mascheroni = 0.577215664901533;

        assert_eq!(-FRAC_PI_2 - 3.0 * LN_2 - euler_mascheroni, super::digamma(0.25));
    }
}
<|endoftext|>


<commit_before>#![feature(alloc)]
#![feature(core)]
#![cfg_attr(test, feature(std_misc))]

use std::boxed::FnBox;
use std::cell::{Ref, RefMut, RefCell};
use std::marker::PhantomData;
use std::mem;
use std::sync::{Arc, Weak};
use std::sync::mpsc::sync_channel;

use self::debug::ThreadDebugger;

pub trait IsolationRunner: Sync + 'static {
    fn run_on_owning_thread(&self, f: Box<FnBox() + Send>);
}

pub enum OwningThread {}
pub enum NonOwningThread {}

pub struct ThreadIsolated<T, ThreadKind> {
    inner: Arc<Inner<T>>,
    debug: ThreadDebugger,
    _marker: PhantomData<ThreadKind>,
}

struct Inner<T> {
    item: RefCell<T>,
    runner: Box<IsolationRunner>,
}

impl<T> ThreadIsolated<T, OwningThread> {
    pub unsafe fn new<R: IsolationRunner>(item: T, runner: R) -> ThreadIsolated<T, OwningThread> {
        ThreadIsolated{
            inner: Arc::new(Inner{
                item: RefCell::new(item),
                runner: Box::new(runner),
            }),
            debug: ThreadDebugger::new(),
            _marker: PhantomData,
        }
    }

    pub fn borrow(&self) -> Ref<T> {
        self.debug.assert_on_originating_thread();
        self.inner.item.borrow()
    }

    pub fn borrow_mut(&self) -> RefMut<T> {
        self.debug.assert_on_originating_thread();
        self.inner.item.borrow_mut()
    }

    pub fn clone_for_non_owning_thread(&self) -> ThreadIsolated<T, NonOwningThread> {
        ThreadIsolated{
            inner: self.inner.clone(),
            debug: self.debug,
            _marker: PhantomData,
        }
    }

    pub fn downgrade_for_non_owning_thread(&self) -> ThreadIsolatedWeak<T> {
        ThreadIsolatedWeak{
            inner: self.inner.downgrade(),
            debug: self.debug,
        }
    }
}

impl<T> ThreadIsolated<T, NonOwningThread> {
    pub unsafe fn as_owning_thread(self) -> ThreadIsolated<T, OwningThread> {
        self.debug.assert_on_originating_thread();
        ThreadIsolated{
            inner: self.inner,
            debug: self.debug,
            _marker: PhantomData,
        }
    }

    pub fn with<U, F>(&self, f: F) -> U where
        F: FnOnce(&RefCell<T>) -> U + Send,
        U: Send,
    {
        self.debug.assert_not_on_originating_thread();

        let (tx, rx) = sync_channel(1);

        let closure: Box<FnBox() + Send> = Box::new(move|| {
            self.debug.assert_on_originating_thread();
            let u = f(&self.inner.item);
            tx.send(u).unwrap();
        });

        // `closure` contains references, but IsolationRunner expects an FnBox
        // that is 'static. We're using a channel to block until after `f` has been
        // called, so any references it contains will be alive as long as they need
        // to be. The borrow checker can't know that (the channels are purely a
        // runtime thing), so we'll use mem::transmute to force `closure` to *look*
        // like a 'static FnBox.
        //
        // This is safe because the runner can only call closure once, and we won't
        // return until after that call finishes.
        let closure: Box<FnBox() + Send + 'static> = unsafe { mem::transmute(closure) };
        self.inner.runner.run_on_owning_thread(closure);

        // Memory safety of the above closure relies on this recv() blocking until
        // the closure has run. It's not safe for us to just panic if recv() fails;
        // we need to tear down the whole process.
        match rx.recv() {
            Ok(u) => u,
            Err(err) => {
                println!("recv() failed: {}", err);
                unsafe { std::intrinsics::abort(); }
            }
        }
    }
}

impl<T> Clone for ThreadIsolated<T, NonOwningThread> {
    fn clone(&self) -> ThreadIsolated<T, NonOwningThread> {
        ThreadIsolated{
            inner: self.inner.clone(),
            debug: self.debug,
            _marker: PhantomData,
        }
    }
}

unsafe impl<T> Send for ThreadIsolated<T, NonOwningThread> {}
unsafe impl<T> Sync for ThreadIsolated<T, NonOwningThread> {}

pub struct ThreadIsolatedWeak<T> {
    inner: Weak<Inner<T>>,
    debug: ThreadDebugger,
}

impl<T> ThreadIsolatedWeak<T> {
    pub fn upgrade(&self) -> Option<ThreadIsolated<T, NonOwningThread>> {
        self.inner.upgrade().map(|inner| {
            ThreadIsolated{
                inner: inner,
                debug: self.debug,
                _marker: PhantomData,
            }
        })
    }
}

unsafe impl<T> Send for ThreadIsolatedWeak<T> {}
unsafe impl<T> Sync for ThreadIsolatedWeak<T> {}

#[cfg(debug_assertions)]
mod debug {
    use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};

    static THREAD_ID_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;

    fn next_thread_id() -> usize {
        THREAD_ID_COUNTER.fetch_add(1, Ordering::SeqCst)
    }

    thread_local!(static THREAD_ID: usize = next_thread_id());

    fn our_thread_id() -> usize {
        THREAD_ID.with(|t| *t)
    }

    #[derive(Copy,Clone)]
    pub struct ThreadDebugger {
        thread_id: usize,
    }

    impl ThreadDebugger {
        pub fn new() -> ThreadDebugger {
            ThreadDebugger{
                thread_id: our_thread_id(),
            }
        }

        pub fn assert_on_originating_thread(&self) {
            assert!(self.thread_id == our_thread_id(), "item accessed off of owning thread");
        }

        pub fn assert_not_on_originating_thread(&self) {
            assert!(self.thread_id != our_thread_id(),
                    "item unexpectedly accessed on owning thread");
        }
    }
}

#[cfg(not(debug_assertions))]
mod debug {
    #[derive(Copy,Clone)]
    pub struct ThreadDebugger;

    impl ThreadDebugger {
        pub fn new() -> ThreadDebugger { ThreadDebugger }
        pub fn assert_on_originating_thread(&self) {}
        pub fn assert_not_on_originating_thread(&self) {}
    }
}

#[cfg(test)]
mod test {
    use std::thread;
    use std::sync::{Arc, Barrier, Mutex};
    use std::sync::mpsc::{channel, Sender};
    use std::boxed::FnBox;

    use super::{IsolationRunner, ThreadIsolated};

    #[test]
    fn test_normal_use() {
        // Create an isolation runner that uses channels to send boxed functions
        // back to the main thread for it to run.
        struct Runner {
            tx: Mutex<Sender<Box<FnBox() + Send>>>,
        }

        impl IsolationRunner for Runner {
            fn run_on_owning_thread(&self, boxed: Box<FnBox() + Send>) {
                let guard = self.tx.lock().unwrap();
                guard.send(boxed).unwrap();
            }
        }

        let (tx, rx) = channel();
        let (tx_f, rx_f) = channel();
        let (tx_clone, rx_clone) = channel();
        let runner = Runner{ tx: Mutex::new(tx_f) };

        // start up the owning thread
        let handle = thread::spawn(move|| {
            // create our ThreadIsolated...
            let t = unsafe { ThreadIsolated::new(0i32, runner) };

            // ...and give a non-owning clone back to the test_normal_use thread.
            tx_clone.send(t.clone_for_non_owning_thread()).unwrap();

            loop {
                select! (
                    // If we receive a message on rx, confirm that t has been incremented
                    // the expected number of times, then exit.
                    _ = rx.recv() => {
                        assert_eq!(*t.borrow(), 20);
                        return
                    },

                    // If we receive a function on rx_f, run it.
                    f = rx_f.recv() => {
                        f.unwrap()();
                    }
                )
            }
        });

        // start up 10 worker threads, each of which will try to increment the counter
        // owned by the thread above twice.
        let barrier = Arc::new(Barrier::new(11));
        let non_owning_t = rx_clone.recv().unwrap();
        for _ in 0 .. 10 {
            let b = barrier.clone();
            let t = non_owning_t.clone();
            thread::spawn(move|| {
                let t2 = t.clone();
                t.with(|refcell| {
                    *refcell.borrow_mut() += 1;

                    // Inside `with`, we're on the owning thread, so we can (unsafely)
                    // convert a NonOwningThread handle to an OwningThread handle.
                    let owning_t = unsafe { t2.as_owning_thread() };
                    *owning_t.borrow_mut() += 1;
                });
                b.wait();
            });
        }

        // wait until all worker threads are finished
        barrier.wait();

        // send the owning thread the message to check that its counter is as expected
        tx.send(()).unwrap();

        assert!(handle.join().is_ok());
    }

    #[cfg(debug_assertions)]
    mod debug_tests {
        use std::thread;
        use std::boxed::FnBox;
        use ::{IsolationRunner, ThreadIsolated};

        struct UnsafeNoopRunner;

        impl IsolationRunner for UnsafeNoopRunner {
            fn run_on_owning_thread(&self, f: Box<FnBox() + Send>) {
                f()
            }
        }

        #[test]
        fn test_accessing_nonowning_value_from_owning_thread_panics() {
            let handle = thread::spawn(move|| {
                let t = unsafe { ThreadIsolated::new(0i32, UnsafeNoopRunner) };
                let t2 = t.clone_for_non_owning_thread();

                t2.with(|t| {
                    *t.borrow_mut() = 1;
                });
            });

            assert!(handle.join().is_err());
        }

        #[test]
        fn test_accessing_owning_value_from_nonowning_thread_panics() {
            let t = unsafe { ThreadIsolated::new(0i32, UnsafeNoopRunner) };
            let t2 = t.clone_for_non_owning_thread();

            let handle = thread::spawn(move|| {
                t2.with(|t| {
                    *t.borrow_mut() = 1;
                });
            });

            assert!(handle.join().is_err());
        }

        #[test]
        fn test_as_owning_thread_panics_if_called_off_owning_thread() {
            let t = unsafe { ThreadIsolated::new(0i32, UnsafeNoopRunner) };
            let t2 = t.clone_for_non_owning_thread();

            let handle = thread::spawn(move|| {
                let _ = unsafe { t2.as_owning_thread() };
            });

            assert!(handle.join().is_err());
        }
    }
}
<commit_msg>Misc. cleanup (no functional changes)<commit_after>#![feature(alloc)]
#![feature(core)]
#![cfg_attr(test, feature(std_misc))]

use std::boxed::FnBox;
use std::cell::{Ref, RefMut, RefCell};
use std::marker::PhantomData;
use std::mem;
use std::sync::{Arc, Weak};
use std::sync::mpsc::sync_channel;

use self::debug::ThreadDebugger;

pub trait IsolationRunner: Sync + 'static {
    fn run_on_owning_thread(&self, f: Box<FnBox() + Send>);
}

pub enum OwningThread {}
pub enum NonOwningThread {}

pub struct ThreadIsolated<T, ThreadKind> {
    inner: Arc<Inner<T>>,
    debug: ThreadDebugger,
    _marker: PhantomData<ThreadKind>,
}

struct Inner<T> {
    item: RefCell<T>,
    runner: Box<IsolationRunner>,
}

impl<T> ThreadIsolated<T, OwningThread> {
    pub unsafe fn new<R: IsolationRunner>(item: T, runner: R) -> ThreadIsolated<T, OwningThread> {
        ThreadIsolated{
            inner: Arc::new(Inner{
                item: RefCell::new(item),
                runner: Box::new(runner),
            }),
            debug: ThreadDebugger::new(),
            _marker: PhantomData,
        }
    }

    pub fn borrow(&self) -> Ref<T> {
        self.debug.assert_on_originating_thread();
        self.inner.item.borrow()
    }

    pub fn borrow_mut(&self) -> RefMut<T> {
        self.debug.assert_on_originating_thread();
        self.inner.item.borrow_mut()
    }

    pub fn clone_for_non_owning_thread(&self) -> ThreadIsolated<T, NonOwningThread> {
        ThreadIsolated{
            inner: self.inner.clone(),
            debug: self.debug,
            _marker: PhantomData,
        }
    }

    pub fn downgrade_for_non_owning_thread(&self) -> ThreadIsolatedWeak<T> {
        ThreadIsolatedWeak{
            inner: self.inner.downgrade(),
            debug: self.debug,
        }
    }
}

impl<T> ThreadIsolated<T, NonOwningThread> {
    pub unsafe fn as_owning_thread(self) -> ThreadIsolated<T, OwningThread> {
        self.debug.assert_on_originating_thread();
        ThreadIsolated{
            inner: self.inner,
            debug: self.debug,
            _marker: PhantomData,
        }
    }

    pub fn with<U, F>(&self, f: F) -> U where
        F: FnOnce(&RefCell<T>) -> U + Send,
        U: Send,
    {
        self.debug.assert_not_on_originating_thread();

        let (tx, rx) = sync_channel(1);

        let closure: Box<FnBox() + Send> = Box::new(move|| {
            self.debug.assert_on_originating_thread();
            let u = f(&self.inner.item);
            tx.send(u).unwrap();
        });

        // `closure` contains references, but IsolationRunner expects an FnBox
        // that is 'static. We're using a channel to block until after `f` has been
        // called, so any references it contains will be alive as long as they need
        // to be. The borrow checker can't know that (the channels are purely a
        // runtime thing), so we'll use mem::transmute to force `closure` to *look*
        // like a 'static FnBox.
        //
        // This is safe because the runner can only call closure once, and we won't
        // return until after that call finishes.
        let closure: Box<FnBox() + Send + 'static> = unsafe { mem::transmute(closure) };
        self.inner.runner.run_on_owning_thread(closure);

        // Memory safety of the above closure relies on this recv() blocking until
        // the closure has run. It's not safe for us to just panic if recv() fails;
        // we need to tear down the whole process.
        match rx.recv() {
            Ok(u) => u,
            Err(err) => {
                println!("recv() failed: {}", err);
                unsafe { std::intrinsics::abort(); }
            }
        }
    }
}

impl<T> Clone for ThreadIsolated<T, NonOwningThread> {
    fn clone(&self) -> ThreadIsolated<T, NonOwningThread> {
        ThreadIsolated{
            inner: self.inner.clone(),
            debug: self.debug,
            _marker: PhantomData,
        }
    }
}

unsafe impl<T> Send for ThreadIsolated<T, NonOwningThread> {}
unsafe impl<T> Sync for ThreadIsolated<T, NonOwningThread> {}

pub struct ThreadIsolatedWeak<T> {
    inner: Weak<Inner<T>>,
    debug: ThreadDebugger,
}

impl<T> ThreadIsolatedWeak<T> {
    pub fn upgrade(&self) -> Option<ThreadIsolated<T, NonOwningThread>> {
        self.inner.upgrade().map(|inner| {
            ThreadIsolated{
                inner: inner,
                debug: self.debug,
                _marker: PhantomData,
            }
        })
    }
}

unsafe impl<T> Send for ThreadIsolatedWeak<T> {}
unsafe impl<T> Sync for ThreadIsolatedWeak<T> {}

#[cfg(debug_assertions)]
mod debug {
    use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};

    static THREAD_ID_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;

    fn next_thread_id() -> usize {
        THREAD_ID_COUNTER.fetch_add(1, Ordering::SeqCst)
    }

    thread_local!(static THREAD_ID: usize = next_thread_id());

    fn our_thread_id() -> usize {
        THREAD_ID.with(|t| *t)
    }

    #[derive(Copy, Clone)]
    pub struct ThreadDebugger {
        thread_id: usize,
    }

    impl ThreadDebugger {
        pub fn new() -> ThreadDebugger {
            ThreadDebugger{
                thread_id: our_thread_id(),
            }
        }

        pub fn assert_on_originating_thread(&self) {
            assert!(self.thread_id == our_thread_id(), "item accessed off of owning thread");
        }

        pub fn assert_not_on_originating_thread(&self) {
            assert!(self.thread_id != our_thread_id(), "item accessed on owning thread");
        }
    }
}

#[cfg(not(debug_assertions))]
mod debug {
    #[derive(Copy, Clone)]
    pub struct ThreadDebugger;

    impl ThreadDebugger {
        pub fn new() -> ThreadDebugger { ThreadDebugger }
        pub fn assert_on_originating_thread(&self) {}
        pub fn assert_not_on_originating_thread(&self) {}
    }
}

#[cfg(test)]
mod test {
    use std::thread;
    use std::sync::{Arc, Barrier, Mutex};
    use std::sync::mpsc::{channel, Sender};
    use std::boxed::FnBox;

    use super::{IsolationRunner, ThreadIsolated};

    #[test]
    fn test_normal_use() {
        // Create an isolation runner that uses channels to send boxed functions
        // back to the main thread for it to run.
        struct Runner {
            tx: Mutex<Sender<Box<FnBox() + Send>>>,
        }

        impl IsolationRunner for Runner {
            fn run_on_owning_thread(&self, boxed: Box<FnBox() + Send>) {
                let guard = self.tx.lock().unwrap();
                guard.send(boxed).unwrap();
            }
        }

        let (tx_check_done, rx_check_done) = channel();
        let (tx_f, rx_f) = channel();
        let (tx_clone, rx_clone) = channel();

        // start up the owning thread
        let handle = thread::spawn(move|| {
            // create our ThreadIsolated...
            let runner = Runner{ tx: Mutex::new(tx_f) };
            let t = unsafe { ThreadIsolated::new(0i32, runner) };

            // ...and give a non-owning clone back to the test_normal_use thread.
            tx_clone.send(t.clone_for_non_owning_thread()).unwrap();

            loop {
                select! (
                    // If we receive a message on rx_check_done, confirm that t has been
                    // incremented the expected number of times, then exit.
                    _ = rx_check_done.recv() => {
                        assert_eq!(*t.borrow(), 20);
                        return
                    },

                    // If we receive a function on rx_f, run it.
                    f = rx_f.recv() => {
                        f.unwrap()();
                    }
                )
            }
        });

        // start up 10 worker threads, each of which will try to increment the counter
        // owned by the thread above twice.
        let barrier = Arc::new(Barrier::new(11));
        let non_owning_t = rx_clone.recv().unwrap();
        for _ in 0 .. 10 {
            let b = barrier.clone();
            let t = non_owning_t.clone();
            thread::spawn(move|| {
                let t2 = t.clone();
                t.with(|refcell| {
                    *refcell.borrow_mut() += 1;

                    // Inside `with`, we're on the owning thread, so we can (unsafely)
                    // convert a NonOwningThread handle to an OwningThread handle.
                    let owning_t = unsafe { t2.as_owning_thread() };
                    *owning_t.borrow_mut() += 1;
                });
                b.wait();
            });
        }

        // wait until all worker threads are finished
        barrier.wait();

        // send the owning thread the message to check that its counter is as expected
        tx_check_done.send(()).unwrap();

        assert!(handle.join().is_ok());
    }

    #[cfg(debug_assertions)]
    mod debug_tests {
        use std::thread;
        use std::boxed::FnBox;
        use ::{IsolationRunner, ThreadIsolated};

        struct UnsafeNoopRunner;

        impl IsolationRunner for UnsafeNoopRunner {
            fn run_on_owning_thread(&self, f: Box<FnBox() + Send>) {
                f()
            }
        }

        #[test]
        fn test_accessing_nonowning_value_from_owning_thread_panics() {
            let handle = thread::spawn(move|| {
                let t = unsafe { ThreadIsolated::new(0i32, UnsafeNoopRunner) };
                let t2 = t.clone_for_non_owning_thread();

                t2.with(|t| {
                    *t.borrow_mut() = 1;
                });
            });

            assert!(handle.join().is_err());
        }

        #[test]
        fn test_accessing_owning_value_from_nonowning_thread_panics() {
            let t = unsafe { ThreadIsolated::new(0i32, UnsafeNoopRunner) };
            let t2 = t.clone_for_non_owning_thread();

            let handle = thread::spawn(move|| {
                t2.with(|t| {
                    *t.borrow_mut() = 1;
                });
            });

            assert!(handle.join().is_err());
        }

        #[test]
        fn test_as_owning_thread_panics_if_called_off_owning_thread() {
            let t = unsafe { ThreadIsolated::new(0i32, UnsafeNoopRunner) };
            let t2 = t.clone_for_non_owning_thread();

            let handle = thread::spawn(move|| {
                let _ = unsafe { t2.as_owning_thread() };
            });

            assert!(handle.join().is_err());
        }
    }
}
<|endoftext|>


<commit_before>//! indicatif is a library for Rust that helps you build command line
//! interfaces that report progress to users.  It comes with various
//! tools and utilities for formatting anything that indicates progress.
//!
//! # Progress Bars and Spinners
//!
//! indicatif comes with a `ProgressBar` type that support both bounded
//! progress bar uses as well as unbounded "spinner" type progress reports.
//! Progress bars are `Sync` and `Send` objects which means that they are
//! internally locked and can be passed from thread to thread.
//!
//! Additionally a `MultiProgress` utility is provided that can manage
//! rendering multiple progress bars at once (eg: for instance from
//! multiple threads).
//!
//! Progress bars are manually advanced and by default draw to stdout.
//! When you are done the progress bar can be finished either visibly
//! (eg: the progress bar stays on the screen) or cleared (the progress
//! bar will be removed).
//!
//! ```rust
//! use indicatif::ProgressBar;
//!
//! let bar = ProgressBar::new(1000);
//! for _ in 0..1000 {
//!     bar.inc();
//!     // ...
//! }
//! bar.finish();
//! ```
//!
//! # Templates
//!
//! Progress bars can be styled with simple format strings similar to the
//! ones in Rust itself.  The format for a placeholder is `{key:options}`
//! where the `options` part is optional.  If provided the format is this:
//!
//! ```
//! [<^>]           for an optional alignment specification
//! WIDTH           an optional width as positive integer
//! !               an optional exclamation mark to enable truncation
//! .STYLE          an optional dot separated style string
//! /STYLE          an optional dot separated alternative style string
//! ```
//!
//! For the style component see `Styled::from_dotted_str` for more
//! information.
//!
//! Some examples for templates:
//!
//! ```
//! [{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}
//! ```
//!
//! This sets a progress bar that is 40 characters wide and has cyan
//! as primary style color and blue as alternative style color.
//! Alternative styles are currently only used for progress bars.
//!
//! The following keys exist:
//!
//! * `bar`: renders a progress bar. By default 20 characters wide.  The
//!   style string is used to color the elapsed part, the alternative
//!   style is used for the bar that is yet to render.
//! * `wide_bar`: like `bar` but always fills the remaining space.
//! * `spinner`: renders the spinner (current tick char)
//! * `msg`: renders the currently set message on the progress bar.
//! * `pos`: renders the current position of the bar as integer
//! * `len`: renders the total length of the bar as integer
//! * `bytes`: renders the current position of the bar as bytes.
//! * `total_bytes`: renders the total length of the bar as bytes.
//! * `elapsed_precise`: renders the elapsed time as `HH:MM:SS`.
//! * `elapased`: renders the elapsed time as `42s`, `1m` etc.
//! * `eta_precise`: the remaining time (like `elapsed_precise`).
//! * `eta`: the remaining time (like `elapsed`).
//!
//! The design of the progress bar can be altered with the integrated
//! template functionality.
//!
//! # Colors
//!
//! `indicatif` uses `clicolors-control` to control colors.  It also
//! provides higher level wrappers for styling text and other things
//! that can be displayed with the `style` function.
#[cfg(unix)] extern crate libc;
#[cfg(windows)] extern crate winapi;
#[cfg(windows)] extern crate kernel32;
extern crate parking_lot;
extern crate regex;
#[macro_use] extern crate lazy_static;
extern crate unicode_width;
extern crate clicolors_control;

mod term;
mod progress;
mod utils;
mod ansistyle;
mod format;

pub use progress::{ProgressBar, MultiProgress, ProgressState, DrawState,
                   DrawTarget, ProgressStyle};
pub use term::Term;
pub use ansistyle::{style, Styled, Color, Style,
                    strip_ansi_codes, measure_text_width,
                    colors_enabled, set_colors_enabled};
pub use format::{HumanDuration, FormattedDuration, HumanBytes};
<commit_msg>Added more doc stuff<commit_after>//! indicatif is a library for Rust that helps you build command line
//! interfaces that report progress to users.  It comes with various
//! tools and utilities for formatting anything that indicates progress.
//!
//! # Progress Bars and Spinners
//!
//! indicatif comes with a `ProgressBar` type that support both bounded
//! progress bar uses as well as unbounded "spinner" type progress reports.
//! Progress bars are `Sync` and `Send` objects which means that they are
//! internally locked and can be passed from thread to thread.
//!
//! Additionally a `MultiProgress` utility is provided that can manage
//! rendering multiple progress bars at once (eg: for instance from
//! multiple threads).
//!
//! Progress bars are manually advanced and by default draw to stdout.
//! When you are done the progress bar can be finished either visibly
//! (eg: the progress bar stays on the screen) or cleared (the progress
//! bar will be removed).
//!
//! ```rust
//! use indicatif::ProgressBar;
//!
//! let bar = ProgressBar::new(1000);
//! for _ in 0..1000 {
//!     bar.inc();
//!     // ...
//! }
//! bar.finish();
//! ```
//!
//! # Templates
//!
//! Progress bars can be styled with simple format strings similar to the
//! ones in Rust itself.  The format for a placeholder is `{key:options}`
//! where the `options` part is optional.  If provided the format is this:
//!
//! ```
//! [<^>]           for an optional alignment specification
//! WIDTH           an optional width as positive integer
//! !               an optional exclamation mark to enable truncation
//! .STYLE          an optional dot separated style string
//! /STYLE          an optional dot separated alternative style string
//! ```
//!
//! For the style component see `Styled::from_dotted_str` for more
//! information.
//!
//! Some examples for templates:
//!
//! ```text
//! [{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}
//! ```
//!
//! This sets a progress bar that is 40 characters wide and has cyan
//! as primary style color and blue as alternative style color.
//! Alternative styles are currently only used for progress bars.
//!
//! The following keys exist:
//!
//! * `bar`: renders a progress bar. By default 20 characters wide.  The
//!   style string is used to color the elapsed part, the alternative
//!   style is used for the bar that is yet to render.
//! * `wide_bar`: like `bar` but always fills the remaining space.
//! * `spinner`: renders the spinner (current tick char)
//! * `msg`: renders the currently set message on the progress bar.
//! * `pos`: renders the current position of the bar as integer
//! * `len`: renders the total length of the bar as integer
//! * `bytes`: renders the current position of the bar as bytes.
//! * `total_bytes`: renders the total length of the bar as bytes.
//! * `elapsed_precise`: renders the elapsed time as `HH:MM:SS`.
//! * `elapased`: renders the elapsed time as `42s`, `1m` etc.
//! * `eta_precise`: the remaining time (like `elapsed_precise`).
//! * `eta`: the remaining time (like `elapsed`).
//!
//! The design of the progress bar can be altered with the integrated
//! template functionality.  The template can be set by changing a
//! `ProgressStyle` and attaching it to the progress bar.
//!
//! # Terminal Access
//!
//! The library provides a basic abstraction over working with terminals
//! through the `Term` object.  For instance you can use it to move
//! cursors or clear contents.
//!
//! # Colors and Styles
//!
//! `indicatif` uses `clicolors-control` to control colors.  It also
//! provides higher level wrappers for styling text and other things
//! that can be displayed with the `style` function.
//!
//! Example usage:
//!
//! ```
//! use indicatif::style;
//!
//! println!("This is {} neat", style("fo").cyan());
//! ```
//!
//! # Human Readable Formatting
//!
//! There are some formatting wrappers for showing elapsed time and
//! file sizes for human users:
//!
//! ```ignore
//! use std::time::Instant;
//! use indicatif::{HumanDuration, HumanBytes};
//!
//! let started = Instant::now();
//! println!("The file is {} large", HumanBytes(file.size));
//! println!("The script took {}", HumanDuration(started.elapsed()));
//! ```
#[cfg(unix)] extern crate libc;
#[cfg(windows)] extern crate winapi;
#[cfg(windows)] extern crate kernel32;
extern crate parking_lot;
extern crate regex;
#[macro_use] extern crate lazy_static;
extern crate unicode_width;
extern crate clicolors_control;

mod term;
mod progress;
mod utils;
mod ansistyle;
mod format;

pub use progress::{ProgressBar, MultiProgress, ProgressState, DrawState,
                   DrawTarget, ProgressStyle};
pub use term::Term;
pub use ansistyle::{style, Styled, Color, Style,
                    strip_ansi_codes, measure_text_width,
                    colors_enabled, set_colors_enabled};
pub use format::{HumanDuration, FormattedDuration, HumanBytes};
<|endoftext|>


<commit_before>#![feature(const_fn)]
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

extern crate serde;
extern crate serde_json;

use serde::Deserialize;
use std::fmt;
use std::io::{self, Read};
use std::convert;
use std::collections::HashMap;
use std::net::{
    TcpListener,
    TcpStream,
    SocketAddr,
};
use std::sync::{
    self,
    Mutex,
    Arc,
};
use std::sync::mpsc::{
    channel,
    Sender,
    Receiver,
    TryRecvError,
};
use std::thread::{
    self,
    JoinHandle,
};

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Json(serde_json::Error),
    Sender,
    Unimplemented,
    Impossible
}

impl convert::From<serde_json::Error> for Error {
    fn from(err: serde_json::Error) -> Error {
        match err {
            serde_json::Error::IoError(err) => Error::Io(err),
            err => Error::Json(err),
        }
    }
}

impl convert::From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl<T> convert::From<sync::mpsc::SendError<T>> for Error {
    fn from(_: sync::mpsc::SendError<T>) -> Error {
        Error::Sender
    }
}

pub type Result<T> = std::result::Result<T, Error>;

pub fn handle_conn<F, Request, Reply>(mut stream: TcpStream, f: F) -> Result<()>
    where Request: 'static + fmt::Debug + Send + serde::de::Deserialize + serde::ser::Serialize,
          Reply: 'static + fmt::Debug + serde::ser::Serialize,
          F: 'static + Clone + Serve<Request, Reply>
{
    let read_stream = try!(stream.try_clone());
    let mut de = serde_json::Deserializer::new(read_stream.bytes());
    let stream = Arc::new(Mutex::new(stream));
    loop {
        let request_packet: Packet<Request> = try!(Packet::deserialize(&mut de));
        match request_packet {
            Packet::Shutdown => {
                let stream = stream.clone();
                let mut my_stream = stream.lock().unwrap();
                try!(serde_json::to_writer(&mut *my_stream, &request_packet));
                break;
            },
            Packet::Message(id, message) => {
                let f = f.clone();
                let arc_stream = stream.clone();
                thread::spawn(move || {
                    let reply = f.serve(&message).unwrap();
                    let reply_packet = Packet::Message(id, reply);
                    let mut my_stream = arc_stream.lock().unwrap();
                    serde_json::to_writer(&mut *my_stream, &reply_packet).unwrap();
                });
            },
        }
    }
    Ok(())
}

pub struct Shutdown {
    tx: Sender<()>,
    join_handle: JoinHandle<()>,
    addr: SocketAddr,
}

impl Shutdown {
    fn wait(self) {
        self.join_handle.join().unwrap();
    }

    fn shutdown(self) {
        self.tx.send(()).expect(&line!().to_string());
        TcpStream::connect(&self.addr).unwrap();
        self.join_handle.join().expect(&line!().to_string());
    }
}

pub fn serve_async<F, Request, Reply>(addr: &SocketAddr, f: F) -> io::Result<Shutdown>
    where Request: 'static + fmt::Debug + Send + serde::de::Deserialize + fmt::Debug + serde::ser::Serialize,
          Reply: 'static + fmt::Debug + serde::ser::Serialize,
          F: 'static + Clone + Serve<Request, Reply>,
{
    let listener = try!(TcpListener::bind(addr));
    let (die_tx, die_rx) = channel();
    let join_handle = thread::spawn(move || {
        for conn in listener.incoming() {
            match die_rx.try_recv() {
                Ok(_) => break,
                Err(TryRecvError::Disconnected) => {
                    println!("serve: sender disconnected ");
                    break;
                },
                _ => (),
            }
            let conn = match conn {
                Err(err) => {
                    println!("I couldn't unwrap the connection :( {:?}", err);
                    return;
                },
                Ok(c) => c,
            };
            let f = f.clone();
            thread::spawn(move || {
                if let Err(err) = handle_conn(conn, f) {
                    println!("error handling connection: {:?}", err);
                }
            });
        }
    });
    Ok(Shutdown{
        tx: die_tx,
        join_handle: join_handle,
        addr: addr.clone(),
    })
}

pub trait Serve<Request, Reply>: Send + Sync {
    fn serve(&self, request: &Request) -> io::Result<Reply>;
}

impl<Request, Reply, S> Serve<Request, Reply> for Arc<S>
    where S: Serve<Request, Reply>
{
    fn serve(&self, request: &Request) -> io::Result<Reply> {
        S::serve(self, request)
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
enum Packet<T> {
    Message(u64, T),
    Shutdown,
}

fn reader<Reply>(
    stream: TcpStream,
    requests: Arc<Mutex<HashMap<u64, Sender<Reply>>>>)
    where Reply: serde::Deserialize
{
    let mut de = serde_json::Deserializer::new(stream.bytes());
    loop {
        match Packet::deserialize(&mut de) {
            Ok(Packet::Message(id, reply)) => {
                let mut requests = requests.lock().unwrap();
                let reply_tx = requests.remove(&id).unwrap();
                reply_tx.send(reply).unwrap();
            },
            Ok(Packet::Shutdown) => {
                break;
            }
            // TODO: This shutdown logic is janky.. What's the right way to do this?
            Err(err) => panic!("unexpected error while parsing!: {:?}", err),
        }
    }
}

fn increment(cur_id: &mut u64) -> u64 {
    let id = *cur_id;
    *cur_id += 1;
    id
}

struct SyncedClientState {
    next_id: u64,
    stream: TcpStream,
}

pub struct Client<Reply> {
    synced_state: Mutex<SyncedClientState>,
    requests: Arc<Mutex<HashMap<u64, Sender<Reply>>>>,
    reader_guard: thread::JoinHandle<()>,
}

impl<Reply> Client<Reply>
    where Reply: serde::de::Deserialize + Send + 'static
{
    pub fn new(stream: TcpStream) -> Result<Self> {
        let requests = Arc::new(Mutex::new(HashMap::new()));
        let reader_stream = try!(stream.try_clone());
        let reader_requests = requests.clone();
        let reader_guard =
            thread::spawn(move || reader(reader_stream, reader_requests));
        Ok(Client{
            synced_state: Mutex::new(SyncedClientState{
                next_id: 0,
                stream: stream,
            }),
            requests: requests,
            reader_guard: reader_guard,
        })
    }

    pub fn rpc<Request>(&self, request: &Request) -> Result<Reply>
        where Request: serde::ser::Serialize + Clone + Send + 'static
    {
        let (tx, rx) = channel();
        let mut state = self.synced_state.lock().unwrap();
        let id = increment(&mut state.next_id);
        {
            let mut requests = self.requests.lock().unwrap();
            requests.insert(id, tx);
        }
        let packet = Packet::Message(id, request.clone());
        try!(serde_json::to_writer(&mut state.stream, &packet));
        drop(state);
        Ok(rx.recv().unwrap())
    }

    pub fn disconnect<Request: serde::Serialize>(self) -> Result<()> {
        {
            let mut state = self.synced_state.lock().unwrap();
            let packet: Packet<Request> = Packet::Shutdown;
            try!(serde_json::to_writer(&mut state.stream, &packet));
        }
        self.reader_guard.join().unwrap();
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use serde;
    use super::*;
    use std::fmt;
    use std::io;
    use std::net::{TcpStream, TcpListener, SocketAddr, ToSocketAddrs};
    use std::str::FromStr;
    use std::sync::{Arc, Mutex, Barrier};
    use std::sync::mpsc::channel;
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::thread;

    const port: AtomicUsize = AtomicUsize::new(10000);

    fn next_addr() -> SocketAddr {
        let addr = format!("127.0.0.1:{}", port.fetch_add(1, Ordering::SeqCst));
        addr.to_socket_addrs().unwrap().next().unwrap()
        //ToSocketAddrs::to_socket_addrs(addr.as_ref()).unwrap().next().unwrap()
    }

    #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
    enum Request {
        Increment
    }

    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    enum Reply {
        Increment(u64)
    }

    struct Server {
        counter: Mutex<u64>,
    }

    impl Serve<Request, Reply> for Server {
        fn serve(&self, _: &Request) -> io::Result<Reply> {
            let mut counter = self.counter.lock().unwrap();
            let reply = Reply::Increment(*counter);
            *counter += 1;
            Ok(reply)
        }
    }

    impl Server {
        fn new() -> Server {
            Server{counter: Mutex::new(0)}
        }

        fn count(&self) -> u64 {
            *self.counter.lock().unwrap()
        }
    }

    fn wtf<F, Request, Reply>(server: F) -> (SocketAddr, Shutdown)
        where Request: 'static + fmt::Debug + Send + serde::de::Deserialize + fmt::Debug + serde::ser::Serialize,
              Reply: 'static + fmt::Debug + Send + serde::ser::Serialize,
              F: 'static + Clone + Serve<Request, Reply>
    {
        let mut addr;
        let mut shutdown;
        while let &Err(_) = {shutdown = serve_async({addr = next_addr(); &addr}, server.clone()); &shutdown} { }
        (addr, shutdown.unwrap())
    }

    #[test]
    fn test_handle() {
        let server = Arc::new(Server::new());
        let (addr, shutdown) = wtf(server.clone());
        let client_stream = TcpStream::connect(&addr).unwrap();
        let client: Client<Reply> = Client::new(client_stream).expect(&line!().to_string());
        client.disconnect::<Request>();
        shutdown.shutdown();
    }

    #[test]
    fn test() {
        let server = Arc::new(Server::new());
        let (addr, shutdown) = wtf(server.clone());
        let client_stream = TcpStream::connect(&addr).unwrap();
        let client = Client::new(client_stream).unwrap();
        assert_eq!(Reply::Increment(0), client.rpc(&Request::Increment).unwrap());
        assert_eq!(1, server.count());
        assert_eq!(Reply::Increment(1), client.rpc(&Request::Increment).unwrap());
        assert_eq!(2, server.count());
        client.disconnect::<Request>().unwrap();
        shutdown.shutdown();
    }

    struct BarrierServer {
        barrier: Barrier,
        inner: Server,
    }

    impl Serve<Request, Reply> for BarrierServer {
        fn serve(&self, request: &Request) -> io::Result<Reply> {
            self.barrier.wait();
            let reply = try!(self.inner.serve(request));
            Ok(reply)
        }
    }

    impl BarrierServer {
        fn new(n: usize) -> BarrierServer {
            BarrierServer{barrier: Barrier::new(n), inner: Server::new()}
        }

        fn count(&self) -> u64 {
            self.inner.count()
        }
    }

    #[test]
    fn test_concurrent() {
        let server = Arc::new(BarrierServer::new(10));
        let (addr, shutdown) = wtf(server.clone());
        let client_stream = TcpStream::connect(&addr).unwrap();
        let client: Arc<Client<Reply>> = Arc::new(Client::new(client_stream).unwrap());
        let mut join_handles = vec![];
        for _ in 0..10 {
            let my_client = client.clone();
            join_handles.push(thread::spawn(move || my_client.rpc(&Request::Increment).unwrap()));
        }
        for handle in join_handles.into_iter() {
            handle.join();
        }
        assert_eq!(10, server.count());
        let client = match Arc::try_unwrap(client) {
            Err(_) => panic!("couldn't unwrap arc"),
            Ok(c) => c,
        };
        client.disconnect::<Request>().unwrap();
        shutdown.shutdown();
    }
}
<commit_msg>Clean up those unused thingies<commit_after>#![feature(const_fn)]
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

extern crate serde;
extern crate serde_json;

use serde::Deserialize;
use std::fmt;
use std::io::{self, Read};
use std::convert;
use std::collections::HashMap;
use std::net::{
    TcpListener,
    TcpStream,
    SocketAddr,
};
use std::sync::{
    self,
    Mutex,
    Arc,
};
use std::sync::mpsc::{
    channel,
    Sender,
    TryRecvError,
};
use std::thread::{
    self,
    JoinHandle,
};

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Json(serde_json::Error),
    Sender,
    Unimplemented,
    Impossible
}

impl convert::From<serde_json::Error> for Error {
    fn from(err: serde_json::Error) -> Error {
        match err {
            serde_json::Error::IoError(err) => Error::Io(err),
            err => Error::Json(err),
        }
    }
}

impl convert::From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl<T> convert::From<sync::mpsc::SendError<T>> for Error {
    fn from(_: sync::mpsc::SendError<T>) -> Error {
        Error::Sender
    }
}

pub type Result<T> = std::result::Result<T, Error>;

pub fn handle_conn<F, Request, Reply>(stream: TcpStream, f: F) -> Result<()>
    where Request: 'static + fmt::Debug + Send + serde::de::Deserialize + serde::ser::Serialize,
          Reply: 'static + fmt::Debug + serde::ser::Serialize,
          F: 'static + Clone + Serve<Request, Reply>
{
    let read_stream = try!(stream.try_clone());
    let mut de = serde_json::Deserializer::new(read_stream.bytes());
    let stream = Arc::new(Mutex::new(stream));
    loop {
        let request_packet: Packet<Request> = try!(Packet::deserialize(&mut de));
        match request_packet {
            Packet::Shutdown => {
                let stream = stream.clone();
                let mut my_stream = stream.lock().unwrap();
                try!(serde_json::to_writer(&mut *my_stream, &request_packet));
                break;
            },
            Packet::Message(id, message) => {
                let f = f.clone();
                let arc_stream = stream.clone();
                thread::spawn(move || {
                    let reply = f.serve(&message).unwrap();
                    let reply_packet = Packet::Message(id, reply);
                    let mut my_stream = arc_stream.lock().unwrap();
                    serde_json::to_writer(&mut *my_stream, &reply_packet).unwrap();
                });
            },
        }
    }
    Ok(())
}

pub struct Shutdown {
    tx: Sender<()>,
    join_handle: JoinHandle<()>,
    addr: SocketAddr,
}

impl Shutdown {
    pub fn wait(self) {
        self.join_handle.join().unwrap();
    }

    pub fn shutdown(self) {
        self.tx.send(()).expect(&line!().to_string());
        TcpStream::connect(&self.addr).unwrap();
        self.join_handle.join().expect(&line!().to_string());
    }
}

pub fn serve_async<F, Request, Reply>(addr: &SocketAddr, f: F) -> io::Result<Shutdown>
    where Request: 'static + fmt::Debug + Send + serde::de::Deserialize + fmt::Debug + serde::ser::Serialize,
          Reply: 'static + fmt::Debug + serde::ser::Serialize,
          F: 'static + Clone + Serve<Request, Reply>,
{
    let listener = try!(TcpListener::bind(addr));
    let (die_tx, die_rx) = channel();
    let join_handle = thread::spawn(move || {
        for conn in listener.incoming() {
            match die_rx.try_recv() {
                Ok(_) => break,
                Err(TryRecvError::Disconnected) => {
                    println!("serve: sender disconnected ");
                    break;
                },
                _ => (),
            }
            let conn = match conn {
                Err(err) => {
                    println!("I couldn't unwrap the connection :( {:?}", err);
                    return;
                },
                Ok(c) => c,
            };
            let f = f.clone();
            thread::spawn(move || {
                if let Err(err) = handle_conn(conn, f) {
                    println!("error handling connection: {:?}", err);
                }
            });
        }
    });
    Ok(Shutdown{
        tx: die_tx,
        join_handle: join_handle,
        addr: addr.clone(),
    })
}

pub trait Serve<Request, Reply>: Send + Sync {
    fn serve(&self, request: &Request) -> io::Result<Reply>;
}

impl<Request, Reply, S> Serve<Request, Reply> for Arc<S>
    where S: Serve<Request, Reply>
{
    fn serve(&self, request: &Request) -> io::Result<Reply> {
        S::serve(self, request)
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
enum Packet<T> {
    Message(u64, T),
    Shutdown,
}

fn reader<Reply>(
    stream: TcpStream,
    requests: Arc<Mutex<HashMap<u64, Sender<Reply>>>>)
    where Reply: serde::Deserialize
{
    let mut de = serde_json::Deserializer::new(stream.bytes());
    loop {
        match Packet::deserialize(&mut de) {
            Ok(Packet::Message(id, reply)) => {
                let mut requests = requests.lock().unwrap();
                let reply_tx = requests.remove(&id).unwrap();
                reply_tx.send(reply).unwrap();
            },
            Ok(Packet::Shutdown) => {
                break;
            }
            // TODO: This shutdown logic is janky.. What's the right way to do this?
            Err(err) => panic!("unexpected error while parsing!: {:?}", err),
        }
    }
}

fn increment(cur_id: &mut u64) -> u64 {
    let id = *cur_id;
    *cur_id += 1;
    id
}

struct SyncedClientState {
    next_id: u64,
    stream: TcpStream,
}

pub struct Client<Reply> {
    synced_state: Mutex<SyncedClientState>,
    requests: Arc<Mutex<HashMap<u64, Sender<Reply>>>>,
    reader_guard: thread::JoinHandle<()>,
}

impl<Reply> Client<Reply>
    where Reply: serde::de::Deserialize + Send + 'static
{
    pub fn new(stream: TcpStream) -> Result<Self> {
        let requests = Arc::new(Mutex::new(HashMap::new()));
        let reader_stream = try!(stream.try_clone());
        let reader_requests = requests.clone();
        let reader_guard =
            thread::spawn(move || reader(reader_stream, reader_requests));
        Ok(Client{
            synced_state: Mutex::new(SyncedClientState{
                next_id: 0,
                stream: stream,
            }),
            requests: requests,
            reader_guard: reader_guard,
        })
    }

    pub fn rpc<Request>(&self, request: &Request) -> Result<Reply>
        where Request: serde::ser::Serialize + Clone + Send + 'static
    {
        let (tx, rx) = channel();
        let mut state = self.synced_state.lock().unwrap();
        let id = increment(&mut state.next_id);
        {
            let mut requests = self.requests.lock().unwrap();
            requests.insert(id, tx);
        }
        let packet = Packet::Message(id, request.clone());
        try!(serde_json::to_writer(&mut state.stream, &packet));
        drop(state);
        Ok(rx.recv().unwrap())
    }

    pub fn disconnect<Request: serde::Serialize>(self) -> Result<()> {
        {
            let mut state = self.synced_state.lock().unwrap();
            let packet: Packet<Request> = Packet::Shutdown;
            try!(serde_json::to_writer(&mut state.stream, &packet));
        }
        self.reader_guard.join().unwrap();
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use serde;
    use super::*;
    use std::fmt;
    use std::io;
    use std::net::{TcpStream, TcpListener, SocketAddr, ToSocketAddrs};
    use std::str::FromStr;
    use std::sync::{Arc, Mutex, Barrier};
    use std::sync::mpsc::channel;
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::thread;

    const port: AtomicUsize = AtomicUsize::new(10000);

    fn next_addr() -> SocketAddr {
        let addr = format!("127.0.0.1:{}", port.fetch_add(1, Ordering::SeqCst));
        addr.to_socket_addrs().unwrap().next().unwrap()
        //ToSocketAddrs::to_socket_addrs(addr.as_ref()).unwrap().next().unwrap()
    }

    #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
    enum Request {
        Increment
    }

    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    enum Reply {
        Increment(u64)
    }

    struct Server {
        counter: Mutex<u64>,
    }

    impl Serve<Request, Reply> for Server {
        fn serve(&self, _: &Request) -> io::Result<Reply> {
            let mut counter = self.counter.lock().unwrap();
            let reply = Reply::Increment(*counter);
            *counter += 1;
            Ok(reply)
        }
    }

    impl Server {
        fn new() -> Server {
            Server{counter: Mutex::new(0)}
        }

        fn count(&self) -> u64 {
            *self.counter.lock().unwrap()
        }
    }

    fn wtf<F, Request, Reply>(server: F) -> (SocketAddr, Shutdown)
        where Request: 'static + fmt::Debug + Send + serde::de::Deserialize + fmt::Debug + serde::ser::Serialize,
              Reply: 'static + fmt::Debug + Send + serde::ser::Serialize,
              F: 'static + Clone + Serve<Request, Reply>
    {
        let mut addr;
        let mut shutdown;
        while let &Err(_) = {shutdown = serve_async({addr = next_addr(); &addr}, server.clone()); &shutdown} { }
        (addr, shutdown.unwrap())
    }

    #[test]
    fn test_handle() {
        let server = Arc::new(Server::new());
        let (addr, shutdown) = wtf(server.clone());
        let client_stream = TcpStream::connect(&addr).unwrap();
        let client: Client<Reply> = Client::new(client_stream).expect(&line!().to_string());
        client.disconnect::<Request>();
        shutdown.shutdown();
    }

    #[test]
    fn test() {
        let server = Arc::new(Server::new());
        let (addr, shutdown) = wtf(server.clone());
        let client_stream = TcpStream::connect(&addr).unwrap();
        let client = Client::new(client_stream).unwrap();
        assert_eq!(Reply::Increment(0), client.rpc(&Request::Increment).unwrap());
        assert_eq!(1, server.count());
        assert_eq!(Reply::Increment(1), client.rpc(&Request::Increment).unwrap());
        assert_eq!(2, server.count());
        client.disconnect::<Request>().unwrap();
        shutdown.shutdown();
    }

    struct BarrierServer {
        barrier: Barrier,
        inner: Server,
    }

    impl Serve<Request, Reply> for BarrierServer {
        fn serve(&self, request: &Request) -> io::Result<Reply> {
            self.barrier.wait();
            let reply = try!(self.inner.serve(request));
            Ok(reply)
        }
    }

    impl BarrierServer {
        fn new(n: usize) -> BarrierServer {
            BarrierServer{barrier: Barrier::new(n), inner: Server::new()}
        }

        fn count(&self) -> u64 {
            self.inner.count()
        }
    }

    #[test]
    fn test_concurrent() {
        let server = Arc::new(BarrierServer::new(10));
        let (addr, shutdown) = wtf(server.clone());
        let client_stream = TcpStream::connect(&addr).unwrap();
        let client: Arc<Client<Reply>> = Arc::new(Client::new(client_stream).unwrap());
        let mut join_handles = vec![];
        for _ in 0..10 {
            let my_client = client.clone();
            join_handles.push(thread::spawn(move || my_client.rpc(&Request::Increment).unwrap()));
        }
        for handle in join_handles.into_iter() {
            handle.join();
        }
        assert_eq!(10, server.count());
        let client = match Arc::try_unwrap(client) {
            Err(_) => panic!("couldn't unwrap arc"),
            Ok(c) => c,
        };
        client.disconnect::<Request>().unwrap();
        shutdown.shutdown();
    }
}
<|endoftext|>