<commit_before>extern crate num;

mod hardcoded_butterflies;

use num::{Complex, Zero};
use std::iter::repeat;
use std::f32;

use hardcoded_butterflies::{butterfly_2, butterfly_3, butterfly_4, butterfly_5};

pub struct FFT {
    factors: Vec<(usize, usize)>,
    twiddles: Vec<Complex<f32>>,
}

impl FFT {
    pub fn new(len: usize) -> Self {
        FFT {
            factors: factor(len),
            twiddles: (0..len)
                      .map(|i| -1. * (i as f32) * 2.0 * f32::consts::PI / (len as f32))
                      .map(|phase| Complex::from_polar(&1., &phase))
                      .collect(),
        }
    }

    pub fn process(&mut self, signal: &[Complex<f32>], spectrum: &mut [Complex<f32>]) {
        cooley_tukey(signal, spectrum, 1, &self.twiddles[..], &self.factors[..]);
    }
}

fn cooley_tukey(signal: &[Complex<f32>],
                spectrum: &mut [Complex<f32>],
                stride: usize,
                twiddles: &[Complex<f32>],
                factors: &[(usize, usize)]) {
    if let Some(&(n1, n2)) = factors.first() {
        if n2 == 1 {
            // An FFT of length 1 is just the identity operator
            let mut spectrum_idx = 0usize;
            for i in (0..signal.len() / stride) {
                unsafe { *spectrum.get_unchecked_mut(spectrum_idx) =
                    *signal.get_unchecked(i * stride); }
                spectrum_idx += 1;
            }
        } else {
            // Recursive call to perform n1 ffts of length n2
            for i in (0..n1) {
                cooley_tukey(&signal[i * stride..],
                             &mut spectrum[i * n2..],
                             stride * n1, twiddles, &factors[1..]);
            }
        }

        match n1 {
            5 => butterfly_5(spectrum, stride, twiddles, n2),
            4 => butterfly_4(spectrum, stride, twiddles, n2),
            3 => butterfly_3(spectrum, stride, twiddles, n2),
            2 => butterfly_2(spectrum, stride, twiddles, n2),
            _ => butterfly(spectrum, stride, twiddles, n2, n1),
        }
    }
}

fn butterfly(data: &mut [Complex<f32>], stride: usize,
             twiddles: &[Complex<f32>], num_ffts: usize, fft_len: usize) {

    // TODO pre-allocate this space at FFT initialization
    let mut scratch: Vec<Complex<f32>> = repeat(Zero::zero()).take(fft_len).collect();

    // for each fft we have to perform...
    for fft_idx in (0..num_ffts) {

        // copy over data into scratch space
        let mut data_idx = fft_idx;
        for s in scratch.iter_mut() {
            *s = unsafe { *data.get_unchecked(data_idx) };
            data_idx += num_ffts;
        }

        // perfom the butterfly from the scratch space into the original buffer
        for i in (fft_idx..fft_len) {
            let data_idx = i * num_ffts;
            let out_sample = unsafe { data.get_unchecked_mut(data_idx) };
            *out_sample = Zero::zero();
            let mut twiddle_idx = 0usize;
            for in_sample in scratch.iter() {
                let twiddle = unsafe { twiddles.get_unchecked(twiddle_idx) };
                *out_sample = *out_sample + in_sample * twiddle;
                twiddle_idx += stride * data_idx;
                if twiddle_idx >= twiddles.len() { twiddle_idx -= twiddles.len() }
            }
        }

    }
}

pub fn dft<'a, 'b, I, O>(signal: I, spectrum: O)
where I: Iterator<Item=&'a Complex<f32>> + ExactSizeIterator + Clone,
      O: Iterator<Item=&'b mut Complex<f32>>
{
    for (k, spec_bin) in spectrum.enumerate()
    {
        let signal_iter = signal.clone();
        let mut sum: Complex<f32> = Zero::zero();
        for (i, &x) in signal_iter.enumerate() {
            let angle = -1. * ((i * k) as f32) * 2.0 * f32::consts::PI / (signal.len() as f32);
            let twiddle: Complex<f32> = Complex::from_polar(&1f32, &angle);
            sum = sum + twiddle * x;
        }
        *spec_bin = sum;
    }
}

fn factor(n: usize) -> Vec<(usize, usize)>
{
    let mut factors = Vec::new();
    let mut next = n;
    while next > 1 {
        for div in (2..next) {
            if next % div == 0 {
                next = next / div;
                factors.push((div, next));
                break;
            }
        }
    }
    return factors;
}
<commit_msg>Fixed some bugs from changing to stable branch in the last commit. Tests now pass, but still no benchmarking.<commit_after>extern crate num;

mod hardcoded_butterflies;

use num::{Complex, Zero};
use std::iter::repeat;
use std::f32;

use hardcoded_butterflies::{butterfly_2, butterfly_3, butterfly_4, butterfly_5};

pub struct FFT {
    factors: Vec<(usize, usize)>,
    twiddles: Vec<Complex<f32>>,
}

impl FFT {
    pub fn new(len: usize) -> Self {
        FFT {
            factors: factor(len),
            twiddles: (0..len)
                      .map(|i| -1. * (i as f32) * 2.0 * f32::consts::PI / (len as f32))
                      .map(|phase| Complex::from_polar(&1., &phase))
                      .collect(),
        }
    }

    pub fn process(&mut self, signal: &[Complex<f32>], spectrum: &mut [Complex<f32>]) {
        cooley_tukey(signal, spectrum, 1, &self.twiddles[..], &self.factors[..]);
    }
}

fn cooley_tukey(signal: &[Complex<f32>],
                spectrum: &mut [Complex<f32>],
                stride: usize,
                twiddles: &[Complex<f32>],
                factors: &[(usize, usize)]) {
    if let Some(&(n1, n2)) = factors.first() {
        if n2 == 1 {
            // An FFT of length 1 is just the identity operator
            let mut spectrum_idx = 0usize;
            let mut signal_idx = 0usize;
            while signal_idx < signal.len() {
                unsafe { *spectrum.get_unchecked_mut(spectrum_idx) =
                    *signal.get_unchecked(signal_idx); }
                spectrum_idx += 1;
                signal_idx += stride;
            }
        } else {
            // Recursive call to perform n1 ffts of length n2
            for i in (0..n1) {
                cooley_tukey(&signal[i * stride..],
                             &mut spectrum[i * n2..],
                             stride * n1, twiddles, &factors[1..]);
            }
        }

        match n1 {
            5 => butterfly_5(spectrum, stride, twiddles, n2),
            4 => butterfly_4(spectrum, stride, twiddles, n2),
            3 => butterfly_3(spectrum, stride, twiddles, n2),
            2 => butterfly_2(spectrum, stride, twiddles, n2),
            _ => butterfly(spectrum, stride, twiddles, n2, n1),
        }
    }
}

fn butterfly(data: &mut [Complex<f32>], stride: usize,
             twiddles: &[Complex<f32>], num_ffts: usize, fft_len: usize) {

    // TODO pre-allocate this space at FFT initialization
    let mut scratch: Vec<Complex<f32>> = repeat(Zero::zero()).take(fft_len).collect();

    // for each fft we have to perform...
    for fft_idx in (0..num_ffts) {

        // copy over data into scratch space
        let mut data_idx = fft_idx;
        for s in scratch.iter_mut() {
            *s = unsafe { *data.get_unchecked(data_idx) };
            data_idx += num_ffts;
        }

        // perfom the butterfly from the scratch space into the original buffer
        let mut data_idx = fft_idx;
        while data_idx < fft_len * num_ffts {
            let out_sample = unsafe { data.get_unchecked_mut(data_idx) };
            *out_sample = Zero::zero();
            let mut twiddle_idx = 0usize;
            for in_sample in scratch.iter() {
                let twiddle = unsafe { twiddles.get_unchecked(twiddle_idx) };
                *out_sample = *out_sample + in_sample * twiddle;
                twiddle_idx += stride * data_idx;
                if twiddle_idx >= twiddles.len() { twiddle_idx -= twiddles.len() }
            }
            data_idx += num_ffts;
        }

    }
}

pub fn dft<'a, 'b, I, O>(signal: I, spectrum: O)
where I: Iterator<Item=&'a Complex<f32>> + ExactSizeIterator + Clone,
      O: Iterator<Item=&'b mut Complex<f32>>
{
    for (k, spec_bin) in spectrum.enumerate()
    {
        let signal_iter = signal.clone();
        let mut sum: Complex<f32> = Zero::zero();
        for (i, &x) in signal_iter.enumerate() {
            let angle = -1. * ((i * k) as f32) * 2.0 * f32::consts::PI / (signal.len() as f32);
            let twiddle: Complex<f32> = Complex::from_polar(&1f32, &angle);
            sum = sum + twiddle * x;
        }
        *spec_bin = sum;
    }
}

fn factor(n: usize) -> Vec<(usize, usize)>
{
    let mut factors = Vec::new();
    let mut next = n;
    while next > 1 {
        for div in (2..next + 1) {
            if next % div == 0 {
                next = next / div;
                factors.push((div, next));
                break;
            }
        }
    }
    return factors;
}
<|endoftext|>


<commit_before>/*!
# nalgebra

[![Build Status](https://travis-ci.org/sebcrozet/nalgebra.png?branch=master)](https://travis-ci.org/sebcrozet/nalgebra)

**nalgebra** is a linear algebra library written for Rust targeting:

* general-purpose linear algebra (still misses a lot of features…).
* real time computer graphics.
* real time computer physics.

An on-line version of this documentation is available [here](http://www.rust-ci.org/sebcrozet/nalgebra/doc/nalgebra/index.html).

## Using **nalgebra**
All the functionalities of **nalgebra** are grouped in one place: the `na` module.
This module re-exports everything and includes free functions for all traits methods doing
out-of-place modifications.

* You can import the whole prelude using:

```
use nalgebra::na::*;
```

The preferred way to use **nalgebra** is to import types and traits explicitly, and call
free-functions using the `na::` prefix:

```.rust
extern mod nalgebra;
use nalgebra::na::{Vec3, Rot3, Rotation};
use nalgebra::na;

fn main() {
    let     a = Vec3::new(1.0f64, 1.0, 1.0);
    let mut b = Rot3::new(na::zero());

    b.append_rotation(&a);

    assert!(na::approx_eq(&na::rotation(&b), &a));
}
```

## Features
**nalgebra** is meant to be a general-purpose linear algebra library (but is very far from that…),
and keeps an optimized set of tools for computational graphics and physics. Those features include:

* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
* Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `.
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
* Isometries: `Iso2`, `Iso3`, `Iso4`.
* Dynamically sized vector: `DVec`.
* Dynamically sized (square or rectangular) matrix: `DMat`.
* A few methods for data analysis: `Cov`, `Mean`.
* Almost one trait per functionality: useful for generic programming.
* Operator overloading using the double trait dispatch
  [trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/).
  For example, the following works:

```rust
extern mod nalgebra;
use nalgebra::na::{Vec3, Mat3};
use nalgebra::na;

fn main() {
    let v: Vec3<f64> = na::zero();
    let m: Mat3<f64> = na::one();

    let _ = m * v;   // matrix-vector multiplication.
    let _ = v * m;   // vector-matrix multiplication.
    let _ = m * m;   // matrix-matrix multiplication.
    let _ = v * 2.0; // vector-scalar multiplication.
}
```

## Compilation
You will need the last rust compiler from the master branch.
If you encounter problems, make sure you have the last version before creating an issue.

    git clone git://github.com/sebcrozet/nalgebra.git
    cd nalgebra
    make

You can build the documentation on the `doc` folder using:

```
make doc
```

## **nalgebra** in use
Here are some projects using **nalgebra**.
Feel free to add your project to this list if you happen to use **nalgebra**!

* [nphysics](https://github.com/sebcrozet/nphysics): a real-time physics engine.
* [ncollide](https://github.com/sebcrozet/ncollide): a collision detection library.
* [kiss3d](https://github.com/sebcrozet/kiss3d): a minimalistic graphics engine.
* [frog](https://github.com/natal/frog): a machine learning library.
*/

