<commit_before>#[macro_use]
extern crate string_cache;
extern crate html5ever;

use std::io;
use std::io::Write;
use html5ever::{Parser,parse_document};
use html5ever::driver::ParseOpts;
use html5ever::tree_builder::TreeBuilderOpts;
use html5ever::rcdom::{RcDom,Handle,Text,Element,Document,Comment};
use html5ever::tendril::TendrilSink;

fn get_text(handle: Handle) -> String {
    let node = handle.borrow();
    let mut result = String::new();
    if let Text(ref tstr) = node.node {
        result.push_str(&tstr);
    } else {
        for child in node.children.iter() {
            result.push_str(&get_text(child.clone()));
        }
    }
    result
}

fn dom_to_string<T:Write>(handle: Handle, err_out: &mut T, width: usize) -> String {
    let node = handle.borrow();
    let mut result = String::new();
    match node.node {
        Document => {},
        Element(ref name, _, ref attrs) => {
            match *name {
                qualname!(html, "html") |
                qualname!(html, "div") |
                qualname!(html, "span") |
                qualname!(html, "body") => {
                    /* process children, but don't add anything */
                },
                qualname!(html, "link") |
                qualname!(html, "meta") |
                qualname!(html, "hr") |
                qualname!(html, "head") => {
                    /* Ignore the head and its children */
                    return result;
                },
                qualname!(html, "h4") |
                qualname!(html, "p") => {
                    return get_text(handle.clone()) + "\n\n";
                },
                qualname!(html, "br") => {
                    result.push('\n');
                }
                qualname!(html, "table") => return table_to_string(handle.clone(), err_out, width),
                _ => {
                    write!(err_out, "Unhandled element: {:?}\n", name.local);
                },
            }
          },
        Text(ref tstr) => {
            return tstr.to_string();
        }
        Comment(_) => {},
        _ => { write!(err_out, "Unhandled: {:?}\n", node); },
    }
    for child in node.children.iter() {
        result.push_str(&dom_to_string(child.clone(), err_out, width));
    }
    result
}

#[derive(Debug)]
struct TableCell {
    content: Handle,
}

#[derive(Debug)]
struct TableRow {
    cells: Vec<TableCell>,
}

#[derive(Debug)]
struct Table {
    rows: Vec<TableRow>,
}

impl Table {
    pub fn new() -> Table {
        Table{ rows: Vec::new() }
    }
    pub fn push(&mut self, row: TableRow) {
        self.rows.push(row);
    }
    pub fn rows(&self) -> std::slice::Iter<TableRow> {
        self.rows.iter()
    }
}

impl TableRow {
    pub fn new() -> TableRow {
        TableRow{ cells: Vec::new() }
    }
    pub fn push(&mut self, cell: TableCell) {
        self.cells.push(cell);
    }
    pub fn cells(&self) -> std::slice::Iter<TableCell> {
        self.cells.iter()
    }
    pub fn num_cells(&self) -> usize {
        self.cells.len()
    }
}

impl TableCell {
    pub fn new(s: Handle) -> TableCell {
        TableCell{ content: s }
    }
    pub fn render<T:Write>(&self, width: usize, err_out: &mut T) -> String
    {
        dom_to_string(self.content.clone(), err_out, width)
    }
}

fn handle_td(handle: Handle) -> TableCell {
    TableCell::new(handle)
}

fn handle_tr<T:Write>(handle: Handle, err_out: &mut T) -> TableRow {
    let node = handle.borrow();

    let mut row = TableRow::new();

    for child in node.children.iter() {
        match child.borrow().node {
            Element(ref name, _, ref attrs) => {
                match *name {
                    qualname!(html, "td") => {
                        row.push(handle_td(child.clone()));
                    },
                    _ => println!("  [[tr child: {:?}]]", name),
                }
            },
            Comment(_) => {},
            _ => { /*result.push_str(&format!("Unhandled in table: {:?}\n", node));*/ },
        }
    }

    row
}

fn handle_tbody<T:Write>(handle: Handle, err_out: &mut T, width: usize) -> String {
    let node = handle.borrow();

    let mut table = Table::new();

    for child in node.children.iter() {
        match child.borrow().node {
            Element(ref name, _, ref attrs) => {
                match *name {
                    qualname!(html, "tr") => {
                        table.push(handle_tr(child.clone(), err_out));
                    },
                    _ => println!("  [[tbody child: {:?}]]", name),
                }
            },
            Comment(_) => {},
            _ => { /*result.push_str(&format!("Unhandled in table: {:?}\n", node));*/ },
        }
    }

    /* Now lay out the table.  Use the simple option of giving each column
     * same width.  TODO: be cleverer, and handle multi-width cells, etc. */
    let num_columns = table.rows().map(|r| r.num_cells()).max().unwrap();

    // Allow for | between columns.
    let col_width = (width - (num_columns-1))/num_columns;

    let cell_bottom: String = (0..col_width).map(|_| '-').collect::<String>() + "+";
    let rowline: String = (0..num_columns-1).map(|_| &cell_bottom[..]).collect::<String>() + &cell_bottom[..col_width];

    let mut result = rowline.clone();
    result.push('\n');

    for row in table.rows() {
        let formatted_cells: Vec<String> = row.cells()
                                              .map(|cell| cell.render(col_width, err_out))
                                              .collect();
        let line_sets: Vec<Vec<&str>> = formatted_cells.iter()
                                                       .map(|s| s.lines()
                                                                 .map(|line| line.trim_right())
                                                                 .collect())
                                                       .collect();
        let cell_height = line_sets.iter()
                                   .map(|v| v.len())
                                   .max().unwrap();
        for i in 0..cell_height {
            for (cellno, ls) in line_sets.iter().enumerate() {
                result.push_str(&format!("{: <width$}", ls.get(i).cloned().unwrap_or(""), width = col_width));
                if cellno == line_sets.len()-1 {
                    result.push('\n')
                } else {
                    result.push('|')
                }
            }
        }
        result.push_str(&rowline);
        result.push('\n');
    }

    result
}

fn table_to_string<T:Write>(handle: Handle, err_out: &mut T, width: usize) -> String {
    let node = handle.borrow();
    let mut result = String::new();

    for child in node.children.iter() {
        match child.borrow().node {
            Element(ref name, _, ref attrs) => {
                match *name {
                    qualname!(html, "tbody") => return handle_tbody(child.clone(), err_out, width),
                    _ => { writeln!(err_out, "  [[table child: {:?}]]", name);},
                }
            },
            Comment(_) => {},
            _ => { /*result.push_str(&format!("Unhandled in table: {:?}\n", node));*/ },
        }
    }

    result
}

pub fn from_read<R>(mut input: R) -> String where R: io::Read {
    let opts = ParseOpts {
        tree_builder: TreeBuilderOpts {
            drop_doctype: true,
            ..Default::default()
        },
        ..Default::default()
    };
    let dom = parse_document(RcDom::default(), opts)
                   .from_utf8()
                   .read_from(&mut input)
                   .unwrap();

    dom_to_string(dom.document, &mut io::stderr(), 80)
}

#[cfg(test)]
mod tests {
}
<commit_msg>Start a table with a newline too.<commit_after>#[macro_use]
extern crate string_cache;
extern crate html5ever;

use std::io;
use std::io::Write;
use html5ever::{Parser,parse_document};
use html5ever::driver::ParseOpts;
use html5ever::tree_builder::TreeBuilderOpts;
use html5ever::rcdom::{RcDom,Handle,Text,Element,Document,Comment};
use html5ever::tendril::TendrilSink;

fn get_text(handle: Handle) -> String {
    let node = handle.borrow();
    let mut result = String::new();
    if let Text(ref tstr) = node.node {
        result.push_str(&tstr);
    } else {
        for child in node.children.iter() {
            result.push_str(&get_text(child.clone()));
        }
    }
    result
}

fn dom_to_string<T:Write>(handle: Handle, err_out: &mut T, width: usize) -> String {
    let node = handle.borrow();
    let mut result = String::new();
    match node.node {
        Document => {},
        Element(ref name, _, ref attrs) => {
            match *name {
                qualname!(html, "html") |
                qualname!(html, "div") |
                qualname!(html, "span") |
                qualname!(html, "body") => {
                    /* process children, but don't add anything */
                },
                qualname!(html, "link") |
                qualname!(html, "meta") |
                qualname!(html, "hr") |
                qualname!(html, "head") => {
                    /* Ignore the head and its children */
                    return result;
                },
                qualname!(html, "h4") |
                qualname!(html, "p") => {
                    return get_text(handle.clone()) + "\n\n";
                },
                qualname!(html, "br") => {
                    result.push('\n');
                }
                qualname!(html, "table") => return table_to_string(handle.clone(), err_out, width),
                _ => {
                    write!(err_out, "Unhandled element: {:?}\n", name.local);
                },
            }
          },
        Text(ref tstr) => {
            return tstr.to_string();
        }
        Comment(_) => {},
        _ => { write!(err_out, "Unhandled: {:?}\n", node); },
    }
    for child in node.children.iter() {
        result.push_str(&dom_to_string(child.clone(), err_out, width));
    }
    result
}

#[derive(Debug)]
struct TableCell {
    content: Handle,
}

#[derive(Debug)]
struct TableRow {
    cells: Vec<TableCell>,
}

#[derive(Debug)]
struct Table {
    rows: Vec<TableRow>,
}

impl Table {
    pub fn new() -> Table {
        Table{ rows: Vec::new() }
    }
    pub fn push(&mut self, row: TableRow) {
        self.rows.push(row);
    }
    pub fn rows(&self) -> std::slice::Iter<TableRow> {
        self.rows.iter()
    }
}

impl TableRow {
    pub fn new() -> TableRow {
        TableRow{ cells: Vec::new() }
    }
    pub fn push(&mut self, cell: TableCell) {
        self.cells.push(cell);
    }
    pub fn cells(&self) -> std::slice::Iter<TableCell> {
        self.cells.iter()
    }
    pub fn num_cells(&self) -> usize {
        self.cells.len()
    }
}

impl TableCell {
    pub fn new(s: Handle) -> TableCell {
        TableCell{ content: s }
    }
    pub fn render<T:Write>(&self, width: usize, err_out: &mut T) -> String
    {
        dom_to_string(self.content.clone(), err_out, width)
    }
}

