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

#[cfg(test)]
extern crate assert;

extern crate libc;
extern crate num;

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

mod beta;

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

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

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

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

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

/// Compute the real valued digamma function. `d/dx ln Gamma(x)`.
/// Appriximation based on Beal, Matthew J. (2003). *Variational
/// Algorithms for Approximate Bayesian Inference* (PhD thesis). The
/// Gatsby Computational Neuroscience Unit, University College
/// London. pp. 265–266
///
/// # Examples
///
/// ```
/// use special::digamma;
///
/// let euler_mascheroni = 0.5772156649015325;
/// assert_eq!(-euler_mascheroni, digamma(1.0));
/// ```
#[inline]
pub fn digamma(x: f64)-> f64 {
    if x > 8.0 {
        let inv_x = x.recip();
        let inv_x_e2 = inv_x.powi(2);
        x.ln() - 0.5*inv_x - inv_x_e2 * (0.08333333333333333
                                         - 0.008333333333333333 * inv_x_e2
                                         + 0.003968253968253968 * inv_x_e2.powi(2)
                                         - 0.004166666666666667 * inv_x_e2.powi(3)
                                         + 0.007575757575757576 * inv_x_e2.powi(4)
                                         - 0.021092796092796094 * inv_x_e2.powi(5)
                                         + 0.08333333333333333 * inv_x_e2.powi(6)
                                         - 0.4432598039215686 * inv_x_e2.powi(7))
    } else {
        // Shift by recurrence
        digamma(x + 1.0) - x.recip()
    }
}

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

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

        assert_eq!(-FRAC_PI_2 - 3.0 * LN_2 - euler_mascheroni, digamma(0.25));
    }
}
<commit_msg>Replaced crude polynomial evaluation with horner<commit_after>//! [Special functions][1].
//!
//! [1]: https://en.wikipedia.org/wiki/Special_functions

#[cfg(test)]
extern crate assert;

extern crate libc;
extern crate num;

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

mod beta;

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

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

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

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

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

// Use Horners method to evaluate polynomials at `x0`
macro_rules! eval_poly {
    ( $x0:expr; $( $p:expr ),* ) => {
        {
            let mut coefs = vec![$($p,)*];
            coefs.reverse();
            let mut sum = 0.0;
            for c in coefs.iter() {
                sum = sum * $x0 + c;
            }
            sum
        }
    }
}

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

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

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

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


<commit_before>//! A dead-simple test helper for rust.
//!
//! Example
//! --------
//!
//! ```rust
//! use bear::fixture;
//!
//! // Get a content of 'tests/fixtures/hello.txt'
//! let content = fixture("hello.txt");
//!
//! // Do whatever you want with it
//! ```

#![doc(
    html_logo_url = "https://simnalamburt.github.io/bear/cute.png",
    html_favicon_url = "https://simnalamburt.github.io/bear/cute.png",
    html_root_url = "https://simnalamburt.github.io/bear"
)]

use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::Path;

/// Open a file from the 'tests/fixtures' directory, and return its content as a `String`
///
/// Example
/// --------
///
/// ```rust
/// use bear::fixture;
///
/// // Get a content of 'tests/fixtures/hello.txt'
/// let content = fixture("hello.txt");
///
/// /* Do whatever you want with it */
/// ```
pub fn fixture(filename: &str) -> String {
    let path = Path::new("tests").join("fixtures").join(filename);
    let file = File::open(&path).unwrap();
    let mut reader = BufReader::new(file);

    let mut ret = String::new();

    reader.read_to_string(&mut ret).unwrap();

    ret
}
<commit_msg>lib.rs: Fix logo<commit_after>//! A dead-simple test helper for rust.
//!
//! Example
//! --------
//!
//! ```rust
//! use bear::fixture;
//!
//! // Get a content of 'tests/fixtures/hello.txt'
//! let content = fixture("hello.txt");
//!
//! // Do whatever you want with it
//! ```

#![doc(
    html_logo_url = "https://raw.githubusercontent.com/simnalamburt/i/master/bear/cute.png",
    html_favicon_url = "https://raw.githubusercontent.com/simnalamburt/i/master/bear/cute.png",
)]

use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::Path;

/// Open a file from the 'tests/fixtures' directory, and return its content as a `String`
///
/// Example
/// --------
///
/// ```rust
/// use bear::fixture;
///
/// // Get a content of 'tests/fixtures/hello.txt'
/// let content = fixture("hello.txt");
///
/// /* Do whatever you want with it */
/// ```
pub fn fixture(filename: &str) -> String {
    let path = Path::new("tests").join("fixtures").join(filename);
    let file = File::open(&path).unwrap();
    let mut reader = BufReader::new(file);

    let mut ret = String::new();

    reader.read_to_string(&mut ret).unwrap();

    ret
}
<|endoftext|>


<commit_before>/* Rust doesn't directly expose __attribute__((constructor)), but this
 * is how dyld implements it. */
#[link_section = "__DATA,__mod_init_func"]
pub static INITIALIZE_CTOR: extern "C" fn() = ::initialize;

#[macro_export]
macro_rules! hook {
    (unsafe fn $real_fn:ident ( $($v:ident : $t:ty),* ) -> $r:ty => $hook_fn:ident $body:block) => {
        pub mod $real_fn {
            #[allow(non_camel_case_types)]
            pub struct $real_fn {
                _new: *const (),
                _old: *const (),
            }

            #[allow(dead_code)]
            #[allow(non_upper_case_globals)]
            #[link_section="__DATA,__interpose"]
            pub static mut $real_fn: $real_fn = $real_fn {
                _new: super::$hook_fn as *const (),
                _old: super::$real_fn as *const (),
            };
        }

        extern {
            pub fn $real_fn ( $($v : $t),* ) -> $r;
        }

        pub unsafe extern fn $hook_fn ( $($v : $t),* ) -> $r {
            if $crate::initialized() {
                ::std::panic::catch_unwind(|| $body ).ok()
            } else {
                None
            }.unwrap_or_else(|| $real_fn ( $($v),* ))
        }
    };

    (unsafe fn $real_fn:ident ( $($v:ident : $t:ty),* ) => $hook_fn:ident $body:block) => {
        hook! { unsafe fn $real_fn ( $($v : $t),* ) -> () => $hook_fn $body }
    };
}

#[macro_export]
macro_rules! real {
    ($real_fn:ident) => {
        $real_fn
    };
}
<commit_msg>Also on macOS<commit_after>/* Rust doesn't directly expose __attribute__((constructor)), but this
 * is how dyld implements it. */
#[link_section = "__DATA,__mod_init_func"]
pub static INITIALIZE_CTOR: extern "C" fn() = ::initialize;

#[macro_export]
macro_rules! hook {
    (unsafe fn $real_fn:ident ( $($v:ident : $t:ty),* ) -> $r:ty => $hook_fn:ident $body:block) => {
        pub mod $real_fn {
            #[allow(non_camel_case_types)]
            pub struct $real_fn {
                _new: *const (),
                _old: *const (),
            }

            #[allow(dead_code)]
            #[allow(non_upper_case_globals)]
            #[link_section="__DATA,__interpose"]
            pub static mut $real_fn: $real_fn = $real_fn {
                _new: super::$hook_fn as *const (),
                _old: super::$real_fn as *const (),
            };
        }

        extern {
            pub fn $real_fn ( $($v : $t),* ) -> $r;
        }

        pub unsafe extern fn $hook_fn ( $($v : $t),* ) -> $r {
            if $crate::initialized() {
                ::std::panic::catch_unwind(|| $body ).ok()
            } else {
                None
            }.unwrap_or_else(|| $real_fn ( $($v),* ))
        }
    };

    (unsafe fn $real_fn:ident ( $($v:ident : $t:ty),* ) => $hook_fn:ident $body:block) => {
        $crate::hook! { unsafe fn $real_fn ( $($v : $t),* ) -> () => $hook_fn $body }
    };
}

#[macro_export]
macro_rules! real {
    ($real_fn:ident) => {
        $real_fn
    };
}
<|endoftext|>


<commit_before>//! Algorithmia client library
//!
//! # Examples
//!
//! ```no_run
//! use algorithmia::Algorithmia;
//!
//! // Initialize with an API key
//! let client = Algorithmia::client("111112222233333444445555566");
//! let moving_avg = client.algo("timeseries/SimpleMovingAverage/0.1");
//!
//! // Run the algorithm using a type safe decoding of the output to Vec<int>
//! //   since this algorithm outputs results as a JSON array of integers
//! let input = (vec![0,1,2,3,15,4,5,6,7], 3);
//! let result: Vec<f64> = moving_avg.pipe(&input).unwrap().decode().unwrap();
//! println!("Completed with result: {:?}", result);
//! ```

#![doc(html_logo_url = "https://algorithmia.com/assets/images/logos/png/bintreePurple.png")]
#![doc(test(attr(allow(unused_variables), allow(dead_code))))]

#![cfg_attr(feature="nightly", feature(specialization))]
#![recursion_limit = "1024"]

#![allow(unknown_lints)]

#[cfg(feature="with-serde")]
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate mime;
#[macro_use]
extern crate hyper;
#[macro_use]
extern crate error_chain;

#[cfg(feature="with-serde")]
extern crate serde;
#[cfg(feature="with-serde")]
extern crate serde_json;
#[cfg(feature="with-rustc-serialize")]
extern crate rustc_serialize;
extern crate reqwest;
extern crate base64;
extern crate chrono;
extern crate url;

