<commit_before>use std::ops::{Mul, Add};

/// Structure for computing the B-spline with the given control points
/// and knots.
pub struct BSpline<T: Mul<f32, Output = T> + Add<Output = T> + Copy> {
    /// Degree of the polynomial that we use to make the curve segments
    degree: usize,
    /// Control points for the curve
    control_points: Vec<T>,
    /// TODO: What is a good description for the knots?
    knots: Vec<f32>,
}

impl<T: Mul<f32, Output = T> + Add<Output = T> + Copy> BSpline<T> {
    /// Create a new B-spline curve of the desired degree that will blend between
    /// the passed control points using the knots. The knots should be sorted in ascending
    /// order, otherwise they will be sorted for you which may lead to undesired knots
    /// for control points
    pub fn new(degree: usize, control_points: Vec<T>, mut knots: Vec<f32>) -> BSpline<T> {
        if control_points.len() < degree {
            panic!("Too few control points for curve");
        }
        knots.sort_by(|a, b| a.partial_cmp(b).unwrap());
        BSpline { degree: degree, control_points: control_points, knots: knots }
    }
    /// Compute a point on the curve at `t`
    /// TODO: Handling of out of bounds t values? Are t values not in the domain considered
    /// out of range? The extra `degree` values are just for when we're going down the tree
    /// to find the interpolated values there right?
    pub fn point(&self, t: f32) -> T {
        // Find the first index with a knot value greater than the t we're searching for. We want
        // to find i such that: knot[i] <= t < knot[i + 1]
        let (mut i, _) = self.knots.iter().take_while(|&x| !(*x > t)).enumerate().last().unwrap();
        i = i + 1;
        if i == self.knots.len() {
            i = self.knots.len() - self.degree - 1;
        } else if i == 0 {
            i = self.degree;
        }
        /*
        let i = match upper_bounds(&self.knots[self.degree - 1..self.knots.len() - self.degree], t) {
            Some(x) => x,
            None => self.knots.len() - self.degree - 1,
        };
        */
        println!("Found i = {} for t = {}\n\tknots = {:?}", i, t, self.knots);
        println!("degree = {}", self.degree);
        self.de_boors(t, self.degree, i)
    }
    /// Recursively compute de Boor's B-spline algorithm. TODO: This is terrible,
    /// compute it iteratively! Recursive version is just for a simple formualation
    /// of the initial implementation.
    fn de_boors(&self, t: f32, k: usize, i: usize) -> T {
        if k == 0 {
            println!("Returning control point {}", i);
            self.control_points[i - 1]
        } else {
            println!("Looking at k = {}, i = {}, t = {}", k, i, t);
            println!("\tknots[i + self.degree - k] = {}, self.knots[i - 1] = {}",
                     self.knots[i + self.degree - k], self.knots[i - 1]);
            // TODO: This is still broken
            let alpha = (t - self.knots[i - 1]) / (self.knots[i + self.degree - k] - self.knots[i - 1]);
            self.de_boors(t, k - 1, i - 1) * (1.0 - alpha) + self.de_boors(t, k - 1, i) * alpha
        }
    }
}

/// Return the index of the first element greater than the value passed.
/// The data **must** be sorted.
/// If no element greater than the value passed is found the function returns None.
fn upper_bounds(data: &[f32], value: f32) -> Option<usize> {
    let mut first = 0usize;
    let mut step;
    let mut count = data.len() as isize;
    while count > 0 {
        step = count / 2;
        let it = first + step as usize;
        if !value.lt(&data[it]) {
            first = it + 1;
            count -= step + 1;
        } else {
            count = step;
        }
    }
    // If we didn't find an element greater than value
    if first == data.len() {
        None
    } else {
        Some(first)
    }
}

#[cfg(test)]
mod test {
    use std::ops::{Mul, Add};
    use std::iter;

    use super::BSpline;

    #[derive(Copy, Clone, Debug)]
    struct Point {
        x: f32,
        y: f32,
    }
    impl Point {
        fn new(x: f32, y: f32) -> Point {
            Point { x: x, y: y }
        }
    }
    impl Mul<f32> for Point {
        type Output = Point;
        fn mul(self, rhs: f32) -> Point {
            Point { x: self.x * rhs, y: self.y * rhs }
        }
    }
    impl Add for Point {
        type Output = Point;
        fn add(self, rhs: Point) -> Point {
            Point { x: self.x + rhs.x, y: self.y + rhs.y }
        }
    }

    #[derive(Copy, Clone, Debug)]
    struct Pointi {
        x: i32,
        y: i32,
    }
    impl Pointi {
        fn new(x: i32, y: i32) -> Pointi {
            Pointi { x: x, y: y }
        }
    }
    impl Mul<f32> for Pointi {
        type Output = Pointi;
        fn mul(self, rhs: f32) -> Pointi {
            Pointi { x: (self.x as f32 * rhs) as i32,
                    y: (self.y as f32 * rhs) as i32 }
        }
    }
    impl Add for Pointi {
        type Output = Pointi;
        fn add(self, rhs: Pointi) -> Pointi {
            Pointi { x: self.x + rhs.x, y: self.y + rhs.y }
        }
    }

    //#[test]
    fn linear_bspline(){
        let points = vec![Point::new(-1.0, 0.0), Point::new(0.0, 1.0),
                          Point::new(1.0, 1.0), Point::new(1.0, 2.0)];
        let knots = vec![0.0, 0.0, 1.0, 2.0, 3.0, 3.0];
        let spline = BSpline::new(1, points, knots);
        let x = spline.point(1.5);
        println!("spline(1.5) = {:?}", x);
        assert!(x.x == 0.5 && x.y == 1.0);
    }

    //#[test]
    fn quadratic_bspline(){
        let points = vec![Point::new(-2.0, 0.0), Point::new(0.0, 2.0),
                          Point::new(2.0, 0.0), Point::new(0.0, -2.0)];
        let knots = vec![0.0, 0.0, 0.0, 1.0, 2.0, 2.0, 2.0];
        let spline = BSpline::new(3, points, knots);
        let x = spline.point(1.5);
        println!("spline(1.5) = {:?}", x);
        assert!(x.x == 1.25 && x.y == -0.25);
    }

    //#[test]
    fn bspline_plot(){
        let points = vec![Pointi::new(0, 5), Pointi::new(10, 20),
                          Pointi::new(30, 20), Pointi::new(39, 5)];
        let knots = vec![0.0, 0.0, 0.1, 1.0, 1.9, 2.0, 2.0];

        // TODO: This doesn't compute or plot the correct curve
        let plot_w = 80;
        let plot_h = 50;
        let mut plot: Vec<_> = iter::repeat(' ').take(plot_w * plot_h).collect();

        let t_start = knots[2];
        let t_end = knots[4];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(2, points.clone(), knots);

        let steps = 20;
        let step_size = (t_end - t_start) / steps as f32;
        for s in 0..steps {
            let t = step_size * s as f32 + t_start;
            println!("t = {}", t);
            let x = spline.point(t);
            println!("x = {:?}", x);
            if x.x > -1 && x.x < plot_w as i32 && x.y > -1 && x.y < plot_h as i32 {
                plot[(plot_h - 1 - x.y as usize) * plot_w + x.x as usize] = 'X';
            }
        }
        for i in 0..points.len() {
            let symbol = match i {
                x if x == 0 => 'S',
                x if x == points.len() - 1 => 'E',
                _ => 'C',
            };
            plot[(plot_h - 1 - points[i].y as usize) * plot_w + points[i].x as usize] = symbol;
        }

        for y in 0..plot_h {
            for x in 0..plot_w {
                print!("{}", plot[y * plot_w + x]);
            }
            println!("");
        }
    }

    #[test]
    fn bspline_plot1d() {
        let points = vec![0.0, 0.0, 1.0, 0.0, 0.0];
        let knots = vec![0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0];
        let t_start = knots[2];
        let t_end = knots[5];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(2, points, knots);
        let t = 0.5;
        println!("spline({}) = {}", t, spline.point(t));
    }
}

<commit_msg>More testing with some wikipedia examples, this may actually be working!<commit_after>use std::ops::{Mul, Add};

/// Structure for computing the B-spline with the given control points
/// and knots.
pub struct BSpline<T: Mul<f32, Output = T> + Add<Output = T> + Copy> {
    /// Degree of the polynomial that we use to make the curve segments
    degree: usize,
    /// Control points for the curve
    control_points: Vec<T>,
    /// TODO: What is a good description for the knots?
    knots: Vec<f32>,
}

impl<T: Mul<f32, Output = T> + Add<Output = T> + Copy> BSpline<T> {
    /// Create a new B-spline curve of the desired degree that will blend between
    /// the passed control points using the knots. The knots should be sorted in ascending
    /// order, otherwise they will be sorted for you which may lead to undesired knots
    /// for control points
    pub fn new(degree: usize, control_points: Vec<T>, mut knots: Vec<f32>) -> BSpline<T> {
        if control_points.len() < degree {
            panic!("Too few control points for curve");
        }
        knots.sort_by(|a, b| a.partial_cmp(b).unwrap());
        BSpline { degree: degree, control_points: control_points, knots: knots }
    }
    /// Compute a point on the curve at `t`
    /// TODO: Handling of out of bounds t values? Are t values not in the domain considered
    /// out of range? The extra `degree` values are just for when we're going down the tree
    /// to find the interpolated values there right?
    pub fn point(&self, t: f32) -> T {
        // Find the first index with a knot value greater than the t we're searching for. We want
        // to find i such that: knot[i] <= t < knot[i + 1]
        let (mut i, _) = self.knots.iter().take_while(|&x| !(*x > t)).enumerate().last().unwrap();
        i = i + 1;
        if i == self.knots.len() {
            i = self.knots.len() - self.degree - 1;
        } else if i == 0 {
            i = self.degree;
        }
        /*
        let i = match upper_bounds(&self.knots[self.degree - 1..self.knots.len() - self.degree], t) {
            Some(x) => x,
            None => self.knots.len() - self.degree - 1,
        };
        */
        println!("Found i = {} for t = {}\n\tknots = {:?}", i, t, self.knots);
        println!("degree = {}", self.degree);
        self.de_boors(t, self.degree, i)
    }
    /// Recursively compute de Boor's B-spline algorithm. TODO: This is terrible,
    /// compute it iteratively! Recursive version is just for a simple formualation
    /// of the initial implementation.
    fn de_boors(&self, t: f32, k: usize, i: usize) -> T {
        if k == 0 {
            println!("Returning control point {}", i);
            self.control_points[i - 1]
        } else {
            println!("Looking at k = {}, i = {}, t = {}", k, i, t);
            println!("\tknots[i + self.degree - k] = {}, self.knots[i - 1] = {}",
                     self.knots[i + self.degree - k], self.knots[i - 1]);
            // TODO: This is still broken
            let alpha = (t - self.knots[i - 1]) / (self.knots[i + self.degree - k] - self.knots[i - 1]);
            self.de_boors(t, k - 1, i - 1) * (1.0 - alpha) + self.de_boors(t, k - 1, i) * alpha
        }
    }
}