fn handle_td(handle: Handle) -> TableCell {
    TableCell::new(handle)
}

fn handle_tr<T:Write>(handle: Handle, err_out: &mut T) -> TableRow {
    let node = handle.borrow();

    let mut row = TableRow::new();

    for child in node.children.iter() {
        match child.borrow().node {
            Element(ref name, _, ref attrs) => {
                match *name {
                    qualname!(html, "td") => {
                        row.push(handle_td(child.clone()));
                    },
                    _ => println!("  [[tr child: {:?}]]", name),
                }
            },
            Comment(_) => {},
            _ => { /*result.push_str(&format!("Unhandled in table: {:?}\n", node));*/ },
        }
    }

    row
}

fn handle_tbody<T:Write>(handle: Handle, err_out: &mut T, width: usize) -> String {
    let node = handle.borrow();

    let mut table = Table::new();

    for child in node.children.iter() {
        match child.borrow().node {
            Element(ref name, _, ref attrs) => {
                match *name {
                    qualname!(html, "tr") => {
                        table.push(handle_tr(child.clone(), err_out));
                    },
                    _ => println!("  [[tbody child: {:?}]]", name),
                }
            },
            Comment(_) => {},
            _ => { /*result.push_str(&format!("Unhandled in table: {:?}\n", node));*/ },
        }
    }

    /* Now lay out the table.  Use the simple option of giving each column
     * same width.  TODO: be cleverer, and handle multi-width cells, etc. */
    let num_columns = table.rows().map(|r| r.num_cells()).max().unwrap();

    // Allow for | between columns.
    let col_width = (width - (num_columns-1))/num_columns;

    let cell_bottom: String = (0..col_width).map(|_| '-').collect::<String>() + "+";
    let rowline: String = (0..num_columns-1).map(|_| &cell_bottom[..]).collect::<String>() + &cell_bottom[..col_width];

    let mut result = String::new();
    result.push('\n');  // Make sure to start on a new line.
    result.push_str(&rowline);
    result.push('\n');

    for row in table.rows() {
        let formatted_cells: Vec<String> = row.cells()
                                              .map(|cell| cell.render(col_width, err_out))
                                              .collect();
        let line_sets: Vec<Vec<&str>> = formatted_cells.iter()
                                                       .map(|s| s.lines()
                                                                 .map(|line| line.trim_right())
                                                                 .collect())
                                                       .collect();
        let cell_height = line_sets.iter()
                                   .map(|v| v.len())
                                   .max().unwrap();
        for i in 0..cell_height {
            for (cellno, ls) in line_sets.iter().enumerate() {
                result.push_str(&format!("{: <width$}", ls.get(i).cloned().unwrap_or(""), width = col_width));
                if cellno == line_sets.len()-1 {
                    result.push('\n')
                } else {
                    result.push('|')
                }
            }
        }
        result.push_str(&rowline);
        result.push('\n');
    }

    result
}

fn table_to_string<T:Write>(handle: Handle, err_out: &mut T, width: usize) -> String {
    let node = handle.borrow();
    let mut result = String::new();

    for child in node.children.iter() {
        match child.borrow().node {
            Element(ref name, _, ref attrs) => {
                match *name {
                    qualname!(html, "tbody") => return handle_tbody(child.clone(), err_out, width),
                    _ => { writeln!(err_out, "  [[table child: {:?}]]", name);},
                }
            },
            Comment(_) => {},
            _ => { /*result.push_str(&format!("Unhandled in table: {:?}\n", node));*/ },
        }
    }

    result
}

pub fn from_read<R>(mut input: R) -> String where R: io::Read {
    let opts = ParseOpts {
        tree_builder: TreeBuilderOpts {
            drop_doctype: true,
            ..Default::default()
        },
        ..Default::default()
    };
    let dom = parse_document(RcDom::default(), opts)
                   .from_utf8()
                   .read_from(&mut input)
                   .unwrap();

    dom_to_string(dom.document, &mut io::stderr(), 80)
}

#[cfg(test)]
mod tests {
}
<|endoftext|>


<commit_before>
extern crate ndarray;
extern crate num_traits;

pub mod lapack_binding;
pub mod error;

use ndarray::prelude::*;
use ndarray::LinalgScalar;
use num_traits::float::Float;
use lapack_binding::LapackScalar;
use error::{LinalgError, NotSquareError};

pub fn norm<A: Float + LinalgScalar>(v: &Array<A, Ix>) -> A {
    let n2 = &v.dot(&v);
    n2.sqrt()
}

pub trait Matrix: Sized {
    type Scalar;
    type Vector;
    /// number of rows and cols
    fn size(&self) -> (usize, usize);
    fn norm_1(&self) -> Self::Scalar;
    fn norm_i(&self) -> Self::Scalar;
    fn norm_f(&self) -> Self::Scalar;
    // fn svd(self) -> (Self, Self::Vector, Self);
}

pub trait SquareMatrix: Matrix {
    // fn qr(self) -> (Self, Self);
    // fn lu(self) -> (Self, Self);
    // fn eig(self) -> (Self::Vector, Self);
    /// eigenvalue decomposition for Hermite matrix
    fn eigh(self) -> Result<(Self::Vector, Self), LinalgError>;
    fn check_square(&self) -> Result<(), NotSquareError> {
        let (rows, cols) = self.size();
        if rows == cols {
            Ok(())
        } else {
            Err(NotSquareError {
                rows: rows,
                cols: cols,
            })
        }
    }
}

impl<A: LapackScalar> Matrix for Array<A, (Ix, Ix)> {
    type Scalar = A;
    type Vector = Array<A, Ix>;
    fn size(&self) -> (usize, usize) {
        (self.rows(), self.cols())
    }
    fn norm_1(&self) -> Self::Scalar {
        let (m, n) = self.size();
        LapackScalar::norm_1(m, n, self.clone().into_raw_vec())
    }
    fn norm_i(&self) -> Self::Scalar {
        let (m, n) = self.size();
        LapackScalar::norm_i(m, n, self.clone().into_raw_vec())
    }
    fn norm_f(&self) -> Self::Scalar {
        let (m, n) = self.size();
        LapackScalar::norm_f(m, n, self.clone().into_raw_vec())
    }
}

impl<A: LapackScalar> SquareMatrix for Array<A, (Ix, Ix)> {
    fn eigh(self) -> Result<(Self::Vector, Self), LinalgError> {
        try!(self.check_square());
        let (rows, cols) = self.size();
        let (w, a) = try!(LapackScalar::eigh(rows, self.into_raw_vec()));
        let ea = Array::from_vec(w);
        let va = Array::from_vec(a).into_shape((rows, cols)).unwrap().reversed_axes();
        Ok((ea, va))
    }
}
<commit_msg>Check stride and switch norm_{1,i}<commit_after>
extern crate ndarray;
extern crate num_traits;

pub mod lapack_binding;
pub mod error;

use ndarray::prelude::*;
use ndarray::LinalgScalar;
use num_traits::float::Float;
use lapack_binding::LapackScalar;
use error::{LinalgError, NotSquareError};

pub fn norm<A: Float + LinalgScalar>(v: &Array<A, Ix>) -> A {
    let n2 = &v.dot(&v);
    n2.sqrt()
}

pub trait Matrix: Sized {
    type Scalar;
    type Vector;
    /// number of rows and cols
    fn size(&self) -> (usize, usize);
    fn norm_1(&self) -> Self::Scalar;
    fn norm_i(&self) -> Self::Scalar;
    fn norm_f(&self) -> Self::Scalar;
    // fn svd(self) -> (Self, Self::Vector, Self);
}

pub trait SquareMatrix: Matrix {
    // fn qr(self) -> (Self, Self);
    // fn lu(self) -> (Self, Self);
    // fn eig(self) -> (Self::Vector, Self);
    /// eigenvalue decomposition for Hermite matrix
    fn eigh(self) -> Result<(Self::Vector, Self), LinalgError>;
    fn check_square(&self) -> Result<(), NotSquareError> {
        let (rows, cols) = self.size();
        if rows == cols {
            Ok(())
        } else {
            Err(NotSquareError {
                rows: rows,
                cols: cols,
            })
        }
    }
}

impl<A: LapackScalar> Matrix for Array<A, (Ix, Ix)> {
    type Scalar = A;
    type Vector = Array<A, Ix>;
    fn size(&self) -> (usize, usize) {
        (self.rows(), self.cols())
    }
    fn norm_1(&self) -> Self::Scalar {
        let (m, n) = self.size();
        let strides = self.strides();
        if strides[0] > strides[1] {
            LapackScalar::norm_i(n, m, self.clone().into_raw_vec())
        } else {
            LapackScalar::norm_1(m, n, self.clone().into_raw_vec())
        }
    }
    fn norm_i(&self) -> Self::Scalar {
        let (m, n) = self.size();
        let strides = self.strides();
        if strides[0] > strides[1] {
            LapackScalar::norm_1(n, m, self.clone().into_raw_vec())
        } else {
            LapackScalar::norm_i(m, n, self.clone().into_raw_vec())
        }
    }
    fn norm_f(&self) -> Self::Scalar {
        let (m, n) = self.size();
        LapackScalar::norm_f(m, n, self.clone().into_raw_vec())
    }
}

impl<A: LapackScalar> SquareMatrix for Array<A, (Ix, Ix)> {
    fn eigh(self) -> Result<(Self::Vector, Self), LinalgError> {
        try!(self.check_square());
        let (rows, cols) = self.size();
        let (w, a) = try!(LapackScalar::eigh(rows, self.into_raw_vec()));
        let ea = Array::from_vec(w);
        let va = Array::from_vec(a).into_shape((rows, cols)).unwrap().reversed_axes();
        Ok((ea, va))
    }
}
<|endoftext|>


<commit_before>//! **Plexus** is a library for 2D and 3D mesh processing.
//!
//! Please note that versions in the `0.0.*` series are experimental and
//! unstable! Use exact version constraints when specifying a dependency to
//! avoid spurious breakage.
#![allow(unknown_lints)] // Allow clippy lints.