#[crate_id = "nalgebra#0.1"];
#[crate_type = "lib"];
#[deny(non_camel_case_types)];
#[deny(non_uppercase_statics)];
#[deny(unnecessary_qualification)];
#[warn(missing_doc)];
#[feature(macro_rules)];
#[doc(html_root_url = "http://crozet.re/nalgebra/doc")];

extern mod std;
extern mod extra;

pub mod na;
mod structs;
mod traits;

// mod lower_triangular;
// mod chol;

#[cfg(test)]
mod tests {
    mod vec;
    mod mat;
}

#[cfg(test)]
mod bench {
    mod vec;
    mod mat;
}
<commit_msg>Fix the doc root url.<commit_after>/*!
# nalgebra

[![Build Status](https://travis-ci.org/sebcrozet/nalgebra.png?branch=master)](https://travis-ci.org/sebcrozet/nalgebra)

**nalgebra** is a linear algebra library written for Rust targeting:

* general-purpose linear algebra (still misses a lot of features…).
* real time computer graphics.
* real time computer physics.

An on-line version of this documentation is available [here](http://www.rust-ci.org/sebcrozet/nalgebra/doc/nalgebra/index.html).

## Using **nalgebra**
All the functionalities of **nalgebra** are grouped in one place: the `na` module.
This module re-exports everything and includes free functions for all traits methods doing
out-of-place modifications.

* You can import the whole prelude using:

```
use nalgebra::na::*;
```

The preferred way to use **nalgebra** is to import types and traits explicitly, and call
free-functions using the `na::` prefix:

```.rust
extern mod nalgebra;
use nalgebra::na::{Vec3, Rot3, Rotation};
use nalgebra::na;

fn main() {
    let     a = Vec3::new(1.0f64, 1.0, 1.0);
    let mut b = Rot3::new(na::zero());

    b.append_rotation(&a);

    assert!(na::approx_eq(&na::rotation(&b), &a));
}
```

## Features
**nalgebra** is meant to be a general-purpose linear algebra library (but is very far from that…),
and keeps an optimized set of tools for computational graphics and physics. Those features include:

* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
* Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `.
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
* Isometries: `Iso2`, `Iso3`, `Iso4`.
* Dynamically sized vector: `DVec`.
* Dynamically sized (square or rectangular) matrix: `DMat`.
* A few methods for data analysis: `Cov`, `Mean`.
* Almost one trait per functionality: useful for generic programming.
* Operator overloading using the double trait dispatch
  [trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/).
  For example, the following works:

```rust
extern mod nalgebra;
use nalgebra::na::{Vec3, Mat3};
use nalgebra::na;

fn main() {
    let v: Vec3<f64> = na::zero();
    let m: Mat3<f64> = na::one();

    let _ = m * v;   // matrix-vector multiplication.
    let _ = v * m;   // vector-matrix multiplication.
    let _ = m * m;   // matrix-matrix multiplication.
    let _ = v * 2.0; // vector-scalar multiplication.
}
```

## Compilation
You will need the last rust compiler from the master branch.
If you encounter problems, make sure you have the last version before creating an issue.

    git clone git://github.com/sebcrozet/nalgebra.git
    cd nalgebra
    make

You can build the documentation on the `doc` folder using:

```
make doc
```

## **nalgebra** in use
Here are some projects using **nalgebra**.
Feel free to add your project to this list if you happen to use **nalgebra**!

* [nphysics](https://github.com/sebcrozet/nphysics): a real-time physics engine.
* [ncollide](https://github.com/sebcrozet/ncollide): a collision detection library.
* [kiss3d](https://github.com/sebcrozet/kiss3d): a minimalistic graphics engine.
* [frog](https://github.com/natal/frog): a machine learning library.
*/

#[crate_id = "nalgebra#0.1"];
#[crate_type = "lib"];
#[deny(non_camel_case_types)];
#[deny(non_uppercase_statics)];
#[deny(unnecessary_qualification)];
#[warn(missing_doc)];
#[feature(macro_rules)];
#[doc(html_root_url = "http://www.rust-ci.org/sebcrozet/nalgebra/doc")];

extern mod std;
extern mod extra;

pub mod na;
mod structs;
mod traits;

// mod lower_triangular;
// mod chol;

#[cfg(test)]
mod tests {
    mod vec;
    mod mat;
}

#[cfg(test)]
mod bench {
    mod vec;
    mod mat;
}
<|endoftext|>


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

pub use sys::Window;

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

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

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

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

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

    let x = 10;
    let mut y = 10;

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

    y += label.rect.get().height as isize + 10;

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

    let text_button = Button::new()
        .text("Test Button")
        .position(x + text_box.rect.get().width as isize + 10, y)
        .size(88, 32)
        .on_click(move |_button: &Button, _point: Point| {
            label.text.set(format!("Input: {}", text_box.text.get()));
        })
        .place(&mut window);

    y += text_button.rect.get().height as isize + 10;

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

    y += progress_label.rect.get().height as isize + 10;

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

    y += progress_bar.rect.get().height as isize + 10;

    let multi_line_label = Label::new()
        .text("Multi-Line Text")
        .position(x, y)
        .size(400, 16)
        .place(&mut window);

    y += multi_line_label.rect.get().height as isize + 10;

    TextBox::new()
        .position(x, y)
        .size(400, 128)
        .place(&mut window);

    window.exec();
}
<commit_msg>Make first textbox a single-line, update label above it<commit_after>#![crate_type="lib"]
#![feature(str_char)]

pub use sys::Window;

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

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

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

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

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

    let x = 10;
    let mut y = 10;

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

    y += label.rect.get().height as isize + 10;

    let text_box = TextBox::new()
        .position(x, y)
        .size(302, 16)
        .on_enter(move |text_box: &TextBox| -> bool {
            label.text.set(text_box.text.get());
            false
        })
        .place(&mut window);

    y += text_box.rect.get().height as isize + 10;

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

    y += progress_label.rect.get().height as isize + 10;

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

    y += progress_bar.rect.get().height as isize + 10;

    let multi_line_label = Label::new()
        .text("Multi-Line Text")
        .position(x, y)
        .size(400, 16)
        .place(&mut window);

    y += multi_line_label.rect.get().height as isize + 10;

    TextBox::new()
        .position(x, y)
        .size(400, 128)
        .place(&mut window);

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


<commit_before>#![crate_name = "liquid"]
#![doc(html_root_url = "https://cobalt-org.github.io/liquid-rust/")]

// This library uses Clippy!
#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

// Deny warnings, except in dev mode
#![deny(warnings)]
#![cfg_attr(feature="dev", warn(warnings))]

// Ignore clippy, except in dev mode
#![cfg_attr(feature="clippy", allow(clippy))]
#![cfg_attr(feature="dev", warn(clippy))]

// Stuff we want clippy to fail on
#![cfg_attr(feature="clippy", deny(
        explicit_iter_loop,
        clone_on_copy,
        len_zero,
        map_clone,
        map_entry,
        match_bool,
        match_same_arms,
        new_ret_no_self,
        new_without_default,
        needless_lifetimes,
        needless_range_loop,
        no_effect,
        ok_expect,
        out_of_bounds_indexing,
        ptr_arg,
        redundant_closure,
        single_char_pattern,
        unused_collect,
        useless_vec,
        ))]

#[macro_use]
extern crate lazy_static;
extern crate regex;

use std::collections::HashMap;
use lexer::Element;
use tags::{assign_tag, include_tag, break_tag, continue_tag,
           comment_block, raw_block, for_block, if_block, capture_block};
use std::default::Default;
use error::Result;

pub use value::Value;
pub use context::Context;
pub use template::Template;
pub use error::Error;
pub use filters::{FilterResult, FilterError};
pub use token::Token;

pub mod lexer;
pub mod parser;

mod token;
mod error;
mod template;
mod output;
mod text;
mod tags;
mod filters;
mod value;
mod variable;
mod context;

/// The ErrorMode to use.
/// This currently does not have an effect, until
/// ErrorModes are properly implemented.
#[derive(Clone, Copy)]
pub enum ErrorMode {
    Strict,
    Warn,
    Lax,
}

impl Default for ErrorMode {
    fn default() -> ErrorMode {
        ErrorMode::Warn
    }
}

/// A trait for creating custom tags. This is a simple type alias for a function.
///
/// This function will be called whenever the parser encounters a tag and returns
/// a new [Renderable](trait.Renderable.html) based on its parameters. The received parameters
/// specify the name of the tag, the argument [Tokens](lexer/enum.Token.html) passed to
/// the tag and the global [LiquidOptions](struct.LiquidOptions.html).
///
/// ## Minimal Example
/// ```
/// # use liquid::{Renderable, LiquidOptions, Context, Error};
///
/// struct HelloWorld;
///
/// impl Renderable for HelloWorld {
///     fn render(&self, _context: &mut Context) -> Result<Option<String>, Error>{
///         Ok(Some("Hello World!".to_owned()))
///     }
/// }
///
/// let mut options : LiquidOptions = Default::default();
/// options.tags.insert("hello_world".to_owned(), Box::new(|_tag_name, _arguments, _options| {
///      Ok(Box::new(HelloWorld))
/// }));
///
/// let template = liquid::parse("{{hello_world}}", options).unwrap();
/// let mut data = Context::new();
/// let output = template.render(&mut data);
/// assert_eq!(output.unwrap(), Some("Hello World!".to_owned()));
/// ```
pub type Tag = Fn(&str, &[Token], &LiquidOptions) -> Result<Box<Renderable>>;