/// Return the index of the first element greater than the value passed.
/// The data **must** be sorted.
/// If no element greater than the value passed is found the function returns None.
fn upper_bounds(data: &[f32], value: f32) -> Option<usize> {
    let mut first = 0usize;
    let mut step;
    let mut count = data.len() as isize;
    while count > 0 {
        step = count / 2;
        let it = first + step as usize;
        if !value.lt(&data[it]) {
            first = it + 1;
            count -= step + 1;
        } else {
            count = step;
        }
    }
    // If we didn't find an element greater than value
    if first == data.len() {
        None
    } else {
        Some(first)
    }
}

#[cfg(test)]
mod test {
    use std::ops::{Mul, Add};
    use std::iter;

    use super::BSpline;

    #[derive(Copy, Clone, Debug)]
    struct Point {
        x: f32,
        y: f32,
    }
    impl Point {
        fn new(x: f32, y: f32) -> Point {
            Point { x: x, y: y }
        }
    }
    impl Mul<f32> for Point {
        type Output = Point;
        fn mul(self, rhs: f32) -> Point {
            Point { x: self.x * rhs, y: self.y * rhs }
        }
    }
    impl Add for Point {
        type Output = Point;
        fn add(self, rhs: Point) -> Point {
            Point { x: self.x + rhs.x, y: self.y + rhs.y }
        }
    }

    #[derive(Copy, Clone, Debug)]
    struct Pointi {
        x: i32,
        y: i32,
    }
    impl Pointi {
        fn new(x: i32, y: i32) -> Pointi {
            Pointi { x: x, y: y }
        }
    }
    impl Mul<f32> for Pointi {
        type Output = Pointi;
        fn mul(self, rhs: f32) -> Pointi {
            Pointi { x: (self.x as f32 * rhs) as i32,
                    y: (self.y as f32 * rhs) as i32 }
        }
    }
    impl Add for Pointi {
        type Output = Pointi;
        fn add(self, rhs: Pointi) -> Pointi {
            Pointi { x: self.x + rhs.x, y: self.y + rhs.y }
        }
    }

    //#[test]
    fn linear_bspline(){
        let points = vec![Point::new(-1.0, 0.0), Point::new(0.0, 1.0),
                          Point::new(1.0, 1.0), Point::new(1.0, 2.0)];
        let knots = vec![0.0, 0.0, 1.0, 2.0, 3.0, 3.0];
        let spline = BSpline::new(1, points, knots);
        let x = spline.point(1.5);
        println!("spline(1.5) = {:?}", x);
        assert!(x.x == 0.5 && x.y == 1.0);
    }
    //#[test]
    fn quadratic_bspline(){
        let points = vec![Point::new(-2.0, 0.0), Point::new(0.0, 2.0),
                          Point::new(2.0, 0.0), Point::new(0.0, -2.0)];
        let knots = vec![0.0, 0.0, 0.0, 1.0, 2.0, 2.0, 2.0];
        let spline = BSpline::new(3, points, knots);
        let x = spline.point(1.5);
        println!("spline(1.5) = {:?}", x);
        assert!(x.x == 1.25 && x.y == -0.25);
    }
    //#[test]
    fn bspline_plot(){
        let points = vec![Pointi::new(0, 5), Pointi::new(10, 20),
                          Pointi::new(30, 20), Pointi::new(39, 5)];
        let knots = vec![0.0, 0.0, 0.1, 1.0, 1.9, 2.0, 2.0];

        // TODO: This doesn't compute or plot the correct curve
        let plot_w = 80;
        let plot_h = 50;
        let mut plot: Vec<_> = iter::repeat(' ').take(plot_w * plot_h).collect();

        let t_start = knots[2];
        let t_end = knots[4];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(2, points.clone(), knots);

        let steps = 20;
        let step_size = (t_end - t_start) / steps as f32;
        for s in 0..steps {
            let t = step_size * s as f32 + t_start;
            println!("t = {}", t);
            let x = spline.point(t);
            println!("x = {:?}", x);
            if x.x > -1 && x.x < plot_w as i32 && x.y > -1 && x.y < plot_h as i32 {
                plot[(plot_h - 1 - x.y as usize) * plot_w + x.x as usize] = 'X';
            }
        }
        for i in 0..points.len() {
            let symbol = match i {
                x if x == 0 => 'S',
                x if x == points.len() - 1 => 'E',
                _ => 'C',
            };
            plot[(plot_h - 1 - points[i].y as usize) * plot_w + points[i].x as usize] = symbol;
        }

        for y in 0..plot_h {
            for x in 0..plot_w {
                print!("{}", plot[y * plot_w + x]);
            }
            println!("");
        }
    }
    //#[test]
    fn quadratic_bspline_plot1d() {
        let points = vec![0.0, 0.0, 1.0, 0.0, 0.0];
        let knots = vec![0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0];
        let t_start = knots[0];
        let t_end = knots[knots.len() - 1];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(2, points, knots);
        let t = 0.5;
        println!("spline({}) = {}", t, spline.point(t));
    }
    //#[test]
    fn cubic_bspline_plot1d() {
        let points = vec![0.0, 0.0, 0.0, 6.0, 0.0, 0.0, 0.0];
        let knots = vec![-2.0, -2.0, -2.0, -2.0, -1.0, 0.0, 1.0, 2.0, 2.0, 2.0, 2.0];
        let t_start = knots[0];
        let t_end = knots[knots.len() - 1];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(3, points, knots);
        let t = 0.5;
        println!("spline({}) = {}", t, spline.point(t));
    }
    #[test]
    fn quartic_bspline_plot1d() {
        let points = vec![0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0];
        let knots = vec![0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0];
        let t_start = knots[0];
        let t_end = knots[knots.len() - 1];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(4, points, knots);
        let t = 3.5;
        println!("spline({}) = {}", t, spline.point(t));
    }
}

<|endoftext|>


<commit_before>//! Open URLs in the web browsers available on a platform.
//!
//! Inspired by the [webbrowser](https://docs.python.org/2/library/webbrowser.html) python library.
//!
//! ## Examples
//!
//! ```no_run
//! use webbrowser;
//!
//! if webbrowser::open("http://github.com").is_ok() {
//!     // ...
//! }
//! ```
//!
//! ## Platform Support Status
//!
//! | Platform | Supported | Browsers | Test status |
//! |----------|-----------|----------|-------------|
//! | macos    | ✅        | default + [others](https://docs.rs/webbrowser/latest/webbrowser/enum.Browser.html) | ✅ |
//! | windows  | ✅        | default only | ✅ |
//! | linux/*bsd  | ✅     | default only (respects $BROWSER env var, so can be used with other browsers) | ✅ |
//! | android  | ✅        | default only | ✅ |
//! | wasm     | ✅        | default only | ✅ |
//! | haiku    | ✅ (experimental) | default only | ❌ |
//! | ios      | ❌        | unsupported | ❌ |
//!
//! ## Consistent Behaviour
//! `webbrowser` defines consistent behaviour on all platforms as follows:
//! * **Non-Blocking** for GUI based browsers (e.g. Firefox, Chrome etc.), while **Blocking** for text based browser (e.g. lynx etc.)
//! * **Suppressed output** by default for GUI based browsers, so that their stdout/stderr don't pollute the main program's output. This can be overridden by `webbrowser::open_browser_with_options`.

#[cfg_attr(target_os = "macos", path = "macos.rs")]
#[cfg_attr(target_os = "android", path = "android.rs")]
#[cfg_attr(target_arch = "wasm32", path = "wasm.rs")]
#[cfg_attr(windows, path = "windows.rs")]
#[cfg_attr(
    any(
        target_os = "linux",
        target_os = "freebsd",
        target_os = "netbsd",
        target_os = "openbsd",
        target_os = "haiku"
    ),
    path = "unix.rs"
)]
mod os;

#[cfg(not(any(
    target_os = "android",
    target_os = "windows",
    target_os = "macos",
    target_os = "linux",
    target_os = "freebsd",
    target_os = "netbsd",
    target_os = "openbsd",
    target_os = "haiku",
    target_arch = "wasm32"
)))]
compile_error!("Only Windows, Mac OS, Linux, *BSD and Haiku and Wasm32 are currently supported");

use std::default::Default;
use std::io::{Error, ErrorKind, Result};
use std::str::FromStr;
use std::{error, fmt};

#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
/// Browser types available
pub enum Browser {
    ///Operating system's default browser
    Default,

    ///Mozilla Firefox
    Firefox,

    ///Microsoft's Internet Explorer
    InternetExplorer,

    ///Google Chrome
    Chrome,

    ///Opera
    Opera,

    ///Mac OS Safari
    Safari,

    ///Haiku's WebPositive
    WebPositive,
}

///The Error type for parsing a string into a Browser.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
pub struct ParseBrowserError;

impl fmt::Display for ParseBrowserError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("Invalid browser given")
    }
}

impl error::Error for ParseBrowserError {
    fn description(&self) -> &str {
        "invalid browser"
    }
}

impl Default for Browser {
    fn default() -> Self {
        Browser::Default
    }
}

impl fmt::Display for Browser {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Browser::Default => f.write_str("Default"),
            Browser::Firefox => f.write_str("Firefox"),
            Browser::InternetExplorer => f.write_str("Internet Explorer"),
            Browser::Chrome => f.write_str("Chrome"),
            Browser::Opera => f.write_str("Opera"),
            Browser::Safari => f.write_str("Safari"),
            Browser::WebPositive => f.write_str("WebPositive"),
        }
    }
}

impl FromStr for Browser {
    type Err = ParseBrowserError;

    fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
        match s {
            "firefox" => Ok(Browser::Firefox),
            "default" => Ok(Browser::Default),
            "ie" | "internet explorer" | "internetexplorer" => Ok(Browser::InternetExplorer),
            "chrome" => Ok(Browser::Chrome),
            "opera" => Ok(Browser::Opera),
            "safari" => Ok(Browser::Safari),
            "webpositive" => Ok(Browser::WebPositive),
            _ => Err(ParseBrowserError),
        }
    }
}

#[derive(Debug, Eq, PartialEq, Clone, Hash)]
/// BrowserOptions to override certain default behaviour
///
/// e.g. by default, we suppress stdout/stderr, but that behaviour can be overridden here
pub struct BrowserOptions {
    pub suppress_output: bool,
    pub target_hint: String,
}

impl fmt::Display for BrowserOptions {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_fmt(format_args!(
            "BrowserOptions(supress_output={})",
            self.suppress_output
        ))
    }
}