use algo::{Algorithm, AlgoUri};
use data::{DataDir, DataFile, DataObject, HasDataPath};
use client::HttpClient;

pub mod algo;
pub mod data;
pub mod error;
mod client;
pub use error::Error;
pub use reqwest::{Url, IntoUrl};
pub use client::ApiAuth;
pub use reqwest::Body;

#[cfg(feature="with-serde")]
#[path = "json-serde.rs"]
mod json;

#[cfg(feature="with-rustc-serialize")]
#[path = "json-rustc-serialize.rs"]
mod json;

/// Reexports of the most common types and traits
pub mod prelude {
    pub use Algorithmia;
    pub use client::ApiAuth;
    pub use algo::{EntryPoint, DecodedEntryPoint, AlgoInput, AlgoOutput, JsonValue};
    pub use data::HasDataPath;
}

mod version;

static DEFAULT_API_BASE_URL: &'static str = "https://api.algorithmia.com";

/// The top-level struct for instantiating Algorithmia client endpoints
pub struct Algorithmia {
    http_client: HttpClient,
}

impl<'a, 'c> Algorithmia {
    /// Instantiate a new client
    ///
    /// Client should be instatiated with your API key, except
    ///   when running within an algorithm on the Algorithmia platform.
    ///
    /// # Examples
    /// ```
    /// use algorithmia::*;
    /// // Initialize a client
    /// let client = Algorithmia::client("simUseYourApiKey");
    ///
    /// // Initialize a client (for algorithms running on the Algorithmia platform)
    /// let client = Algorithmia::client(ApiAuth::None);
    /// ```
    pub fn client<A: Into<ApiAuth>>(api_key: A) -> Algorithmia {
        let api_address = std::env::var("ALGORITHMIA_API")
            .unwrap_or_else(|_| DEFAULT_API_BASE_URL.into());
        Algorithmia { http_client: HttpClient::new(api_key.into(), &api_address) }
    }

    /// Instantiate a new client against alternate API servers
    pub fn client_with_url<A: Into<ApiAuth>, U: IntoUrl>(base_url: U, api_key: A) -> Algorithmia {
        Algorithmia { http_client: HttpClient::new(api_key.into(), base_url) }
    }

    /// Instantiate an [`Algorithm`](algo/algorithm.struct.html) from this client
    ///
    /// By using In
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let factor = client.algo("anowell/Dijkstra/0.1");
    /// ```
    pub fn algo<A: Into<AlgoUri>>(&self, algorithm: A) -> Algorithm {
        Algorithm::new(self.http_client.clone(), algorithm.into())
    }

    /// Instantiate a `DataDirectory` from this client
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let rustfoo = client.dir("data://.my/rustfoo");
    /// ```
    pub fn dir(&self, path: &'a str) -> DataDir {
        DataDir::new(self.http_client.clone(), path)
    }

    /// Instantiate a `DataDirectory` from this client
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let rustfoo = client.file("data://.my/rustfoo");
    /// ```
    pub fn file(&self, path: &'a str) -> DataFile {
        DataFile::new(self.http_client.clone(), path)
    }

    /// Instantiate a `DataPath` from this client
    ///
    /// Use this if you don't explicitly know if a Data URI is to a directory or file
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let rustfoo = client.data("data://.my/rustfoo/what_am_i");
    /// ```
    pub fn data(&self, path: &'a str) -> DataObject {
        DataObject::new(self.http_client.clone(), path)
    }
}

/// Allow cloning in order to reuse http client (and API key) for multiple connections
impl Clone for Algorithmia {
    fn clone(&self) -> Algorithmia {
        Algorithmia { http_client: self.http_client.clone() }
    }
}

/// The default Algorithmia client uses environment variables
///   `ALGORITHMIA_API` to override the default base URL of the API
///   and `ALGORITHMIA_API_KEY` to optionally the API key.
impl Default for Algorithmia {
    fn default() -> Algorithmia {
        let api_address = std::env::var("ALGORITHMIA_API")
            .unwrap_or_else(|_| DEFAULT_API_BASE_URL.into());
        let api_key =
            std::env::var("ALGORITHMIA_API_KEY").map(ApiAuth::from).unwrap_or(ApiAuth::None);
        Algorithmia { http_client: HttpClient::new(api_key, &api_address) }
    }
}
<commit_msg>leave Error behind the error module<commit_after>//! Algorithmia client library
//!
//! # Examples
//!
//! ```no_run
//! use algorithmia::Algorithmia;
//!
//! // Initialize with an API key
//! let client = Algorithmia::client("111112222233333444445555566");
//! let moving_avg = client.algo("timeseries/SimpleMovingAverage/0.1");
//!
//! // Run the algorithm using a type safe decoding of the output to Vec<int>
//! //   since this algorithm outputs results as a JSON array of integers
//! let input = (vec![0,1,2,3,15,4,5,6,7], 3);
//! let result: Vec<f64> = moving_avg.pipe(&input).unwrap().decode().unwrap();
//! println!("Completed with result: {:?}", result);
//! ```

#![doc(html_logo_url = "https://algorithmia.com/assets/images/logos/png/bintreePurple.png")]
#![doc(test(attr(allow(unused_variables), allow(dead_code))))]

#![cfg_attr(feature="nightly", feature(specialization))]
#![recursion_limit = "1024"]

#![allow(unknown_lints)]

#[cfg(feature="with-serde")]
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate mime;
#[macro_use]
extern crate hyper;
#[macro_use]
extern crate error_chain;

#[cfg(feature="with-serde")]
extern crate serde;
#[cfg(feature="with-serde")]
extern crate serde_json;
#[cfg(feature="with-rustc-serialize")]
extern crate rustc_serialize;
extern crate reqwest;
extern crate base64;
extern crate chrono;
extern crate url;

use algo::{Algorithm, AlgoUri};
use data::{DataDir, DataFile, DataObject, HasDataPath};
use client::HttpClient;

pub mod algo;
pub mod data;
pub mod error;
pub use reqwest::{Url, IntoUrl};
pub use client::ApiAuth;
pub use reqwest::Body;

#[cfg(feature="with-serde")]
#[path = "json-serde.rs"]
mod json;

#[cfg(feature="with-rustc-serialize")]
#[path = "json-rustc-serialize.rs"]
mod json;

/// Reexports of the most common types and traits
pub mod prelude {
    pub use Algorithmia;
    pub use client::ApiAuth;
    pub use algo::{EntryPoint, DecodedEntryPoint, AlgoInput, AlgoOutput, JsonValue};
    pub use data::HasDataPath;
}

mod client;
mod version;

static DEFAULT_API_BASE_URL: &'static str = "https://api.algorithmia.com";

/// The top-level struct for instantiating Algorithmia client endpoints
pub struct Algorithmia {
    http_client: HttpClient,
}

impl<'a, 'c> Algorithmia {
    /// Instantiate a new client
    ///
    /// Client should be instatiated with your API key, except
    ///   when running within an algorithm on the Algorithmia platform.
    ///
    /// # Examples
    /// ```
    /// use algorithmia::*;
    /// // Initialize a client
    /// let client = Algorithmia::client("simUseYourApiKey");
    ///
    /// // Initialize a client (for algorithms running on the Algorithmia platform)
    /// let client = Algorithmia::client(ApiAuth::None);
    /// ```
    pub fn client<A: Into<ApiAuth>>(api_key: A) -> Algorithmia {
        let api_address = std::env::var("ALGORITHMIA_API")
            .unwrap_or_else(|_| DEFAULT_API_BASE_URL.into());
        Algorithmia { http_client: HttpClient::new(api_key.into(), &api_address) }
    }

    /// Instantiate a new client against alternate API servers
    pub fn client_with_url<A: Into<ApiAuth>, U: IntoUrl>(base_url: U, api_key: A) -> Algorithmia {
        Algorithmia { http_client: HttpClient::new(api_key.into(), base_url) }
    }

    /// Instantiate an [`Algorithm`](algo/algorithm.struct.html) from this client
    ///
    /// By using In
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let factor = client.algo("anowell/Dijkstra/0.1");
    /// ```
    pub fn algo<A: Into<AlgoUri>>(&self, algorithm: A) -> Algorithm {
        Algorithm::new(self.http_client.clone(), algorithm.into())
    }

    /// Instantiate a `DataDirectory` from this client
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let rustfoo = client.dir("data://.my/rustfoo");
    /// ```
    pub fn dir(&self, path: &'a str) -> DataDir {
        DataDir::new(self.http_client.clone(), path)
    }

    /// Instantiate a `DataDirectory` from this client
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let rustfoo = client.file("data://.my/rustfoo");
    /// ```
    pub fn file(&self, path: &'a str) -> DataFile {
        DataFile::new(self.http_client.clone(), path)
    }

    /// Instantiate a `DataPath` from this client
    ///
    /// Use this if you don't explicitly know if a Data URI is to a directory or file
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let rustfoo = client.data("data://.my/rustfoo/what_am_i");
    /// ```
    pub fn data(&self, path: &'a str) -> DataObject {
        DataObject::new(self.http_client.clone(), path)
    }
}

/// Allow cloning in order to reuse http client (and API key) for multiple connections
impl Clone for Algorithmia {
    fn clone(&self) -> Algorithmia {
        Algorithmia { http_client: self.http_client.clone() }
    }
}