/// A trait for creating custom custom block-size tags (`{% if something %}{% endif %}`). This is a simple type alias for a function.
///
/// This function will be called whenever the parser encounters a block and returns
/// a new `Renderable` based on its parameters. The received parameters specify the name
/// of the block, the argument [Tokens](lexer/enum.Token.html) passed to
/// the block, a Vec of all [Elements](lexer/enum.Element.html) inside the block and the global [LiquidOptions](struct.LiquidOptions.html).
pub type Block = Fn(&str, &[Token], Vec<Element>, &LiquidOptions) -> Result<Box<Renderable>>;

/// Any object (tag/block) that can be rendered by liquid must implement this trait.
pub trait Renderable{
    fn render(&self, context: &mut Context) -> Result<Option<String>>;
}

#[derive(Default)]
pub struct LiquidOptions {
    pub blocks: HashMap<String, Box<Block>>,
    pub tags: HashMap<String, Box<Tag>>,
    pub error_mode: ErrorMode,
}

impl LiquidOptions {
    pub fn register_block(&mut self, name: &str, block: Box<Block>) {
        self.blocks.insert(name.to_owned(), block);
    }

    pub fn register_tag(&mut self, name: &str, tag: Box<Tag>) {
        self.tags.insert(name.to_owned(), tag);
    }
}

/// Parses a liquid template, returning a Template object.
/// # Examples
///
/// ## Minimal Template
///
/// ```
/// use liquid::{Renderable, LiquidOptions, Context};
///
/// let template = liquid::parse("Liquid!", LiquidOptions::default()).unwrap();
/// let mut data = Context::new();
/// let output = template.render(&mut data);
/// assert_eq!(output.unwrap(), Some("Liquid!".to_owned()));
/// ```
///
pub fn parse(text: &str, options: LiquidOptions) -> Result<Template> {
    let mut options = options;
    let tokens = try!(lexer::tokenize(&text));

    options.register_tag("assign", Box::new(assign_tag));
<<<<<<< HEAD
    options.register_tag("break", Box::new(break_tag));
    options.register_tag("continue", Box::new(continue_tag));
=======
    options.register_tag("include", Box::new(include_tag));
>>>>>>> added Include tag

    options.register_block("raw", Box::new(raw_block));
    options.register_block("if", Box::new(if_block));
    options.register_block("for", Box::new(for_block));
    options.register_block("comment", Box::new(comment_block));
    options.register_block("capture", Box::new(capture_block));

    parser::parse(&tokens, &options).map(Template::new)
}
<commit_msg>reverted format problems<commit_after>#![crate_name = "liquid"]
#![doc(html_root_url = "https://cobalt-org.github.io/liquid-rust/")]

// This library uses Clippy!
#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

// Deny warnings, except in dev mode
#![deny(warnings)]
#![cfg_attr(feature="dev", warn(warnings))]

// Ignore clippy, except in dev mode
#![cfg_attr(feature="clippy", allow(clippy))]
#![cfg_attr(feature="dev", warn(clippy))]

// Stuff we want clippy to fail on
#![cfg_attr(feature="clippy", deny(
        explicit_iter_loop,
        clone_on_copy,
        len_zero,
        map_clone,
        map_entry,
        match_bool,
        match_same_arms,
        new_ret_no_self,
        new_without_default,
        needless_lifetimes,
        needless_range_loop,
        no_effect,
        ok_expect,
        out_of_bounds_indexing,
        ptr_arg,
        redundant_closure,
        single_char_pattern,
        unused_collect,
        useless_vec,
        ))]

#[macro_use]
extern crate lazy_static;
extern crate regex;

use std::collections::HashMap;
use lexer::Element;
use tags::{assign_tag, include_tag, break_tag, continue_tag, comment_block, raw_block, for_block,
           if_block, capture_block};
use std::default::Default;
use error::Result;

pub use value::Value;
pub use context::Context;
pub use template::Template;
pub use error::Error;
pub use filters::{FilterResult, FilterError};
pub use token::Token;

pub mod lexer;
pub mod parser;

mod token;
mod error;
mod template;
mod output;
mod text;
mod tags;
mod filters;
mod value;
mod variable;
mod context;

/// The ErrorMode to use.
/// This currently does not have an effect, until
/// ErrorModes are properly implemented.
#[derive(Clone, Copy)]
pub enum ErrorMode {
    Strict,
    Warn,
    Lax,
}

impl Default for ErrorMode {
    fn default() -> ErrorMode {
        ErrorMode::Warn
    }
}

/// A trait for creating custom tags. This is a simple type alias for a function.
///
/// This function will be called whenever the parser encounters a tag and returns
/// a new [Renderable](trait.Renderable.html) based on its parameters. The received parameters
/// specify the name of the tag, the argument [Tokens](lexer/enum.Token.html) passed to
/// the tag and the global [LiquidOptions](struct.LiquidOptions.html).
///
/// ## Minimal Example
/// ```
/// # use liquid::{Renderable, LiquidOptions, Context, Error};
///
/// struct HelloWorld;
///
/// impl Renderable for HelloWorld {
///     fn render(&self, _context: &mut Context) -> Result<Option<String>, Error>{
///         Ok(Some("Hello World!".to_owned()))
///     }
/// }
///
/// let mut options : LiquidOptions = Default::default();
/// options.tags.insert("hello_world".to_owned(), Box::new(|_tag_name, _arguments, _options| {
///      Ok(Box::new(HelloWorld))
/// }));
///
/// let template = liquid::parse("{{hello_world}}", options).unwrap();
/// let mut data = Context::new();
/// let output = template.render(&mut data);
/// assert_eq!(output.unwrap(), Some("Hello World!".to_owned()));
/// ```
pub type Tag = Fn(&str, &[Token], &LiquidOptions) -> Result<Box<Renderable>>;

/// A trait for creating custom custom block-size tags (`{% if something %}{% endif %}`). This is a simple type alias for a function.
///
/// This function will be called whenever the parser encounters a block and returns
/// a new `Renderable` based on its parameters. The received parameters specify the name
/// of the block, the argument [Tokens](lexer/enum.Token.html) passed to
/// the block, a Vec of all [Elements](lexer/enum.Element.html) inside the block and the global [LiquidOptions](struct.LiquidOptions.html).
pub type Block = Fn(&str, &[Token], Vec<Element>, &LiquidOptions) -> Result<Box<Renderable>>;

/// Any object (tag/block) that can be rendered by liquid must implement this trait.
pub trait Renderable{
    fn render(&self, context: &mut Context) -> Result<Option<String>>;
}

#[derive(Default)]
pub struct LiquidOptions {
    pub blocks: HashMap<String, Box<Block>>,
    pub tags: HashMap<String, Box<Tag>>,
    pub error_mode: ErrorMode,
}

impl LiquidOptions {
    pub fn register_block(&mut self, name: &str, block: Box<Block>) {
        self.blocks.insert(name.to_owned(), block);
    }

    pub fn register_tag(&mut self, name: &str, tag: Box<Tag>) {
        self.tags.insert(name.to_owned(), tag);
    }
}

/// Parses a liquid template, returning a Template object.
/// # Examples
///
/// ## Minimal Template
///
/// ```
/// use liquid::{Renderable, LiquidOptions, Context};
///
/// let template = liquid::parse("Liquid!", LiquidOptions::default()).unwrap();
/// let mut data = Context::new();
/// let output = template.render(&mut data);
/// assert_eq!(output.unwrap(), Some("Liquid!".to_owned()));
/// ```
///
pub fn parse(text: &str, options: LiquidOptions) -> Result<Template> {
    let mut options = options;
    let tokens = try!(lexer::tokenize(&text));

    options.register_tag("assign", Box::new(assign_tag));
    options.register_tag("break", Box::new(break_tag));
    options.register_tag("continue", Box::new(continue_tag));
    options.register_tag("include", Box::new(include_tag));

    options.register_block("raw", Box::new(raw_block));
    options.register_block("if", Box::new(if_block));
    options.register_block("for", Box::new(for_block));
    options.register_block("comment", Box::new(comment_block));
    options.register_block("capture", Box::new(capture_block));

    parser::parse(&tokens, &options).map(Template::new)
}
<|endoftext|>


<commit_before>#![feature(str_char)]
extern crate nalgebra;
use nalgebra::DMat;
use std::fmt::{Debug, Formatter, Result};
use std::thread;
use std::sync::mpsc;
use std::collections::HashSet;

/// The `SmithWaterman` struct
///
/// genome_sequence: String
///
/// read_sequence: String
///
/// matrix:  DMat<isize>
pub struct SmithWaterman{
    /// Genome
    pub genome_sequence: String,
    /// Compared Genome
    pub  read_sequence: String,
    /// Matrix used to store data
    pub matrix:  DMat<isize>,
    pub matched: isize,
    pub missed: isize,
}
pub enum GraphMovements {Blank, Left, Top, Diagonal}

impl SmithWaterman{
    /// Constructs a new `SmithWaterman`.
    ///
    /// # Examples
    ///
    /// ```
    /// use smith_waterman;
    ///
    /// let mut smitty = smith_waterman::SmithWaterman::new("ab".to_string(), "cb".to_string());
    /// ```
    pub fn new(genome_sequence: String, read_sequence: String) -> SmithWaterman {
        let matrix = DMat::new_zeros(0,0);
        SmithWaterman{matrix: matrix, genome_sequence: genome_sequence,
        read_sequence: read_sequence, matched: 2, missed: -1}
    }

    fn penalty(&self, value: isize, penalty_value: isize) -> isize{
        match value.checked_add(penalty_value){
            Some(i) =>{
                if i<0 { 0 }else { i }
            },
            _ => {0}
        }
    }

    /// Runs the matrix to obtain the optimum local alignment.
    /// Uses the set_matrix_loops function.
    /// returns a tuple of strings. The fist is the genome sequence the second is the read
    /// sequence.
    /// # Examples
    ///
    /// ```
    /// let mut smitty = smith_waterman::SmithWaterman::new("ab".to_string(), "cb".to_string());
    /// let alignment = smitty.align();
    /// ```
    pub fn align(&mut self) -> (String, String){
        let max_point = self.set_matrix_loops();
        return self.local_alignment(max_point);
    }

    pub fn align_fn(&mut self) -> (String, String){
        let max_point = self.set_matrix_fn();
        return self.local_alignment(max_point);
    }