impl std::default::Default for BrowserOptions {
    fn default() -> Self {
        BrowserOptions {
            suppress_output: true,
            target_hint: String::from("_blank"),
        }
    }
}

/// Opens the URL on the default browser of this platform
///
/// Returns Ok(..) so long as the browser invocation was successful. An Err(..) is returned only if
/// there was an error in running the command, or if the browser was not found.
///
/// Equivalent to:
/// ```no_run
/// # use webbrowser::{Browser, open_browser};
/// # let url = "http://example.com";
/// open_browser(Browser::Default, url);
/// ```
///
/// # Examples
/// ```no_run
/// use webbrowser;
///
/// if webbrowser::open("http://github.com").is_ok() {
///     // ...
/// }
/// ```
pub fn open(url: &str) -> Result<()> {
    open_browser(Browser::Default, url)
}

/// Opens the specified URL on the specific browser (if available) requested. Return semantics are
/// the same as for [open](fn.open.html).
///
/// # Examples
/// ```no_run
/// use webbrowser::{open_browser, Browser};
///
/// if open_browser(Browser::Firefox, "http://github.com").is_ok() {
///     // ...
/// }
/// ```
pub fn open_browser(browser: Browser, url: &str) -> Result<()> {
    open_browser_with_options(browser, url, &BrowserOptions::default())
}

/// Opens the specified URL on the specific browser (if available) requested, while overriding the
/// default options.
///
/// Return semantics are
/// the same as for [open](fn.open.html).
///
/// # Examples
/// ```no_run
/// use webbrowser::{open_browser_with_options, Browser, BrowserOptions};
///
/// if open_browser_with_options(Browser::Default, "http://github.com", &BrowserOptions { suppress_output: false }).is_ok() {
///     // ...
/// }
/// ```
pub fn open_browser_with_options(
    browser: Browser,
    url: &str,
    options: &BrowserOptions,
) -> Result<()> {
    let url_s: String = match url::Url::parse(url) {
        Ok(u) => u.as_str().into(),
        Err(_) => url.into(),
    };
    os::open_browser_internal(browser, &url_s, options)
}

#[test]
#[ignore]
fn test_open_firefox() {
    assert!(open_browser(Browser::Firefox, "http://github.com").is_ok());
}

#[test]
#[ignore]
fn test_open_chrome() {
    assert!(open_browser(Browser::Chrome, "http://github.com").is_ok());
}

#[test]
#[ignore]
fn test_open_safari() {
    assert!(open_browser(Browser::Safari, "http://github.com").is_ok());
}

#[test]
#[ignore]
fn test_open_webpositive() {
    assert!(open_browser(Browser::WebPositive, "http://github.com").is_ok());
}
<commit_msg>use builder pattern, fix default target & display impl<commit_after>//! Open URLs in the web browsers available on a platform.
//!
//! Inspired by the [webbrowser](https://docs.python.org/2/library/webbrowser.html) python library.
//!
//! ## Examples
//!
//! ```no_run
//! use webbrowser;
//!
//! if webbrowser::open("http://github.com").is_ok() {
//!     // ...
//! }
//! ```
//!
//! ## Platform Support Status
//!
//! | Platform | Supported | Browsers | Test status |
//! |----------|-----------|----------|-------------|
//! | macos    | ✅        | default + [others](https://docs.rs/webbrowser/latest/webbrowser/enum.Browser.html) | ✅ |
//! | windows  | ✅        | default only | ✅ |
//! | linux/*bsd  | ✅     | default only (respects $BROWSER env var, so can be used with other browsers) | ✅ |
//! | android  | ✅        | default only | ✅ |
//! | wasm     | ✅        | default only | ✅ |
//! | haiku    | ✅ (experimental) | default only | ❌ |
//! | ios      | ❌        | unsupported | ❌ |
//!
//! ## Consistent Behaviour
//! `webbrowser` defines consistent behaviour on all platforms as follows:
//! * **Non-Blocking** for GUI based browsers (e.g. Firefox, Chrome etc.), while **Blocking** for text based browser (e.g. lynx etc.)
//! * **Suppressed output** by default for GUI based browsers, so that their stdout/stderr don't pollute the main program's output. This can be overridden by `webbrowser::open_browser_with_options`.

#[cfg_attr(target_os = "macos", path = "macos.rs")]
#[cfg_attr(target_os = "android", path = "android.rs")]
#[cfg_attr(target_arch = "wasm32", path = "wasm.rs")]
#[cfg_attr(windows, path = "windows.rs")]
#[cfg_attr(
    any(
        target_os = "linux",
        target_os = "freebsd",
        target_os = "netbsd",
        target_os = "openbsd",
        target_os = "haiku"
    ),
    path = "unix.rs"
)]
mod os;

#[cfg(not(any(
    target_os = "android",
    target_os = "windows",
    target_os = "macos",
    target_os = "linux",
    target_os = "freebsd",
    target_os = "netbsd",
    target_os = "openbsd",
    target_os = "haiku",
    target_arch = "wasm32"
)))]
compile_error!("Only Windows, Mac OS, Linux, *BSD and Haiku and Wasm32 are currently supported");

use std::default::Default;
use std::io::{Error, ErrorKind, Result};
use std::str::FromStr;
use std::{error, fmt};

#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
/// Browser types available
pub enum Browser {
    ///Operating system's default browser
    Default,

    ///Mozilla Firefox
    Firefox,

    ///Microsoft's Internet Explorer
    InternetExplorer,

    ///Google Chrome
    Chrome,

    ///Opera
    Opera,

    ///Mac OS Safari
    Safari,

    ///Haiku's WebPositive
    WebPositive,
}

///The Error type for parsing a string into a Browser.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
pub struct ParseBrowserError;

impl fmt::Display for ParseBrowserError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("Invalid browser given")
    }
}

impl error::Error for ParseBrowserError {
    fn description(&self) -> &str {
        "invalid browser"
    }
}

impl Default for Browser {
    fn default() -> Self {
        Browser::Default
    }
}

impl fmt::Display for Browser {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Browser::Default => f.write_str("Default"),
            Browser::Firefox => f.write_str("Firefox"),
            Browser::InternetExplorer => f.write_str("Internet Explorer"),
            Browser::Chrome => f.write_str("Chrome"),
            Browser::Opera => f.write_str("Opera"),
            Browser::Safari => f.write_str("Safari"),
            Browser::WebPositive => f.write_str("WebPositive"),
        }
    }
}

impl FromStr for Browser {
    type Err = ParseBrowserError;

    fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
        match s {
            "firefox" => Ok(Browser::Firefox),
            "default" => Ok(Browser::Default),
            "ie" | "internet explorer" | "internetexplorer" => Ok(Browser::InternetExplorer),
            "chrome" => Ok(Browser::Chrome),
            "opera" => Ok(Browser::Opera),
            "safari" => Ok(Browser::Safari),
            "webpositive" => Ok(Browser::WebPositive),
            _ => Err(ParseBrowserError),
        }
    }
}

#[derive(Debug, Eq, PartialEq, Clone, Hash)]
/// BrowserOptions to override certain default behaviour
///
/// e.g. by default, we suppress stdout/stderr, but that behaviour can be overridden here
pub struct BrowserOptions {
    pub suppress_output: bool,
    pub target_hint: String,
}

impl fmt::Display for BrowserOptions {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_fmt(format_args!(
            "BrowserOptions(supress_output={}, target_hint={})",
            self.suppress_output, self.target_hint,
        ))
    }
}

impl std::default::Default for BrowserOptions {
    fn default() -> Self {
        let target_hint = String::from(option_env!("WEBBROWSER_WASM_TARGET").unwrap_or("_blank"));
        BrowserOptions {
            suppress_output: true,
            target_hint,
        }
    }
}

impl BrowserOptions {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn with_suppress_output<'a>(&'a mut self, suppress_output: bool) -> &'a mut Self {
        self.suppress_output = suppress_output;
        self
    }

    pub fn with_target_hint<'a>(&'a mut self, target_hint: &str) -> &'a mut Self {
        self.target_hint = target_hint.to_owned();
        self
    }
}

/// Opens the URL on the default browser of this platform
///
/// Returns Ok(..) so long as the browser invocation was successful. An Err(..) is returned only if
/// there was an error in running the command, or if the browser was not found.
///
/// Equivalent to:
/// ```no_run
/// # use webbrowser::{Browser, open_browser};
/// # let url = "http://example.com";
/// open_browser(Browser::Default, url);
/// ```
///
/// # Examples
/// ```no_run
/// use webbrowser;
///
/// if webbrowser::open("http://github.com").is_ok() {
///     // ...
/// }
/// ```
pub fn open(url: &str) -> Result<()> {
    open_browser(Browser::Default, url)
}

/// Opens the specified URL on the specific browser (if available) requested. Return semantics are
/// the same as for [open](fn.open.html).
///
/// # Examples
/// ```no_run
/// use webbrowser::{open_browser, Browser};
///
/// if open_browser(Browser::Firefox, "http://github.com").is_ok() {
///     // ...
/// }
/// ```
pub fn open_browser(browser: Browser, url: &str) -> Result<()> {
    open_browser_with_options(browser, url, &BrowserOptions::default())
}

/// Opens the specified URL on the specific browser (if available) requested, while overriding the
/// default options.
///
/// Return semantics are
/// the same as for [open](fn.open.html).
///
/// # Examples
/// ```no_run
/// use webbrowser::{open_browser_with_options, Browser, BrowserOptions};
///
/// if open_browser_with_options(Browser::Default, "http://github.com", BrowserOptions::new().with_suppress_output(false)).is_ok() {
///     // ...
/// }
/// ```
pub fn open_browser_with_options(
    browser: Browser,
    url: &str,
    options: &BrowserOptions,
) -> Result<()> {
    let url_s: String = match url::Url::parse(url) {
        Ok(u) => u.as_str().into(),
        Err(_) => url.into(),
    };
    os::open_browser_internal(browser, &url_s, options)
}

#[test]
#[ignore]
fn test_open_firefox() {
    assert!(open_browser(Browser::Firefox, "http://github.com").is_ok());
}

#[test]
#[ignore]
fn test_open_chrome() {
    assert!(open_browser(Browser::Chrome, "http://github.com").is_ok());
}

#[test]
#[ignore]
fn test_open_safari() {
    assert!(open_browser(Browser::Safari, "http://github.com").is_ok());
}

#[test]
#[ignore]
fn test_open_webpositive() {
    assert!(open_browser(Browser::WebPositive, "http://github.com").is_ok());
}
<|endoftext|>