/// The default Algorithmia client uses environment variables
///   `ALGORITHMIA_API` to override the default base URL of the API
///   and `ALGORITHMIA_API_KEY` to optionally the API key.
impl Default for Algorithmia {
    fn default() -> Algorithmia {
        let api_address = std::env::var("ALGORITHMIA_API")
            .unwrap_or_else(|_| DEFAULT_API_BASE_URL.into());
        let api_key =
            std::env::var("ALGORITHMIA_API_KEY").map(ApiAuth::from).unwrap_or(ApiAuth::None);
        Algorithmia { http_client: HttpClient::new(api_key, &api_address) }
    }
}
<|endoftext|>


<commit_before>extern crate itertools;

use std::collections::{BTreeMap, HashSet};
use std::hash::{Hash, Hasher};
use std::rc::Rc;

use itertools::Itertools;

/// A Document contains an id and content.
/// Hashing and equality are based only on the id field.
#[derive(Clone, Eq, Debug)]
pub struct Document {
    id: String,
    content: String,
}

impl Document {
    /// Construct a new Document from an id and content.
    /// Both two arguments can be anything that can be turned into a String.
    pub fn new<S, T>(id: S, content: T) -> Document
        where S: Into<String>,
              T: Into<String>
    {
        Document { id: id.into(), content: content.into(), }
    }

    pub fn id(&self) -> &str {
        &self.id
    }

    pub fn content(&self) -> &str {
        &self.content
    }
}

impl Hash for Document {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        state.write(self.id.as_bytes());
    }
}

impl PartialEq<Document> for Document {
    fn eq(&self, other: &Document) -> bool {
        self.id == other.id
    }
}

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
struct SearchResult {
    pub doc: Rc<Document>,
    pub highlighted: (usize, usize)
}

/// An Index is anything that can store Documents and return matching Documents for a query.
trait Index {
    /// Given a Document, stores it in the index.
    fn index(&mut self, doc: Document);
    /// Given a query, return the set of Documents that match the query.
    /// What constitutes a "match" is implementation-specific; loosely, a Document should
    /// match a query if they are somehow related. A naive implementation might simply
    /// return the set of Documents for which `query` is a substring of their content.
    fn search(&self, query: &str) -> HashSet<SearchResult>;
}

/// A basic implementation of an `Index`, the inverted index is a data structure that maps
/// from words to sets of Documents.
type InvertedIndex = BTreeMap<String, HashSet<SearchResult>>;

impl Index for InvertedIndex {
    /// A basic implementation of index, splits the document's content into whitespace-separated
    /// words, and inserts each word-document pair into the map.
    fn index(&mut self, doc: Document) {
        let doc = Rc::new(doc);
        let analyzed = doc.content()
            .char_indices()
            .group_by(|&(_, c)| c.is_whitespace())
            .filter(|&(is_whitespace, _)| !is_whitespace)
            .flat_map(|(_, chars)| (1..chars.len() + 1).map(move |to| {
                let word: String = chars[..to].iter().map(|&(_, c)| c).collect();
                let start = chars[0].0;
                let (last_idx, last_char) = chars[to - 1];
                let finish = last_idx + last_char.len_utf8();
                (word, (start, finish))
            }));

        for (ngram, highlighted) in analyzed {
            self.entry(ngram).or_insert_with(|| HashSet::new())
                .insert(SearchResult { doc: doc.clone(), highlighted: highlighted });
        }
    }

    /// A basic search implementation that splits the query's content into whitespace-separated
    /// words, looks up the set of Documents for each word, and then concatenates the sets.
    fn search(&self, query: &str) -> HashSet<SearchResult> {
        query.split_whitespace()
            .flat_map(|word| self.get(word))
            .flat_map(|docs| docs)
            .cloned()
            .collect()
    }
}

#[test]
fn test_search1() {
    let mut index = InvertedIndex::new();
    let doc1 = Document::new("1", "learn to program in rust today");
    let doc2 = Document::new("2", "what did you today do");
    index.index(doc1.clone());
    index.index(doc2.clone());
    let search_results = index.search("today");
    assert!(search_results.contains(&SearchResult { doc: Rc::new(doc1), highlighted: (25, 30) }));
    assert!(search_results.contains(&SearchResult { doc: Rc::new(doc2), highlighted: (13, 18) }));
}

#[test]
fn test_ngrams() {
    let mut index = InvertedIndex::new();
    let doc1 = Document::new("1", "learn to program in rust today");
    let doc2 = Document::new("2", "what did you today do");
    index.index(doc1.clone());
    index.index(doc2.clone());
    let search_results = index.search("to");
    println!("{:?}", search_results);
    assert!(search_results.contains(&SearchResult { doc: Rc::new(doc1), highlighted: (25, 27) }));
    assert!(search_results.contains(&SearchResult { doc: Rc::new(doc2), highlighted: (13, 15) }));
}

#[test]
fn test_search2() {
    let mut index = InvertedIndex::new();
    index.index(Document::new("2", "what to do today"));
    index.index(Document::new("3", "hey today"));
    let search_results = index.search("to");
    assert_eq!(search_results.len(), 3);
}

#[test]
fn test_unicode() {
    let mut index = InvertedIndex::new();
    let doc = Document::new("0", "abc åäö");
    index.index(doc.clone());
    let to_search = "å";
    let result = index.search(to_search).into_iter().next().unwrap();
    let (begin, end) = result.highlighted;
    assert_eq!(&result.doc.content()[begin..end], to_search);
}

<commit_msg>Implement highlighted content (not just highlight indexes)<commit_after>extern crate itertools;

use std::collections::{BTreeMap, HashMap, HashSet};
use std::hash::{Hash, Hasher};
use std::rc::Rc;

use itertools::Itertools;

/// A Document contains an id and content.
/// Hashing and equality are based only on the id field.
#[derive(Clone, Eq, Debug)]
pub struct Document {
    id: String,
    content: String,
}

impl Document {
    /// Construct a new Document from an id and content.
    /// Both two arguments can be anything that can be turned into a String.
    pub fn new<S, T>(id: S, content: T) -> Document
        where S: Into<String>,
              T: Into<String>
    {
        Document { id: id.into(), content: content.into(), }
    }

    pub fn id(&self) -> &str {
        &self.id
    }

    pub fn content(&self) -> &str {
        &self.content
    }
}

impl Hash for Document {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        state.write(self.id.as_bytes());
    }
}

impl PartialEq<Document> for Document {
    fn eq(&self, other: &Document) -> bool {
        self.id == other.id
    }
}

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
struct IndexedDocument {
    pub doc: Rc<Document>,
    pub highlighted: (usize, usize),
}

/// An Index is anything that can store Documents and return matching Documents for a query.
trait Index {
    /// Given a Document, stores it in the index.
    fn index(&mut self, doc: Document);
    /// Given a query, return the set of Documents that match the query.
    /// What constitutes a "match" is implementation-specific; loosely, a Document should
    /// match a query if they are somehow related. A naive implementation might simply
    /// return the set of Documents for which `query` is a substring of their content.
    fn search(&self, query: &str) -> HashSet<SearchResult>;
}

/// A basic implementation of an `Index`, the inverted index is a data structure that maps
/// from words to sets of Documents.
type InvertedIndex = BTreeMap<String, HashSet<IndexedDocument>>;

impl Index for InvertedIndex {
    /// A basic implementation of index, splits the document's content into whitespace-separated
    /// words, and inserts each word-document pair into the map.
    fn index(&mut self, doc: Document) {
        let doc = Rc::new(doc);
        let analyzed = doc.content()
            .char_indices()
            .group_by(|&(_, c)| c.is_whitespace())
            .filter(|&(is_whitespace, _)| !is_whitespace)
            .flat_map(|(_, chars)| (1..chars.len() + 1).map(move |to| {
                let word: String = chars[..to].iter().map(|&(_, c)| c).collect();
                let start = chars[0].0;
                let (last_idx, last_char) = chars[to - 1];
                let finish = last_idx + last_char.len_utf8();
                (word, (start, finish))
            }));

        for (ngram, highlighted) in analyzed {
            self.entry(ngram).or_insert_with(|| HashSet::new())
                .insert(IndexedDocument { doc: doc.clone(), highlighted: highlighted });
        }
    }

    /// A basic search implementation that splits the query's content into whitespace-separated
    /// words, looks up the set of Documents for each word, and then concatenates the sets.
    fn search(&self, query: &str) -> HashSet<SearchResult> {
        let map = query.split_whitespace()
            .flat_map(|word| self.get(word))
            .flat_map(|docs| docs)
            .cloned()
            .fold(HashMap::new(), |mut map, search_result| {
                map.entry(search_result.doc)
                    .or_insert(Vec::new())
                    .push(search_result.highlighted);
                map
            });
        map.into_iter()
            .map(|(doc, mut highlights)| {
                highlights.sort();
                SearchResult { doc: doc, highlights: highlights }
            })
        .collect()
    }
}

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct SearchResult {
    doc: Rc<Document>,
    highlights: Vec<(usize, usize)>,
}

impl SearchResult {
    #[cfg(test)]
    fn new(doc: Rc<Document>, highlights: Vec<(usize, usize)>) -> SearchResult {
        SearchResult {
            doc: doc,
            highlights: highlights,
        }
    }

    pub fn doc(&self) -> &Rc<Document> {
        &self.doc
    }

    pub fn highlights(&self) -> &Vec<(usize, usize)> {
        &self.highlights
    }