extern crate arrayvec;
#[cfg(feature = "geometry-cgmath")]
extern crate cgmath;
extern crate decorum;
#[macro_use]
extern crate derivative;
extern crate either;
#[macro_use]
extern crate failure;
extern crate fnv;
extern crate fool;
#[macro_use]
extern crate itertools;
#[cfg(feature = "geometry-mint")]
extern crate mint;
#[cfg(feature = "geometry-nalgebra")]
extern crate nalgebra;
extern crate num;
extern crate smallvec;
extern crate typenum;

use decorum::Real;
use num::{One, Zero};
use std::fmt::Debug;
use std::ops::Div;

pub mod buffer;
pub mod geometry;
pub mod graph;
pub mod primitive;

// TODO: Documentation comments include static image content from the GitHub
//       repository. This is fragile and difficult to maintain. Use a mechanism
//       provided by rustdoc or doxidize for this instead.

pub mod prelude {
    pub use crate::buffer::{IntoFlatIndex, IntoStructuredIndex};
    pub use crate::geometry::{Duplet, Triplet};
    pub use crate::graph::Selector;
    pub use crate::primitive::decompose::{
        Edges, IntoEdges, IntoSubdivisions, IntoTetrahedrons, IntoTriangles, IntoVertices,
        Subdivide, Tetrahedrons, Triangulate, Vertices,
    };
    pub use crate::primitive::generate::{
        IndicesForNormal, IndicesForPosition, PolygonGenerator, PolygonsWithNormal,
        PolygonsWithPosition, PolygonsWithUvMap, VerticesWithNormal, VerticesWithPosition,
    };
    pub use crate::primitive::index::{CollectWithIndexer, FlatIndexVertices, IndexVertices};
    pub use crate::primitive::{Converged, Map, MapVertices, Zip};
    pub use crate::IteratorExt;
    pub use crate::{FromRawBuffers, FromRawBuffersWithArity};

    pub use Selector::ByIndex;
    pub use Selector::ByKey;
}

pub trait FromRawBuffers<N, G>: Sized {
    type Error: Debug;

    fn from_raw_buffers<I, J>(indices: I, vertices: J) -> Result<Self, Self::Error>
    where
        I: IntoIterator<Item = N>,
        J: IntoIterator<Item = G>;
}

pub trait FromRawBuffersWithArity<N, G>: Sized {
    type Error: Debug;

    fn from_raw_buffers_with_arity<I, J>(
        indices: I,
        vertices: J,
        arity: usize,
    ) -> Result<Self, Self::Error>
    where
        I: IntoIterator<Item = N>,
        J: IntoIterator<Item = G>;
}

/// Extension methods for types implementing `Iterator`.
pub trait IteratorExt: Iterator + Sized {
    /// Provides an iterator over a window of duplets that includes the first
    /// value in the sequence at the beginning and end of the iteration.
    ///
    /// Given a collection with ordered elements `a`, `b`, and `c`, this
    /// iterator yeilds the ordered items `(a, b)`, `(b, c)`, `(c, a)`.
    fn perimeter(self) -> Perimeter<Self>
    where
        Self::Item: Clone;
}

impl<I> IteratorExt for I
where
    I: Iterator,
{
    fn perimeter(self) -> Perimeter<I>
    where
        I::Item: Clone,
    {
        Perimeter::new(self)
    }
}

pub struct Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    input: I,
    first: Option<I::Item>,
    previous: Option<I::Item>,
}

impl<I> Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    fn new(mut input: I) -> Self {
        let first = input.next();
        let previous = first.clone();
        Perimeter {
            input,
            first,
            previous,
        }
    }
}

impl<I> Iterator for Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    type Item = (I::Item, I::Item);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.input.next();
        match (self.previous.clone(), next.or_else(|| self.first.take())) {
            (Some(a), Some(b)) => {
                self.previous = Some(b.clone());
                Some((a, b))
            }
            _ => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}

trait Half {
    fn half() -> Self;
}

impl<T> Half for T
where
    T: Div<T, Output = T> + One + Real + Zero,
{
    fn half() -> Self {
        let one = T::one();
        one / (one + one)
    }
}
<commit_msg>Re-export traits as `_` in the `prelude` module.<commit_after>//! **Plexus** is a library for 2D and 3D mesh processing.
//!
//! Please note that versions in the `0.0.*` series are experimental and
//! unstable! Use exact version constraints when specifying a dependency to
//! avoid spurious breakage.
#![allow(unknown_lints)] // Allow clippy lints.

extern crate arrayvec;
#[cfg(feature = "geometry-cgmath")]
extern crate cgmath;
extern crate decorum;
#[macro_use]
extern crate derivative;
extern crate either;
#[macro_use]
extern crate failure;
extern crate fnv;
extern crate fool;
#[macro_use]
extern crate itertools;
#[cfg(feature = "geometry-mint")]
extern crate mint;
#[cfg(feature = "geometry-nalgebra")]
extern crate nalgebra;
extern crate num;
extern crate smallvec;
extern crate typenum;

use decorum::Real;
use num::{One, Zero};
use std::fmt::Debug;
use std::ops::Div;

pub mod buffer;
pub mod geometry;
pub mod graph;
pub mod primitive;

// TODO: Documentation comments include static image content from the GitHub
//       repository. This is fragile and difficult to maintain. Use a mechanism
//       provided by rustdoc or doxidize for this instead.

pub mod prelude {
    //! Re-exports commonly used types and traits.
    //!
    //! Importing the contents of this module is recommended when working with
    //! generators and iterator expressions, as those operations are expressed
    //! mostly through traits.
    //!
    //! # Traits
    //!
    //! This module re-exports numerous traits. Traits from the `primitive`
    //! module for generating, decomposing, and indexing iterators over
    //! topological data (e.g., `Triangle`, `Quad`, etc.) are re-exported so
    //! that functions in iterator expressions can be used without lengthy
    //! imports.
    //!
    //! Basic traits for (de)constructing `MeshBuffer`s and `MeshGraph`s are
    //! also re-exported. These traits allow mesh types to be constructed from
    //! raw buffers and buffers to be re-indexed.
    //!
    //! # Types
    //!
    //! The `Selector` enum and its variants are re-exported for convenience.
    //! `Selector` is often used when mutating `MeshGraph`s.
    //!
    //! The geometric `Duplet` and `Triplet` types are also re-exported. These
    //! types are emitted by generators and support various conversions.

    pub use crate::buffer::{IntoFlatIndex as _, IntoStructuredIndex as _};
    pub use crate::geometry::{Duplet, Triplet};
    pub use crate::graph::Selector;
    pub use crate::primitive::decompose::{
        Edges as _, IntoEdges as _, IntoSubdivisions as _, IntoTetrahedrons as _,
        IntoTriangles as _, IntoVertices as _, Subdivide as _, Tetrahedrons as _, Triangulate as _,
        Vertices as _,
    };
    pub use crate::primitive::generate::{
        IndicesForNormal as _, IndicesForPosition as _, PolygonGenerator as _,
        PolygonsWithNormal as _, PolygonsWithPosition as _, PolygonsWithUvMap as _,
        VerticesWithNormal as _, VerticesWithPosition as _,
    };
    pub use crate::primitive::index::{
        CollectWithIndexer as _, FlatIndexVertices as _, IndexVertices as _,
    };
    pub use crate::primitive::{Converged as _, Map as _, MapVertices as _, Zip as _};
    pub use crate::IteratorExt as _;
    pub use crate::{FromRawBuffers as _, FromRawBuffersWithArity as _};

    pub use Selector::ByIndex;
    pub use Selector::ByKey;
}

pub trait FromRawBuffers<N, G>: Sized {
    type Error: Debug;

    fn from_raw_buffers<I, J>(indices: I, vertices: J) -> Result<Self, Self::Error>
    where
        I: IntoIterator<Item = N>,
        J: IntoIterator<Item = G>;
}

pub trait FromRawBuffersWithArity<N, G>: Sized {
    type Error: Debug;

    fn from_raw_buffers_with_arity<I, J>(
        indices: I,
        vertices: J,
        arity: usize,
    ) -> Result<Self, Self::Error>
    where
        I: IntoIterator<Item = N>,
        J: IntoIterator<Item = G>;
}

/// Extension methods for types implementing `Iterator`.
pub trait IteratorExt: Iterator + Sized {
    /// Provides an iterator over a window of duplets that includes the first
    /// value in the sequence at the beginning and end of the iteration.
    ///
    /// Given a collection with ordered elements `a`, `b`, and `c`, this
    /// iterator yeilds the ordered items `(a, b)`, `(b, c)`, `(c, a)`.
    fn perimeter(self) -> Perimeter<Self>
    where
        Self::Item: Clone;
}

impl<I> IteratorExt for I
where
    I: Iterator,
{
    fn perimeter(self) -> Perimeter<I>
    where
        I::Item: Clone,
    {
        Perimeter::new(self)
    }
}

pub struct Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    input: I,
    first: Option<I::Item>,
    previous: Option<I::Item>,
}

impl<I> Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    fn new(mut input: I) -> Self {
        let first = input.next();
        let previous = first.clone();
        Perimeter {
            input,
            first,
            previous,
        }
    }
}

impl<I> Iterator for Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    type Item = (I::Item, I::Item);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.input.next();
        match (self.previous.clone(), next.or_else(|| self.first.take())) {
            (Some(a), Some(b)) => {
                self.previous = Some(b.clone());
                Some((a, b))
            }
            _ => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}

trait Half {
    fn half() -> Self;
}

impl<T> Half for T
where
    T: Div<T, Output = T> + One + Real + Zero,
{
    fn half() -> Self {
        let one = T::one();
        one / (one + one)
    }
}
<|endoftext|>


<commit_before>//! # Type safety for the weary netlink user
//!
//! ## Rationale
//!
//! The `libc` crate currently provides an interface for sockets but
//! the constants to configure the socket to do anything useful in netlink
//! are not included in the crate because they live in `/usr/include/linux/netlink.h` and friends.
//! As a result, doing anything with netlink in Rust is currently a bit of a headache.
//!
//! This crate aims to define the necessary constants and wrap them in types to both take
//! advantage of the Rust type system and also avoid the need to pop open `.h` files
//! to find the information necessary to construct netlink messages.
//!
//! ## Notes
//!
//! This crate is currently under heavy development.
//!
//! The `cc` crate is a build dependency to provide as much of a natively cross distribution
//! approach as possible regarding `#define`s in C. It is used to compile a C file that includes
//! the appropriate headers and exports them to the corresponding `stdint.h` types in C.