<commit_before>/*
 * chamkho - a word breaker written in Rust
 * Copyright (C) 2015  Vee Satayamas
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
#[macro_use]
extern crate clap;

mod lib;

use std::io;
use std::io::BufRead;
use clap::App;
use std::path::Path;

fn main() {
    let yaml = load_yaml!("cli.yaml");
    let matches = App::from_yaml(yaml).get_matches();
    let lang = matches.value_of("lang");
    let dict_path = match matches.value_of("dict_path") {
        Some(_dict_path) => Path::new(_dict_path),
        None => {
            match lang {
                Some("lao") => lib::lao_path(),
                Some("thai") | Some(_) | None => lib::default_path()
            }
        }
    };
    let word_delim = match matches.value_of("word_delimiter") {
        Some(word_delim) => word_delim,
        None => "|"
    };
    let dict = lib::load_dict(dict_path).unwrap();
    let wordcut = lib::Wordcut::new(dict);

    for line_opt in io::BufReader::new(io::stdin()).lines() {

        let cleaned_line = match line_opt {
            Ok(line) => if line.len() > 0 {
                line.trim_right_matches('\n').to_string()
            } else {
                line
            },
            Err(e) => panic!("Cannot read line {}", e)
        };

        let segmented_string = wordcut.put_delimiters(&cleaned_line, word_delim);
        println!("{}", segmented_string);
    }
}
<commit_msg>Update API<commit_after>/*
 * chamkho - a word breaker written in Rust
 * Copyright (C) 2015  Vee Satayamas
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
#[macro_use]
extern crate clap;

mod lib;

use std::io;
use std::io::BufRead;
use clap::App;
use std::path::Path;

fn main() {
    let yaml = load_yaml!("cli.yaml");
    let matches = App::from_yaml(yaml).get_matches();
    let lang = matches.value_of("lang");
    let dict_path = match matches.value_of("dict_path") {
        Some(_dict_path) => Path::new(_dict_path),
        None => {
            match lang {
                Some("lao") => lib::lao_path(),
                Some("thai") | Some(_) | None => lib::default_path()
            }
        }
    };
    let word_delim = match matches.value_of("word_delimiter") {
        Some(word_delim) => word_delim,
        None => "|"
    };
    let dict = lib::load_dict(dict_path).unwrap();
    let wordcut = lib::Wordcut::new(dict);

    for line_opt in io::BufReader::new(io::stdin()).lines() {

        let cleaned_line = match line_opt {
            Ok(line) => if line.len() > 0 {
                line.trim_end_matches('\n').to_string()
            } else {
                line
            },
            Err(e) => panic!("Cannot read line {}", e)
        };

        let segmented_string = wordcut.put_delimiters(&cleaned_line, word_delim);
        println!("{}", segmented_string);
    }
}
<|endoftext|>


<commit_before>//! The `lonlat_bng` crate provides a function that converts decimal longitude
//! and latitude coordinates into British National Grid Coordinates
//!
//! Examples
//!
//!```
//! assert_eq!((516276, 173141), lonlat_bng::convert(-0.32824866, 51.44533267));
//!```

#[allow(non_snake_case)]
use std::f32::consts;
use std::mem;
use std::slice;
use std::thread::{self, JoinHandle};

extern crate libc;
use libc::{c_float, size_t, uint32_t};

const NUMTHREADS: i32 = 4;

#[repr(C)]
pub struct Tuple {
    a: uint32_t,
    b: uint32_t,
}

#[repr(C)]
pub struct Array {
    data: *const libc::c_void,
    len: libc::size_t,
}

impl Array {
    unsafe fn as_f32_slice(&self) -> &[f32] {
        assert!(!self.data.is_null());
        slice::from_raw_parts(self.data as *const f32, self.len as usize)
    }

    fn from_vec<T>(mut vec: Vec<T>) -> Array {
        // Important to make length and capacity match
        // A better solution is to track both length and capacity
        vec.shrink_to_fit();

        let array = Array {
            data: vec.as_ptr() as *const libc::c_void,
            len: vec.len() as libc::size_t
        };

        // Whee! Leak the memory, and now the raw pointer (and
        // eventually C) is the owner.
        mem::forget(vec);

        array
    }
}

// http://stackoverflow.com/a/28124775/155423
fn round(x: f32) -> f32 {
    let y = x.floor();
    if x == y {
        x
    } else {
        let z = (2.0*x-y).floor();
        z * x.signum() // Should use copysign, but not stably-available
    }
}

/// This function performs lon, lat to BNG conversion
///
/// Examples
///
/// ```
/// use lonlat_bng::convert;
/// assert_eq!((516276, 173141), convert(-0.32824866, 51.44533267));
#[no_mangle]
pub extern fn convert(input_lon: f32, input_lat: f32) -> (i32, i32) {

    // if not all([0 <= input_lat <= 90, -180 <= input_lon <= 180]):
    match input_lon {
        -180.0...180.0 => input_lon,
        _ => panic!("Out of bounds! Longitude must be between -180 and 180.")
    };
    match input_lat {
        -90.0...90.0 => input_lat,
        _ => panic!("Out of bounds! Latitude must be between -90 and 90.")
    };
    let pi: f32 = consts::PI;
    //Convert input to degrees
    let lat_1: f32 = input_lat * pi / 180.;
    let lon_1: f32 = input_lon * pi / 180.;
    // The GSR80 semi-major and semi-minor axes used for WGS84 (m)
    let a_1: f32 = 6378137.;
    let b_1: f32 = 6356752.3141;
    // The eccentricity (squared) of the GRS80 ellipsoid
    let e2_1: f32 = 1. - (b_1.powf(2.)) / (a_1.powf(2.));
    // Transverse radius of curvature
    let nu_1: f32 = a_1 / (1. - e2_1 * lat_1.sin().powf(2.)).sqrt();
    // Third spherical coordinate is 0, in this case
    let H: f32 = 0.;
    let x_1: f32 = (nu_1 + H) * lat_1.cos() * lon_1.cos();
    let y_1: f32 = (nu_1 + H) * lat_1.cos() * lon_1.sin();
    let z_1: f32 = ((1. - e2_1) * nu_1 + H) * lat_1.sin();

    // Perform Helmert transform (to go between Airy 1830 (_1) and GRS80 (_2))
    let small: f32 = 10.;
    let cst: f32 = 20.4894;
    let s: f32 =  cst * small.powf(-6.);
    // The translations along x, y, z axes respectively
    let tx: f32 = -446.448;
    let ty: f32 = 125.157;
    let tz: f32 = -542.060;
    // The rotations along x, y, z respectively, in seconds
    let rxs: f32 = -0.1502;
    let rys: f32 = -0.2470;
    let rzs: f32 = -0.8421;
    // In radians
    let rx: f32 = rxs * pi / (180. * 3600.);
    let ry: f32 = rys * pi / (180. * 3600.);
    let rz: f32 = rzs * pi / (180. * 3600.);
    // panic begins on line 46
    let x_2: f32 = tx + (1. + s) * x_1 + -rz * y_1 + ry * z_1;
    let y_2: f32 = ty + rz * x_1 + (1. + s) * y_1 + -rx * z_1;
    let z_2: f32 = tz + -ry * x_1 + rx * y_1 + (1. + s) * z_1;

    // The GSR80 semi-major and semi-minor axes used for WGS84 (m)
    let a: f32 = 6377563.396;
    let b: f32 = 6356256.909;
    // The eccentricity of the Airy 1830 ellipsoid
    let e2: f32 = 1. - b.powf(2.) / a.powf(2.);
    let p: f32 = (x_2.powf(2.) + y_2.powf(2.)).sqrt();
    // Initial value
    let mut lat: f32 = z_2.atan2((p * (1. - e2)));
    let mut latold: f32 = 2. * pi;
    // this is cheating, but not sure how else to initialise nu
    let mut nu: f32 = 1.;
    // Latitude is obtained by iterative procedure
    while (lat - latold).abs() > small.powf(-16.) {
        mem::swap(&mut lat, &mut latold);
        nu = a / (1. - e2 * latold.sin().powf(2.)).sqrt();
        lat = (z_2 + e2 * nu * latold.sin()).atan2(p);
    };
    let lon: f32 = y_2.atan2(x_2);
    // Scale factor on the central meridian
    let F0: f32 = 0.9996012717;
    // Latitude of true origin (radians)
    let lat0: f32 = 49. * pi / 180.;
    // Longtitude of true origin and central meridian (radians)
    let lon0: f32 = -2. * pi / 180.;
    // Northing & easting of true origin (m)
    let N0: f32 = -100000.;
    let E0: f32 = 400000.;
    let n: f32 = (a - b) / (a + b);
    // Meridional radius of curvature
    let rho: f32 = a * F0 * (1. - e2) * (1. - e2 * lat.sin().powf(2.)).powf(-1.5);
    let eta2: f32 = nu * F0 / rho - 1.;

    let M1: f32 = (1. + n + (5. / 4.) * n.powf(2.) + (5. / 4.) * n.powf(3.)) * (lat - lat0);
    let M2: f32 = (3. * n + 3. * n.powf(2.) + (21. / 8.) * n.powf(3.)) * (lat - lat0).sin() * (lat + lat0).cos();
    let M3: f32 = ((15. / 8.) * n.powf(2.) + (15. / 8.) * n.powf(3.)) * (2. * (lat-lat0)).sin() * (2. * (lat + lat0)).cos();
    let M4: f32 = (35. / 24.) * n.powf(3.) * (3. * (lat - lat0)).sin() * (3. * (lat + lat0)).cos();
    let M: f32 = b * F0 * (M1 - M2 + M3 - M4);

    let I: f32 = M + N0;
    let II: f32 = nu * F0 * lat.sin() * lat.cos() / 2.;
    let III: f32 = nu * F0 * lat.sin() * lat.cos().powf(3.) * (5. - lat.tan().powf(2.) + 9. * eta2) / 24.;
    let IIIA: f32 = nu * F0 * lat.sin() * lat.cos().powf(5.) * (61. - 58. * lat.tan().powf(2.) + lat.tan().powf(4.)) / 720.;
    let IV: f32 = nu * F0 * lat.cos();
    let V: f32 = nu * F0 * lat.cos().powf(3.) * (nu / rho - lat.tan().powf(2.)) / 6.;
    let VI: f32 = nu * F0 * lat.cos().powf(5.) * (5. - 18. * lat.tan().powf(2.) + lat.tan().powf(4.) + 14. * eta2 - 58. * eta2 * lat.tan().powf(2.)) / 120.;
    let N: f32 = I + II * (lon - lon0).powf(2.) + III * (lon - lon0).powf(4.) + IIIA * (lon - lon0).powf(6.);
    let E: f32 = E0 + IV * (lon - lon0) + V * (lon - lon0).powf(3.) + VI * (lon - lon0).powf(5.);
    return (round(E) as i32, round(N) as i32);
}

/// A wrapper for convert, which maps it over the zipped input vectors
pub fn convert_vec(input_lon: Vec<f32>, input_lat: Vec<f32>) -> Vec<(i32, i32)> {
    let combined: Vec<(i32, i32)> = input_lon
        .iter()
        .zip(input_lat.iter())
        .map(|each| convert(*each.0, *each.1))
        .collect();
    return combined
}

/// Essentially just a C-compatible wrapper for convert_vec
// http://stackoverflow.com/a/30511235/416626
#[no_mangle]
pub extern fn convert_vec_py(input_lon: *const c_float,
                            lon_size: size_t ,
                            input_lat: *const c_float,
                            lat_size: size_t) -> *const (i32, i32) {
    let input_lon = unsafe {
        slice::from_raw_parts(input_lon, lon_size as usize).to_owned()
    };
    let input_lat = unsafe {
        slice::from_raw_parts(input_lat, lat_size as usize).to_owned()
    };
    let res: Vec<(i32, i32)> = convert_vec(input_lon, input_lat).to_owned();
    let inter = res.as_ptr();
    mem::forget(res);
    inter
}

/// A safer C-compatible wrapper for convert
#[no_mangle]
pub extern fn convert_vec_c(lon: Array, lat: Array) -> Array {
    // we're receiving floats
    let lon = unsafe { lon.as_f32_slice() };
    let lat = unsafe { lat.as_f32_slice() };
    // map convert over our slices. Returns vector of integer tuples
    let vec: Vec<(i32, i32)> =
        lon.iter().zip(lat.iter())
        .map(|(&lon, &lat)| convert(lon, lat))
        .collect();
    // convert back to vector of unsigned integer Tuples
    let nvec = vec.iter()
        .map(|ints| Tuple { a: ints.0 as u32, b: ints.1 as u32 })
        .collect();

    Array::from_vec(nvec)
}

pub extern fn convert_vec_c_threaded(lon: Array, lat: Array) -> Array {
    // we're receiving floats
    let lon = unsafe { lon.as_f32_slice() };
    let lat = unsafe { lat.as_f32_slice() };
    let orig: Vec<(&f32, &f32)> = lon.iter().zip(lat.iter()).to_owned().collect();
    let mut guards: Vec<JoinHandle<Vec<(i32, i32)>>> = vec!();
    // split into slices
    for chunk in orig.chunks(orig.len() / NUMTHREADS as usize) {
        let chunk = chunk.to_owned();
        let g = thread::spawn(move || chunk
            .into_iter()
            .map(|(&lon, &lat)| convert(lon, lat))
            .collect());
        guards.push(g);
    };
    // collect the results
    let mut result: Vec<(i32, i32)> = Vec::with_capacity(orig.len());
    for g in guards {
        result.extend(g.join().unwrap().into_iter());
    }
    let newres = result.iter()
            .map(|ints| Tuple { a: ints.0 as u32, b: ints.1 as u32 })
            .collect();
    Array::from_vec(newres)
}

#[test]
fn test_vector_conversion() {
    let lons = vec![-0.32824866];
    let lats = vec![51.44533267];
    // let lon_s: size_t = 1;
    // let lat_s: size_t = 1;

    // let lons: Vec<f32> = vec![-0.32824866];
    // let lats: Vec<f32> = vec![51.44533267];
    assert_eq!(
        vec![(516276, 173141)],
        convert_vec(lons, lats,));
}

#[test]
fn test_conversion() {
    // verified to be correct at http://www.bgs.ac.uk/data/webservices/convertForm.cfm
    assert_eq!((516276, 173141), convert(-0.32824866, 51.44533267));
}

#[test]
#[should_panic]
fn test_bad_lon() {
    assert_eq!((516276, 173141), convert(181., 51.44533267));
}

#[test]
#[should_panic]
fn test_bad_lat() {
    assert_eq!((516276, 173141), convert(-0.32824866, -90.01));
}
<commit_msg>Removing unneeded older FFI-compatible function<commit_after>//! The `lonlat_bng` crate provides a function that converts decimal longitude
//! and latitude coordinates into British National Grid Coordinates
//!
//! Examples
//!
//!```
//! assert_eq!((516276, 173141), lonlat_bng::convert(-0.32824866, 51.44533267));
//!```

#[allow(non_snake_case)]
use std::f32::consts;
use std::mem;
use std::slice;
use std::thread::{self, JoinHandle};

extern crate libc;
use libc::{c_float, size_t, uint32_t};

const NUMTHREADS: i32 = 4;

#[repr(C)]
pub struct Tuple {
    a: uint32_t,
    b: uint32_t,
}

#[repr(C)]
pub struct Array {
    data: *const libc::c_void,
    len: libc::size_t,
}

impl Array {
    unsafe fn as_f32_slice(&self) -> &[f32] {
        assert!(!self.data.is_null());
        slice::from_raw_parts(self.data as *const f32, self.len as usize)
    }

    fn from_vec<T>(mut vec: Vec<T>) -> Array {
        // Important to make length and capacity match
        // A better solution is to track both length and capacity
        vec.shrink_to_fit();

        let array = Array {
            data: vec.as_ptr() as *const libc::c_void,
            len: vec.len() as libc::size_t
        };

        // Whee! Leak the memory, and now the raw pointer (and
        // eventually C) is the owner.
        mem::forget(vec);

        array
    }
}

// http://stackoverflow.com/a/28124775/155423
fn round(x: f32) -> f32 {
    let y = x.floor();
    if x == y {
        x
    } else {
        let z = (2.0*x-y).floor();
        z * x.signum() // Should use copysign, but not stably-available
    }
}

/// This function performs lon, lat to BNG conversion
///
/// Examples
///
/// ```
/// use lonlat_bng::convert;
/// assert_eq!((516276, 173141), convert(-0.32824866, 51.44533267));
#[no_mangle]
pub extern fn convert(input_lon: f32, input_lat: f32) -> (i32, i32) {

    // if not all([0 <= input_lat <= 90, -180 <= input_lon <= 180]):
    match input_lon {
        -180.0...180.0 => input_lon,
        _ => panic!("Out of bounds! Longitude must be between -180 and 180.")
    };
    match input_lat {
        -90.0...90.0 => input_lat,
        _ => panic!("Out of bounds! Latitude must be between -90 and 90.")
    };
    let pi: f32 = consts::PI;
    //Convert input to degrees
    let lat_1: f32 = input_lat * pi / 180.;
    let lon_1: f32 = input_lon * pi / 180.;
    // The GSR80 semi-major and semi-minor axes used for WGS84 (m)
    let a_1: f32 = 6378137.;
    let b_1: f32 = 6356752.3141;
    // The eccentricity (squared) of the GRS80 ellipsoid
    let e2_1: f32 = 1. - (b_1.powf(2.)) / (a_1.powf(2.));
    // Transverse radius of curvature
    let nu_1: f32 = a_1 / (1. - e2_1 * lat_1.sin().powf(2.)).sqrt();
    // Third spherical coordinate is 0, in this case
    let H: f32 = 0.;
    let x_1: f32 = (nu_1 + H) * lat_1.cos() * lon_1.cos();
    let y_1: f32 = (nu_1 + H) * lat_1.cos() * lon_1.sin();
    let z_1: f32 = ((1. - e2_1) * nu_1 + H) * lat_1.sin();

    // Perform Helmert transform (to go between Airy 1830 (_1) and GRS80 (_2))
    let small: f32 = 10.;
    let cst: f32 = 20.4894;
    let s: f32 =  cst * small.powf(-6.);
    // The translations along x, y, z axes respectively
    let tx: f32 = -446.448;
    let ty: f32 = 125.157;
    let tz: f32 = -542.060;
    // The rotations along x, y, z respectively, in seconds
    let rxs: f32 = -0.1502;
    let rys: f32 = -0.2470;
    let rzs: f32 = -0.8421;
    // In radians
    let rx: f32 = rxs * pi / (180. * 3600.);
    let ry: f32 = rys * pi / (180. * 3600.);
    let rz: f32 = rzs * pi / (180. * 3600.);
    // panic begins on line 46
    let x_2: f32 = tx + (1. + s) * x_1 + -rz * y_1 + ry * z_1;
    let y_2: f32 = ty + rz * x_1 + (1. + s) * y_1 + -rx * z_1;
    let z_2: f32 = tz + -ry * x_1 + rx * y_1 + (1. + s) * z_1;

    // The GSR80 semi-major and semi-minor axes used for WGS84 (m)
    let a: f32 = 6377563.396;
    let b: f32 = 6356256.909;
    // The eccentricity of the Airy 1830 ellipsoid
    let e2: f32 = 1. - b.powf(2.) / a.powf(2.);
    let p: f32 = (x_2.powf(2.) + y_2.powf(2.)).sqrt();
    // Initial value
    let mut lat: f32 = z_2.atan2((p * (1. - e2)));
    let mut latold: f32 = 2. * pi;
    // this is cheating, but not sure how else to initialise nu
    let mut nu: f32 = 1.;
    // Latitude is obtained by iterative procedure
    while (lat - latold).abs() > small.powf(-16.) {
        mem::swap(&mut lat, &mut latold);
        nu = a / (1. - e2 * latold.sin().powf(2.)).sqrt();
        lat = (z_2 + e2 * nu * latold.sin()).atan2(p);
    };
    let lon: f32 = y_2.atan2(x_2);
    // Scale factor on the central meridian
    let F0: f32 = 0.9996012717;
    // Latitude of true origin (radians)
    let lat0: f32 = 49. * pi / 180.;
    // Longtitude of true origin and central meridian (radians)
    let lon0: f32 = -2. * pi / 180.;
    // Northing & easting of true origin (m)
    let N0: f32 = -100000.;
    let E0: f32 = 400000.;
    let n: f32 = (a - b) / (a + b);
    // Meridional radius of curvature
    let rho: f32 = a * F0 * (1. - e2) * (1. - e2 * lat.sin().powf(2.)).powf(-1.5);
    let eta2: f32 = nu * F0 / rho - 1.;

    let M1: f32 = (1. + n + (5. / 4.) * n.powf(2.) + (5. / 4.) * n.powf(3.)) * (lat - lat0);
    let M2: f32 = (3. * n + 3. * n.powf(2.) + (21. / 8.) * n.powf(3.)) * (lat - lat0).sin() * (lat + lat0).cos();
    let M3: f32 = ((15. / 8.) * n.powf(2.) + (15. / 8.) * n.powf(3.)) * (2. * (lat-lat0)).sin() * (2. * (lat + lat0)).cos();
    let M4: f32 = (35. / 24.) * n.powf(3.) * (3. * (lat - lat0)).sin() * (3. * (lat + lat0)).cos();
    let M: f32 = b * F0 * (M1 - M2 + M3 - M4);

    let I: f32 = M + N0;
    let II: f32 = nu * F0 * lat.sin() * lat.cos() / 2.;
    let III: f32 = nu * F0 * lat.sin() * lat.cos().powf(3.) * (5. - lat.tan().powf(2.) + 9. * eta2) / 24.;
    let IIIA: f32 = nu * F0 * lat.sin() * lat.cos().powf(5.) * (61. - 58. * lat.tan().powf(2.) + lat.tan().powf(4.)) / 720.;
    let IV: f32 = nu * F0 * lat.cos();
    let V: f32 = nu * F0 * lat.cos().powf(3.) * (nu / rho - lat.tan().powf(2.)) / 6.;
    let VI: f32 = nu * F0 * lat.cos().powf(5.) * (5. - 18. * lat.tan().powf(2.) + lat.tan().powf(4.) + 14. * eta2 - 58. * eta2 * lat.tan().powf(2.)) / 120.;
    let N: f32 = I + II * (lon - lon0).powf(2.) + III * (lon - lon0).powf(4.) + IIIA * (lon - lon0).powf(6.);
    let E: f32 = E0 + IV * (lon - lon0) + V * (lon - lon0).powf(3.) + VI * (lon - lon0).powf(5.);
    return (round(E) as i32, round(N) as i32);
}

/// A wrapper for convert, which maps it over the zipped input vectors
pub fn convert_vec(input_lon: Vec<f32>, input_lat: Vec<f32>) -> Vec<(i32, i32)> {
    let combined: Vec<(i32, i32)> = input_lon
        .iter()
        .zip(input_lat.iter())
        .map(|each| convert(*each.0, *each.1))
        .collect();
    return combined
}

/// A safer C-compatible wrapper for convert
#[no_mangle]
pub extern fn convert_vec_c(lon: Array, lat: Array) -> Array {
    // we're receiving floats
    let lon = unsafe { lon.as_f32_slice() };
    let lat = unsafe { lat.as_f32_slice() };
    // map convert over our slices. Returns vector of integer tuples
    let vec: Vec<(i32, i32)> =
        lon.iter().zip(lat.iter())
        .map(|(&lon, &lat)| convert(lon, lat))
        .collect();
    // convert back to vector of unsigned integer Tuples
    let nvec = vec.iter()
        .map(|ints| Tuple { a: ints.0 as u32, b: ints.1 as u32 })
        .collect();

    Array::from_vec(nvec)
}

pub extern fn convert_vec_c_threaded(lon: Array, lat: Array) -> Array {
    // we're receiving floats
    let lon = unsafe { lon.as_f32_slice() };
    let lat = unsafe { lat.as_f32_slice() };
    let orig: Vec<(&f32, &f32)> = lon.iter().zip(lat.iter()).to_owned().collect();
    let mut guards: Vec<JoinHandle<Vec<(i32, i32)>>> = vec!();
    // split into slices
    for chunk in orig.chunks(orig.len() / NUMTHREADS as usize) {
        let chunk = chunk.to_owned();
        let g = thread::spawn(move || chunk
            .into_iter()
            .map(|(&lon, &lat)| convert(lon, lat))
            .collect());
        guards.push(g);
    };
    // collect the results
    let mut result: Vec<(i32, i32)> = Vec::with_capacity(orig.len());
    for g in guards {
        result.extend(g.join().unwrap().into_iter());
    }
    let newres = result.iter()
            .map(|ints| Tuple { a: ints.0 as u32, b: ints.1 as u32 })
            .collect();
    Array::from_vec(newres)
}

#[test]
fn test_vector_conversion() {
    let lons = vec![-0.32824866];
    let lats = vec![51.44533267];
    // let lon_s: size_t = 1;
    // let lat_s: size_t = 1;

    // let lons: Vec<f32> = vec![-0.32824866];
    // let lats: Vec<f32> = vec![51.44533267];
    assert_eq!(
        vec![(516276, 173141)],
        convert_vec(lons, lats,));
}

#[test]
fn test_conversion() {
    // verified to be correct at http://www.bgs.ac.uk/data/webservices/convertForm.cfm
    assert_eq!((516276, 173141), convert(-0.32824866, 51.44533267));
}

#[test]
#[should_panic]
fn test_bad_lon() {
    assert_eq!((516276, 173141), convert(181., 51.44533267));
}

#[test]
#[should_panic]
fn test_bad_lat() {
    assert_eq!((516276, 173141), convert(-0.32824866, -90.01));
}
<|endoftext|>


<commit_before>extern crate regex;

use std::process::Command;
mod lsb_release;
mod windows_ver;
mod rhel_release;
mod sw_vers;
mod utils;

///A list of supported operating system types
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Clone)]
pub enum OSType {
    Unknown,
    Redhat,
    OSX,
    Ubuntu,
    Debian,
    Arch,
    CentOS
}

pub struct OSInformation {
    pub os_type: self::OSType,
    pub version: String
}

fn default_version() -> String {
    "0.0.0".into()
}

fn unknown_os() -> OSInformation {
    OSInformation {
        os_type: OSType::Unknown,
        version: default_version()
    }
}

fn is_os_x() -> bool {
    match Command::new("sw_vers").output() {
        Ok(output) => output.status.success(),
        Err(_) => false
    }
}

fn get_sw_vers() -> OSInformation {
    if let Some(osx_info) = sw_vers::retrieve() {
        OSInformation {
            os_type: OSType::OSX,
            version: osx_info.product_version.unwrap_or(default_version())
        }
    } else {
        unknown_os()
    }
}

fn lsb_release() -> OSInformation {
    match lsb_release::retrieve() {
        Some(release) => {
            if release.distro == Some("Ubuntu".to_string()) {
                OSInformation {
                    os_type: OSType::Ubuntu,
                    version: release.version.unwrap_or(default_version())
                }
            }
            else if release.distro == Some("Debian".to_string()) {
                OSInformation {
                    os_type: OSType::Debian,
                    version: release.version.unwrap_or(default_version())
                }
            } else if release.distro == Some("Arch".to_string()) {
                OSInformation {
                    os_type: OSType::Arch,
                    version: release.version.unwrap_or(default_version())
                }
            }
            else if release.distro == Some("CentOS".to_string()){
                OSInformation {
                    os_type: OSType::CentOS,
                    version: release.version.unwrap_or(default_version())
                }
            }
            else {
                unknown_os()
            }
        },
        None => unknown_os()
    }
}

fn rhel_release() -> OSInformation {
    match rhel_release::retrieve() {
        Some(release) => {
            if release.distro == Some("CentOS".to_string()) {
                OSInformation {
                    os_type: OSType::CentOS,
                    version: release.version.unwrap_or(default_version())
                }
            } else {
                OSInformation {
                    os_type: OSType::Redhat,
                    version: release.version.unwrap_or(default_version())
                }
            }
        },
        None => unknown_os()
    }
}

///Returns the current operating system type
///
///#Example
///
///```
///use os_type;
///let os = os_type::current_platform();
///```
pub fn current_platform() -> OSInformation {
    if is_os_x() {
        get_sw_vers()
    }
    else if lsb_release::is_available() {
        lsb_release()
    }
    else if utils::file_exists("/etc/redhat-release") || utils::file_exists("/etc/centos-release") {
        rhel_release()
    }
    else {
        unknown_os()
    }
}
<commit_msg>doc: Update API documentation<commit_after>extern crate regex;

use std::process::Command;
mod lsb_release;
mod windows_ver;
mod rhel_release;
mod sw_vers;
mod utils;

///A list of supported operating system types
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Clone)]
pub enum OSType {
    Unknown,
    Redhat,
    OSX,
    Ubuntu,
    Debian,
    Arch,
    CentOS
}

/// Holds information about Operating System type and its version
/// If the version could not be fetched it defaults to `0.0.0`
#[derive(Debug)]
#[derive(Clone)]
#[derive(PartialEq)]
pub struct OSInformation {
    pub os_type: self::OSType,
    pub version: String
}

fn default_version() -> String {
    "0.0.0".into()
}

fn unknown_os() -> OSInformation {
    OSInformation {
        os_type: OSType::Unknown,
        version: default_version()
    }
}

fn is_os_x() -> bool {
    match Command::new("sw_vers").output() {
        Ok(output) => output.status.success(),
        Err(_) => false
    }
}

fn get_sw_vers() -> OSInformation {
    if let Some(osx_info) = sw_vers::retrieve() {
        OSInformation {
            os_type: OSType::OSX,
            version: osx_info.product_version.unwrap_or(default_version())
        }
    } else {
        unknown_os()
    }
}

fn lsb_release() -> OSInformation {
    match lsb_release::retrieve() {
        Some(release) => {
            if release.distro == Some("Ubuntu".to_string()) {
                OSInformation {
                    os_type: OSType::Ubuntu,
                    version: release.version.unwrap_or(default_version())
                }
            }
            else if release.distro == Some("Debian".to_string()) {
                OSInformation {
                    os_type: OSType::Debian,
                    version: release.version.unwrap_or(default_version())
                }
            } else if release.distro == Some("Arch".to_string()) {
                OSInformation {
                    os_type: OSType::Arch,
                    version: release.version.unwrap_or(default_version())
                }
            }
            else if release.distro == Some("CentOS".to_string()){
                OSInformation {
                    os_type: OSType::CentOS,
                    version: release.version.unwrap_or(default_version())
                }
            }
            else {
                unknown_os()
            }
        },
        None => unknown_os()
    }
}

fn rhel_release() -> OSInformation {
    match rhel_release::retrieve() {
        Some(release) => {
            if release.distro == Some("CentOS".to_string()) {
                OSInformation {
                    os_type: OSType::CentOS,
                    version: release.version.unwrap_or(default_version())
                }
            } else {
                OSInformation {
                    os_type: OSType::Redhat,
                    version: release.version.unwrap_or(default_version())
                }
            }
        },
        None => unknown_os()
    }
}

///Returns the current operating system type
///
///#Example
///
///```
///use os_type;
///let os = os_type::current_platform();
///println!("Type: {:?}", os.os_type);
///println!("Version: {}", os.version);
///```
pub fn current_platform() -> OSInformation {
    if is_os_x() {
        get_sw_vers()
    }
    else if lsb_release::is_available() {
        lsb_release()
    }
    else if utils::file_exists("/etc/redhat-release") || utils::file_exists("/etc/centos-release") {
        rhel_release()
    }
    else {
        unknown_os()
    }
}
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://jarusk.github.io/Spork/")]
//! Some sample documentation
//!

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>Added an image to the documentation<commit_after>#![warn(missing_docs)]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://jarusk.github.io/Spork")]
//! Some sample documentation
//!

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


<commit_before>#![feature(plugin, core, collections, std_misc)]

//! # 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 supported 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 and Registration
//!
//! Templates are created from String and registered to `Handlebars` with a name.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use handlebars::Handlebars;
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   let source = "hello {{world}}";
//!
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().expect("template created");
//! }
//! ```
//!
//! ### 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 "rustc-serialize" as serialize;
//! extern crate handlebars;
//!
//! use serialize::json::{Json, ToJson};
//! use std::collections::BTreeMap;
//!
//! use handlebars::Handlebars;
//!
//! struct Person {
//!   name: String,
//!   age: i16,
//! }
//!
//! impl ToJson for Person {
//!   fn to_json(&self) -> Json {
//!     let mut m = BTreeMap::new();
//!     m.insert("name".to_string(), self.name.to_json());
//!     m.insert("age".to_string(), self.age.to_json());
//!     Json::Object(m)
//!   }
//! }
//!
//!
//! fn main() {
//!   let source = "hello {{world}}";
//!
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().expect("template creation failed");
//!
//!   let mut data = Person {
//!       name: "Ning Sun".to_string(),
//!       age: 27
//!   };
//!   let result = handlebars.render("helloworld", &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 `call` function. For your convenience, most of stateless helpers can be implemented as bare functions.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use handlebars::{Handlebars, HelperDef, RenderError, RenderContext, Helper, Context};
//!
//! // implement by a structure impls HelperDef
//! #[derive(Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn call(&self, c: &Context, h: &Helper, _: &Handlebars, 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))
//!   }
//! }
//!
//! // implement via bare function
//! fn another_simple_helper (c: &Context, h: &Helper, _: &Handlebars, 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 second helper dumps: {} ", value))
//! }
//!
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_helper("simple-helper", Box::new(SimpleHelper));
//!   handlebars.register_helper("another-simple-helper", Box::new(another_simple_helper));
//!
//!   //...
//! }
//! ```
//!
//! #### Arguments of HelpDef
//!
//! You can get data from the `Helper` argument about the template information:
//!
//! * `name()` for the helper name. This is known to you for most situation but if you are defining `helperMissing` or `blockHelperMissing`, this is important.
//! * `params()` is a vector of 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.
//!
//! #### Built-in Helpers
//!
//! * `{{#raw}} ... {{/raw}}` escape handlebars expression within the block
//! * `{{#if ...}} ... {{else}} ... {{/if}}` if-else block
//! * `{{#unless ...}} ... {{else}} .. {{/unless}}` if-not-else block
//! * `{{#each ...}} ... {{/each}}` iterates over an array or object. Handlebar-rust doesn't support mustach iteration syntax so use this instead.
//! * `{{#with ...}} ... {{/with}}` change current context. Similar to {{#each}}, used for replace corresponding mustach syntax.
//! * `{{lookup ... ...}}` get value from array by `@index` or `@key`
//! * `{{#partial ...}} ... {{/partial}}` template reuse, used to replace block with same name
//! * `{{#block ...}} ... {{/block}}` template reuse, used to be replaced by partial with same name, with default content if partial not found.
//! * `{{> ...}}` include template with name
//! * `{{log ...}}` log value with rust logger, default level: INFO. Currently you cannot change the level.
//!

#[macro_use]
extern crate log;
#[plugin]
extern crate regex_macros;

extern crate "rustc-serialize" as serialize;
extern crate regex;

pub use self::template::{Template, Helper};
pub use self::registry::Registry as Handlebars;
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>Don't link to regex_macros at runtime.<commit_after>#![feature(plugin, core, collections, std_misc)]

//! # 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 supported 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 and Registration
//!
//! Templates are created from String and registered to `Handlebars` with a name.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use handlebars::Handlebars;
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   let source = "hello {{world}}";
//!
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().expect("template created");
//! }
//! ```
//!
//! ### 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 "rustc-serialize" as serialize;
//! extern crate handlebars;
//!
//! use serialize::json::{Json, ToJson};
//! use std::collections::BTreeMap;
//!
//! use handlebars::Handlebars;
//!
//! struct Person {
//!   name: String,
//!   age: i16,
//! }
//!
//! impl ToJson for Person {
//!   fn to_json(&self) -> Json {
//!     let mut m = BTreeMap::new();
//!     m.insert("name".to_string(), self.name.to_json());
//!     m.insert("age".to_string(), self.age.to_json());
//!     Json::Object(m)
//!   }
//! }
//!
//!
//! fn main() {
//!   let source = "hello {{world}}";
//!
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().expect("template creation failed");
//!
//!   let mut data = Person {
//!       name: "Ning Sun".to_string(),
//!       age: 27
//!   };
//!   let result = handlebars.render("helloworld", &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 `call` function. For your convenience, most of stateless helpers can be implemented as bare functions.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use handlebars::{Handlebars, HelperDef, RenderError, RenderContext, Helper, Context};
//!
//! // implement by a structure impls HelperDef
//! #[derive(Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn call(&self, c: &Context, h: &Helper, _: &Handlebars, 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))
//!   }
//! }
//!
//! // implement via bare function
//! fn another_simple_helper (c: &Context, h: &Helper, _: &Handlebars, 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 second helper dumps: {} ", value))
//! }
//!
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_helper("simple-helper", Box::new(SimpleHelper));
//!   handlebars.register_helper("another-simple-helper", Box::new(another_simple_helper));
//!
//!   //...
//! }
//! ```
//!
//! #### Arguments of HelpDef
//!
//! You can get data from the `Helper` argument about the template information:
//!
//! * `name()` for the helper name. This is known to you for most situation but if you are defining `helperMissing` or `blockHelperMissing`, this is important.
//! * `params()` is a vector of 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.
//!
//! #### Built-in Helpers
//!
//! * `{{#raw}} ... {{/raw}}` escape handlebars expression within the block
//! * `{{#if ...}} ... {{else}} ... {{/if}}` if-else block
//! * `{{#unless ...}} ... {{else}} .. {{/unless}}` if-not-else block
//! * `{{#each ...}} ... {{/each}}` iterates over an array or object. Handlebar-rust doesn't support mustach iteration syntax so use this instead.
//! * `{{#with ...}} ... {{/with}}` change current context. Similar to {{#each}}, used for replace corresponding mustach syntax.
//! * `{{lookup ... ...}}` get value from array by `@index` or `@key`
//! * `{{#partial ...}} ... {{/partial}}` template reuse, used to replace block with same name
//! * `{{#block ...}} ... {{/block}}` template reuse, used to be replaced by partial with same name, with default content if partial not found.
//! * `{{> ...}}` include template with name
//! * `{{log ...}}` log value with rust logger, default level: INFO. Currently you cannot change the level.
//!

#[macro_use]
extern crate log;
#[plugin]
#[no_link]
extern crate regex_macros;

extern crate "rustc-serialize" as serialize;
extern crate regex;

pub use self::template::{Template, Helper};
pub use self::registry::Registry as Handlebars;
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|>


<commit_before>//! [![ggez logo](docs/ggez-logo-maroon-full.svg)](http://ggez.rs/)
//!
//! # What is this?
//!
//! ![Build status](https://github.com/ggez/ggez/workflows/CI/badge.svg)
//! [![Docs Status](https://docs.rs/ggez/badge.svg)](https://docs.rs/ggez)
//! [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/ggez/ggez/blob/master/LICENSE)
//! [![Crates.io](https://img.shields.io/crates/v/ggez.svg)](https://crates.io/crates/ggez)
//! [![Crates.io](https://img.shields.io/crates/d/ggez.svg)](https://crates.io/crates/ggez)
//!
//! ggez is a Rust library to create a Good Game Easily.
//!
//! More specifically, ggez is a lightweight cross-platform game framework
//! for making 2D games with minimum friction.  It aims to implement an
//! API based on (a Rustified version of) the [LÖVE](https://love2d.org/)
//! game framework.  This means it contains basic and portable 2D
//! drawing, sound, resource loading and event handling, but finer details
//! and performance characteristics may be different than LÖVE.
//!
//! ggez is not meant to be everything to everyone, but rather a good
//! base upon which to build.  Thus it takes a fairly
//! batteries-included approach without needing a million additions
//! and plugins for everything imaginable, but also does not dictate
//! higher-level functionality such as physics engine or entity
//! component system.  Instead the goal is to allow you to use
//! whichever libraries you want to provide these functions, or build
//! your own libraries atop ggez.
//!
//! ## Features
//!
//! * Filesystem abstraction that lets you load resources from folders or zip files
//! * Hardware-accelerated 2D rendering built on the `gfx-rs` graphics engine
//! * Loading and playing .ogg, .wav and .flac files via the `rodio` crate
//! * TTF font rendering with `rusttype` and `glyph_brush`.
//! * Interface for handling keyboard and mouse events easily through callbacks
//! * Config file for defining engine and game settings
//! * Easy timing and FPS measurement functions.
//! * Math library integration with `mint`.
//! * Some more advanced graphics options: shaders, sprite batches and render targets
//!
//! ## Supported platforms
//!
//!  * Fully supported: Windows, Linux
//!  * Not officially supported but might work anyway: Mac, iOS
//!  * Work in progress: WebAssembly
//!  * Not officially supported yet (but maybe you can help!): Android
//!
//! For details, see [docs/BuildingForEveryPlatform.md](docs/BuildingForEveryPlatform.md)
//!
//! ## Who's using ggez?
//!
//! Check out the [projects list!](docs/Projects.md)
//!
//! ## Usage
//!
//! ggez requires rustc >= 1.40 and is distributed on
//! crates.io. To include it in your project, just add the dependency
//! line to your `Cargo.toml` file:
//!
//! ```text
//! ggez = "0.6"
//! ```
//!
//! ggez consists of three main parts: A `Context` object which
//! contains all the state required to interface with the computer's
//! hardware, an `EventHandler` trait that the user implements to
//! register callbacks for events, and various sub-modules such as
//! `graphics` and `audio` that provide the functionality to actually
//! get stuff done.  The general pattern is to create a struct holding
//! your game's data which implements the `EventHandler` trait.
//! Create a new `Context` object with default objects from a `ContextBuilder`
//! or `Conf` object, and then call `event::run()` with
//! the `Context` and an instance of your `EventHandler` to run your game's
//! main loop.
//!
//! See the [API docs](https://docs.rs/ggez/) for full documentation, or the [examples](/examples) directory for a number of commented examples of varying complexity.  Most examples show off
//! a single feature of ggez, while `astroblasto` and `snake` are small but complete games.
//!
//! ## Getting started
//!
//! For a quick tutorial on ggez, see the [Hello ggez](https://github.com/ggez/ggez/blob/master/docs/guides/HelloGgez.md) guide in the `docs/` directory.
//!
//! ## Examples
//!
//! See the `examples/` directory in the source.  Most examples show off
//! a single feature of ggez, while `astroblasto` is a small  but
//! complete Asteroids-like game.
//!
//! To run the examples, just check out the source and execute `cargo run --example`
//! in the root directory:
//!
//! ```text
//! git clone https://github.com/ggez/ggez.git
//! cd ggez
//! cargo run --example 05_astroblasto
//! ```
//!
//! If this doesn't work, see the
//! [FAQ](https://github.com/ggez/ggez/blob/master/docs/FAQ.md) for solutions
//! to common problems.
//!
//! ### Basic Project Template
//!
//! ```rust,no_run
//! use ggez::{Context, ContextBuilder, GameResult};
//! use ggez::graphics::{self, Color};
//! use ggez::event::{self, EventHandler};
//!
//! fn main() {
//!     // Make a Context.
//!     let (mut ctx, event_loop) = ContextBuilder::new("my_game", "Cool Game Author")
//!         .build()
//!         .expect("aieee, could not create ggez context!");
//!
//!     // Create an instance of your event handler.
//!     // Usually, you should provide it with the Context object to
//!     // use when setting your game up.
//!     let my_game = MyGame::new(&mut ctx);
//!
//!     // Run!
//!     event::run(ctx, event_loop, my_game);
//! }
//!
//! struct MyGame {
//!     // Your state here...
//! }
//!
//! impl MyGame {
//!     pub fn new(_ctx: &mut Context) -> MyGame {
//!         // Load/create resources such as images here.
//!         MyGame {
//!             // ...
//!         }
//!     }
//! }
//!
//! impl EventHandler for MyGame {
//!     fn update(&mut self, _ctx: &mut Context) -> GameResult<()> {
//!         // Update code here...
//!         Ok(())
//!     }
//!
//!     fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
//!         graphics::clear(ctx, Color::WHITE);
//!         // Draw code here...
//!         graphics::present(ctx)
//!     }
//! }
//! ```
//!
//! ## Implementation details
//!
//! ggez is built upon `winit` for windowing and events, `rodio` for
//! sound, and a 2D drawing engine implemented in `gfx` using the OpenGL
//! backend (which currently defaults to use OpenGL 3.2).  It is entirely
//! thread-safe (though platform constraints mean the event-handling loop
//! and drawing must be done in the main thread), and portable to Windows
//! and Linux.
//!
//! ggez is pure Rust™.
//!
//! ## Help!
//!
//! Sources of information:
//!
//!  * The [FAQ](https://github.com/ggez/ggez/blob/master/docs/FAQ.md) has answers to common questions and problems.
//!  * The [API docs](https://docs.rs/ggez/), a lot of design stuff is explained there.
//!  * Check out the [examples](https://github.com/ggez/ggez/tree/master/examples).
//!
//!  If you still have problems or questions, feel free to ask!  Easiest ways are:
//!
//!  * Open an issue on [the Github issue tracker](https://github.com/ggez/ggez/issues)
//!  * Say hi on the [unofficial Rust Discord server](http://bit.ly/rust-community) or the [Rust Gamedev server](https://discord.gg/yNtPTb2)

#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unused_results)]
// This is not as strong a constraint as `#![forbid(unsafe_code)]` but is good enough.
// It means the only place we use unsafe is then in the modules noted as allowing it.
#![deny(unsafe_code)]
#![warn(bare_trait_objects)]
#![warn(missing_copy_implementations)]

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate gfx;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate smart_default;

pub extern crate mint;

pub mod audio;
pub mod conf;
mod context;
pub mod error;
pub mod event;
pub mod filesystem;
pub mod graphics;
pub mod input;
pub mod timer;
mod vfs;

#[cfg(test)]
pub mod tests;

pub use crate::context::{Context, ContextBuilder};
pub use crate::error::*;
<commit_msg>allows clippy::needless_doctest_main<commit_after>//! [![ggez logo](docs/ggez-logo-maroon-full.svg)](http://ggez.rs/)
//!
//! # What is this?
//!
//! ![Build status](https://github.com/ggez/ggez/workflows/CI/badge.svg)
//! [![Docs Status](https://docs.rs/ggez/badge.svg)](https://docs.rs/ggez)
//! [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/ggez/ggez/blob/master/LICENSE)
//! [![Crates.io](https://img.shields.io/crates/v/ggez.svg)](https://crates.io/crates/ggez)
//! [![Crates.io](https://img.shields.io/crates/d/ggez.svg)](https://crates.io/crates/ggez)
//!
//! ggez is a Rust library to create a Good Game Easily.
//!
//! More specifically, ggez is a lightweight cross-platform game framework
//! for making 2D games with minimum friction.  It aims to implement an
//! API based on (a Rustified version of) the [LÖVE](https://love2d.org/)
//! game framework.  This means it contains basic and portable 2D
//! drawing, sound, resource loading and event handling, but finer details
//! and performance characteristics may be different than LÖVE.
//!
//! ggez is not meant to be everything to everyone, but rather a good
//! base upon which to build.  Thus it takes a fairly
//! batteries-included approach without needing a million additions
//! and plugins for everything imaginable, but also does not dictate
//! higher-level functionality such as physics engine or entity
//! component system.  Instead the goal is to allow you to use
//! whichever libraries you want to provide these functions, or build
//! your own libraries atop ggez.
//!
//! ## Features
//!
//! * Filesystem abstraction that lets you load resources from folders or zip files
//! * Hardware-accelerated 2D rendering built on the `gfx-rs` graphics engine
//! * Loading and playing .ogg, .wav and .flac files via the `rodio` crate
//! * TTF font rendering with `rusttype` and `glyph_brush`.
//! * Interface for handling keyboard and mouse events easily through callbacks
//! * Config file for defining engine and game settings
//! * Easy timing and FPS measurement functions.
//! * Math library integration with `mint`.
//! * Some more advanced graphics options: shaders, sprite batches and render targets
//!
//! ## Supported platforms
//!
//!  * Fully supported: Windows, Linux
//!  * Not officially supported but might work anyway: Mac, iOS
//!  * Work in progress: WebAssembly
//!  * Not officially supported yet (but maybe you can help!): Android
//!
//! For details, see [docs/BuildingForEveryPlatform.md](docs/BuildingForEveryPlatform.md)
//!
//! ## Who's using ggez?
//!
//! Check out the [projects list!](docs/Projects.md)
//!
//! ## Usage
//!
//! ggez requires rustc >= 1.40 and is distributed on
//! crates.io. To include it in your project, just add the dependency
//! line to your `Cargo.toml` file:
//!
//! ```text
//! ggez = "0.6"
//! ```
//!
//! ggez consists of three main parts: A `Context` object which
//! contains all the state required to interface with the computer's
//! hardware, an `EventHandler` trait that the user implements to
//! register callbacks for events, and various sub-modules such as
//! `graphics` and `audio` that provide the functionality to actually
//! get stuff done.  The general pattern is to create a struct holding
//! your game's data which implements the `EventHandler` trait.
//! Create a new `Context` object with default objects from a `ContextBuilder`
//! or `Conf` object, and then call `event::run()` with
//! the `Context` and an instance of your `EventHandler` to run your game's
//! main loop.
//!
//! See the [API docs](https://docs.rs/ggez/) for full documentation, or the [examples](/examples) directory for a number of commented examples of varying complexity.  Most examples show off
//! a single feature of ggez, while `astroblasto` and `snake` are small but complete games.
//!
//! ## Getting started
//!
//! For a quick tutorial on ggez, see the [Hello ggez](https://github.com/ggez/ggez/blob/master/docs/guides/HelloGgez.md) guide in the `docs/` directory.
//!
//! ## Examples
//!
//! See the `examples/` directory in the source.  Most examples show off
//! a single feature of ggez, while `astroblasto` is a small  but
//! complete Asteroids-like game.
//!
//! To run the examples, just check out the source and execute `cargo run --example`
//! in the root directory:
//!
//! ```text
//! git clone https://github.com/ggez/ggez.git
//! cd ggez
//! cargo run --example 05_astroblasto
//! ```
//!
//! If this doesn't work, see the
//! [FAQ](https://github.com/ggez/ggez/blob/master/docs/FAQ.md) for solutions
//! to common problems.
//!
//! ### Basic Project Template
//!
//! ```rust,no_run
//! use ggez::{Context, ContextBuilder, GameResult};
//! use ggez::graphics::{self, Color};
//! use ggez::event::{self, EventHandler};
//!
//! fn main() {
//!     // Make a Context.
//!     let (mut ctx, event_loop) = ContextBuilder::new("my_game", "Cool Game Author")
//!         .build()
//!         .expect("aieee, could not create ggez context!");
//!
//!     // Create an instance of your event handler.
//!     // Usually, you should provide it with the Context object to
//!     // use when setting your game up.
//!     let my_game = MyGame::new(&mut ctx);
//!
//!     // Run!
//!     event::run(ctx, event_loop, my_game);
//! }
//!
//! struct MyGame {
//!     // Your state here...
//! }
//!
//! impl MyGame {
//!     pub fn new(_ctx: &mut Context) -> MyGame {
//!         // Load/create resources such as images here.
//!         MyGame {
//!             // ...
//!         }
//!     }
//! }
//!
//! impl EventHandler for MyGame {
//!     fn update(&mut self, _ctx: &mut Context) -> GameResult<()> {
//!         // Update code here...
//!         Ok(())
//!     }
//!
//!     fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
//!         graphics::clear(ctx, Color::WHITE);
//!         // Draw code here...
//!         graphics::present(ctx)
//!     }
//! }
//! ```
//!
//! ## Implementation details
//!
//! ggez is built upon `winit` for windowing and events, `rodio` for
//! sound, and a 2D drawing engine implemented in `gfx` using the OpenGL
//! backend (which currently defaults to use OpenGL 3.2).  It is entirely
//! thread-safe (though platform constraints mean the event-handling loop
//! and drawing must be done in the main thread), and portable to Windows
//! and Linux.
//!
//! ggez is pure Rust™.
//!
//! ## Help!
//!
//! Sources of information:
//!
//!  * The [FAQ](https://github.com/ggez/ggez/blob/master/docs/FAQ.md) has answers to common questions and problems.
//!  * The [API docs](https://docs.rs/ggez/), a lot of design stuff is explained there.
//!  * Check out the [examples](https://github.com/ggez/ggez/tree/master/examples).
//!
//!  If you still have problems or questions, feel free to ask!  Easiest ways are:
//!
//!  * Open an issue on [the Github issue tracker](https://github.com/ggez/ggez/issues)
//!  * Say hi on the [unofficial Rust Discord server](http://bit.ly/rust-community) or the [Rust Gamedev server](https://discord.gg/yNtPTb2)

#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unused_results)]
// This is not as strong a constraint as `#![forbid(unsafe_code)]` but is good enough.
// It means the only place we use unsafe is then in the modules noted as allowing it.
#![deny(unsafe_code)]
#![warn(bare_trait_objects)]
#![warn(missing_copy_implementations)]
#![allow(clippy::needless_doctest_main)]

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate gfx;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate smart_default;

pub extern crate mint;

pub mod audio;
pub mod conf;
mod context;
pub mod error;
pub mod event;
pub mod filesystem;
pub mod graphics;
pub mod input;
pub mod timer;
mod vfs;

#[cfg(test)]
pub mod tests;

pub use crate::context::{Context, ContextBuilder};
pub use crate::error::*;
<|endoftext|>