    pub fn highlighted_content(&self) -> String {
        let &SearchResult {ref doc, ref highlights} = self;
        let content = doc.content();
        let mut begin_idx = 0;
        let mut parts = vec![];
        for &(begin, end) in highlights {
            parts.push(&content[begin_idx..begin]);
            parts.push("");
            parts.push(&content[begin..end]);
            parts.push("");
            begin_idx = end;
        }
        parts.push(&content[begin_idx..]);
        parts.into_iter().join("")
    }
}

#[test]
fn test_search1() {
    let mut index = InvertedIndex::new();
    let doc1 = Document::new("1", "learn to program in rust today");
    index.index(doc1.clone());
    let doc2 = Document::new("2", "what did you today do");
    index.index(doc2.clone());
    let search_results = index.search("today");
    let expected = [
        SearchResult::new(Rc::new(doc1), vec![(25, 30)]),
        SearchResult::new(Rc::new(doc2), vec![(13, 18)])
    ];
    assert_eq!(search_results, expected.iter().cloned().collect());
    assert_eq!("learn to program in rust today", expected[0].highlighted_content());
}

#[test]
fn test_ngrams() {
    let mut index = InvertedIndex::new();
    let doc1 = Document::new("1", "learn to program in rust today");
    let doc2 = Document::new("2", "what did you today do");
    index.index(doc1.clone());
    index.index(doc2.clone());
    let search_results = index.search("to");
    let expected = [
        SearchResult::new(Rc::new(doc1), vec![(6, 8), (25, 27)]),
        SearchResult::new(Rc::new(doc2), vec![(13, 15)]),
    ];
    assert_eq!(search_results, expected.iter().cloned().collect());
    assert_eq!("learn to program in rust today", expected[0].highlighted_content());

}

#[test]
fn test_search2() {
    let mut index = InvertedIndex::new();
    let doc1 = Document::new("2", "what to do today");
    let doc2 = Document::new("3", "hey today");
    index.index(doc1.clone());
    index.index(doc2.clone());
    let search_results = index.search("to");
    let expected = [
        SearchResult::new(Rc::new(doc1), vec![(5, 7), (11, 13)]),
        SearchResult::new(Rc::new(doc2), vec![(4, 6)]),
    ];
    assert_eq!(search_results, expected.iter().cloned().collect());
    assert_eq!(expected[0].highlighted_content(), "what to do today");
}

#[test]
fn test_unicode() {
    let mut index = InvertedIndex::new();
    let doc = Document::new("0", "abc åäö");
    index.index(doc.clone());
    let to_search = "å";
    let search_results = index.search(to_search);
    let &SearchResult { ref doc, ref highlights } = search_results.iter().next().unwrap();
    let (begin, end) = highlights[0];
    assert_eq!(&doc.content()[begin..end], to_search);
}
<|endoftext|>


<commit_before>use std::env::args;
use std::env::var;
use std::slice;
use std::str;

#[derive(Debug)]
pub struct Loger {
    // mod 路径 。通过init!()初始化(默认只打印当前 crate 的)，..用参数/环境变量设置
    ptr: *const u8,
    len: usize,
    // log状态,默认关闭。
    status: bool,
}
static mut LOGER: Loger = Loger {
    ptr: 0 as *const u8,
    len: 0,
    status: false,
};

const KEY_VAR: &'static str = "LOG"; // env LOG=*
const KEY_ARG: &'static str = "log"; // exe -log[--log]

impl Loger {
    pub fn set(module_path: &str) {
        let (mut mp, mut status) = (module_path.to_owned(), false);

        // 取环境变量
        if let Ok(ok) = var(KEY_VAR) {
            mp = ok;
            status = true;
        }
        //环境变量为空则取命令行参数
        if !status {
            let args_vec: Vec<String> = args().collect();
            let mut idx = 0;
            for _ in 0..args_vec.len() {
                if args_vec[idx] == format!("-{}", KEY_ARG) ||
                   args_vec[idx] == format!("--{}", KEY_ARG) {
                    //如果无值，开启crate的log.
                    status = true;
                    if idx + 1 < args_vec.len() {
                        mp = args_vec[idx + 1].clone();
                    }
                    break;
                }
                idx += 1;
            }
        }
        unsafe {
            LOGER.ptr = mp.as_str().as_ptr();
            LOGER.len = mp.len();
            LOGER.status = status;
        }
    }
    pub fn get() -> String {
        unsafe { String::from_utf8_lossy(slice::from_raw_parts(LOGER.ptr, LOGER.len)).into_owned() }
    }
    pub fn status() -> bool {
        unsafe { LOGER.status }
    }

    // #[doc(hidden)]
    pub fn mp_parse(module_path: &'static str) -> bool {
        let refer = Self::get();
        //"*"匹配的全部。
        if refer == "*" {
            return true;
        }
        //完全匹配,避免后面切片失败。
        if module_path == refer {
            return true;
        }
        //属于该模块。
        if module_path.starts_with(&refer) && (&module_path[refer.len()..]).starts_with(':') {
            return true;
        }
        false
    }
}