#![deny(missing_docs)]

extern crate libc;
extern crate byteorder;

/// C constants defined as types
pub mod ffi;
/// Wrapper for `libc` sockets
pub mod socket;
/// Top-level netlink header
pub mod nlhdr;
/// Genetlink (generic netlink) header and attribute helpers
pub mod genlhdr;
/// Error module
pub mod err;

use std::io::{Cursor,Read,Write};
use std::mem;
use std::ffi::CString;

use byteorder::{NativeEndian,ReadBytesExt,WriteBytesExt};

use ffi::alignto;
use err::{SerError,DeError};

/// Struct representing the necessary state to serialize an object
pub struct NlSerState(Cursor<Vec<u8>>, Option<usize>);

impl NlSerState {
    /// Create new serialization state object
    pub fn new() -> Self {
        NlSerState(Cursor::new(Vec::new()), None)
    }

    /// Store length of payload for later use
    pub fn set_usize(&mut self, sz: usize) {
        self.1 = Some(sz);
    }

    /// Get length of payload
    pub fn get_usize(&mut self) -> Option<usize> {
        self.1.take()
    }

    /// Get buffer with serialized representation of consumed struct
    pub fn into_inner(self) -> Vec<u8> {
        self.0.into_inner()
    }
}

/// Struct representing the necessary state to deserialize an object
pub struct NlDeState<'a>(Cursor<&'a [u8]>, Option<usize>);

impl<'a> NlDeState<'a> {
    /// Create new deserialization state object
    pub fn new(s: &'a [u8]) -> Self {
        NlDeState(Cursor::new(s), None)
    }

    /// Store length of payload for later use
    pub fn set_usize(&mut self, sz: usize) {
        self.1 = Some(sz);
    }

    /// Get length of payload
    pub fn get_usize(&mut self) -> Option<usize> {
        self.1.take()
    }
}

/// Trait defining basic actions required for netlink communication
pub trait Nl: Sized + Default {
    /// Serialization method
    fn serialize(&self, &mut NlSerState) -> Result<(), SerError>;
    /// Deserialization method
    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError>;
    /// The size of the binary representation of a struct - not aligned to word size
    fn size(&self) -> usize;
    /// The size of the binary representation of a struct - aligned to word size
    fn asize(&self) -> usize {
        alignto(self.size())
    }
}

impl Nl for u8 {
    fn serialize(&self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_u8(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_u8()))
    }

    fn size(&self) -> usize {
        mem::size_of::<u8>()
    }
}

impl Nl for u16 {
    fn serialize(&self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_u16::<NativeEndian>(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_u16::<NativeEndian>()))
    }

    fn size(&self) -> usize {
        mem::size_of::<u16>()
    }
}

impl Nl for u32 {
    fn serialize(&self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_u32::<NativeEndian>(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_u32::<NativeEndian>()))
    }

    fn size(&self) -> usize {
        mem::size_of::<u32>()
    }
}

impl Nl for i32 {
    fn serialize(&self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_i32::<NativeEndian>(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_i32::<NativeEndian>()))
    }

    fn size(&self) -> usize {
        mem::size_of::<i32>()
    }
}

impl Nl for Vec<u8> {
    fn serialize(&self, state: &mut NlSerState) -> Result<(), SerError> {
        let len = state.get_usize().unwrap_or(self.len());
        let num_bytes = state.0.write(&self)?;
        if len - num_bytes > 0 {
            let padding = vec![0; len - num_bytes];
            state.0.write(&padding)?;
        }
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        let input = state.get_usize().unwrap_or(state.0.get_ref().len());
        let mut v = vec![0; input];
        let num_bytes = state.0.by_ref().take(input as u64).read(&mut v)?;
        if input > num_bytes {
            v.truncate(num_bytes);
        }
        Ok(v)
    }

    fn size(&self) -> usize {
        self.len()
    }
}

impl Nl for String {
    fn serialize(&self, state: &mut NlSerState) -> Result<(), SerError> {
        let c_str = try!(CString::new(self.as_bytes()).map_err(|_| {
            SerError::new("Unable to serialize string containing null byte")
        }));
        let bytes = c_str.as_bytes_with_nul();
        let len = state.get_usize().unwrap_or(bytes.len());
        let num_bytes = state.0.write(bytes)?;
        if len - num_bytes > 0 {
            let padding = vec![0; len - num_bytes];
            state.0.write(&padding)?;
        }
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        let input = state.get_usize().unwrap_or(state.0.get_ref().len());
        let mut v = vec![0; input];
        let num_bytes = state.0.by_ref().take(input as u64).read(&mut v)?;
        if input > num_bytes {
            v.truncate(num_bytes);
        }
        let pos = v.iter().position(|b| *b == 0);
        if let Some(p) = pos {
            v.truncate(p);
        }
        let string = String::from_utf8(v)?;
        Ok(string)
    }

    fn size(&self) -> usize {
        self.len()
    }
}

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

    #[test]
    fn test_nl_u8() {
        let v: u8 = 5;
        let s: &[u8; 1] = &[5];
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(s, state.into_inner().as_slice());

        let s: &[u8; 1] = &[5];
        let mut state = NlDeState::new(s);
        let v = u8::deserialize(&mut state).unwrap();
        assert_eq!(v, 5)
    }

    #[test]
    fn test_nl_u16() {
        let v: u16 = 6000;
        let s: &mut [u8] = &mut [0; 2];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u16::<NativeEndian>(6000).unwrap();
        }
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(s, state.into_inner().as_slice());

        let s: &mut [u8] = &mut [0; 2];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u16::<NativeEndian>(6000).unwrap();
        }
        let mut state = NlDeState::new(&*s);
        let v = u16::deserialize(&mut state).unwrap();
        assert_eq!(v, 6000)
    }

    #[test]
    fn test_nl_u32() {
        let v: u32 = 600000;
        let s: &mut [u8] = &mut [0; 4];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u32::<NativeEndian>(600000).unwrap();
        }
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(s, state.into_inner().as_slice());

        let s: &mut [u8] = &mut [0; 4];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u32::<NativeEndian>(600000).unwrap();
        }
        let mut state = NlDeState::new(&*s);
        let v = u32::deserialize(&mut state).unwrap();
        assert_eq!(v, 600000)
    }

    #[test]
    fn test_nl_vec() {
        let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(vec![1, 2, 3, 4, 5, 6, 7, 8, 9], state.into_inner().as_slice());

        let s = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0];
        let mut state = NlDeState::new(s);
        state.set_usize(s.len() as usize);
        let v = Vec::<u8>::deserialize(&mut state).unwrap();
        assert_eq!(v, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0])
    }

    #[test]
    fn test_nl_string() {
        let s = "AAAAA".to_string();
        let mut state = NlSerState::new();
        s.serialize(&mut state).unwrap();
        assert_eq!(vec![65, 65, 65, 65, 65, 0], state.into_inner().as_slice());

        let s = &[65, 65, 65, 65, 65, 65, 65, 0, 0, 0, 0];
        let mut state = NlDeState::new(s);
        state.set_usize(s.len() as usize);
        let string = String::deserialize(&mut state).unwrap();
        assert_eq!(string, "AAAAAAA".to_string())
    }
}
<commit_msg>Fix Nl::size impl on String<commit_after>//! # Type safety for the weary netlink user
//!
//! ## Rationale
//!
//! The `libc` crate currently provides an interface for sockets but
//! the constants to configure the socket to do anything useful in netlink
//! are not included in the crate because they live in `/usr/include/linux/netlink.h` and friends.
//! As a result, doing anything with netlink in Rust is currently a bit of a headache.
//!
//! This crate aims to define the necessary constants and wrap them in types to both take
//! advantage of the Rust type system and also avoid the need to pop open `.h` files
//! to find the information necessary to construct netlink messages.
//!
//! ## Notes
//!
//! This crate is currently under heavy development.
//!
//! The `cc` crate is a build dependency to provide as much of a natively cross distribution
//! approach as possible regarding `#define`s in C. It is used to compile a C file that includes
//! the appropriate headers and exports them to the corresponding `stdint.h` types in C.

#![deny(missing_docs)]

extern crate libc;
extern crate byteorder;

/// C constants defined as types
pub mod ffi;
/// Wrapper for `libc` sockets
pub mod socket;
/// Top-level netlink header
pub mod nlhdr;
/// Genetlink (generic netlink) header and attribute helpers
pub mod genlhdr;
/// Error module
pub mod err;

use std::io::{Cursor,Read,Write};
use std::mem;
use std::ffi::CString;

use byteorder::{NativeEndian,ReadBytesExt,WriteBytesExt};

use ffi::alignto;
use err::{SerError,DeError};

/// Struct representing the necessary state to serialize an object
pub struct NlSerState(Cursor<Vec<u8>>, Option<usize>);

impl NlSerState {
    /// Create new serialization state object
    pub fn new() -> Self {
        NlSerState(Cursor::new(Vec::new()), None)
    }

    /// Store length of payload for later use
    pub fn set_usize(&mut self, sz: usize) {
        self.1 = Some(sz);
    }

    /// Get length of payload
    pub fn get_usize(&mut self) -> Option<usize> {
        self.1.take()
    }

    /// Get buffer with serialized representation of consumed struct
    pub fn into_inner(self) -> Vec<u8> {
        self.0.into_inner()
    }
}

/// Struct representing the necessary state to deserialize an object
pub struct NlDeState<'a>(Cursor<&'a [u8]>, Option<usize>);

impl<'a> NlDeState<'a> {
    /// Create new deserialization state object
    pub fn new(s: &'a [u8]) -> Self {
        NlDeState(Cursor::new(s), None)
    }

    /// Store length of payload for later use
    pub fn set_usize(&mut self, sz: usize) {
        self.1 = Some(sz);
    }

    /// Get length of payload
    pub fn get_usize(&mut self) -> Option<usize> {
        self.1.take()
    }
}