    /// Fills the matrix with values.
    /// This uses a naïve double loop to fill the matrix.
    ///
    /// # Examples
    /// ```
    /// let mut smitty = smith_waterman::SmithWaterman::new("ab".to_string(), "cb".to_string());
    /// let max_point = smitty.set_matrix_loops();
    /// ```
    pub fn set_matrix_fn(&mut self) -> (usize, usize) {
        let mut max_point = (0,0);
        let mut max = 0;

        let rows = self.read_sequence.len()+1;
        let cols = self.genome_sequence.len()+1;
        self.matrix = nalgebra::DMat::new_zeros(self.read_sequence.len()+1, self.genome_sequence.len()+1);
        for i in (0..rows * cols){
            let col = i / rows;
            let row = i - col * rows;
            let n = self.calculated_movement(row, col);
            if n >= max{
                max = n;
                max_point = (row,col);
            }
            self.matrix[(row, col)]=n;
        }

        return max_point;
    }

    fn calculated_movement(&self, row: usize, col: usize) -> isize{
            let left = if col>=1 {self.penalty(self.matrix[(row, col-1)], self.missed)} else {0};
            let top = if row>=1 {self.penalty(self.matrix[(row-1, col)], self.missed)} else {0};
            let diagonal_value = if row>=1 && col>=1 {self.matrix[(row-1, col-1)]} else {0};
            let diagonal_match = if row == 0 || col == 0{
               0
            }else if self.read_sequence.char_at(row-1) == self.genome_sequence.char_at(col-1){
                self.penalty(diagonal_value, self.matched)
            }else{
                self.penalty(diagonal_value, self.missed)
            };
            std::cmp::max(left, std::cmp::max(top, diagonal_match))
    }

    /// Fills the matrix with values.
    /// This uses a naïve double loop to fill the matrix.
    ///
    /// returns a tuple of usize. The fist is the row and the second is the column of the largest
    /// value in the matrix.
    ///
    /// This value can also be calculated out from `smitty.matrix`
    /// # Examples
    ///
    /// ```
    /// let mut smitty = smith_waterman::SmithWaterman::new("ab".to_string(), "cb".to_string());
    /// let max_point = smitty.set_matrix_loops();
    /// ```
    pub fn set_matrix_loops(&mut self) -> (usize, usize) {
        self.matrix = nalgebra::DMat::new_zeros(self.read_sequence.len()+1, self.genome_sequence.len()+1);
        let mut max_point = (0,0);
        let mut max = 0;
        for row in (1..self.read_sequence.len()+1){
            for col in (1..self.genome_sequence.len()+1){
                let n = self.calculated_movement(row, col);
                if n >= max{
                    max = n;
                    max_point = (row,col);
                }
                self.matrix[(row, col)] = n;
            }
        }
        return max_point;
    }

    fn local_alignment(&self, max_point_value: (usize, usize)) -> (String, String){
        let mut max_point = max_point_value;
        let mut max = self.matrix[max_point];
        let mut last_movement = GraphMovements::Blank;
        let mut genome_sequence_alignment = String::new();
        let mut read_sequence_alignment = String::new();
        genome_sequence_alignment.reserve(self.genome_sequence.len());
        read_sequence_alignment.reserve(self.read_sequence.len());
        while max > 0 {
            let (row, col) = max_point;
            let one = self.genome_sequence.char_at(col-1);
            let two = self.read_sequence.char_at(row-1);
            let top = self.matrix[(row-1, col)];
            let left = self.matrix[(row, col-1)];
            let diagonal = self.matrix[(row-1, col-1)];
            max  = std::cmp::max(left, std::cmp::max(top, diagonal));
            max_point = if diagonal == max{
                last_movement = GraphMovements::Diagonal;
                (row-1, col-1)
            } else if left == max{
                last_movement = GraphMovements::Left;
                (row, col-1)
            } else {
                last_movement = GraphMovements::Top;
                (row-1, col)
            };

            match last_movement {
                GraphMovements::Blank  => {
                    genome_sequence_alignment.push(one);
                    read_sequence_alignment.push(two);
                },
                GraphMovements::Diagonal => {
                    genome_sequence_alignment.push(one);
                    read_sequence_alignment.push(two);
                },
                GraphMovements::Top => {
                    genome_sequence_alignment.push('-');
                    read_sequence_alignment.push(two);
                },
                GraphMovements::Left => {
                    genome_sequence_alignment.push(one);
                    read_sequence_alignment.push('-');
                },
            }
        };

        let x1: String = genome_sequence_alignment.chars().rev().collect();
        let x2: String = read_sequence_alignment.chars().rev().collect();
        return (x1,x2)
    }
}

impl Debug for SmithWaterman {
    fn fmt(&self, form:&mut Formatter) -> Result {
        //nrows already has an extra over the sequence counts for the row of zeros
        for row in 0..self.matrix.nrows()+1 {
            for col in 0..self.matrix.ncols()+1 {
                let _ = if col==0 && row>1{
                    write!(form, "{:>5}", self.read_sequence.char_at(row-2).to_string())
                } else if row==0 && col>1{
                    write!(form, "{:>5}", self.genome_sequence.char_at(col-2).to_string())
                } else if row>=1 && col>=1{
                    write!(form, "{:>5}", self.matrix[(row-1,col-1)])
                }else{
                    write!(form, "{:>5}", "-")
                };
            }
            let _ = write!(form, "\n");
        }
        write!(form, "\n")
    }
}

#[test]
fn its_debugging() {
    let mut smitty = SmithWaterman::new("atgcatgcatgc".to_string(), "atgggcatg".to_string());
    let alignment = smitty.align();
    println!("{:?}", smitty);
    println!("{:?}", alignment);

    let mut smitty = SmithWaterman::new( "ACACACTA".to_string(),"AGCACACA".to_string());
    let alignment = smitty.align_fn();
    println!("fn::{:?}", smitty);
    println!("fn::{:?}", alignment);

}
<commit_msg>Update docs with benchmarks<commit_after>#![feature(str_char)]
extern crate nalgebra;
use nalgebra::DMat;
use std::fmt::{Debug, Formatter, Result};
use std::thread;
use std::sync::mpsc;
use std::collections::HashSet;

/// The `SmithWaterman` struct
///
/// genome_sequence: String
///
/// read_sequence: String
///
/// matrix:  DMat<isize>
pub struct SmithWaterman{
    /// Genome
    pub genome_sequence: String,
    /// Compared Genome
    pub  read_sequence: String,
    /// Matrix used to store data
    pub matrix:  DMat<isize>,
    pub matched: isize,
    pub missed: isize,
}
pub enum GraphMovements {Blank, Left, Top, Diagonal}

impl SmithWaterman{
    /// Constructs a new `SmithWaterman`.
    ///
    /// # Examples
    ///
    /// ```
    /// use smith_waterman;
    ///
    /// let mut smitty = smith_waterman::SmithWaterman::new("ab".to_string(), "cb".to_string());
    /// ```
    pub fn new(genome_sequence: String, read_sequence: String) -> SmithWaterman {
        let matrix = DMat::new_zeros(0,0);
        SmithWaterman{matrix: matrix, genome_sequence: genome_sequence,
        read_sequence: read_sequence, matched: 2, missed: -1}
    }

    fn penalty(&self, value: isize, penalty_value: isize) -> isize{
        match value.checked_add(penalty_value){
            Some(i) =>{
                if i<0 { 0 }else { i }
            },
            _ => {0}
        }
    }

    /// Runs the matrix to obtain the optimum local alignment.
    /// Uses the set_matrix_loops function.
    /// returns a tuple of strings. The fist is the genome sequence the second is the read
    /// sequence.
    /// # Examples
    ///
    /// ```
    /// let mut smitty = smith_waterman::SmithWaterman::new("ab".to_string(), "cb".to_string());
    /// let alignment = smitty.align();
    /// ```
    pub fn align(&mut self) -> (String, String){
        let max_point = self.set_matrix_loops();
        return self.local_alignment(max_point);
    }

    /// Runs the matrix to obtain the optimum local alignment.
    /// Uses the set_matrix_fn function.
    /// returns a tuple of strings. The fist is the genome sequence the second is the read
    /// sequence.
    ///
    /// In benchmarks this function can be 2x faster. Tested with a 70k and 7k string. < Caveat
    /// Emptor>
    /// # Examples
    ///
    /// ```
    /// let mut smitty = smith_waterman::SmithWaterman::new("ab".to_string(), "cb".to_string());
    /// let alignment = smitty.align_fn();
    /// ```
    pub fn align_fn(&mut self) -> (String, String){
        let max_point = self.set_matrix_fn();
        return self.local_alignment(max_point);
    }

    /// Fills the matrix with values.
    /// This uses a single loop and calculates the correct col and row on the fly.
    /// In benchmarks this function can be 2x faster. Tested with a 70k and 7k string. < Caveat
    /// Emptor>
    ///
    /// # Examples
    /// ```
    /// let mut smitty = smith_waterman::SmithWaterman::new("ab".to_string(), "cb".to_string());
    /// let max_point = smitty.set_matrix_fn();
    /// ```
    pub fn set_matrix_fn(&mut self) -> (usize, usize) {
        let mut max_point = (0,0);
        let mut max = 0;

        let rows = self.read_sequence.len()+1;
        let cols = self.genome_sequence.len()+1;
        self.matrix = nalgebra::DMat::new_zeros(self.read_sequence.len()+1, self.genome_sequence.len()+1);
        for i in (0..rows * cols){
            let col = i / rows;
            let row = i - col * rows;
            let n = self.calculated_movement(row, col);
            if n >= max{
                max = n;
                max_point = (row,col);
            }
            self.matrix[(row, col)]=n;
        }

        return max_point;
    }

    fn calculated_movement(&self, row: usize, col: usize) -> isize{
            let left = if col>=1 {self.penalty(self.matrix[(row, col-1)], self.missed)} else {0};
            let top = if row>=1 {self.penalty(self.matrix[(row-1, col)], self.missed)} else {0};
            let diagonal_value = if row>=1 && col>=1 {self.matrix[(row-1, col-1)]} else {0};
            let diagonal_match = if row == 0 || col == 0{
               0
            }else if self.read_sequence.char_at(row-1) == self.genome_sequence.char_at(col-1){
                self.penalty(diagonal_value, self.matched)
            }else{
                self.penalty(diagonal_value, self.missed)
            };
            std::cmp::max(left, std::cmp::max(top, diagonal_match))
    }

    /// Fills the matrix with values.
    /// This uses a naïve double loop to fill the matrix.
    ///
    /// returns a tuple of usize. The fist is the row and the second is the column of the largest
    /// value in the matrix.
    ///
    /// This value can also be calculated out from `smitty.matrix`
    /// # Examples
    ///
    /// ```
    /// let mut smitty = smith_waterman::SmithWaterman::new("ab".to_string(), "cb".to_string());
    /// let max_point = smitty.set_matrix_loops();
    /// ```
    pub fn set_matrix_loops(&mut self) -> (usize, usize) {
        self.matrix = nalgebra::DMat::new_zeros(self.read_sequence.len()+1, self.genome_sequence.len()+1);
        let mut max_point = (0,0);
        let mut max = 0;
        for row in (1..self.read_sequence.len()+1){
            for col in (1..self.genome_sequence.len()+1){
                let n = self.calculated_movement(row, col);
                if n >= max{
                    max = n;
                    max_point = (row,col);
                }
                self.matrix[(row, col)] = n;
            }
        }
        return max_point;
    }