#[macro_export]
macro_rules! init {
    () => {
        let msg= module_path!();
        //fht2p::server::args::app -> fht2p
        let sep_idx= msg.find(":").unwrap_or(msg.len()) ;
        Loger::set(&msg[..sep_idx] );
    };
}
#[macro_export]
macro_rules! db {
    ($($arg:tt)*) => {
        {
             if Loger::status() &&Loger::mp_parse(module_path!()) {
                use std::io::{self, Write};
                // Panics if writing to io::stdout() fails.
                write!(&mut io::stderr(),$($arg)*).unwrap();
         }
        }
        };
}
#[macro_export]
macro_rules! dbln {
       () => (db!("\n"));
       ($fmt:expr) => (db!(concat!($fmt, "\n")));
        ($fmt:expr, $($arg:tt)*) => (db!(concat!($fmt, "\n"), $($arg)*));
}
// dbst!,dbstln!
#[macro_export]
macro_rules! dbst {
    ($($arg:tt)*) => {
        {
         if Loger::status() &&Loger::mp_parse(module_path!()) {
                    use std::io::{self, Write};
                    if let Ok(..) =  write!(&mut io::stderr(),$($arg)* ) {};
                    // Do nothing if writing to io::stdout() fails(silent->st).
              }
        }
        };
}
#[macro_export]
macro_rules! dbstln {
       () => (dbst!("\n"));
       ($fmt:expr) => (dbst!(concat!($fmt, "\n")));
        ($fmt:expr, $($arg:tt)*) => (dbst!(concat!($fmt, "\n"), $($arg)*));
        // Do nothing if writing to io::stdout() fails(silent->st).
}
<commit_msg>fix bug about drop  by `mem::forget.<commit_after>use std::mem::forget;
use std::env::args;
use std::env::var;
use std::slice;
use std::str;

#[derive(Debug)]
pub struct Loger {
    // mod 路径 。通过init!()初始化(默认只打印当前 crate 的)，..用参数/环境变量设置
    ptr: *const u8,
    len: usize,
    // log状态,默认关闭。
    status: bool,
}
static mut LOGER: Loger = Loger {
    ptr: 0 as *const u8,
    len: 0,
    status: false,
};
// 不知道string的那个from_raw_parts方法也这样搞是不是也对。
const KEY_VAR: &'static str = "LOG"; // env LOG=*
const KEY_ARG: &'static str = "log"; // exe -log[--log]

impl Loger {
    pub fn set(module_path: &str) {
        let (mut mp, mut status) = (module_path.to_owned(), false);

        // 取环境变量
        if let Ok(ok) = var(KEY_VAR) {
            mp = ok;
            status = true;
        }
        //环境变量为空则取命令行参数
        if !status {
            let args_vec: Vec<String> = args().collect();
            let mut idx = 0;
            for _ in 0..args_vec.len() {
                if args_vec[idx] == format!("-{}", KEY_ARG) ||
                   args_vec[idx] == format!("--{}", KEY_ARG) {
                    //如果无值，开启crate的log.
                    status = true;
                    if idx + 1 < args_vec.len() {
                        mp = args_vec[idx + 1].clone();
                    }
                    break;
                }
                idx += 1;
            }
        }
        let ptr = mp.as_str().as_ptr();
        let len = mp.len();
        forget(mp);
        unsafe {
            LOGER.ptr = ptr;
            LOGER.len = len;
            LOGER.status = status;
        }
    }
    pub fn get() -> String {
        unsafe { String::from_utf8_lossy(slice::from_raw_parts(LOGER.ptr, LOGER.len)).into_owned() }
    }
    pub fn status() -> bool {
        unsafe { LOGER.status }
    }

    // #[doc(hidden)]
    pub fn mp_parse(module_path: &'static str) -> bool {
        let refer = Self::get();
        // println!("mp_parse()-Debug: {:?}@{:?}", refer, module_path);
        // println!("mp_parse()-Display: {}@{}", refer, module_path);
        //"*"匹配的全部。
        if refer == "*" {
            return true;
        }
        //完全匹配,避免后面切片失败。
        if module_path == refer {
            return true;
        }
        //属于该模块。
        // println!("mp_parse()-slice: {:?}", &module_path[refer.len()..]);
        if module_path.starts_with(&refer) && (&module_path[refer.len()..]).starts_with(":") {
            return true;
        }
        false
    }
}

#[macro_export]
macro_rules! init {
    () => {
        let msg= module_path!();
        //fht2p::server::args::app -> fht2p
        let sep_idx= msg.find(":").unwrap_or(msg.len()) ;
        Loger::set(&msg[..sep_idx] );
    };
}
#[macro_export]
macro_rules! db {
    ($($arg:tt)*) => {
        {
             if Loger::status() &&Loger::mp_parse(module_path!()) {
                use std::io::{self, Write};
                // Panics if writing to io::stdout() fails.
                write!(&mut io::stderr(),$($arg)*).unwrap();
         }
        }
        };
}
#[macro_export]
macro_rules! dbln {
       () => (db!("\n"));
       ($fmt:expr) => (db!(concat!($fmt, "\n")));
        ($fmt:expr, $($arg:tt)*) => (db!(concat!($fmt, "\n"), $($arg)*));
}
// dbst!,dbstln!
#[macro_export]
macro_rules! dbst {
    ($($arg:tt)*) => {
        {
         if Loger::status() &&Loger::mp_parse(module_path!()) {
                    use std::io::{self, Write};
                    if let Ok(..) =  write!(&mut io::stderr(),$($arg)* ) {};
                    // Do nothing if writing to io::stdout() fails(silent->st).
              }
        }
        };
}
#[macro_export]
macro_rules! dbstln {
       () => (dbst!("\n"));
       ($fmt:expr) => (dbst!(concat!($fmt, "\n")));
        ($fmt:expr, $($arg:tt)*) => (dbst!(concat!($fmt, "\n"), $($arg)*));
        // Do nothing if writing to io::stdout() fails(silent->st).
}
<|endoftext|>


<commit_before>use nom::{
  IResult,
  ErrorCode, Err,
  Needed,
};

use frame;
use frame::subframe;

fn leading_zeros(input: (&[u8], usize)) -> IResult<(&[u8], usize), u32> {
  let (bytes, mut offset) = input;

  let mut index     = 0;
  let mut count     = 0;
  let mut is_parsed = false;
  let bytes_len     = bytes.len();

  for i in 0..bytes_len {
    // Clear the number of offset bits
    let byte  = bytes[i] << offset;
    let zeros = byte.leading_zeros() as usize;

    if byte > 0 {
      index     = i;
      is_parsed = true;
      count    += zeros;
      offset   += zeros + 1;

      if offset >= 8 {
        index  += 1;
        offset -= 8;
      }

      break;
    } else {
      count += zeros - offset;
      offset = 0;
    }
  }

  if is_parsed {
    IResult::Done((&bytes[index..], offset), count as u32)
  } else if index + 1 > bytes_len {
    IResult::Incomplete(Needed::Size(index + 1))
  } else {
    IResult::Error(Err::Position(ErrorCode::TakeUntil as u32, bytes))
  }
}

fn header(input: (&[u8], usize)) -> IResult<(&[u8], usize), (u8, bool)> {
  let result = chain!(input,
    bit_padding: take_bits!(u8, 1) ~
    subframe_type: take_bits!(u8, 6) ~
    wasted_bit_flag: take_bits!(u8, 1),
    || {
      let is_valid        = bit_padding == 0;
      let has_wasted_bits = wasted_bit_flag == 1;

      (is_valid, subframe_type, has_wasted_bits)
    }
  );

  match result {
    IResult::Done(i, data)    => {
      let (is_valid, subframe_type, has_wasted_bits) = data;

      if is_valid {
        IResult::Done(i, (subframe_type, has_wasted_bits))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn data<'a>(input: (&'a [u8], usize),
            frame_header: &frame::Header,
            subframe_type: usize,
            wasted_bits: usize)
            -> IResult<'a, (&'a [u8], usize), subframe::Data> {
  let bits_per_sample = frame_header.bits_per_sample - wasted_bits;
  let block_size      = frame_header.block_size as usize;

  match subframe_type {
    0b000000 => constant(input, bits_per_sample),
    _        => IResult::Error(Err::Position(ErrorCode::Alt as u32, input.0))
  }
}

fn constant(input: (&[u8], usize), bits_per_sample: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  map!(input, take_bits!(i32, bits_per_sample), subframe::Data::Constant)
}

fn verbatim(input: (&[u8], usize), bits_per_sample: usize, block_size: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  // TODO: Use nom's `count!` macro as soon as it is fixed for bit parsers.
  map!(input, count_bits!(take_bits!(i32, bits_per_sample), block_size),
       subframe::Data::Verbatim)
}
<commit_msg>Add `verbatim` to the subframe data parser<commit_after>use nom::{
  IResult,
  ErrorCode, Err,
  Needed,
};

use frame;
use frame::subframe;

fn leading_zeros(input: (&[u8], usize)) -> IResult<(&[u8], usize), u32> {
  let (bytes, mut offset) = input;

  let mut index     = 0;
  let mut count     = 0;
  let mut is_parsed = false;
  let bytes_len     = bytes.len();

  for i in 0..bytes_len {
    // Clear the number of offset bits
    let byte  = bytes[i] << offset;
    let zeros = byte.leading_zeros() as usize;

    if byte > 0 {
      index     = i;
      is_parsed = true;
      count    += zeros;
      offset   += zeros + 1;

      if offset >= 8 {
        index  += 1;
        offset -= 8;
      }

      break;
    } else {
      count += zeros - offset;
      offset = 0;
    }
  }

  if is_parsed {
    IResult::Done((&bytes[index..], offset), count as u32)
  } else if index + 1 > bytes_len {
    IResult::Incomplete(Needed::Size(index + 1))
  } else {
    IResult::Error(Err::Position(ErrorCode::TakeUntil as u32, bytes))
  }
}

fn header(input: (&[u8], usize)) -> IResult<(&[u8], usize), (u8, bool)> {
  let result = chain!(input,
    bit_padding: take_bits!(u8, 1) ~
    subframe_type: take_bits!(u8, 6) ~
    wasted_bit_flag: take_bits!(u8, 1),
    || {
      let is_valid        = bit_padding == 0;
      let has_wasted_bits = wasted_bit_flag == 1;

      (is_valid, subframe_type, has_wasted_bits)
    }
  );

  match result {
    IResult::Done(i, data)    => {
      let (is_valid, subframe_type, has_wasted_bits) = data;

      if is_valid {
        IResult::Done(i, (subframe_type, has_wasted_bits))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn data<'a>(input: (&'a [u8], usize),
            frame_header: &frame::Header,
            subframe_type: usize,
            wasted_bits: usize)
            -> IResult<'a, (&'a [u8], usize), subframe::Data> {
  let bits_per_sample = frame_header.bits_per_sample - wasted_bits;
  let block_size      = frame_header.block_size as usize;

  match subframe_type {
    0b000000 => constant(input, bits_per_sample),
    0b000001 => verbatim(input, bits_per_sample, block_size),
    _        => IResult::Error(Err::Position(ErrorCode::Alt as u32, input.0))
  }
}

fn constant(input: (&[u8], usize), bits_per_sample: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  map!(input, take_bits!(i32, bits_per_sample), subframe::Data::Constant)
}

fn verbatim(input: (&[u8], usize), bits_per_sample: usize, block_size: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  // TODO: Use nom's `count!` macro as soon as it is fixed for bit parsers.
  map!(input, count_bits!(take_bits!(i32, bits_per_sample), block_size),
       subframe::Data::Verbatim)
}
<|endoftext|>


<commit_before>use nom::{
  IResult,
  ErrorCode, Err,
  Needed,
};

use frame;
use frame::subframe;
use frame::SubFrame;

fn leading_zeros(input: (&[u8], usize)) -> IResult<(&[u8], usize), u32> {
  let (bytes, mut offset) = input;

  let mut index     = 0;
  let mut count     = 0;
  let mut is_parsed = false;
  let bytes_len     = bytes.len();

  for i in 0..bytes_len {
    // Clear the number of offset bits
    let byte  = bytes[i] << offset;
    let zeros = byte.leading_zeros() as usize;

    if byte > 0 {
      index     = i;
      is_parsed = true;
      count    += zeros;
      offset   += zeros + 1;

      if offset >= 8 {
        index  += 1;
        offset -= 8;
      }

      break;
    } else {
      count += zeros - offset;
      offset = 0;
    }
  }

  if is_parsed {
    IResult::Done((&bytes[index..], offset), count as u32)
  } else if index + 1 > bytes_len {
    IResult::Incomplete(Needed::Size(index + 1))
  } else {
    IResult::Error(Err::Position(ErrorCode::TakeUntil as u32, bytes))
  }
}

pub fn subframe_parser<'a>(input: (&'a [u8], usize),
                           frame_header: &frame::Header)
                           -> IResult<'a, (&'a [u8], usize), SubFrame> {
  chain!(input,
    subframe_header: header ~
    wasted_bits: map!(
      cond!(subframe_header.1, leading_zeros),
      |option: Option<u32>| option.map_or(0, |zeros| zeros + 1)
    ) ~
    subframe_data: apply!(data, frame_header, subframe_header.0 as usize,
                          wasted_bits as usize),
    || {
      SubFrame {
        data: subframe_data,
        wasted_bits: wasted_bits,
      }
    }
  )
}

fn header(input: (&[u8], usize)) -> IResult<(&[u8], usize), (u8, bool)> {
  match take_bits!(input, u8, 8) {
    IResult::Done(i, byte)    => {
      let is_valid        = (byte >> 7) == 0;
      let subframe_type   = (byte >> 1) & 0b111111;
      let has_wasted_bits = (byte & 0b01) == 1;

      if is_valid {
        IResult::Done(i, (subframe_type, has_wasted_bits))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn data<'a>(input: (&'a [u8], usize),
            frame_header: &frame::Header,
            subframe_type: usize,
            wasted_bits: usize)
            -> IResult<'a, (&'a [u8], usize), subframe::Data> {
  let bits_per_sample = frame_header.bits_per_sample - wasted_bits;
  let block_size      = frame_header.block_size as usize;

  match subframe_type {
    0b000000 => constant(input, bits_per_sample),
    0b000001 => verbatim(input, bits_per_sample, block_size),
    _        => IResult::Error(Err::Position(ErrorCode::Alt as u32, input.0))
  }
}

fn constant(input: (&[u8], usize), bits_per_sample: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  map!(input, take_bits!(i32, bits_per_sample), subframe::Data::Constant)
}

fn verbatim(input: (&[u8], usize), bits_per_sample: usize, block_size: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  // TODO: Use nom's `count!` macro as soon as it is fixed for bit parsers.
  map!(input, count_bits!(take_bits!(i32, bits_per_sample), block_size),
       subframe::Data::Verbatim)
}

fn residual_data<'a>(input: (&'a [u8], usize),
                     option: Option<usize>,
                     rice_parameter: u32,
                     raw_bit: &mut u32,
                     samples: &mut [i32])
                     -> IResult<'a, (&'a [u8], usize), ()> {
  if let Some(size) = option {
    unencoded_residuals(input, size, raw_bit, samples)
  } else {
    encoded_residuals(input, rice_parameter, raw_bit, samples)
  }
}

fn unencoded_residuals<'a>(input: (&'a [u8], usize),
                           bits_per_sample: usize,
                           raw_bit: &mut u32,
                           samples: &mut [i32])
                           -> IResult<'a, (&'a[u8], usize), ()> {
  *raw_bit = bits_per_sample as u32;

  count_slice!(input, take_bits!(i32, bits_per_sample), &mut samples[..])
}

fn encoded_residuals<'a>(input: (&'a [u8], usize),
                         parameter: u32,
                         raw_bit: &mut u32,
                         samples: &mut [i32])
                         -> IResult<'a, (&'a[u8], usize), ()> {
  let length = samples.len();

  let mut count     = 0;
  let mut is_error  = false;
  let mut mut_input = input;

  *raw_bit = 0;

  for sample in samples {
    let result = chain!(mut_input,
      quotient: leading_zeros ~
      remainder: take_bits!(u32, parameter as usize),
      || {
        let value = quotient * parameter + remainder;

        ((value as i32) >> 1) ^ -((value as i32) & 1)
      });

    match result {
      IResult::Done(i, value) => {
        mut_input = i;
        count    += 1;

        *sample = value
      }
      IResult::Error(_)       => {
        is_error = true;

        break;
      }
      IResult::Incomplete(_)  => break,
    }
  }

  if is_error {
    IResult::Error(Err::Position(ErrorCode::Count as u32, input.0))
  } else if count == length {
    IResult::Done(mut_input, ())
  } else {
    IResult::Incomplete(Needed::Unknown)
  }
}
<commit_msg>Add `rice_partition` parser<commit_after>use nom::{
  IResult,
  ErrorCode, Err,
  Needed,
};

use frame;
use frame::subframe;
use frame::SubFrame;
use frame::subframe::{CodingMethod, PartitionedRiceContents};

fn leading_zeros(input: (&[u8], usize)) -> IResult<(&[u8], usize), u32> {
  let (bytes, mut offset) = input;

  let mut index     = 0;
  let mut count     = 0;
  let mut is_parsed = false;
  let bytes_len     = bytes.len();

  for i in 0..bytes_len {
    // Clear the number of offset bits
    let byte  = bytes[i] << offset;
    let zeros = byte.leading_zeros() as usize;

    if byte > 0 {
      index     = i;
      is_parsed = true;
      count    += zeros;
      offset   += zeros + 1;

      if offset >= 8 {
        index  += 1;
        offset -= 8;
      }

      break;
    } else {
      count += zeros - offset;
      offset = 0;
    }
  }

  if is_parsed {
    IResult::Done((&bytes[index..], offset), count as u32)
  } else if index + 1 > bytes_len {
    IResult::Incomplete(Needed::Size(index + 1))
  } else {
    IResult::Error(Err::Position(ErrorCode::TakeUntil as u32, bytes))
  }
}

pub fn subframe_parser<'a>(input: (&'a [u8], usize),
                           frame_header: &frame::Header)
                           -> IResult<'a, (&'a [u8], usize), SubFrame> {
  chain!(input,
    subframe_header: header ~
    wasted_bits: map!(
      cond!(subframe_header.1, leading_zeros),
      |option: Option<u32>| option.map_or(0, |zeros| zeros + 1)
    ) ~
    subframe_data: apply!(data, frame_header, subframe_header.0 as usize,
                          wasted_bits as usize),
    || {
      SubFrame {
        data: subframe_data,
        wasted_bits: wasted_bits,
      }
    }
  )
}

fn header(input: (&[u8], usize)) -> IResult<(&[u8], usize), (u8, bool)> {
  match take_bits!(input, u8, 8) {
    IResult::Done(i, byte)    => {
      let is_valid        = (byte >> 7) == 0;
      let subframe_type   = (byte >> 1) & 0b111111;
      let has_wasted_bits = (byte & 0b01) == 1;

      if is_valid {
        IResult::Done(i, (subframe_type, has_wasted_bits))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn data<'a>(input: (&'a [u8], usize),
            frame_header: &frame::Header,
            subframe_type: usize,
            wasted_bits: usize)
            -> IResult<'a, (&'a [u8], usize), subframe::Data> {
  let bits_per_sample = frame_header.bits_per_sample - wasted_bits;
  let block_size      = frame_header.block_size as usize;

  match subframe_type {
    0b000000 => constant(input, bits_per_sample),
    0b000001 => verbatim(input, bits_per_sample, block_size),
    _        => IResult::Error(Err::Position(ErrorCode::Alt as u32, input.0))
  }
}

fn constant(input: (&[u8], usize), bits_per_sample: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  map!(input, take_bits!(i32, bits_per_sample), subframe::Data::Constant)
}

fn verbatim(input: (&[u8], usize), bits_per_sample: usize, block_size: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  // TODO: Use nom's `count!` macro as soon as it is fixed for bit parsers.
  map!(input, count_bits!(take_bits!(i32, bits_per_sample), block_size),
       subframe::Data::Verbatim)
}

fn rice_partition(input: (&[u8], usize),
                  partition_order: u32,
                  predictor_order: usize,
                  block_size: usize,
                  method: CodingMethod)
                  -> IResult<(&[u8], usize),
                             (subframe::EntropyCodingMethod, Vec<i32>)> {
  let (param_size, escape_code) = match method {
    CodingMethod::PartitionedRice  => (4, 0b1111),
    CodingMethod::PartitionedRice2 => (5, 0b11111),
  };

  // Adjust block size to not include allocation for warm up samples
  let residual_size = block_size - predictor_order;

  let mut mut_input = input;
  let mut residual  = Vec::with_capacity(residual_size);
  let mut sample    = 0;
  let mut contents  = PartitionedRiceContents::new(partition_order);

  unsafe { residual.set_len(residual_size) }

  let partitions = 2_usize.pow(partition_order);

  for partition in 0..partitions {
    let offset = if partition_order == 0 {
      block_size - predictor_order
    } else if partition > 0 {
      block_size / partitions
    } else {
      (block_size / partitions) - predictor_order
    };
    let start = sample;
    let end   = sample + offset;

    let result = chain!(mut_input,
      rice_parameter: take_bits!(u32, param_size) ~
      size: cond!(rice_parameter == escape_code, take_bits!(usize, 5)) ~
      data: apply!(residual_data,
        size, rice_parameter,
        &mut contents.raw_bits[partition],
        &mut residual[start..end]
      ),
      || { rice_parameter }
    );

    match result {
      IResult::Done(i, parameter) => {
        mut_input = i;
        sample    = end;

        contents.parameters[partition] = parameter;
      }
      IResult::Error(error)       => return IResult::Error(error),
      IResult::Incomplete(need)   => return IResult::Incomplete(need),
    }
  }

  let entropy_coding_method = subframe::EntropyCodingMethod {
    method_type: method,
    data: subframe::PartitionedRice {
      order: partition_order,
      contents: contents,
    },
  };

  IResult::Done(mut_input, (entropy_coding_method, residual))
}

fn residual_data<'a>(input: (&'a [u8], usize),
                     option: Option<usize>,
                     rice_parameter: u32,
                     raw_bit: &mut u32,
                     samples: &mut [i32])
                     -> IResult<'a, (&'a [u8], usize), ()> {
  if let Some(size) = option {
    unencoded_residuals(input, size, raw_bit, samples)
  } else {
    encoded_residuals(input, rice_parameter, raw_bit, samples)
  }
}

fn unencoded_residuals<'a>(input: (&'a [u8], usize),
                           bits_per_sample: usize,
                           raw_bit: &mut u32,
                           samples: &mut [i32])
                           -> IResult<'a, (&'a[u8], usize), ()> {
  *raw_bit = bits_per_sample as u32;

  count_slice!(input, take_bits!(i32, bits_per_sample), &mut samples[..])
}

fn encoded_residuals<'a>(input: (&'a [u8], usize),
                         parameter: u32,
                         raw_bit: &mut u32,
                         samples: &mut [i32])
                         -> IResult<'a, (&'a[u8], usize), ()> {
  let length = samples.len();

  let mut count     = 0;
  let mut is_error  = false;
  let mut mut_input = input;

  *raw_bit = 0;

  for sample in samples {
    let result = chain!(mut_input,
      quotient: leading_zeros ~
      remainder: take_bits!(u32, parameter as usize),
      || {
        let value = quotient * parameter + remainder;

        ((value as i32) >> 1) ^ -((value as i32) & 1)
      });

    match result {
      IResult::Done(i, value) => {
        mut_input = i;
        count    += 1;

        *sample = value
      }
      IResult::Error(_)       => {
        is_error = true;

        break;
      }
      IResult::Incomplete(_)  => break,
    }
  }

  if is_error {
    IResult::Error(Err::Position(ErrorCode::Count as u32, input.0))
  } else if count == length {
    IResult::Done(mut_input, ())
  } else {
    IResult::Incomplete(Needed::Unknown)
  }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};

use graph::geometry::Geometry;
use graph::mesh::{Edge, Mesh, Vertex};
use graph::storage::{EdgeKey, VertexKey};
use graph::topology::{EdgeView, OrphanEdgeView, OrphanView, Topological, View};

#[derive(Clone, Copy)]
pub struct VertexView<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    mesh: M,
    key: VertexKey,
    phantom: PhantomData<G>,
}

impl<M, G> VertexView<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    pub(crate) fn new(mesh: M, vertex: VertexKey) -> Self {
        VertexView {
            mesh: mesh,
            key: vertex,
            phantom: PhantomData,
        }
    }

    pub fn key(&self) -> VertexKey {
        self.key
    }

    pub fn outgoing_edge(&self) -> Option<EdgeView<&Mesh<G>, G>> {
        self.edge
            .map(|edge| EdgeView::new(self.mesh.as_ref(), edge))
    }

    pub fn into_outgoing_edge(self) -> Option<EdgeView<M, G>> {
        let edge = self.edge;
        let mesh = self.mesh;
        edge.map(|edge| EdgeView::new(mesh, edge))
    }

    pub fn edges(&self) -> EdgeCirculator<&Mesh<G>, G> {
        EdgeCirculator::new(self.with_mesh_ref())
    }

    // Resolve the `M` parameter to a concrete reference.
    fn with_mesh_ref(&self) -> VertexView<&Mesh<G>, G> {
        VertexView::new(self.mesh.as_ref(), self.key)
    }
}

impl<M, G> VertexView<M, G>
where
    M: AsRef<Mesh<G>> + AsMut<Mesh<G>>,
    G: Geometry,
{
    pub fn outgoing_edge_mut(&mut self) -> Option<OrphanEdgeView<G>> {
        let edge = self.edge;
        edge.map(move |edge| {
            OrphanEdgeView::new(
                &mut self.mesh.as_mut().edges.get_mut(&edge).unwrap().geometry,
                edge,
            )
        })
    }

    pub fn edges_mut(&mut self) -> EdgeCirculator<&mut Mesh<G>, G> {
        EdgeCirculator::new(self.with_mesh_mut())
    }

    // Resolve the `M` parameter to a concrete reference.
    fn with_mesh_mut(&mut self) -> VertexView<&mut Mesh<G>, G> {
        VertexView::new(self.mesh.as_mut(), self.key)
    }
}

impl<M, G> AsRef<VertexView<M, G>> for VertexView<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    fn as_ref(&self) -> &VertexView<M, G> {
        self
    }
}

impl<M, G> AsMut<VertexView<M, G>> for VertexView<M, G>
where
    M: AsRef<Mesh<G>> + AsMut<Mesh<G>>,
    G: Geometry,
{
    fn as_mut(&mut self) -> &mut VertexView<M, G> {
        self
    }
}

impl<M, G> Deref for VertexView<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    type Target = Vertex<G>;

    fn deref(&self) -> &Self::Target {
        self.mesh.as_ref().vertices.get(&self.key).unwrap()
    }
}

impl<M, G> DerefMut for VertexView<M, G>
where
    M: AsRef<Mesh<G>> + AsMut<Mesh<G>>,
    G: Geometry,
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.mesh.as_mut().vertices.get_mut(&self.key).unwrap()
    }
}

impl<M, G> View<M, G> for VertexView<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    type Topology = Vertex<G>;

    fn of(mesh: M, key: <Self::Topology as Topological>::Key) -> Self {
        VertexView::new(mesh, key)
    }
}

pub struct OrphanVertexView<'a, G>
where
    G: 'a + Geometry,
{
    key: VertexKey,
    // The name `geometry` mirrors the `geometry` field of `Vertex`, to which
    // `VertexView` derefs.
    pub geometry: &'a mut G::Vertex,
}

impl<'a, G> OrphanVertexView<'a, G>
where
    G: 'a + Geometry,
{
    pub(crate) fn new(geometry: &'a mut G::Vertex, vertex: VertexKey) -> Self {
        OrphanVertexView {
            key: vertex,
            geometry: geometry,
        }
    }

    pub fn key(&self) -> VertexKey {
        self.key
    }
}

impl<'a, G> OrphanView<'a, G> for OrphanVertexView<'a, G>
where
    G: 'a + Geometry,
{
    type Topology = Vertex<G>;

    fn of(topology: &'a mut Self::Topology, key: <Self::Topology as Topological>::Key) -> Self {
        OrphanVertexView::new(&mut topology.geometry, key)
    }
}

pub struct EdgeCirculator<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    vertex: VertexView<M, G>,
    edge: Option<EdgeKey>,
    breadcrumb: Option<EdgeKey>,
}

impl<M, G> EdgeCirculator<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    fn new(vertex: VertexView<M, G>) -> Self {
        let edge = vertex.edge;
        EdgeCirculator {
            vertex: vertex,
            edge: edge,
            breadcrumb: edge,
        }
    }

    fn next(&mut self) -> Option<EdgeKey> {
        self.edge
            .map(|outgoing| {
                self.vertex.mesh.as_ref().edges.get(&outgoing).unwrap()
            })
            .and_then(|outgoing| outgoing.opposite)
            .and_then(|incoming| {
                let outgoing = self.vertex.mesh.as_ref().edges.get(&incoming).unwrap().next;
                self.breadcrumb.map(|_| {
                    if self.breadcrumb == outgoing {
                        self.breadcrumb = None;
                    }
                    else {
                        self.edge = outgoing;
                    }
                    incoming
                })
            })
    }
}

impl<'a, G> Iterator for EdgeCirculator<&'a Mesh<G>, G>
where
    G: Geometry,
{
    type Item = EdgeView<&'a Mesh<G>, G>;

    fn next(&mut self) -> Option<Self::Item> {
        <EdgeCirculator<_, _>>::next(self).map(|edge| EdgeView::new(self.vertex.mesh, edge))
    }
}

impl<'a, G> Iterator for EdgeCirculator<&'a mut Mesh<G>, G>
where
    G: Geometry,
{
    type Item = OrphanEdgeView<'a, G>;

    fn next(&mut self) -> Option<Self::Item> {
        <EdgeCirculator<_, _>>::next(self).map(|edge| {
            let geometry = {
                unsafe {
                    use std::mem;

                    // There is no way to bind the anonymous lifetime of this
                    // function to `Self::Item`. This is problematic for the
                    // call to `get_mut`, which requires autoref. However, this
                    // should be safe, because the use of this iterator
                    // requires a mutable borrow of the source mesh with
                    // lifetime `'a`. Therefore, the (disjoint) geometry data
                    // within the mesh should also be valid over the lifetime
                    // '`a'.
                    let edge = mem::transmute::<_, &'a mut Edge<G>>(
                        self.vertex.mesh.edges.get_mut(&edge).unwrap(),
                    );
                    &mut edge.geometry
                }
            };
            OrphanEdgeView::new(geometry, edge)
        })
    }
}