/// Trait defining basic actions required for netlink communication
pub trait Nl: Sized + Default {
    /// Serialization method
    fn serialize(&self, &mut NlSerState) -> Result<(), SerError>;
    /// Deserialization method
    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError>;
    /// The size of the binary representation of a struct - not aligned to word size
    fn size(&self) -> usize;
    /// The size of the binary representation of a struct - aligned to word size
    fn asize(&self) -> usize {
        alignto(self.size())
    }
}

impl Nl for u8 {
    fn serialize(&self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_u8(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_u8()))
    }

    fn size(&self) -> usize {
        mem::size_of::<u8>()
    }
}

impl Nl for u16 {
    fn serialize(&self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_u16::<NativeEndian>(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_u16::<NativeEndian>()))
    }

    fn size(&self) -> usize {
        mem::size_of::<u16>()
    }
}

impl Nl for u32 {
    fn serialize(&self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_u32::<NativeEndian>(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_u32::<NativeEndian>()))
    }

    fn size(&self) -> usize {
        mem::size_of::<u32>()
    }
}

impl Nl for i32 {
    fn serialize(&self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_i32::<NativeEndian>(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_i32::<NativeEndian>()))
    }

    fn size(&self) -> usize {
        mem::size_of::<i32>()
    }
}

impl Nl for Vec<u8> {
    fn serialize(&self, state: &mut NlSerState) -> Result<(), SerError> {
        let len = state.get_usize().unwrap_or(self.len());
        let num_bytes = state.0.write(&self)?;
        if len - num_bytes > 0 {
            let padding = vec![0; len - num_bytes];
            state.0.write(&padding)?;
        }
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        let input = state.get_usize().unwrap_or(state.0.get_ref().len());
        let mut v = vec![0; input];
        let num_bytes = state.0.by_ref().take(input as u64).read(&mut v)?;
        if input > num_bytes {
            v.truncate(num_bytes);
        }
        Ok(v)
    }

    fn size(&self) -> usize {
        self.len()
    }
}

impl Nl for String {
    fn serialize(&self, state: &mut NlSerState) -> Result<(), SerError> {
        let c_str = try!(CString::new(self.as_bytes()).map_err(|_| {
            SerError::new("Unable to serialize string containing null byte")
        }));
        let bytes = c_str.as_bytes_with_nul();
        let len = state.get_usize().unwrap_or(bytes.len());
        let num_bytes = state.0.write(bytes)?;
        if len - num_bytes > 0 {
            let padding = vec![0; len - num_bytes];
            state.0.write(&padding)?;
        }
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        let input = state.get_usize().unwrap_or(state.0.get_ref().len());
        let mut v = vec![0; input];
        let num_bytes = state.0.by_ref().take(input as u64).read(&mut v)?;
        if input > num_bytes {
            v.truncate(num_bytes);
        }
        let pos = v.iter().position(|b| *b == 0);
        if let Some(p) = pos {
            v.truncate(p);
        }
        let string = String::from_utf8(v)?;
        Ok(string)
    }

    fn size(&self) -> usize {
        self.len() + 1
    }
}

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

    #[test]
    fn test_nl_u8() {
        let v: u8 = 5;
        let s: &[u8; 1] = &[5];
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(s, state.into_inner().as_slice());

        let s: &[u8; 1] = &[5];
        let mut state = NlDeState::new(s);
        let v = u8::deserialize(&mut state).unwrap();
        assert_eq!(v, 5)
    }

    #[test]
    fn test_nl_u16() {
        let v: u16 = 6000;
        let s: &mut [u8] = &mut [0; 2];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u16::<NativeEndian>(6000).unwrap();
        }
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(s, state.into_inner().as_slice());

        let s: &mut [u8] = &mut [0; 2];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u16::<NativeEndian>(6000).unwrap();
        }
        let mut state = NlDeState::new(&*s);
        let v = u16::deserialize(&mut state).unwrap();
        assert_eq!(v, 6000)
    }

    #[test]
    fn test_nl_u32() {
        let v: u32 = 600000;
        let s: &mut [u8] = &mut [0; 4];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u32::<NativeEndian>(600000).unwrap();
        }
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(s, state.into_inner().as_slice());

        let s: &mut [u8] = &mut [0; 4];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u32::<NativeEndian>(600000).unwrap();
        }
        let mut state = NlDeState::new(&*s);
        let v = u32::deserialize(&mut state).unwrap();
        assert_eq!(v, 600000)
    }

    #[test]
    fn test_nl_vec() {
        let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(vec![1, 2, 3, 4, 5, 6, 7, 8, 9], state.into_inner().as_slice());

        let s = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0];
        let mut state = NlDeState::new(s);
        state.set_usize(s.len() as usize);
        let v = Vec::<u8>::deserialize(&mut state).unwrap();
        assert_eq!(v, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0])
    }

    #[test]
    fn test_nl_string() {
        let s = "AAAAA".to_string();
        let mut state = NlSerState::new();
        s.serialize(&mut state).unwrap();
        let serialized = state.into_inner();
        assert_eq!(vec![65, 65, 65, 65, 65, 0], serialized.as_slice());
        assert_eq!(Nl::size(&s), serialized.len());

        let s = &[65, 65, 65, 65, 65, 65, 65, 0, 0, 0, 0];
        let mut state = NlDeState::new(s);
        state.set_usize(s.len() as usize);
        let string = String::deserialize(&mut state).unwrap();
        assert_eq!(string, "AAAAAAA".to_string())
    }
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]

include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

#[cfg(test)]
mod tests {
    use super::*;
    use std::path::Path;
    use std::ffi::CString;

    #[test]
    fn it_works() {
        println!("Bindings file is {}", concat!(env!("OUT_DIR"), "/bindings.rs"));

        println!("Libsixel version is {:?}", super::LIBSIXEL_VERSION);
    }

    fn image_root<'a>() -> &'a Path {
        Path::new("libsixel/images/")
    }

    fn snake_of(extension: &str) -> CString {
        let snake_path = image_root()
            .join("snake")
            .with_extension(extension);

        let snake_path = snake_path.to_str().unwrap();

        CString::new(snake_path).unwrap()
    }

    /// Just make sure that it works
    #[test]
    fn convert_snake() {
        round_trip_with_ext("bmp");
        round_trip_with_ext("gif");
        round_trip_with_ext("pbm");
        round_trip_with_ext("pgm");
        round_trip_with_ext("ppm");
        round_trip_with_ext("tga");
        round_trip_with_ext("tiff");

        #[cfg(jpeg)]
        round_trip_with_ext("jpg");
        #[cfg(png)]
        round_trip_with_ext("png");
    }

    fn round_trip_with_ext(extension: &str) {
        use std::ptr;
        use std::os::raw::c_int;
        use std::os::raw::c_uint;
        println!("encoding with {}", extension);

        let assert_ok = |actual: SIXELSTATUS| {
            assert_eq!(SIXEL_OK,
                       actual as c_uint,
                       "when de/encoding snake from a {} file, sixel returned the status {} instead of ok",
                       extension,
                       actual);
        };

        let snake_sixel = "snake_test.six";
        let snake_new = "snake_test.".to_string() + extension;
        let snake_six_out = CString::new(snake_sixel).unwrap();
        let snake_new_out = CString::new(snake_new).unwrap();

        unsafe {
            let mut encoder: *mut sixel_encoder_t = ptr::null_mut() as *mut _;

            let result = sixel_encoder_new(&mut encoder,
                                           ptr::null_mut() as *mut sixel_allocator_t);
            assert_ok(result);

            let result = sixel_encoder_setopt(encoder,
                                              SIXEL_OPTFLAG_OUTFILE as c_int,
                                              snake_six_out.as_ptr());
            assert_ok(result);

            let snake_path = snake_of(extension);

            let result = sixel_encoder_encode(encoder, snake_path.as_ptr());
            assert_ok(result);

            sixel_encoder_unref(encoder);
        }

        unsafe {
            let mut decoder: *mut sixel_decoder_t = ptr::null_mut() as *mut _;

            let result = sixel_decoder_new(&mut decoder,
                                           ptr::null_mut() as *mut sixel_allocator_t);
            assert_ok(result);

            let result = sixel_decoder_setopt(decoder,
                                              SIXEL_OPTFLAG_INPUT as c_int,
                                              snake_six_out.as_ptr());
            assert_ok(result);

            let result = sixel_decoder_setopt(decoder,
                                              SIXEL_OPTFLAG_OUTFILE as c_int,
                                              snake_new_out.as_ptr());
            assert_ok(result);

            let result = sixel_decoder_decode(decoder);
            assert_ok(result);

            sixel_decoder_unref(decoder);
        }
    }
}
<commit_msg>Added top-level doc<commit_after>//! Bindings to libsixel
//!
//! For additional information, please check [its repo](https://github.com/saitoha/libsixel)

#![allow(non_camel_case_types)]

include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

#[cfg(test)]
mod tests {
    use super::*;
    use std::path::Path;
    use std::ffi::CString;

    #[test]
    fn it_works() {
        println!("Bindings file is {}", concat!(env!("OUT_DIR"), "/bindings.rs"));

        println!("Libsixel version is {:?}", super::LIBSIXEL_VERSION);
    }

    fn image_root<'a>() -> &'a Path {
        Path::new("libsixel/images/")
    }

    fn snake_of(extension: &str) -> CString {
        let snake_path = image_root()
            .join("snake")
            .with_extension(extension);

        let snake_path = snake_path.to_str().unwrap();

        CString::new(snake_path).unwrap()
    }

    /// Just make sure that it works
    #[test]
    fn convert_snake() {
        round_trip_with_ext("bmp");
        round_trip_with_ext("gif");
        round_trip_with_ext("pbm");
        round_trip_with_ext("pgm");
        round_trip_with_ext("ppm");
        round_trip_with_ext("tga");
        round_trip_with_ext("tiff");

        #[cfg(jpeg)]
        round_trip_with_ext("jpg");
        #[cfg(png)]
        round_trip_with_ext("png");
    }