    fn local_alignment(&self, max_point_value: (usize, usize)) -> (String, String){
        let mut max_point = max_point_value;
        let mut max = self.matrix[max_point];
        let mut last_movement = GraphMovements::Blank;
        let mut genome_sequence_alignment = String::new();
        let mut read_sequence_alignment = String::new();
        genome_sequence_alignment.reserve(self.genome_sequence.len());
        read_sequence_alignment.reserve(self.read_sequence.len());
        while max > 0 {
            let (row, col) = max_point;
            let one = self.genome_sequence.char_at(col-1);
            let two = self.read_sequence.char_at(row-1);
            let top = self.matrix[(row-1, col)];
            let left = self.matrix[(row, col-1)];
            let diagonal = self.matrix[(row-1, col-1)];
            max  = std::cmp::max(left, std::cmp::max(top, diagonal));
            max_point = if diagonal == max{
                last_movement = GraphMovements::Diagonal;
                (row-1, col-1)
            } else if left == max{
                last_movement = GraphMovements::Left;
                (row, col-1)
            } else {
                last_movement = GraphMovements::Top;
                (row-1, col)
            };

            match last_movement {
                GraphMovements::Blank  => {
                    genome_sequence_alignment.push(one);
                    read_sequence_alignment.push(two);
                },
                GraphMovements::Diagonal => {
                    genome_sequence_alignment.push(one);
                    read_sequence_alignment.push(two);
                },
                GraphMovements::Top => {
                    genome_sequence_alignment.push('-');
                    read_sequence_alignment.push(two);
                },
                GraphMovements::Left => {
                    genome_sequence_alignment.push(one);
                    read_sequence_alignment.push('-');
                },
            }
        };

        let x1: String = genome_sequence_alignment.chars().rev().collect();
        let x2: String = read_sequence_alignment.chars().rev().collect();
        return (x1,x2)
    }
}

impl Debug for SmithWaterman {
    fn fmt(&self, form:&mut Formatter) -> Result {
        //nrows already has an extra over the sequence counts for the row of zeros
        for row in 0..self.matrix.nrows()+1 {
            for col in 0..self.matrix.ncols()+1 {
                let _ = if col==0 && row>1{
                    write!(form, "{:>5}", self.read_sequence.char_at(row-2).to_string())
                } else if row==0 && col>1{
                    write!(form, "{:>5}", self.genome_sequence.char_at(col-2).to_string())
                } else if row>=1 && col>=1{
                    write!(form, "{:>5}", self.matrix[(row-1,col-1)])
                }else{
                    write!(form, "{:>5}", "-")
                };
            }
            let _ = write!(form, "\n");
        }
        write!(form, "\n")
    }
}

#[test]
fn its_debugging() {
    let mut smitty = SmithWaterman::new("atgcatgcatgc".to_string(), "atgggcatg".to_string());
    let alignment = smitty.align();
    println!("{:?}", smitty);
    println!("{:?}", alignment);

    let mut smitty = SmithWaterman::new( "ACACACTA".to_string(),"AGCACACA".to_string());
    let alignment = smitty.align_fn();
    println!("fn::{:?}", smitty);
    println!("fn::{:?}", alignment);

}
<|endoftext|>


<commit_before>/*!

**rust-wtf8** is an implementation of [the WTF-8 encoding](http://simonsapin.github.io/wtf-8/).

It uses Rust’s type system to maintain
[well-formedness](http://simonsapin.github.io/wtf-8/#well-formed),
like the `String` and `&str` types do for UTF-8.

*/
<commit_msg>Code points<commit_after>/*!

**rust-wtf8** is an implementation of [the WTF-8 encoding](http://simonsapin.github.io/wtf-8/).

It uses Rust’s type system to maintain
[well-formedness](http://simonsapin.github.io/wtf-8/#well-formed),
like the `String` and `&str` types do for UTF-8.

*/

use std::fmt;
use std::mem::transmute;

/// A Unicode code point: from U+0000 to U+10FFFF
/// Compare with the `char` type,
/// which represents a Unicode scalar value:
/// a code point that is not a surrogate (U+D800 to U+DFFF).
#[deriving(Eq, PartialEq, Ord, PartialOrd, Clone, Hash)]
pub struct CodePoint {
    value: u32
}

impl fmt::Show for CodePoint {
    #[inline]
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::FormatError> {
        write!(formatter, "U+{:04X}", self.value)
    }
}

impl CodePoint {
    #[inline]
    pub unsafe fn from_u32_unchecked(value: u32) -> CodePoint {
        CodePoint { value: value }
    }

    #[inline]
    pub fn from_u32(value: u32) -> Option<CodePoint> {
        match value {
            0 ... 0x10FFFF => Some(unsafe { CodePoint::from_u32_unchecked(value) }),
            _ => None
        }
    }

    #[inline]
    pub fn from_char(value: char) -> CodePoint {
        unsafe { CodePoint::from_u32_unchecked(value as u32) }
    }

    #[inline]
    pub fn to_u32(&self) -> u32 {
        self.value
    }