#[cfg(test)]
mod tests {
    use generate::*;
    use graph::*;
    use ordered::*;

    #[test]
    fn circulate_over_edges() {
        let mesh = sphere::UVSphere::<f32>::with_unit_radius(4, 2)
            .polygons_with_position() // 6 triangles, 18 vertices.
            .map_vertices(|vertex| vertex.into_hash())
            .collect::<Mesh<Triplet<_>>>();

        // All faces should be triangles and all vertices should have 4
        // (incoming) edges.
        for vertex in mesh.vertices() {
            assert_eq!(4, vertex.edges().count());
        }
    }
}
<commit_msg>Implement face circulator for vertices.<commit_after>use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};

use graph::geometry::Geometry;
use graph::mesh::{Edge, Face, Mesh, Vertex};
use graph::storage::{EdgeKey, FaceKey, VertexKey};
use graph::topology::{EdgeView, FaceView, OrphanEdgeView, OrphanFaceView, OrphanView, Topological,
                      View};

#[derive(Clone, Copy)]
pub struct VertexView<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    mesh: M,
    key: VertexKey,
    phantom: PhantomData<G>,
}

impl<M, G> VertexView<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    pub(crate) fn new(mesh: M, vertex: VertexKey) -> Self {
        VertexView {
            mesh: mesh,
            key: vertex,
            phantom: PhantomData,
        }
    }

    pub fn key(&self) -> VertexKey {
        self.key
    }

    pub fn outgoing_edge(&self) -> Option<EdgeView<&Mesh<G>, G>> {
        self.edge
            .map(|edge| EdgeView::new(self.mesh.as_ref(), edge))
    }

    pub fn into_outgoing_edge(self) -> Option<EdgeView<M, G>> {
        let edge = self.edge;
        let mesh = self.mesh;
        edge.map(|edge| EdgeView::new(mesh, edge))
    }

    pub fn edges(&self) -> EdgeCirculator<&Mesh<G>, G> {
        EdgeCirculator::new(self.with_mesh_ref())
    }

    pub fn faces(&self) -> FaceCirculator<&Mesh<G>, G> {
        FaceCirculator::from_edge_circulator(self.edges())
    }

    // Resolve the `M` parameter to a concrete reference.
    fn with_mesh_ref(&self) -> VertexView<&Mesh<G>, G> {
        VertexView::new(self.mesh.as_ref(), self.key)
    }
}