    fn round_trip_with_ext(extension: &str) {
        use std::ptr;
        use std::os::raw::c_int;
        use std::os::raw::c_uint;
        println!("encoding with {}", extension);

        let assert_ok = |actual: SIXELSTATUS| {
            assert_eq!(SIXEL_OK,
                       actual as c_uint,
                       "when de/encoding snake from a {} file, sixel returned the status {} instead of ok",
                       extension,
                       actual);
        };

        let snake_sixel = "snake_test.six";
        let snake_new = "snake_test.".to_string() + extension;
        let snake_six_out = CString::new(snake_sixel).unwrap();
        let snake_new_out = CString::new(snake_new).unwrap();

        unsafe {
            let mut encoder: *mut sixel_encoder_t = ptr::null_mut() as *mut _;

            let result = sixel_encoder_new(&mut encoder,
                                           ptr::null_mut() as *mut sixel_allocator_t);
            assert_ok(result);

            let result = sixel_encoder_setopt(encoder,
                                              SIXEL_OPTFLAG_OUTFILE as c_int,
                                              snake_six_out.as_ptr());
            assert_ok(result);

            let snake_path = snake_of(extension);

            let result = sixel_encoder_encode(encoder, snake_path.as_ptr());
            assert_ok(result);

            sixel_encoder_unref(encoder);
        }

        unsafe {
            let mut decoder: *mut sixel_decoder_t = ptr::null_mut() as *mut _;

            let result = sixel_decoder_new(&mut decoder,
                                           ptr::null_mut() as *mut sixel_allocator_t);
            assert_ok(result);

            let result = sixel_decoder_setopt(decoder,
                                              SIXEL_OPTFLAG_INPUT as c_int,
                                              snake_six_out.as_ptr());
            assert_ok(result);

            let result = sixel_decoder_setopt(decoder,
                                              SIXEL_OPTFLAG_OUTFILE as c_int,
                                              snake_new_out.as_ptr());
            assert_ok(result);

            let result = sixel_decoder_decode(decoder);
            assert_ok(result);

            sixel_decoder_unref(decoder);
        }
    }
}
<|endoftext|>


<commit_before>//! Demoscene framework.
//!
//! # Foreword
//!
//! This framework is intented to be used to build up [demos](https://en.wikipedia.org/wiki/Demoscene)
//! as a primary purpose. Everything was designed to quickly write demoscene effects and edit them
//! into an audiovisual executable. However, because a lot was added – especially for debugging
//! purposes, it *should* be possible to use this framework for other purposes as well – among
//! *simulations*, *animations* and *video games*.
//!
//! # Design
//!
//! This framework was designed to be *simple* and *flexible*. Following that path, it’s not
//! impossible that some of its features get moved out of the framework to become a set of
//! dependencies – so that people who don’t want those features can just preclude them from the
//! compilation chain.
//!
//! Up to now, the framework provides you with several modules:
//!
//! - **audio**: this module gives you the ability to play a soundtrack (no streaming implemented
//!   yet though; the whole soundtrack is loaded into memory) and interact with basic yet useful
//!   information about playback (play, pause, toggle, track length, track cursor, etc.)
//! - **bootstrapping**: this module abstracts over the underlying technologies and provides several
//!   simple types that can be used to interact with the demo, such as initialization, default
//!   event handling, and so on
//! - **camera**: provides some camera features for both release and debugging purposes
//! - **color**: color types
//! - **edit**: everything you need to edit your demo – it provides types and functions to reason
//!   about timelines, tracks, cuts and clips, hence easing the overall making of a demo
//! - **gui**: this module provides some GUI code that you can use to build nice debugging
//!   interfaces – up to now, it’s not designed for release code, but it might be at some time
//! - **linear**: linear algebra
//! - **model**: this module provides all the code required to abstract other meshes and add them
//!   the concept of *materials*
//! - **object**: linked to **models**, this module adds the concept of *space properties* to
//!   *models* – so that you can actually have them in your scenes
//! - **overlay**: this module provides 2D primitives and rendering functions
//! - **projection**: projection trait and functions
//! - **shader**: provides
//! - **extra**: some extra (but not mandatory) other modules

#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(macro_reexport)]
#![feature(slice_patterns)]

extern crate alto;
extern crate any_cache;
extern crate cgmath;
extern crate chrono;
#[macro_reexport(crate_authors, crate_name, crate_version)]
extern crate clap;
extern crate image;
pub extern crate luminance;
extern crate luminance_glfw;
extern crate glsl;
#[macro_use]
extern crate nom;
extern crate num_traits;
//extern crate rusttype; // FIXME: uncomment when we support text render back
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate vorbis;
extern crate wavefront_obj;
extern crate warmy;

#[macro_use]
pub mod report;
#[macro_use]
pub mod sys;

pub mod audio;
//pub mod gui;
pub mod linear;
//pub mod overlay;
//pub mod text;

pub mod anim;
pub mod render;
pub mod scene;
<commit_msg>Re-export macros from luminance.<commit_after>//! Demoscene framework.
//!
//! # Foreword
//!
//! This framework is intented to be used to build up [demos](https://en.wikipedia.org/wiki/Demoscene)
//! as a primary purpose. Everything was designed to quickly write demoscene effects and edit them
//! into an audiovisual executable. However, because a lot was added – especially for debugging
//! purposes, it *should* be possible to use this framework for other purposes as well – among
//! *simulations*, *animations* and *video games*.
//!
//! # Design
//!
//! This framework was designed to be *simple* and *flexible*. Following that path, it’s not
//! impossible that some of its features get moved out of the framework to become a set of
//! dependencies – so that people who don’t want those features can just preclude them from the
//! compilation chain.
//!
//! Up to now, the framework provides you with several modules:
//!
//! - **audio**: this module gives you the ability to play a soundtrack (no streaming implemented
//!   yet though; the whole soundtrack is loaded into memory) and interact with basic yet useful
//!   information about playback (play, pause, toggle, track length, track cursor, etc.)
//! - **bootstrapping**: this module abstracts over the underlying technologies and provides several
//!   simple types that can be used to interact with the demo, such as initialization, default
//!   event handling, and so on
//! - **camera**: provides some camera features for both release and debugging purposes
//! - **color**: color types
//! - **edit**: everything you need to edit your demo – it provides types and functions to reason
//!   about timelines, tracks, cuts and clips, hence easing the overall making of a demo
//! - **gui**: this module provides some GUI code that you can use to build nice debugging
//!   interfaces – up to now, it’s not designed for release code, but it might be at some time
//! - **linear**: linear algebra
//! - **model**: this module provides all the code required to abstract other meshes and add them
//!   the concept of *materials*
//! - **object**: linked to **models**, this module adds the concept of *space properties* to
//!   *models* – so that you can actually have them in your scenes
//! - **overlay**: this module provides 2D primitives and rendering functions
//! - **projection**: projection trait and functions
//! - **shader**: provides
//! - **extra**: some extra (but not mandatory) other modules

#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(macro_reexport)]
#![feature(slice_patterns)]

extern crate alto;
extern crate any_cache;
extern crate cgmath;
extern crate chrono;
#[macro_reexport(crate_authors, crate_name, crate_version)]
extern crate clap;
extern crate image;
#[macro_reexport(gtup, uniform_interface)]
pub extern crate luminance;
extern crate luminance_glfw;
extern crate glsl;
#[macro_use]
extern crate nom;
extern crate num_traits;
//extern crate rusttype; // FIXME: uncomment when we support text render back
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate vorbis;
extern crate wavefront_obj;
extern crate warmy;

#[macro_use]
pub mod report;
#[macro_use]
pub mod sys;

pub mod audio;
//pub mod gui;
pub mod linear;
//pub mod overlay;
//pub mod text;

pub mod anim;
pub mod render;
pub mod scene;
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Abstraction of a thread pool for basic parallelism.

#![cfg_attr(feature = "scoped-pool", feature(scoped))]

#[cfg(feature = "scoped-pool")]
use std::mem;
use std::sync::mpsc::{channel, Sender, Receiver};
use std::sync::{Arc, Mutex};
use std::thread;
#[cfg(feature = "scoped-pool")]
use std::thread::JoinGuard;

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Thunk<'a> = Box<FnBox + Send + 'a>;

struct Sentinel<'a> {
    jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
    active: bool
}

impl<'a> Sentinel<'a> {
    fn new(jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>) -> Sentinel<'a> {
        Sentinel {
            jobs: jobs,
            active: true
        }
    }

    // Cancel and destroy this sentinel.
    fn cancel(mut self) {
        self.active = false;
    }
}

impl<'a> Drop for Sentinel<'a> {
    fn drop(&mut self) {
        if self.active {
            spawn_in_pool(self.jobs.clone())
        }
    }
}

/// A thread pool used to execute functions in parallel.
///
/// Spawns `n` worker threads and replenishes the pool if any worker threads
/// panic.
///
/// # Example
///
/// ```rust
/// use threadpool::ThreadPool;
/// use std::sync::mpsc::channel;
///
/// let pool = ThreadPool::new(4);
///
/// let (tx, rx) = channel();
/// for i in 0..8 {
///     let tx = tx.clone();
///     pool.execute(move|| {
///         tx.send(i).unwrap();
///     });
/// }
///
/// assert_eq!(rx.iter().take(8).fold(0, |a, b| a + b), 28);
/// ```
pub struct ThreadPool {
    // How the threadpool communicates with subthreads.
    //
    // This is the only such Sender, so when it is dropped all subthreads will
    // quit.
    jobs: Sender<Thunk<'static>>
}

impl ThreadPool {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: usize) -> ThreadPool {
        assert!(threads >= 1);

        let (tx, rx) = channel::<Thunk<'static>>();
        let rx = Arc::new(Mutex::new(rx));

        // Threadpool threads
        for _ in 0..threads {
            spawn_in_pool(rx.clone());
        }

        ThreadPool { jobs: tx }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F : FnOnce() + Send + 'static
    {
        self.jobs.send(Box::new(move || job())).unwrap();
    }
}

fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk<'static>>>>) {
    thread::spawn(move || {
        // Will spawn a new thread on panic unless it is cancelled.
        let sentinel = Sentinel::new(&jobs);

        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The Threadpool was dropped.
                Err(..) => break
            }
        }

        sentinel.cancel();
    });
}