    #[inline]
    pub fn to_char(&self) -> Option<char> {
        match self.value {
            0xD800 ... 0xDFFF => None,
            _ => Some(unsafe { transmute(self.value) })
        }
    }
}

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

    #[test]
    fn code_point() {
        assert_eq!(CodePoint::from_u32(0).unwrap().to_u32(), 0)
        assert_eq!(CodePoint::from_u32(0xD800).unwrap().to_u32(), 0xD800)
        assert_eq!(CodePoint::from_u32(0x10FFFF).unwrap().to_u32(), 0x10FFFF)
        assert_eq!(CodePoint::from_u32(0x110000), None)
        assert_eq!(CodePoint::from_char('a').to_u32(), 0x61)
        assert_eq!(CodePoint::from_char('a').to_string(), "U+0061".to_string())
        assert_eq!(CodePoint::from_char('💩').to_string(), "U+1F4A9".to_string())
        assert_eq!(CodePoint::from_u32(0x1F4A9).unwrap().to_char(), Some('\U0001F4A9'))
        assert_eq!(CodePoint::from_u32(0xD800).unwrap().to_char(), None)
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

enum Node {
    NamedNode(String),
    AnonymousNode(u64)
}

enum Literal {
    LangLiteral(String, String),
    StringLiteral(String),
    BooleanLiteral(bool),
    LongLiteral(i64),
    DoubleLiteral(f64)
}

enum Object {
    Node(Node),
    Literal(Literal)
}

enum Range {
    LangLiteralRange(LangLiteral, LangLiteral),
    StringLiteralRange(StringLiteral, StringLiteral),
    LongLiteralRange(LongLiteral, LongLiteral),
    DoubleLiteralRange(DoubleLiteral, DoubleLiteral)
}

struct Statement {
    subject: Node,
    predicate: NamedNode,
    object: Object
}

struct PersistedStatement {
    collection: NamedNode,
    statement: Statement,
    context: AnonymousNode
}

let a = NamedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")

fn validNamedNode(node: NamedNode): Boolean = "[a-zA-Z_][^\\s()\\[\\]{}'\"`<>\\\\]*".r.matches(node.name)

fn validLangTag(langTag: String): Boolean = "[a-zA-Z]+(-[a-zA-Z0-9]+)*".r.matches(langTag)

trait Ligature {
  fn session: Resource[Task, LigatureSession]
}

trait LigatureSession {
  fn read: Resource[Task, ReadTx]
  fn write: Resource[Task, WriteTx]
}

trait ReadTx {
  fn collections: Observable[NamedNode]
  fn collections(prefix: NamedNode): Observable[NamedNode]
  fn collections(from: NamedNode, to: NamedNode): Observable[NamedNode]
  fn allStatements(collection: NamedNode): Observable[PersistedStatement]
  fn matchStatements(collection: NamedNode,
    subject: Option[Node] = None,
    predicate: Option[NamedNode] = None,
    `object`: Option[Object] = None): Observable[PersistedStatement]
  fn matchStatements(collection: NamedNode,
    subject: Option[Node],
    predicate: Option[NamedNode],
    range: Range): Observable[PersistedStatement]
  fn statementByContext(collection: NamedNode, context: AnonymousNode): Task[Option[PersistedStatement]]
}

trait WriteTx {
    fn createCollection(collection: NamedNode): Task[NamedNode]
    fn deleteCollection(collection: NamedNode): Task[NamedNode]
    fn newNode(collection: NamedNode): Task[AnonymousNode]
    fn addStatement(collection: NamedNode, statement: Statement): Task[PersistedStatement]
    fn removeStatement(collection: NamedNode, statement: Statement): Task[Statement]
    fn cancel(): Unit
}

#[cfg(test)]
mod tests {
test("validIdentifier tests") {
assert(!validNamedNode(NamedNode("")))
assert(validNamedNode(NamedNode("http://localhost/people/7")))
assert(!validNamedNode(NamedNode("http://localhost(/people/7")))
assert(!validNamedNode(NamedNode("http://localhost{/people/7")))
assert(!validNamedNode(NamedNode("http://localhost\\/people/7")))
assert(!validNamedNode(NamedNode("http://localhost</people/7")))
assert(!validNamedNode(NamedNode("http://localhost>/people/7")))
assert(!validNamedNode(NamedNode("http://localhost[/people/7")))
assert(!validNamedNode(NamedNode("http://localhost]/people/7")))
assert(!validNamedNode(NamedNode("http://localhost\"/people/7")))
assert(!validNamedNode(NamedNode("http://localhost'/people/7")))
assert(!validNamedNode(NamedNode("http://localhost`/people/7")))
assert(!validNamedNode(NamedNode("http://localhost\t/people/7")))
assert(!validNamedNode(NamedNode("http://localhost\n/people/7")))
assert(!validNamedNode(NamedNode("http://localhost /people/7")))
assert(validNamedNode(NamedNode("hello")))
assert(validNamedNode(NamedNode("_:")))
assert(validNamedNode(NamedNode("_:valid")))
assert(validNamedNode(NamedNode("_:1")))
assert(validNamedNode(NamedNode("_:1344")))
}

test("validLangTag tests") {
assert(!validLangTag(""))
assert(validLangTag("en"))
assert(!validLangTag("en-"))
assert(validLangTag("en-fr"))
assert(!validLangTag("en-fr-"))
assert(validLangTag("en-fr-sp"))
assert(validLangTag("ennnenefnk-dkfjkjfl-dfakjelfkjalkf-fakjeflkajlkfj"))
assert(!validLangTag("en-fr-ef "))
}
}
<commit_msg>fixing more compilation errors, fixing issues with overloads and defaults (which Rust doesn't have), #147<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

enum Node {
    NamedNode(String),
    AnonymousNode(u64)
}

enum Literal {
    LangLiteral(String, String),
    StringLiteral(String),
    BooleanLiteral(bool),
    LongLiteral(i64),
    DoubleLiteral(f64)
}

enum Object {
    Node(Node),
    Literal(Literal)
}

enum Range {
    LangLiteralRange(LangLiteral, LangLiteral),
    StringLiteralRange(StringLiteral, StringLiteral),
    LongLiteralRange(LongLiteral, LongLiteral),
    DoubleLiteralRange(DoubleLiteral, DoubleLiteral)
}

struct Statement {
    subject: Node,
    predicate: NamedNode,
    object: Object
}

struct PersistedStatement {
    collection: NamedNode,
    statement: Statement,
    context: AnonymousNode
}

//fn validNamedNode(node: NamedNode) -> bool = "[a-zA-Z_][^\\s()\\[\\]{}'\"`<>\\\\]*".r.matches(node.name)

//fn validLangTag(langTag: String) -> bool = "[a-zA-Z]+(-[a-zA-Z0-9]+)*".r.matches(langTag)

trait Ligature {
    async fn read() -> Result<T, String>;
    async fn write() -> Result<Unit, String>;
}

trait ReadTx {
    fn collections() -> Stream<NamedNode>;
    fn collections_prefix(prefix: NamedNode) -> Stream<NamedNode>;
    fn collections_range(from: NamedNode, to: NamedNode) -> Stream<NamedNode>;
    fn all_statements(collection: NamedNode) -> Stream<PersistedStatement>;
    fn match_statements(collection: NamedNode,
        subject: Option<Node>,
        predicate: Option<NamedNode>,
        object: Option<Object>) -> Stream<PersistedStatement>;
    fn match_range(collection: NamedNode,
        subject: Option<Node>,
        predicate: Option<NamedNode>,
        range: Range) -> Stream<PersistedStatement>;
    fn statement_by_context(collection: NamedNode, context: AnonymousNode) -> Option<PersistedStatement>;
}

trait WriteTx {
    fn create_collection(collection: NamedNode) -> NamedNode;
    fn delete_collection(collection: NamedNode) -> NamedNode;
    fn new_node(collection: NamedNode) -> AnonymousNode;
    fn add_statement(collection: NamedNode, statement: Statement) -> PersistedStatement;
    fn remove_statement(collection: NamedNode, statement: Statement) -> Statement;
    fn cancel() -> Unit;
}

#[cfg(test)]
mod tests {
test("validIdentifier tests") {
assert(!validNamedNode(NamedNode("")))
assert(validNamedNode(NamedNode("http://localhost/people/7")))
assert(!validNamedNode(NamedNode("http://localhost(/people/7")))
assert(!validNamedNode(NamedNode("http://localhost{/people/7")))
assert(!validNamedNode(NamedNode("http://localhost\\/people/7")))
assert(!validNamedNode(NamedNode("http://localhost</people/7")))
assert(!validNamedNode(NamedNode("http://localhost>/people/7")))
assert(!validNamedNode(NamedNode("http://localhost[/people/7")))
assert(!validNamedNode(NamedNode("http://localhost]/people/7")))
assert(!validNamedNode(NamedNode("http://localhost\"/people/7")))
assert(!validNamedNode(NamedNode("http://localhost'/people/7")))
assert(!validNamedNode(NamedNode("http://localhost`/people/7")))
assert(!validNamedNode(NamedNode("http://localhost\t/people/7")))
assert(!validNamedNode(NamedNode("http://localhost\n/people/7")))
assert(!validNamedNode(NamedNode("http://localhost /people/7")))
assert(validNamedNode(NamedNode("hello")))
assert(validNamedNode(NamedNode("_:")))
assert(validNamedNode(NamedNode("_:valid")))
assert(validNamedNode(NamedNode("_:1")))
assert(validNamedNode(NamedNode("_:1344")))
}

test("validLangTag tests") {
assert(!validLangTag(""))
assert(validLangTag("en"))
assert(!validLangTag("en-"))
assert(validLangTag("en-fr"))
assert(!validLangTag("en-fr-"))
assert(validLangTag("en-fr-sp"))
assert(validLangTag("ennnenefnk-dkfjkjfl-dfakjelfkjalkf-fakjeflkajlkfj"))
assert(!validLangTag("en-fr-ef "))
}
}
<|endoftext|>


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

/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::http()`.

The `http()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```no_run
let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```no_run
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();

loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    // ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```no_run
# use std::sync::Arc;
# use std::thread;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
let server = Arc::new(server);
let mut guards = Vec::with_capacity(4);

for _ in (0 .. 4) {
    let server = server.clone();

    let guard = thread::spawn(move || {
        loop {
            let rq = server.recv().unwrap();

            // ...
        }
    });

    guards.push(guard);
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.method()` and `request.url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```no_run
# use std::fs::File;
# use std::path::Path;
let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
```

All that remains to do is call `request.respond()`:

```no_run
# use std::fs::File;
# use std::path::Path;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
# let request = server.recv().unwrap();
# let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
let _ = request.respond(response);
```
*/
#![crate_name = "tiny_http"]
#![crate_type = "lib"]
#![forbid(unsafe_code)]

#[macro_use]
extern crate log;

extern crate ascii;
extern crate chunked_transfer;
extern crate encoding;
extern crate url;
extern crate chrono;

#[cfg(feature = "ssl")]
extern crate openssl;

use std::error::Error;
use std::io::Error as IoError;
use std::io::Result as IoResult;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::thread;
use std::net;
use std::net::ToSocketAddrs;
use std::time::Duration;
use std::sync::atomic::Ordering::Relaxed;

use client::ClientConnection;
use util::MessagesQueue;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use request::Request;
pub use response::{ResponseBox, Response};

mod client;
mod common;
mod request;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket annd the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
pub struct Server {
    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // queue for messages received by child threads
    messages: Arc<MessagesQueue<Message>>,

    // result of TcpListener::local_addr()
    listening_addr: net::SocketAddr,
}

enum Message {
    Error(IoError),
    NewRequest(Request),
}

impl From<IoError> for Message {
    fn from(e: IoError) -> Message {
        Message::Error(e)
    }
}

impl From<Request> for Message {
    fn from(rq: Request) -> Message {
        Message::NewRequest(rq)
    }
}

// this trait is to make sure that Server implements Share and Send
#[doc(hidden)]
trait MustBeShareDummy : Sync + Send {}
#[doc(hidden)]
impl MustBeShareDummy for Server {}

pub struct IncomingRequests<'a> {
    server: &'a Server
}

/// Represents the parameters required to create a server.
#[derive(Debug, Clone)]
pub struct ServerConfig<A> where A: ToSocketAddrs {
    /// The addresses to listen to.
    pub addr: A,

    /// If `Some`, then the server will use SSL to encode the communications.
    pub ssl: Option<SslConfig>,
}

/// Configuration of the server for SSL.
#[derive(Debug, Clone)]
pub struct SslConfig {
    /// Contains the public certificate to send to clients.
    pub certificate: Vec<u8>,
    /// Contains the ultra-secret private key used to decode communications.
    pub private_key: Vec<u8>,
}

impl Server {
    /// Shortcut for a simple server on a specific address.
    #[inline]
    pub fn http<A>(addr: A) -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
            ssl: None,
        })
    }

    /// Shortcut for an HTTPS server on a specific address.
    #[cfg(feature = "ssl")]
    #[inline]
    pub fn https<A>(addr: A, config: SslConfig)
                    -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
            ssl: Some(config),
        })
    }

    /// Builds a new server that listens on the specified address.
    pub fn new<A>(config: ServerConfig<A>) -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        // building the "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpListener
        let (server, local_addr) = {
            let listener = try!(net::TcpListener::bind(config.addr));
            let local_addr = try!(listener.local_addr());
            debug!("Server listening on {}", local_addr);
            (listener, local_addr)
        };

        // building the SSL capabilities
        #[cfg(feature = "ssl")]
        type SslContext = openssl::ssl::SslContext;
        #[cfg(not(feature = "ssl"))]
        type SslContext = ();
        let ssl: Option<SslContext> = match config.ssl {
            #[cfg(feature = "ssl")]
            Some(mut config) => {
                use std::io::Cursor;
                use openssl::ssl;
                use openssl::x509::X509;
                use openssl::crypto::pkey::PKey;
                use openssl::ssl::SSL_VERIFY_NONE;

                let mut ctxt = try!(SslContext::new(ssl::SslMethod::Sslv23));
                try!(ctxt.set_cipher_list("DEFAULT"));
                let certificate = try!(X509::from_pem(&mut Cursor::new(&config.certificate[..])));
                try!(ctxt.set_certificate(&certificate));
                let private_key = try!(PKey::private_key_from_pem(&mut Cursor::new(&config.private_key[..])));
                try!(ctxt.set_private_key(&private_key));
                ctxt.set_verify(SSL_VERIFY_NONE, None);
                try!(ctxt.check_private_key());

                // let's wipe the certificate and private key from memory, because we're
                // better safe than sorry
                for b in &mut config.certificate { *b = 0; }
                for b in &mut config.private_key { *b = 0; }

                Some(ctxt)
            },
            #[cfg(not(feature = "ssl"))]
            Some(_) => return Err("Building a server with SSL requires enabling the `ssl` feature \
                                   in tiny-http".to_owned().into()),
            None => None,
        };

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are pushed in the messages queue
        let messages = MessagesQueue::with_capacity(8);

        let inside_close_trigger = close_trigger.clone();
        let inside_messages = messages.clone();
        thread::spawn(move || {
            // a tasks pool is used to dispatch the connections into threads
            let tasks_pool = util::TaskPool::new();

            debug!("Running accept thread");
            while !inside_close_trigger.load(Relaxed) {
                let new_client = match server.accept() {
                    Ok((sock, _)) => {
                        use util::RefinedTcpStream;

                        let (read_closable, write_closable) = match ssl {
                            None => {
                                RefinedTcpStream::new(sock)
                            },
                            #[cfg(feature = "ssl")]
                            Some(ref ssl) => {
                                // trying to apply SSL over the connection
                                // if an error occurs, we just close the socket and resume listening
                                let sock = match openssl::ssl::SslStream::accept(ssl, sock) {
                                    Ok(s) => s,
                                    Err(_) => continue
                                };

                                RefinedTcpStream::new(sock)
                            },
                            #[cfg(not(feature = "ssl"))]
                            Some(_) => unreachable!(),
                        };

                        Ok(ClientConnection::new(write_closable, read_closable))
                    },
                    Err(e) => Err(e),
                };

                match new_client {
                    Ok(client) => {
                        let messages = inside_messages.clone();
                        let mut client = Some(client);
                        tasks_pool.spawn(Box::new(move || {
                            if let Some(client) = client.take() {
                                for rq in client {
                                    messages.push(rq.into());
                                }
                            }
                        }));
                    },

                    Err(e) => {
                        error!("Error accepting new client: {}", e);
                        inside_messages.push(e.into());
                        break;
                    }
                }
            }
            debug!("Terminating accept thread");
        });

        // result
        Ok(Server {
            messages: messages,
            close: close_trigger,
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[inline]
    pub fn incoming_requests(&self) -> IncomingRequests {
        IncomingRequests { server: self }
    }

    /// Returns the address the server is listening to.
    #[inline]
    pub fn server_addr(&self) -> net::SocketAddr {
        self.listening_addr.clone()
    }

    /// Returns the number of clients currently connected to the server.
    pub fn num_connections(&self) -> usize {
        unimplemented!()
        //self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> IoResult<Request> {
        match self.messages.pop() {
            Message::Error(err) => return Err(err),
            Message::NewRequest(rq) => return Ok(rq),
        }
    }

    /// Same as `recv()` but doesn't block longer than timeout
    pub fn recv_timeout(&self, timeout: Duration) -> IoResult<Option<Request>> {
        match self.messages.pop_timeout(timeout) {
            Some(Message::Error(err)) => return Err(err),
            Some(Message::NewRequest(rq)) => return Ok(Some(rq)),
            None => return Ok(None)
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        match self.messages.try_pop() {
            Some(Message::Error(err)) => return Err(err),
            Some(Message::NewRequest(rq)) => return Ok(Some(rq)),
            None => return Ok(None)
        }
    }
}

impl<'a> Iterator for IncomingRequests<'a> {
    type Item = Request;
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.close.store(true, Relaxed);
    }
}
<commit_msg>Unblock the accept thread on shutdown<commit_after>// Copyright 2015 The tiny-http Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::http()`.

The `http()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```no_run
let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```no_run
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();

loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    // ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```no_run
# use std::sync::Arc;
# use std::thread;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
let server = Arc::new(server);
let mut guards = Vec::with_capacity(4);

for _ in (0 .. 4) {
    let server = server.clone();

    let guard = thread::spawn(move || {
        loop {
            let rq = server.recv().unwrap();

            // ...
        }
    });

    guards.push(guard);
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.method()` and `request.url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```no_run
# use std::fs::File;
# use std::path::Path;
let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
```

All that remains to do is call `request.respond()`:

```no_run
# use std::fs::File;
# use std::path::Path;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
# let request = server.recv().unwrap();
# let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
let _ = request.respond(response);
```
*/
#![crate_name = "tiny_http"]
#![crate_type = "lib"]
#![forbid(unsafe_code)]

#[macro_use]
extern crate log;

extern crate ascii;
extern crate chunked_transfer;
extern crate encoding;
extern crate url;
extern crate chrono;

#[cfg(feature = "ssl")]
extern crate openssl;

use std::error::Error;
use std::io::Error as IoError;
use std::io::Result as IoResult;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::thread;
use std::net;
use std::net::{ToSocketAddrs, TcpStream, Shutdown};
use std::time::Duration;
use std::sync::atomic::Ordering::Relaxed;

use client::ClientConnection;
use util::MessagesQueue;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use request::Request;
pub use response::{ResponseBox, Response};

mod client;
mod common;
mod request;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket annd the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
pub struct Server {
    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // queue for messages received by child threads
    messages: Arc<MessagesQueue<Message>>,

    // result of TcpListener::local_addr()
    listening_addr: net::SocketAddr,
}

enum Message {
    Error(IoError),
    NewRequest(Request),
}

impl From<IoError> for Message {
    fn from(e: IoError) -> Message {
        Message::Error(e)
    }
}

impl From<Request> for Message {
    fn from(rq: Request) -> Message {
        Message::NewRequest(rq)
    }
}

// this trait is to make sure that Server implements Share and Send
#[doc(hidden)]
trait MustBeShareDummy : Sync + Send {}
#[doc(hidden)]
impl MustBeShareDummy for Server {}

pub struct IncomingRequests<'a> {
    server: &'a Server
}

/// Represents the parameters required to create a server.
#[derive(Debug, Clone)]
pub struct ServerConfig<A> where A: ToSocketAddrs {
    /// The addresses to listen to.
    pub addr: A,

    /// If `Some`, then the server will use SSL to encode the communications.
    pub ssl: Option<SslConfig>,
}

/// Configuration of the server for SSL.
#[derive(Debug, Clone)]
pub struct SslConfig {
    /// Contains the public certificate to send to clients.
    pub certificate: Vec<u8>,
    /// Contains the ultra-secret private key used to decode communications.
    pub private_key: Vec<u8>,
}

impl Server {
    /// Shortcut for a simple server on a specific address.
    #[inline]
    pub fn http<A>(addr: A) -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
            ssl: None,
        })
    }

    /// Shortcut for an HTTPS server on a specific address.
    #[cfg(feature = "ssl")]
    #[inline]
    pub fn https<A>(addr: A, config: SslConfig)
                    -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
            ssl: Some(config),
        })
    }

    /// Builds a new server that listens on the specified address.
    pub fn new<A>(config: ServerConfig<A>) -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        // building the "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpListener
        let (server, local_addr) = {
            let listener = try!(net::TcpListener::bind(config.addr));
            let local_addr = try!(listener.local_addr());
            debug!("Server listening on {}", local_addr);
            (listener, local_addr)
        };

        // building the SSL capabilities
        #[cfg(feature = "ssl")]
        type SslContext = openssl::ssl::SslContext;
        #[cfg(not(feature = "ssl"))]
        type SslContext = ();
        let ssl: Option<SslContext> = match config.ssl {
            #[cfg(feature = "ssl")]
            Some(mut config) => {
                use std::io::Cursor;
                use openssl::ssl;
                use openssl::x509::X509;
                use openssl::crypto::pkey::PKey;
                use openssl::ssl::SSL_VERIFY_NONE;

                let mut ctxt = try!(SslContext::new(ssl::SslMethod::Sslv23));
                try!(ctxt.set_cipher_list("DEFAULT"));
                let certificate = try!(X509::from_pem(&mut Cursor::new(&config.certificate[..])));
                try!(ctxt.set_certificate(&certificate));
                let private_key = try!(PKey::private_key_from_pem(&mut Cursor::new(&config.private_key[..])));
                try!(ctxt.set_private_key(&private_key));
                ctxt.set_verify(SSL_VERIFY_NONE, None);
                try!(ctxt.check_private_key());

                // let's wipe the certificate and private key from memory, because we're
                // better safe than sorry
                for b in &mut config.certificate { *b = 0; }
                for b in &mut config.private_key { *b = 0; }

                Some(ctxt)
            },
            #[cfg(not(feature = "ssl"))]
            Some(_) => return Err("Building a server with SSL requires enabling the `ssl` feature \
                                   in tiny-http".to_owned().into()),
            None => None,
        };

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are pushed in the messages queue
        let messages = MessagesQueue::with_capacity(8);

        let inside_close_trigger = close_trigger.clone();
        let inside_messages = messages.clone();
        thread::spawn(move || {
            // a tasks pool is used to dispatch the connections into threads
            let tasks_pool = util::TaskPool::new();

            debug!("Running accept thread");
            while !inside_close_trigger.load(Relaxed) {
                let new_client = match server.accept() {
                    Ok((sock, _)) => {
                        use util::RefinedTcpStream;
                        let (read_closable, write_closable) = match ssl {
                            None => {
                                RefinedTcpStream::new(sock)
                            },
                            #[cfg(feature = "ssl")]
                            Some(ref ssl) => {
                                // trying to apply SSL over the connection
                                // if an error occurs, we just close the socket and resume listening
                                let sock = match openssl::ssl::SslStream::accept(ssl, sock) {
                                    Ok(s) => s,
                                    Err(_) => continue
                                };

                                RefinedTcpStream::new(sock)
                            },
                            #[cfg(not(feature = "ssl"))]
                            Some(_) => unreachable!(),
                        };

                        Ok(ClientConnection::new(write_closable, read_closable))
                    },
                    Err(e) => Err(e),
                };

                match new_client {
                    Ok(client) => {
                        let messages = inside_messages.clone();
                        let mut client = Some(client);
                        tasks_pool.spawn(Box::new(move || {
                            if let Some(client) = client.take() {
                                for rq in client {
                                    messages.push(rq.into());
                                }
                            }
                        }));
                    },

                    Err(e) => {
                        error!("Error accepting new client: {}", e);
                        inside_messages.push(e.into());
                        break;
                    }
                }
            }
            debug!("Terminating accept thread");
        });

        // result
        Ok(Server {
            messages: messages,
            close: close_trigger,
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[inline]
    pub fn incoming_requests(&self) -> IncomingRequests {
        IncomingRequests { server: self }
    }

    /// Returns the address the server is listening to.
    #[inline]
    pub fn server_addr(&self) -> net::SocketAddr {
        self.listening_addr.clone()
    }

    /// Returns the number of clients currently connected to the server.
    pub fn num_connections(&self) -> usize {
        unimplemented!()
        //self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> IoResult<Request> {
        match self.messages.pop() {
            Message::Error(err) => return Err(err),
            Message::NewRequest(rq) => return Ok(rq),
        }
    }

    /// Same as `recv()` but doesn't block longer than timeout
    pub fn recv_timeout(&self, timeout: Duration) -> IoResult<Option<Request>> {
        match self.messages.pop_timeout(timeout) {
            Some(Message::Error(err)) => return Err(err),
            Some(Message::NewRequest(rq)) => return Ok(Some(rq)),
            None => return Ok(None)
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        match self.messages.try_pop() {
            Some(Message::Error(err)) => return Err(err),
            Some(Message::NewRequest(rq)) => return Ok(Some(rq)),
            None => return Ok(None)
        }
    }
}

impl<'a> Iterator for IncomingRequests<'a> {
    type Item = Request;
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.close.store(true, Relaxed);
        // Connect briefly to ourselves to unblock the accept thread
        let maybe_stream = TcpStream::connect(self.listening_addr);
        if let Ok(stream) = maybe_stream {
            let _ = stream.shutdown(Shutdown::Both);
        }
    }
}
<|endoftext|>


<commit_before>extern crate term;
extern crate termios;

use term::terminfo::TermInfo;
use termios::Termios;
use std::string::String;
use std::io::{stdin, Stdin, stdout, Stdout, stderr, Stderr};

/// Holds the state for the line editor
#[derive(Clone, PertialEq, Debug)]
pub struct Rebar {
    i: Stdin,   //stdin handle
    o: Stdout,  //stdout handle
    e: Stderr,  //stderr handle
    termio: Termios,
    terms: TermInfo,
    prompt: String,
    buf: String,
    cursor_pos: usize,
}

/// Initialisation function
pub fn rebar() -> Rebar {
    let info = match TermInfo::from_env() {
        Ok(s) => s,
        Err(f) => panic!(f),
    };
    let ios = match Termios::from_fd(0) {
        Ok(s) => s,
        Err(f) => panic!(f),
    };
    let res = Rebar {
        i: stdin(),
        o: stdout(),
        e: stderr(),
        termio: ios,
        terms: info,
        prompt: String::new(),
        buf: String::new(),
        cursor_pos: 0
    };
    res
}

///Clears the screen using terminfo-based clear string
pub fn clear() {
    let info = term::terminfo::TermInfo::from_env();

    let fred = match info {
        Ok(val) => val,
        Err(f) => panic!(f.to_string()),
    };

    let clear = fred.strings.get("clear").unwrap();
    let mut derf = term::stdout().unwrap();
    match derf.write_all(clear) {
        Ok(..) => {},
        Err(f) => println!("Failed to clear: {}", f),
    };
}

///Refresh the line, so that you can move cursors and shit
pub fn refresh_screen(inline: &str) {
    let mut line = String::new();
    line.push_str("\r");
    line.push_str(inline);
    print!("{}", line);
}

#[test]
fn clear_screen() {
    clear();
}
<commit_msg>corrected spelling in PartialEq<commit_after>extern crate term;
extern crate termios;

use term::terminfo::TermInfo;
use termios::Termios;
use std::string::String;
use std::io::{stdin, Stdin, stdout, Stdout, stderr, Stderr};

/// Holds the state for the line editor
#[derive(Clone, PartialEq, Debug)]
pub struct Rebar {
    i: Stdin,   //stdin handle
    o: Stdout,  //stdout handle
    e: Stderr,  //stderr handle
    termio: Termios,
    terms: TermInfo,
    prompt: String,
    buf: String,
    cursor_pos: usize,
}

/// Initialisation function
pub fn rebar() -> Rebar {
    let info = match TermInfo::from_env() {
        Ok(s) => s,
        Err(f) => panic!(f),
    };
    let ios = match Termios::from_fd(0) {
        Ok(s) => s,
        Err(f) => panic!(f),
    };
    let res = Rebar {
        i: stdin(),
        o: stdout(),
        e: stderr(),
        termio: ios,
        terms: info,
        prompt: String::new(),
        buf: String::new(),
        cursor_pos: 0
    };
    res
}

///Clears the screen using terminfo-based clear string
pub fn clear() {
    let info = term::terminfo::TermInfo::from_env();

    let fred = match info {
        Ok(val) => val,
        Err(f) => panic!(f.to_string()),
    };

    let clear = fred.strings.get("clear").unwrap();
    let mut derf = term::stdout().unwrap();
    match derf.write_all(clear) {
        Ok(..) => {},
        Err(f) => println!("Failed to clear: {}", f),
    };
}

///Refresh the line, so that you can move cursors and shit
pub fn refresh_screen(inline: &str) {
    let mut line = String::new();
    line.push_str("\r");
    line.push_str(inline);
    print!("{}", line);
}

#[test]
fn clear_screen() {
    clear();
}
<|endoftext|>


<commit_before>#![feature(core)]

extern crate crypto;
extern crate "rustc-serialize" as rustc_serialize;
extern crate time;

// TODO: find out where this function is going to be once old_io is gone
use std::num::Int;
use crypto::sha1::Sha1;
use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::digest::Digest;
use rustc_serialize::hex::FromHex;

fn u64_from_be_bytes_4(bytes: &[u8], start: usize) -> u64 {
    let mut val = 0u64;

    val += (bytes[start]   as u64) << ((3 * 8) as u64);
    val += (bytes[start+1] as u64) << ((2 * 8) as u64);
    val += (bytes[start+2] as u64) << ((1 * 8) as u64);
    val += (bytes[start+3] as u64) << ((0 * 8) as u64);

    val
}

fn u64_to_be_bytes_8(data: u64) -> Vec<u8> {
    let mut v = Vec::new();
    v.push((data >> 56) as u8);
    v.push((data >> 48) as u8);
    v.push((data >> 40) as u8);
    v.push((data >> 32) as u8);
    v.push((data >> 24) as u8);
    v.push((data >> 16) as u8);
    v.push((data >> 8) as u8);
    v.push(data as u8);

    v
}

fn dynamic_truncation(hs: &[u8]) -> u64 {
    let offset_bits = (hs[19] & 0xf) as usize;
    let p = u64_from_be_bytes_4(hs, offset_bits);

    p & 0x7fffffff
}

pub fn hotp_custom<D: Digest>(key: &[u8], counter: u64, digits: u32,
                              hash: D) -> u64 {
    let mut hmac = Hmac::new(hash, key);
    let bytes = u64_to_be_bytes_8(counter);
    hmac.input(bytes.as_slice());
    let result = hmac.result();
    let hs = result.code();

    dynamic_truncation(hs) % 10.pow(digits)
}

pub fn hotp_raw(key: &[u8], counter: u64, digits: u32) -> u64 {
    let hash = Sha1::new();
    hotp_custom(key, counter, digits, hash)
}

pub fn hotp(key: &str, counter: u64, digits: u32) -> Result<u64, &str> {
    match key.from_hex() {
        Ok(bytes) => Ok(hotp_raw(bytes.as_slice(), counter, digits)),
        Err(_) => Err("Unable to parse hex.")
    }
}

pub fn totp_custom<D: Digest>(key: &[u8], digits: u32, epoch: u64,
                              time_step: u64, current_time: u64,
                              hash: D) -> u64 {
    let counter = (current_time - epoch) / time_step;
    hotp_custom(key, counter, digits, hash)
}

pub fn totp_raw(key: &[u8], digits: u32, epoch: u64, time_step: u64) -> u64 {
    let hash = Sha1::new();
    let current_time = time::get_time();
    totp_custom(key, digits, epoch, time_step, current_time.sec as u64, hash)
}

pub fn totp(key: &str, digits: u32, epoch: u64,
            time_step: u64) -> Result<u64, &str> {
    match key.from_hex() {
        Ok(bytes) => Ok(totp_raw(bytes.as_slice(), digits, epoch, time_step)),
        Err(_) => Err("Unable to parse hex.")
    }
}

#[test]
fn test_hotp() {
    assert_eq!(hotp_raw(b"\xff", 23, 6), 330795);
    assert_eq!(hotp("ff", 23, 6).unwrap(), 330795);
    assert_eq!(hotp_custom(b"\xff", 23, 6, Sha1::new()), 330795);
}

#[test]
fn test_totp() {
    assert_eq!(totp_custom(b"\xff", 6, 0, 1, 23, Sha1::new()), 330795);
}
<commit_msg>Add from_hex() helper function<commit_after>#![feature(core)]

extern crate crypto;
extern crate "rustc-serialize" as rustc_serialize;
extern crate time;

// TODO: find out where this function is going to be once old_io is gone
use std::num::Int;
use crypto::sha1::Sha1;
use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::digest::Digest;
use rustc_serialize::hex::FromHex;

pub fn from_hex(data: &str) -> Result<Vec<u8>, &str> {
    match data.from_hex() {
        Ok(d) => Ok(d),
        Err(_) => Err("Unable to decode hex")
    }
}

fn u64_from_be_bytes_4(bytes: &[u8], start: usize) -> u64 {
    let mut val = 0u64;

    val += (bytes[start]   as u64) << ((3 * 8) as u64);
    val += (bytes[start+1] as u64) << ((2 * 8) as u64);
    val += (bytes[start+2] as u64) << ((1 * 8) as u64);
    val += (bytes[start+3] as u64) << ((0 * 8) as u64);

    val
}

fn u64_to_be_bytes_8(data: u64) -> Vec<u8> {
    let mut v = Vec::new();
    v.push((data >> 56) as u8);
    v.push((data >> 48) as u8);
    v.push((data >> 40) as u8);
    v.push((data >> 32) as u8);
    v.push((data >> 24) as u8);
    v.push((data >> 16) as u8);
    v.push((data >> 8) as u8);
    v.push(data as u8);

    v
}

fn dynamic_truncation(hs: &[u8]) -> u64 {
    let offset_bits = (hs[19] & 0xf) as usize;
    let p = u64_from_be_bytes_4(hs, offset_bits);

    p & 0x7fffffff
}

pub fn hotp_custom<D: Digest>(key: &[u8], counter: u64, digits: u32,
                              hash: D) -> u64 {
    let mut hmac = Hmac::new(hash, key);
    let bytes = u64_to_be_bytes_8(counter);
    hmac.input(bytes.as_slice());
    let result = hmac.result();
    let hs = result.code();

    dynamic_truncation(hs) % 10.pow(digits)
}

pub fn hotp_raw(key: &[u8], counter: u64, digits: u32) -> u64 {
    let hash = Sha1::new();
    hotp_custom(key, counter, digits, hash)
}

pub fn hotp(key: &str, counter: u64, digits: u32) -> Result<u64, &str> {
    match key.from_hex() {
        Ok(bytes) => Ok(hotp_raw(bytes.as_slice(), counter, digits)),
        Err(_) => Err("Unable to parse hex.")
    }
}

pub fn totp_custom<D: Digest>(key: &[u8], digits: u32, epoch: u64,
                              time_step: u64, current_time: u64,
                              hash: D) -> u64 {
    let counter = (current_time - epoch) / time_step;
    hotp_custom(key, counter, digits, hash)
}

pub fn totp_raw(key: &[u8], digits: u32, epoch: u64, time_step: u64) -> u64 {
    let hash = Sha1::new();
    let current_time = time::get_time();
    totp_custom(key, digits, epoch, time_step, current_time.sec as u64, hash)
}

pub fn totp(key: &str, digits: u32, epoch: u64,
            time_step: u64) -> Result<u64, &str> {
    match key.from_hex() {
        Ok(bytes) => Ok(totp_raw(bytes.as_slice(), digits, epoch, time_step)),
        Err(_) => Err("Unable to parse hex.")
    }
}

#[test]
fn test_hotp() {
    assert_eq!(hotp_raw(b"\xff", 23, 6), 330795);
    assert_eq!(hotp("ff", 23, 6).unwrap(), 330795);
    assert_eq!(hotp_custom(b"\xff", 23, 6, Sha1::new()), 330795);
    assert_eq!(hotp_custom(from_hex("ff").unwrap().as_slice(), 23, 6, Sha1::new()), 330795);
}

#[test]
fn test_totp() {
    assert_eq!(totp_custom(b"\xff", 6, 0, 1, 23, Sha1::new()), 330795);
}
<|endoftext|>