impl<M, G> VertexView<M, G>
where
    M: AsRef<Mesh<G>> + AsMut<Mesh<G>>,
    G: Geometry,
{
    pub fn outgoing_edge_mut(&mut self) -> Option<OrphanEdgeView<G>> {
        let edge = self.edge;
        edge.map(move |edge| {
            OrphanEdgeView::new(
                &mut self.mesh.as_mut().edges.get_mut(&edge).unwrap().geometry,
                edge,
            )
        })
    }

    pub fn edges_mut(&mut self) -> EdgeCirculator<&mut Mesh<G>, G> {
        EdgeCirculator::new(self.with_mesh_mut())
    }

    pub fn faces_mut(&mut self) -> FaceCirculator<&mut Mesh<G>, G> {
        FaceCirculator::from_edge_circulator(self.edges_mut())
    }

    // Resolve the `M` parameter to a concrete reference.
    fn with_mesh_mut(&mut self) -> VertexView<&mut Mesh<G>, G> {
        VertexView::new(self.mesh.as_mut(), self.key)
    }
}

impl<M, G> AsRef<VertexView<M, G>> for VertexView<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    fn as_ref(&self) -> &VertexView<M, G> {
        self
    }
}

impl<M, G> AsMut<VertexView<M, G>> for VertexView<M, G>
where
    M: AsRef<Mesh<G>> + AsMut<Mesh<G>>,
    G: Geometry,
{
    fn as_mut(&mut self) -> &mut VertexView<M, G> {
        self
    }
}