/// A scoped thread pool used to execute functions in parallel.
///
/// `ScopedPool` is different from `ThreadPool` in that:
///
/// * When dropped, it propagates panics that occur in the worker threads.
/// * It doesn't require the `'static` bound on the functions that are executed.
/// * Worker threads are joined when the `ScopedPool` is dropped.
///
/// # Example
///
/// ```rust
/// use threadpool::ScopedPool;
///
/// let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
///
/// // We need an extra scope to shorten the lifetime of the pool
/// {
///     let pool = ScopedPool::new(4);
///     for x in &mut numbers[..] {
///         pool.execute(move|| {
///             *x += 1;
///         });
///     }
/// }
///
/// assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
/// ```
#[cfg(feature = "scoped-pool")]
pub struct ScopedPool<'pool> {
    sender: Option<Sender<Thunk<'pool>>>,
    _guards: Vec<JoinGuard<'pool, ()>>
}

#[cfg(feature = "scoped-pool")]
impl<'pool> ScopedPool<'pool> {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: u32) -> ScopedPool<'pool> {
        assert!(threads >= 1);

        let (sender, receiver) = channel();
        let receiver = Arc::new(Mutex::new(receiver));

        let mut guards = Vec::with_capacity(threads as usize);
        for _ in 0..threads {
            guards.push(spawn_scoped_in_pool(receiver.clone()));
        }

        ScopedPool { sender: Some(sender), _guards: guards }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F: FnOnce() + Send + 'pool
    {
        self.sender.as_ref().unwrap().send(Box::new(job)).unwrap();
    }
}

#[cfg(feature = "scoped-pool")]
impl<'a> Drop for ScopedPool<'a> {
    fn drop(&mut self) {
        // We need to ensure that the sender is dropped before the JoinGuards
        // Otherwise the threads will be joined and wait forever in the loop
        mem::replace(&mut self.sender, None);
    }
}

#[cfg(feature = "scoped-pool")]
fn spawn_scoped_in_pool<'a>(jobs: Arc<Mutex<Receiver<Thunk<'a>>>>) -> JoinGuard<'a, ()>
{
    thread::scoped(move || {
        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The pool was dropped.
                Err(..) => break
            }
        }
    })
}

#[cfg(test)]
mod test {
    use super::ThreadPool;
    use std::sync::mpsc::channel;
    use std::sync::{Arc, Barrier};

    const TEST_TASKS: usize = 4;

    #[test]
    fn test_works() {
        let pool = ThreadPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    #[should_panic]
    fn test_zero_tasks_panic() {
        ThreadPool::new(0);
    }

    #[test]
    fn test_recovery_from_subtask_panic() {
        let pool = ThreadPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }

        // Ensure new threads were spawned to compensate.
        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() {

        let pool = ThreadPool::new(TEST_TASKS);
        let waiter = Arc::new(Barrier::new(TEST_TASKS + 1));

        // Panic all the existing threads in a bit.
        for _ in 0..TEST_TASKS {
            let waiter = waiter.clone();
            pool.execute(move|| {
                waiter.wait();
                panic!();
            });
        }

        drop(pool);

        // Kick off the failure.
        waiter.wait();
    }
}

#[cfg(all(test, feature = "scoped-pool"))]
mod test_scoped {
    use super::ScopedPool;
    use std::sync::mpsc::channel;

    const TEST_TASKS: u32 = 4;

    #[test]
    fn test_works_1() {
        let pool = ScopedPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS as usize).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_works_2() {
        let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        {
            let pool = ScopedPool::new(TEST_TASKS);
            for x in numbers.iter_mut() {
                pool.execute(move || {
                    *x += 1;
                });
            }
        }
        assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
    }

    #[test]
    #[should_panic]
    fn test_zero_tasks_panic() {
        ScopedPool::new(0);
    }

    #[test]
    #[should_panic]
    fn test_panic_propagation() {
        let pool = ScopedPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }
    }
}
<commit_msg>update ScopedPool::new arguments<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Abstraction of a thread pool for basic parallelism.

#![cfg_attr(feature = "scoped-pool", feature(scoped))]

#[cfg(feature = "scoped-pool")]
use std::mem;
use std::sync::mpsc::{channel, Sender, Receiver};
use std::sync::{Arc, Mutex};
use std::thread;
#[cfg(feature = "scoped-pool")]
use std::thread::JoinGuard;

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Thunk<'a> = Box<FnBox + Send + 'a>;

struct Sentinel<'a> {
    jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
    active: bool
}

impl<'a> Sentinel<'a> {
    fn new(jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>) -> Sentinel<'a> {
        Sentinel {
            jobs: jobs,
            active: true
        }
    }

    // Cancel and destroy this sentinel.
    fn cancel(mut self) {
        self.active = false;
    }
}

impl<'a> Drop for Sentinel<'a> {
    fn drop(&mut self) {
        if self.active {
            spawn_in_pool(self.jobs.clone())
        }
    }
}

/// A thread pool used to execute functions in parallel.
///
/// Spawns `n` worker threads and replenishes the pool if any worker threads
/// panic.
///
/// # Example
///
/// ```rust
/// use threadpool::ThreadPool;
/// use std::sync::mpsc::channel;
///
/// let pool = ThreadPool::new(4);
///
/// let (tx, rx) = channel();
/// for i in 0..8 {
///     let tx = tx.clone();
///     pool.execute(move|| {
///         tx.send(i).unwrap();
///     });
/// }
///
/// assert_eq!(rx.iter().take(8).fold(0, |a, b| a + b), 28);
/// ```
pub struct ThreadPool {
    // How the threadpool communicates with subthreads.
    //
    // This is the only such Sender, so when it is dropped all subthreads will
    // quit.
    jobs: Sender<Thunk<'static>>
}

impl ThreadPool {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: usize) -> ThreadPool {
        assert!(threads >= 1);

        let (tx, rx) = channel::<Thunk<'static>>();
        let rx = Arc::new(Mutex::new(rx));

        // Threadpool threads
        for _ in 0..threads {
            spawn_in_pool(rx.clone());
        }

        ThreadPool { jobs: tx }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F : FnOnce() + Send + 'static
    {
        self.jobs.send(Box::new(move || job())).unwrap();
    }
}

fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk<'static>>>>) {
    thread::spawn(move || {
        // Will spawn a new thread on panic unless it is cancelled.
        let sentinel = Sentinel::new(&jobs);

        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The Threadpool was dropped.
                Err(..) => break
            }
        }

        sentinel.cancel();
    });
}

/// A scoped thread pool used to execute functions in parallel.
///
/// `ScopedPool` is different from `ThreadPool` in that:
///
/// * When dropped, it propagates panics that occur in the worker threads.
/// * It doesn't require the `'static` bound on the functions that are executed.
/// * Worker threads are joined when the `ScopedPool` is dropped.
///
/// # Example
///
/// ```rust
/// use threadpool::ScopedPool;
///
/// let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
///
/// // We need an extra scope to shorten the lifetime of the pool
/// {
///     let pool = ScopedPool::new(4);
///     for x in &mut numbers[..] {
///         pool.execute(move|| {
///             *x += 1;
///         });
///     }
/// }
///
/// assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
/// ```
#[cfg(feature = "scoped-pool")]
pub struct ScopedPool<'pool> {
    sender: Option<Sender<Thunk<'pool>>>,
    _guards: Vec<JoinGuard<'pool, ()>>
}

#[cfg(feature = "scoped-pool")]
impl<'pool> ScopedPool<'pool> {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: usize) -> ScopedPool<'pool> {
        assert!(threads >= 1);

        let (sender, receiver) = channel();
        let receiver = Arc::new(Mutex::new(receiver));

        let mut guards = Vec::with_capacity(threads);
        for _ in 0..threads {
            guards.push(spawn_scoped_in_pool(receiver.clone()));
        }

        ScopedPool { sender: Some(sender), _guards: guards }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F: FnOnce() + Send + 'pool
    {
        self.sender.as_ref().unwrap().send(Box::new(job)).unwrap();
    }
}

#[cfg(feature = "scoped-pool")]
impl<'a> Drop for ScopedPool<'a> {
    fn drop(&mut self) {
        // We need to ensure that the sender is dropped before the JoinGuards
        // Otherwise the threads will be joined and wait forever in the loop
        mem::replace(&mut self.sender, None);
    }
}

#[cfg(feature = "scoped-pool")]
fn spawn_scoped_in_pool<'a>(jobs: Arc<Mutex<Receiver<Thunk<'a>>>>) -> JoinGuard<'a, ()>
{
    thread::scoped(move || {
        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The pool was dropped.
                Err(..) => break
            }
        }
    })
}

#[cfg(test)]
mod test {
    use super::ThreadPool;
    use std::sync::mpsc::channel;
    use std::sync::{Arc, Barrier};

    const TEST_TASKS: usize = 4;

    #[test]
    fn test_works() {
        let pool = ThreadPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    #[should_panic]
    fn test_zero_tasks_panic() {
        ThreadPool::new(0);
    }

    #[test]
    fn test_recovery_from_subtask_panic() {
        let pool = ThreadPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }

        // Ensure new threads were spawned to compensate.
        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() {

        let pool = ThreadPool::new(TEST_TASKS);
        let waiter = Arc::new(Barrier::new(TEST_TASKS + 1));

        // Panic all the existing threads in a bit.
        for _ in 0..TEST_TASKS {
            let waiter = waiter.clone();
            pool.execute(move|| {
                waiter.wait();
                panic!();
            });
        }

        drop(pool);

        // Kick off the failure.
        waiter.wait();
    }
}

#[cfg(all(test, feature = "scoped-pool"))]
mod test_scoped {
    use super::ScopedPool;
    use std::sync::mpsc::channel;

    const TEST_TASKS: usize = 4;

    #[test]
    fn test_works_1() {
        let pool = ScopedPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_works_2() {
        let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        {
            let pool = ScopedPool::new(TEST_TASKS);
            for x in numbers.iter_mut() {
                pool.execute(move || {
                    *x += 1;
                });
            }
        }
        assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
    }

    #[test]
    #[should_panic]
    fn test_zero_tasks_panic() {
        ScopedPool::new(0);
    }

    #[test]
    #[should_panic]
    fn test_panic_propagation() {
        let pool = ScopedPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code, unused_variables)]
#![feature(unboxed_closures, phase)]
#![experimental]

//! # Handlebars
//! Handlebars is a modern and extensible templating solution originally created in the JavaScript world. It's used by many popular frameworks like [Ember.js](http://emberjs.com) and Chaplin. It's also ported to some other platforms such as [Java](https://github.com/jknack/handlebars.java).
//!
//! And this is handlebars Rust implementation, designed for server-side page generation. It's a general-purpose library so you use it for any kind of text generation.
//!
//! ## Handlebars spec
//!
//! ### Base
//!
//! You can go to [Handlebars.js](http://handlebarsjs.com/) website for its syntax. This implementation should be compatible with most parts of the spec, except:
//!
//! * raw helper syntax `{{{raw-helper}}}...{{{/raw-helper}}}` is implemented as block helper raw.
//! * type inference in hashes (on my TODO list)
//! * configurable logging (hard-coded to rust native logging, with fixed level `INFO`)
//!
//! ### Extensions
//!
//! We have template reuse facilities support via built-in helpers `>`, `partial` and `block`.
//!
//! There are two ways to reuse a template:
//!
//! * include (using `<`)
//! * inheritance (using `<` together with `block` and `partial`)
//!
//! Consult [Handlebar.java document about template inheritance](http://jknack.github.io/handlebars.java/reuse.html).
//!
//! ## Usage
//!
//! ### Template Creation
//!
//! Templates are created from String.
//!
//! ```
//! extern crate handlebars;
//!
//! use handlebars::Template;
//!
//! fn main() {
//!   let source = "hello {{world}}";
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   let tpl = Template::compile(source.to_string).unwrap();
//! }
//! ```
//!
//! ### Registration
//!
//! All the templates and helpers have to be registered into Registry, so they can look up each other by name.
//!
//! ```
//! extern crate handlebars;
//!
//! use handlebars::{Template, Registry};
//!
//! fn main() {
//!   let source = "hello {{world}}";
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   let tpl = Template::compile(source.to_string).unwrap();
//!
//!   let mut handlebars = Registry::new();
//!   handlebars.register_template("hello_world", &tpl);
//! }
//! ```
//!
//! ### Rendering Something
//!
//! I should say that rendering is a little tricky. Since handlebars is originally a JavaScript templating framework. It supports dynamic features like duck-typing, truthy/falsy values. But for a static language like Rust, this is a little difficult. As a solution, I'm using the `serialize::json::Json` internally for data rendering, which seems good by far.
//!
//! That means, if you want to render something, you have to ensure that it implements the `serialize::json::ToJson` trait. Luckily, most built-in types already have trait. However, if you want to render your custom struct, you need to implement this trait manually. (Rust has a deriving facility, but it's just for selected types. Maybe I will add some syntax extensions or macros to simplify this process.)
//!
//! ```
//! extern crate handlebars;
//!
//! use serialize::json::ToJson;
//! use std.collections::BTreeMap;
//!
//! use handlebars::{Template, Registry};
//!
//! fn main() {
//!   let source = "hello {{world}}";
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   let tpl = Template::compile(source.to_string).unwrap();
//!
//!   let mut handlebars = Registry::new();
//!   handlebars.register_template("hello_world", &tpl);
//!
//!   let mut data = BTreeMap::new();
//!   data.insert("world", "world".to_json());
//!   let result = handlebars.render("hello_world", &data);
//! }
//! ```
//!
//! ### Custom Helper
//!
//! Handlebars is nothing without helpers. You can also create your own helpers with rust. Helpers in handlebars-rust are custom struct implements the `HelperDef` trait, concretely, the `resolve` function.
//!
//! ```
//! extern crate handlebars;
//!
//! use handlebars::{Registry, HelperDef, RenderError, RenderContext, Helper, Context};
//!
//! #[deriving(Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn resolve(&self, c: &Context, h: &Helper, _: &Registry, rc: &mut RenderContext) -> Result<String, RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     Ok(format!("My helper dumps: {} ", value))
//!   }
//! }
//!
//! // create an instance
//! static MY_HELPER: SimpleHelper = SimpleHelper;
//!
//! fn main() {
//!   let mut handlebars = Registry::new();
//!   handlebars.register_helper("simple-helper", box MY_HELPER);
//!
//!   //...
//! }
//! ```
//!
//! You can learn more about helpers by looking into source code of built-in helpers.
//!
//! ## TODO
//!
//! * More friendly ToJson
//! * Type inference in helper hash
//! * Better error report
//!

extern crate serialize;
extern crate regex;
#[phase(plugin)]
extern crate regex_macros;

#[phase(plugin, link)]
extern crate log;

pub use self::template::{Template, Helper};
pub use self::registry::{Registry};
pub use self::render::{Renderable, RenderError, RenderContext};
pub use self::helpers::{HelperDef};
pub use self::context::{Context, JsonRender, JsonTruthy};

mod template;
mod registry;
mod render;
mod helpers;
mod context;
<commit_msg>docup.<commit_after>#![allow(dead_code, unused_variables)]
#![feature(unboxed_closures, phase)]
#![experimental]

//! # Handlebars
//! Handlebars is a modern and extensible templating solution originally created in the JavaScript world. It's used by many popular frameworks like [Ember.js](http://emberjs.com) and Chaplin. It's also ported to some other platforms such as [Java](https://github.com/jknack/handlebars.java).
//!
//! And this is handlebars Rust implementation, designed for server-side page generation. It's a general-purpose library so you use it for any kind of text generation.
//!
//! ## Handlebars spec
//!
//! ### Base
//!
//! You can go to [Handlebars.js](http://handlebarsjs.com/) website for its syntax. This implementation should be compatible with most parts of the spec, except:
//!
//! * raw helper syntax `{{{raw-helper}}}...{{{/raw-helper}}}` is implemented as block helper raw.
//! * configurable logging (hard-coded to rust native logging, with fixed level `INFO`)
//!
//! ### Extensions
//!
//! We have template reuse facilities support via built-in helpers `>`, `partial` and `block`.
//!
//! There are two ways to reuse a template:
//!
//! * include (using `<`)
//! * inheritance (using `<` together with `block` and `partial`)
//!
//! Consult [Handlebar.java document about template inheritance](http://jknack.github.io/handlebars.java/reuse.html).
//!
//! ## Usage
//!
//! ### Template Creation
//!
//! Templates are created from String.
//!
//! ```
//! extern crate handlebars;
//!
//! use handlebars::Template;
//!
//! fn main() {
//!   let source = "hello {{world}}";
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   let tpl = Template::compile(source.to_string).unwrap();
//! }
//! ```
//!
//! ### Registration
//!
//! All the templates and helpers have to be registered into Registry, so they can look up each other by name.
//!
//! ```
//! extern crate handlebars;
//!
//! use handlebars::{Template, Registry};
//!
//! fn main() {
//!   let source = "hello {{world}}";
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   let tpl = Template::compile(source.to_string).unwrap();
//!
//!   let mut handlebars = Registry::new();
//!   handlebars.register_template("hello_world", &tpl);
//! }
//! ```
//!
//! ### Rendering Something
//!
//! I should say that rendering is a little tricky. Since handlebars is originally a JavaScript templating framework. It supports dynamic features like duck-typing, truthy/falsy values. But for a static language like Rust, this is a little difficult. As a solution, I'm using the `serialize::json::Json` internally for data rendering, which seems good by far.
//!
//! That means, if you want to render something, you have to ensure that it implements the `serialize::json::ToJson` trait. Luckily, most built-in types already have trait. However, if you want to render your custom struct, you need to implement this trait manually. (Rust has a deriving facility, but it's just for selected types. Maybe I will add some syntax extensions or macros to simplify this process.)
//!
//! ```
//! extern crate handlebars;
//!
//! use serialize::json::ToJson;
//! use std.collections::BTreeMap;
//!
//! use handlebars::{Template, Registry};
//!
//! fn main() {
//!   let source = "hello {{world}}";
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   let tpl = Template::compile(source.to_string).unwrap();
//!
//!   let mut handlebars = Registry::new();
//!   handlebars.register_template("hello_world", &tpl);
//!
//!   let mut data = BTreeMap::new();
//!   data.insert("world", "world".to_json());
//!   let result = handlebars.render("hello_world", &data);
//! }
//! ```
//!
//! ### Custom Helper
//!
//! Handlebars is nothing without helpers. You can also create your own helpers with rust. Helpers in handlebars-rust are custom struct implements the `HelperDef` trait, concretely, the `resolve` function.
//!
//! ```
//! extern crate handlebars;
//!
//! use handlebars::{Registry, HelperDef, RenderError, RenderContext, Helper, Context};
//!
//! #[deriving(Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn resolve(&self, c: &Context, h: &Helper, _: &Registry, rc: &mut RenderContext) -> Result<String, RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     Ok(format!("My helper dumps: {} ", value))
//!   }
//! }
//!
//! // create an instance
//! static MY_HELPER: SimpleHelper = SimpleHelper;
//!
//! fn main() {
//!   let mut handlebars = Registry::new();
//!   handlebars.register_helper("simple-helper", box MY_HELPER);
//!
//!   //...
//! }
//! ```
//!
//! You can get data from the `Helper` argument about the template information:
//!
//! * `name()` for the helper name. This is known to you for most situation but if you are defining `helperMissing` or `blockHelperMissing`, this is important.
//! * `params()` is a vector of String as params in helper, like `{{#somehelper param1 param2 param3}}`.
//! * `hash()` is a map of String key and Json value, defined in helper as `{{@somehelper a=1 b="2" c=true}}`.
//! * `template()` gives you the nested template of block helper.
//! * `inverse()` gives you the inversed template of it, inversed template is the template behind `{{else}}`.
//!
//! You can learn more about helpers by looking into source code of built-in helpers.
//!
//! ## TODO
//!
//! * More friendly ToJson
//! * Better error report
//!

extern crate serialize;
extern crate regex;
#[phase(plugin)]
extern crate regex_macros;

#[phase(plugin, link)]
extern crate log;

pub use self::template::{Template, Helper};
pub use self::registry::{Registry};
pub use self::render::{Renderable, RenderError, RenderContext};
pub use self::helpers::{HelperDef};
pub use self::context::{Context, JsonRender, JsonTruthy};

mod template;
mod registry;
mod render;
mod helpers;
mod context;
<|endoftext|>