impl<M, G> Deref for VertexView<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    type Target = Vertex<G>;

    fn deref(&self) -> &Self::Target {
        self.mesh.as_ref().vertices.get(&self.key).unwrap()
    }
}

impl<M, G> DerefMut for VertexView<M, G>
where
    M: AsRef<Mesh<G>> + AsMut<Mesh<G>>,
    G: Geometry,
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.mesh.as_mut().vertices.get_mut(&self.key).unwrap()
    }
}

impl<M, G> View<M, G> for VertexView<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    type Topology = Vertex<G>;

    fn of(mesh: M, key: <Self::Topology as Topological>::Key) -> Self {
        VertexView::new(mesh, key)
    }
}

pub struct OrphanVertexView<'a, G>
where
    G: 'a + Geometry,
{
    key: VertexKey,
    // The name `geometry` mirrors the `geometry` field of `Vertex`, to which
    // `VertexView` derefs.
    pub geometry: &'a mut G::Vertex,
}

impl<'a, G> OrphanVertexView<'a, G>
where
    G: 'a + Geometry,
{
    pub(crate) fn new(geometry: &'a mut G::Vertex, vertex: VertexKey) -> Self {
        OrphanVertexView {
            key: vertex,
            geometry: geometry,
        }
    }

    pub fn key(&self) -> VertexKey {
        self.key
    }
}

impl<'a, G> OrphanView<'a, G> for OrphanVertexView<'a, G>
where
    G: 'a + Geometry,
{
    type Topology = Vertex<G>;

    fn of(topology: &'a mut Self::Topology, key: <Self::Topology as Topological>::Key) -> Self {
        OrphanVertexView::new(&mut topology.geometry, key)
    }
}

pub struct EdgeCirculator<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    vertex: VertexView<M, G>,
    edge: Option<EdgeKey>,
    breadcrumb: Option<EdgeKey>,
}

impl<M, G> EdgeCirculator<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    fn new(vertex: VertexView<M, G>) -> Self {
        let edge = vertex.edge;
        EdgeCirculator {
            vertex: vertex,
            edge: edge,
            breadcrumb: edge,
        }
    }

    fn next(&mut self) -> Option<EdgeKey> {
        self.edge
            .map(|outgoing| {
                self.vertex.mesh.as_ref().edges.get(&outgoing).unwrap()
            })
            .and_then(|outgoing| outgoing.opposite)
            .and_then(|incoming| {
                let outgoing = self.vertex.mesh.as_ref().edges.get(&incoming).unwrap().next;
                self.breadcrumb.map(|_| {
                    if self.breadcrumb == outgoing {
                        self.breadcrumb = None;
                    }
                    else {
                        self.edge = outgoing;
                    }
                    incoming
                })
            })
    }
}

impl<'a, G> Iterator for EdgeCirculator<&'a Mesh<G>, G>
where
    G: Geometry,
{
    type Item = EdgeView<&'a Mesh<G>, G>;

    fn next(&mut self) -> Option<Self::Item> {
        <EdgeCirculator<_, _>>::next(self).map(|edge| EdgeView::new(self.vertex.mesh, edge))
    }
}

impl<'a, G> Iterator for EdgeCirculator<&'a mut Mesh<G>, G>
where
    G: Geometry,
{
    type Item = OrphanEdgeView<'a, G>;

    fn next(&mut self) -> Option<Self::Item> {
        <EdgeCirculator<_, _>>::next(self).map(|edge| {
            let geometry = {
                unsafe {
                    use std::mem;

                    // There is no way to bind the anonymous lifetime of this
                    // function to `Self::Item`. This is problematic for the
                    // call to `get_mut`, which requires autoref. However, this
                    // should be safe, because the use of this iterator
                    // requires a mutable borrow of the source mesh with
                    // lifetime `'a`. Therefore, the (disjoint) geometry data
                    // within the mesh should also be valid over the lifetime
                    // '`a'.
                    let edge = mem::transmute::<_, &'a mut Edge<G>>(
                        self.vertex.mesh.edges.get_mut(&edge).unwrap(),
                    );
                    &mut edge.geometry
                }
            };
            OrphanEdgeView::new(geometry, edge)
        })
    }
}

pub struct FaceCirculator<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    inner: EdgeCirculator<M, G>,
}

impl<M, G> FaceCirculator<M, G>
where
    M: AsRef<Mesh<G>>,
    G: Geometry,
{
    fn from_edge_circulator(edges: EdgeCirculator<M, G>) -> Self {
        FaceCirculator { inner: edges }
    }

    fn next(&mut self) -> Option<FaceKey> {
        while let Some(edge) = self.inner.next().map(|edge| {
            self.inner.vertex.mesh.as_ref().edges.get(&edge).unwrap()
        }) {
            if let Some(face) = edge.face {
                return Some(face);
            }
            else {
                // Skip edges with no face. This can occur within non-enclosed
                // meshes.
                continue;
            }
        }
        None
    }
}

impl<'a, G> Iterator for FaceCirculator<&'a Mesh<G>, G>
where
    G: Geometry,
{
    type Item = FaceView<&'a Mesh<G>, G>;

    fn next(&mut self) -> Option<Self::Item> {
        <FaceCirculator<_, _>>::next(self).map(|face| FaceView::new(self.inner.vertex.mesh, face))
    }
}

impl<'a, G> Iterator for FaceCirculator<&'a mut Mesh<G>, G>
where
    G: 'a + Geometry,
{
    // This cannot be a `FaceView`, because that would alias the mutable
    // reference to the mesh. Instead, yield the key and a mutable reference to
    // the geometry data as an `OrphanFaceView` that discards any traversable
    // reference into the mesh.
    type Item = OrphanFaceView<'a, G>;

    fn next(&mut self) -> Option<Self::Item> {
        <FaceCirculator<_, _>>::next(self).map(|face| {
            let geometry = {
                unsafe {
                    use std::mem;

                    // There is no way to bind the anonymous lifetime of this
                    // function to `Self::Item`. This is problematic for the
                    // call to `get_mut`, which requires autoref. However, this
                    // should be safe, because the use of this iterator
                    // requires a mutable borrow of the source mesh with
                    // lifetime `'a`. Therefore, the (disjoint) geometry data
                    // within the mesh should also be valid over the lifetime
                    // '`a'.
                    let face = mem::transmute::<_, &'a mut Face<G>>(
                        self.inner.vertex.mesh.faces.get_mut(&face).unwrap(),
                    );
                    &mut face.geometry
                }
            };
            OrphanFaceView::new(geometry, face)
        })
    }
}

#[cfg(test)]
mod tests {
    use generate::*;
    use graph::*;
    use ordered::*;

    #[test]
    fn circulate_over_edges() {
        let mesh = sphere::UVSphere::<f32>::with_unit_radius(4, 2)
            .polygons_with_position() // 6 triangles, 18 vertices.
            .map_vertices(|vertex| vertex.into_hash())
            .collect::<Mesh<Triplet<_>>>();

        // All faces should be triangles and all vertices should have 4
        // (incoming) edges.
        for vertex in mesh.vertices() {
            assert_eq!(4, vertex.edges().count());
        }
    }
}
<|endoftext|>