<commit_before>use serde::Serialize;
use serde_json::value::{Value as Json, Map, to_value};

use pest::prelude::*;
use std::collections::{VecDeque, BTreeMap};

use grammar::{Rdp, Rule};
use error::RenderError;

static DEFAULT_VALUE: Json = Json::Null;

pub type Object = BTreeMap<String, Json>;

/// The context wrap data you render on your templates.
///
#[derive(Debug, Clone)]
pub struct Context {
    data: Json,
}

#[inline]
fn parse_json_visitor_inner<'a>(path_stack: &mut VecDeque<&'a str>,
                                path: &'a str)
                                -> Result<(), RenderError> {
    let path_in = StringInput::new(path);
    let mut parser = Rdp::new(path_in);

    let mut seg_stack: VecDeque<&Token<Rule>> = VecDeque::new();
    if parser.path() {
        for seg in parser.queue().iter() {
            match seg.rule {
                Rule::path_var | Rule::path_idx | Rule::path_key => {}
                Rule::path_up => {
                    path_stack.pop_back();
                    if let Some(p) = seg_stack.pop_back() {
                        // also pop array index like [1]
                        if p.rule == Rule::path_raw_id {
                            seg_stack.pop_back();
                        }
                    }
                }
                Rule::path_id |
                Rule::path_raw_id |
                Rule::path_num_id => {
                    seg_stack.push_back(seg);
                }
                _ => {}
            }
        }

        for i in seg_stack.iter() {
            let id = &path[i.start..i.end];
            path_stack.push_back(id);
        }
        Ok(())
    } else {
        Err(RenderError::new("Invalid JSON path"))
    }
}

#[inline]
fn parse_json_visitor<'a>(path_stack: &mut VecDeque<&'a str>,
                          base_path: &'a str,
                          path_context: &'a VecDeque<String>,
                          relative_path: &'a str)
                          -> Result<(), RenderError> {
    let path_in = StringInput::new(relative_path);
    let mut parser = Rdp::new(path_in);

    if parser.path() {
        let mut path_context_depth: i64 = -1;

        let mut iter = parser.queue().iter();
        loop {
            if let Some(sg) = iter.next() {
                if sg.rule == Rule::path_up {
                    path_context_depth += 1;
                } else {
                    break;
                }
            } else {
                break;
            }
        }

        if path_context_depth >= 0 {
            if let Some(context_base_path) = path_context.get(path_context_depth as usize) {
                parse_json_visitor_inner(path_stack, context_base_path)?;
            } else {
                parse_json_visitor_inner(path_stack, base_path)?;
            }
        } else {
            parse_json_visitor_inner(path_stack, base_path)?;
        }

        parse_json_visitor_inner(path_stack, relative_path)?;
        Ok(())
    } else {
        Err(RenderError::new("Invalid JSON path."))
    }

}

pub fn merge_json(base: &Json, addition: &Object) -> Json {
    let mut base_map = match base {
        &Json::Object(ref m) => m.clone(),
        _ => Map::new(),
    };

    for (k, v) in addition.iter() {
        base_map.insert(k.clone(), v.clone());
    }

    Json::Object(base_map)
}

impl Context {
    /// Create a context with null data
    pub fn null() -> Context {
        Context { data: Json::Null }
    }

    /// Create a context with given data
    pub fn wraps<T: Serialize>(e: &T) -> Result<Context, RenderError> {
        to_value(e)
            .map_err(RenderError::from)
            .map(|d| Context { data: d })
    }

    /// Navigate the context with base path and relative path
    /// Typically you will set base path to `RenderContext.get_path()`
    /// and set relative path to helper argument or so.
    ///
    /// If you want to navigate from top level, set the base path to `"."`
    pub fn navigate(&self,
                    base_path: &str,
                    path_context: &VecDeque<String>,
                    relative_path: &str)
                    -> Result<&Json, RenderError> {
        let mut path_stack: VecDeque<&str> = VecDeque::new();
        parse_json_visitor(&mut path_stack, base_path, path_context, relative_path)?;

        let paths: Vec<&str> = path_stack.iter().map(|x| *x).collect();
        let mut data: &Json = &self.data;
        for p in paths.iter() {
            if *p == "this" {
                continue;
            }
            data = match *data {
                Json::Array(ref l) => {
                    p.parse::<usize>()
                        .and_then(|idx_u| Ok(l.get(idx_u).unwrap_or(&DEFAULT_VALUE)))
                        .unwrap_or(&DEFAULT_VALUE)
                }
                Json::Object(ref m) => m.get(*p).unwrap_or(&DEFAULT_VALUE),
                _ => &DEFAULT_VALUE,
            }
        }
        Ok(data)
    }

    pub fn data(&self) -> &Json {
        &self.data
    }

    pub fn data_mut(&mut self) -> &mut Json {
        &mut self.data
    }
}

/// Render Json data with default format
pub trait JsonRender {
    fn render(&self) -> String;
}

pub trait JsonTruthy {
    fn is_truthy(&self) -> bool;
}

impl JsonRender for Json {
    fn render(&self) -> String {
        match *self {
            Json::String(ref s) => s.to_string(),
            Json::Bool(i) => i.to_string(),
            Json::Number(ref n) => n.to_string(),
            Json::Null => "".to_owned(),
            Json::Array(ref a) => {
                let mut buf = String::new();
                buf.push('[');
                for i in a.iter() {
                    buf.push_str(i.render().as_ref());
                    buf.push_str(", ");
                }
                buf.push(']');
                buf
            }
            Json::Object(_) => "[object]".to_owned(),
        }
    }
}

pub fn to_json<T>(src: &T) -> Json
    where T: Serialize
{
    to_value(src).unwrap_or_default()
}

pub fn as_string(src: &Json) -> Option<&str> {
    src.as_str()
}

impl JsonTruthy for Json {
    fn is_truthy(&self) -> bool {
        match *self {
            Json::Bool(ref i) => *i,
            Json::Number(ref n) => n.as_f64().map(|f| f.is_normal()).unwrap_or(false),
            Json::Null => false,
            Json::String(ref i) => i.len() > 0,
            Json::Array(ref i) => i.len() > 0,
            Json::Object(ref i) => i.len() > 0,
        }
    }
}

#[cfg(test)]
mod test {
    use context::{self, JsonRender, Context};
    use std::collections::VecDeque;
    use serde_json::value::{Value as Json, Map};

    #[test]
    fn test_json_render() {
        let raw = "
Hello world
\n<p thing=\"hello\"
";
        let thing = Json::String(raw.to_string());

        assert_eq!(raw, thing.render());
    }

    #[derive(Serialize)]
    struct Address {
        city: String,
        country: String,
    }

    #[derive(Serialize)]
    struct Person {
        name: String,
        age: i16,
        addr: Address,
        titles: Vec<String>,
    }

    #[test]
    fn test_render() {
        let v = "hello";
        let ctx = Context::wraps(&v.to_string()).unwrap();
        assert_eq!(ctx.navigate(".", &VecDeque::new(), "this")
                       .unwrap()
                       .render(),
                   v.to_string());
    }

    #[test]
    fn test_navigation() {
        let addr = Address {
            city: "Beijing".to_string(),
            country: "China".to_string(),
        };

        let person = Person {
            name: "Ning Sun".to_string(),
            age: 27,
            addr: addr,
            titles: vec!["programmer".to_string(), "cartographier".to_string()],
        };

        let ctx = Context::wraps(&person).unwrap();
        assert_eq!(ctx.navigate(".", &VecDeque::new(), "./name/../addr/country")
                       .unwrap()
                       .render(),
                   "China".to_string());
        assert_eq!(ctx.navigate(".", &VecDeque::new(), "addr.[country]")
                       .unwrap()
                       .render(),
                   "China".to_string());
        assert_eq!(ctx.navigate(".", &VecDeque::new(), "addr.[\"country\"]")
                       .unwrap()
                       .render(),
                   "China".to_string());
        assert_eq!(ctx.navigate(".", &VecDeque::new(), "addr.['country']")
                       .unwrap()
                       .render(),
                   "China".to_string());

        let v = true;
        let ctx2 = Context::wraps(&v).unwrap();
        assert_eq!(ctx2.navigate(".", &VecDeque::new(), "this")
                       .unwrap()
                       .render(),
                   "true".to_string());

        assert_eq!(ctx.navigate(".", &VecDeque::new(), "titles[0]")
                       .unwrap()
                       .render(),
                   "programmer".to_string());
        assert_eq!(ctx.navigate(".", &VecDeque::new(), "titles.[0]")
                       .unwrap()
                       .render(),
                   "programmer".to_string());

        assert_eq!(ctx.navigate(".", &VecDeque::new(), "titles[0]/../../age")
                       .unwrap()
                       .render(),
                   "27".to_string());
        assert_eq!(ctx.navigate(".", &VecDeque::new(), "this.titles[0]/../../age")
                       .unwrap()
                       .render(),
                   "27".to_string());

    }

    #[test]
    fn test_this() {
        let mut map_with_this = Map::new();
        map_with_this.insert("this".to_string(), context::to_json(&"hello"));
        map_with_this.insert("age".to_string(), context::to_json(&5usize));
        let ctx1 = Context::wraps(&map_with_this).unwrap();

        let mut map_without_this = Map::new();
        map_without_this.insert("age".to_string(), context::to_json(&4usize));
        let ctx2 = Context::wraps(&map_without_this).unwrap();

        assert_eq!(ctx1.navigate(".", &VecDeque::new(), "this")
                       .unwrap()
                       .render(),
                   "[object]".to_owned());
        assert_eq!(ctx2.navigate(".", &VecDeque::new(), "age")
                       .unwrap()
                       .render(),
                   "4".to_owned());
    }

    #[test]
    fn test_merge_json() {
        let map = json!({ "age": 4 });
        let s = "hello".to_owned();
        let hash = btreemap!{
            "tag".to_owned() => context::to_json(&"h1")
        };

        let ctx_a1 = Context::wraps(&context::merge_json(&map, &hash)).unwrap();
        assert_eq!(ctx_a1
                       .navigate(".", &VecDeque::new(), "age")
                       .unwrap()
                       .render(),
                   "4".to_owned());
        assert_eq!(ctx_a1
                       .navigate(".", &VecDeque::new(), "tag")
                       .unwrap()
                       .render(),
                   "h1".to_owned());

        let ctx_a2 = Context::wraps(&context::merge_json(&context::to_json(&s), &hash)).unwrap();
        assert_eq!(ctx_a2
                       .navigate(".", &VecDeque::new(), "this")
                       .unwrap()
                       .render(),
                   "[object]".to_owned());
        assert_eq!(ctx_a2
                       .navigate(".", &VecDeque::new(), "tag")
                       .unwrap()
                       .render(),
                   "h1".to_owned());
    }

    #[test]
    fn test_key_name_with_this() {
        let m = btreemap!{
            "this_name".to_string() => "the_value".to_string()
        };
        let ctx = Context::wraps(&m).unwrap();
        assert_eq!(ctx.navigate(".", &VecDeque::new(), "this_name")
                       .unwrap()
                       .render(),
                   "the_value".to_string());
    }
}
<commit_msg>(test) added test for serialize error<commit_after>use serde::Serialize;
use serde_json::value::{Value as Json, Map, to_value};

use pest::prelude::*;
use std::collections::{VecDeque, BTreeMap};

use grammar::{Rdp, Rule};
use error::RenderError;

static DEFAULT_VALUE: Json = Json::Null;

pub type Object = BTreeMap<String, Json>;

/// The context wrap data you render on your templates.
///
#[derive(Debug, Clone)]
pub struct Context {
    data: Json,
}

#[inline]
fn parse_json_visitor_inner<'a>(
    path_stack: &mut VecDeque<&'a str>,
    path: &'a str,
) -> Result<(), RenderError> {
    let path_in = StringInput::new(path);
    let mut parser = Rdp::new(path_in);

    let mut seg_stack: VecDeque<&Token<Rule>> = VecDeque::new();
    if parser.path() {
        for seg in parser.queue().iter() {
            match seg.rule {
                Rule::path_var | Rule::path_idx | Rule::path_key => {}
                Rule::path_up => {
                    path_stack.pop_back();
                    if let Some(p) = seg_stack.pop_back() {
                        // also pop array index like [1]
                        if p.rule == Rule::path_raw_id {
                            seg_stack.pop_back();
                        }
                    }
                }
                Rule::path_id |
                Rule::path_raw_id |
                Rule::path_num_id => {
                    seg_stack.push_back(seg);
                }
                _ => {}
            }
        }

        for i in seg_stack.iter() {
            let id = &path[i.start..i.end];
            path_stack.push_back(id);
        }
        Ok(())
    } else {
        Err(RenderError::new("Invalid JSON path"))
    }
}

#[inline]
fn parse_json_visitor<'a>(
    path_stack: &mut VecDeque<&'a str>,
    base_path: &'a str,
    path_context: &'a VecDeque<String>,
    relative_path: &'a str,
) -> Result<(), RenderError> {
    let path_in = StringInput::new(relative_path);
    let mut parser = Rdp::new(path_in);

    if parser.path() {
        let mut path_context_depth: i64 = -1;

        let mut iter = parser.queue().iter();
        loop {
            if let Some(sg) = iter.next() {
                if sg.rule == Rule::path_up {
                    path_context_depth += 1;
                } else {
                    break;
                }
            } else {
                break;
            }
        }

        if path_context_depth >= 0 {
            if let Some(context_base_path) = path_context.get(path_context_depth as usize) {
                parse_json_visitor_inner(path_stack, context_base_path)?;
            } else {
                parse_json_visitor_inner(path_stack, base_path)?;
            }
        } else {
            parse_json_visitor_inner(path_stack, base_path)?;
        }

        parse_json_visitor_inner(path_stack, relative_path)?;
        Ok(())
    } else {
        Err(RenderError::new("Invalid JSON path."))
    }

}

pub fn merge_json(base: &Json, addition: &Object) -> Json {
    let mut base_map = match base {
        &Json::Object(ref m) => m.clone(),
        _ => Map::new(),
    };

    for (k, v) in addition.iter() {
        base_map.insert(k.clone(), v.clone());
    }

    Json::Object(base_map)
}

impl Context {
    /// Create a context with null data
    pub fn null() -> Context {
        Context { data: Json::Null }
    }

    /// Create a context with given data
    pub fn wraps<T: Serialize>(e: &T) -> Result<Context, RenderError> {
        to_value(e).map_err(RenderError::from).map(|d| {
            Context { data: d }
        })
    }

    /// Navigate the context with base path and relative path
    /// Typically you will set base path to `RenderContext.get_path()`
    /// and set relative path to helper argument or so.
    ///
    /// If you want to navigate from top level, set the base path to `"."`
    pub fn navigate(
        &self,
        base_path: &str,
        path_context: &VecDeque<String>,
        relative_path: &str,
    ) -> Result<&Json, RenderError> {
        let mut path_stack: VecDeque<&str> = VecDeque::new();
        parse_json_visitor(&mut path_stack, base_path, path_context, relative_path)?;

        let paths: Vec<&str> = path_stack.iter().map(|x| *x).collect();
        let mut data: &Json = &self.data;
        for p in paths.iter() {
            if *p == "this" {
                continue;
            }
            data = match *data {
                Json::Array(ref l) => {
                    p.parse::<usize>()
                        .and_then(|idx_u| Ok(l.get(idx_u).unwrap_or(&DEFAULT_VALUE)))
                        .unwrap_or(&DEFAULT_VALUE)
                }
                Json::Object(ref m) => m.get(*p).unwrap_or(&DEFAULT_VALUE),
                _ => &DEFAULT_VALUE,
            }
        }
        Ok(data)
    }

    pub fn data(&self) -> &Json {
        &self.data
    }

    pub fn data_mut(&mut self) -> &mut Json {
        &mut self.data
    }
}

/// Render Json data with default format
pub trait JsonRender {
    fn render(&self) -> String;
}

pub trait JsonTruthy {
    fn is_truthy(&self) -> bool;
}

impl JsonRender for Json {
    fn render(&self) -> String {
        match *self {
            Json::String(ref s) => s.to_string(),
            Json::Bool(i) => i.to_string(),
            Json::Number(ref n) => n.to_string(),
            Json::Null => "".to_owned(),
            Json::Array(ref a) => {
                let mut buf = String::new();
                buf.push('[');
                for i in a.iter() {
                    buf.push_str(i.render().as_ref());
                    buf.push_str(", ");
                }
                buf.push(']');
                buf
            }
            Json::Object(_) => "[object]".to_owned(),
        }
    }
}

pub fn to_json<T>(src: &T) -> Json
where
    T: Serialize,
{
    to_value(src).unwrap_or_default()
}

pub fn as_string(src: &Json) -> Option<&str> {
    src.as_str()
}

impl JsonTruthy for Json {
    fn is_truthy(&self) -> bool {
        match *self {
            Json::Bool(ref i) => *i,
            Json::Number(ref n) => n.as_f64().map(|f| f.is_normal()).unwrap_or(false),
            Json::Null => false,
            Json::String(ref i) => i.len() > 0,
            Json::Array(ref i) => i.len() > 0,
            Json::Object(ref i) => i.len() > 0,
        }
    }
}

#[cfg(test)]
mod test {
    use context::{self, JsonRender, Context};
    use std::collections::VecDeque;
    use serde_json::value::{Value as Json, Map};

    #[test]
    fn test_json_render() {
        let raw = "
Hello world
\n<p thing=\"hello\"
";
        let thing = Json::String(raw.to_string());

        assert_eq!(raw, thing.render());
    }

    #[derive(Serialize)]
    struct Address {
        city: String,
        country: String,
    }

    #[derive(Serialize)]
    struct Person {
        name: String,
        age: i16,
        addr: Address,
        titles: Vec<String>,
    }

    #[test]
    fn test_render() {
        let v = "hello";
        let ctx = Context::wraps(&v.to_string()).unwrap();
        assert_eq!(
            ctx.navigate(".", &VecDeque::new(), "this")
                .unwrap()
                .render(),
            v.to_string()
        );
    }

    #[test]
    fn test_navigation() {
        let addr = Address {
            city: "Beijing".to_string(),
            country: "China".to_string(),
        };

        let person = Person {
            name: "Ning Sun".to_string(),
            age: 27,
            addr: addr,
            titles: vec!["programmer".to_string(), "cartographier".to_string()],
        };

        let ctx = Context::wraps(&person).unwrap();
        assert_eq!(
            ctx.navigate(".", &VecDeque::new(), "./name/../addr/country")
                .unwrap()
                .render(),
            "China".to_string()
        );
        assert_eq!(
            ctx.navigate(".", &VecDeque::new(), "addr.[country]")
                .unwrap()
                .render(),
            "China".to_string()
        );
        assert_eq!(
            ctx.navigate(".", &VecDeque::new(), "addr.[\"country\"]")
                .unwrap()
                .render(),
            "China".to_string()
        );
        assert_eq!(
            ctx.navigate(".", &VecDeque::new(), "addr.['country']")
                .unwrap()
                .render(),
            "China".to_string()
        );

        let v = true;
        let ctx2 = Context::wraps(&v).unwrap();
        assert_eq!(
            ctx2.navigate(".", &VecDeque::new(), "this")
                .unwrap()
                .render(),
            "true".to_string()
        );

        assert_eq!(
            ctx.navigate(".", &VecDeque::new(), "titles[0]")
                .unwrap()
                .render(),
            "programmer".to_string()
        );
        assert_eq!(
            ctx.navigate(".", &VecDeque::new(), "titles.[0]")
                .unwrap()
                .render(),
            "programmer".to_string()
        );

        assert_eq!(
            ctx.navigate(".", &VecDeque::new(), "titles[0]/../../age")
                .unwrap()
                .render(),
            "27".to_string()
        );
        assert_eq!(
            ctx.navigate(".", &VecDeque::new(), "this.titles[0]/../../age")
                .unwrap()
                .render(),
            "27".to_string()
        );

    }

    #[test]
    fn test_this() {
        let mut map_with_this = Map::new();
        map_with_this.insert("this".to_string(), context::to_json(&"hello"));
        map_with_this.insert("age".to_string(), context::to_json(&5usize));
        let ctx1 = Context::wraps(&map_with_this).unwrap();

        let mut map_without_this = Map::new();
        map_without_this.insert("age".to_string(), context::to_json(&4usize));
        let ctx2 = Context::wraps(&map_without_this).unwrap();

        assert_eq!(
            ctx1.navigate(".", &VecDeque::new(), "this")
                .unwrap()
                .render(),
            "[object]".to_owned()
        );
        assert_eq!(
            ctx2.navigate(".", &VecDeque::new(), "age")
                .unwrap()
                .render(),
            "4".to_owned()
        );
    }

    #[test]
    fn test_merge_json() {
        let map = json!({ "age": 4 });
        let s = "hello".to_owned();
        let hash =
            btreemap!{
            "tag".to_owned() => context::to_json(&"h1")
        };

        let ctx_a1 = Context::wraps(&context::merge_json(&map, &hash)).unwrap();
        assert_eq!(ctx_a1
                       .navigate(".", &VecDeque::new(), "age")
                       .unwrap()
                       .render(),
                   "4".to_owned());
        assert_eq!(ctx_a1
                       .navigate(".", &VecDeque::new(), "tag")
                       .unwrap()
                       .render(),
                   "h1".to_owned());

        let ctx_a2 = Context::wraps(&context::merge_json(&context::to_json(&s), &hash)).unwrap();
        assert_eq!(ctx_a2
                       .navigate(".", &VecDeque::new(), "this")
                       .unwrap()
                       .render(),
                   "[object]".to_owned());
        assert_eq!(ctx_a2
                       .navigate(".", &VecDeque::new(), "tag")
                       .unwrap()
                       .render(),
                   "h1".to_owned());
    }

    #[test]
    fn test_key_name_with_this() {
        let m =
            btreemap!{
            "this_name".to_string() => "the_value".to_string()
        };
        let ctx = Context::wraps(&m).unwrap();
        assert_eq!(ctx.navigate(".", &VecDeque::new(), "this_name")
                       .unwrap()
                       .render(),
                   "the_value".to_string());
    }

    use serde::{Serialize, Serializer};
    use serde::ser::Error as SerdeError;

    struct UnserializableType {}

    impl Serialize for UnserializableType {
        fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            Err(SerdeError::custom("test"))
        }
    }

    #[test]
    fn test_serialize_error() {
        let d = UnserializableType {};
        assert!(Context::wraps(&d).is_err());
    }
}
<|endoftext|>


<commit_before>//! Convert sdf files to other formats.

use std::iter::repeat;
use std::path::Path;

use peakbag::{PeakDetector, Peak};
use sdc;

use error::SdfError;
use file::{Block, Channel, File, FileInfo, Record};
use result::Result;

const HIGH_WIDTH: usize = 2;
const HIGH_FLOOR: u16 = 15;
const HIGH_CEILING: u16 = 255;
const LOW_WIDTHS: (usize, usize) = (3, 2);
const LOW_FLOOR: u16 = 15;
const LOW_CEILINGS: (u16, u16) = (250, 255); // heh
const MIN_HEIGHT_ABOVE_BACKGROUND: f64 = 5.0;
const MAX_KURTOSIS: f64 = 0.04;

/// Turns a single sdf record into zero or more `Point`s.
///
/// At this point, we assume that the timestamps are absolute. TODO make this smarter to handle the
/// case when the user has called `File::set_sosbl_mode(SosblMode::Relative)`.
///
/// # Panics
///
/// Panics if there are zero or more than one reference blocks in the record.
///
/// # Examples
///
/// ```
/// use sdf::convert::discretize;
/// use sdf::file::File;
/// let mut file = File::open("data/110630_174316.sdf").unwrap();
/// let ref file_info = file.info().unwrap();
/// file.reindex().unwrap();
/// let ref record = file.read().unwrap();
/// let points = discretize(record, file_info).unwrap();
/// ```
pub fn discretize(record: &Record, file_info: &FileInfo) -> Result<Vec<Point>> {
    let mut high_blocks = Vec::new();
    let mut low_blocks = Vec::new();
    let mut reference_block = None;
    for block in &record.blocks {
        match block.channel {
            Channel::High => high_blocks.push(block),
            Channel::Low => low_blocks.push(block),
            Channel::Reference => {
                if reference_block.is_some() {
                    panic!("More than one reference block in this record");
                } else {
                    reference_block = Some(block);
                }
            }
            _ => {}
        }
    }
    let reference_block = reference_block.unwrap();
    let high_detector = PeakDetector::new(HIGH_WIDTH, HIGH_FLOOR, HIGH_CEILING)
                            .min_height_above_background(MIN_HEIGHT_ABOVE_BACKGROUND)
                            .max_kurtosis(MAX_KURTOSIS);
    let (low_width, low_ceiling) = match high_blocks.len() {
        0 => (LOW_WIDTHS.0, LOW_CEILINGS.0),
        _ => (LOW_WIDTHS.1, LOW_CEILINGS.1),
    };
    let low_detector = PeakDetector::new(low_width, LOW_FLOOR, low_ceiling)
                           .min_height_above_background(MIN_HEIGHT_ABOVE_BACKGROUND)
                           .max_kurtosis(MAX_KURTOSIS)
                           .saturation(LOW_CEILINGS.1);
    let reference_detector = high_detector;

    let reference_peaks = reference_detector.detect_peaks(&reference_block.samples[..]);
    if reference_peaks.len() != 1 {
        debug!("Could not get a single reference peak out of: {:?}", reference_block.samples);
        return Err(SdfError::NeedSingleReferencePeak(reference_peaks.len()));
    }
    let ref reference_peak = reference_peaks[0];
    let t_ref = timestamp(reference_peak, &reference_block, file_info);

    let mut points = Vec::new();
    for (block, detector) in low_blocks.iter()
                                       .zip(repeat(low_detector))
                                       .chain(high_blocks.iter().zip(repeat(high_detector))) {
        let peaks = detector.detect_peaks(&block.samples[..]);
        for peak in peaks {
            let time = timestamp(&peak, block, file_info);
            let range = file_info.v_group / 2.0 * (time - t_ref);
            // x is straight out of the scanner, and the mirror pans it along the
            // z axis.
            let theta = (record.direction[2] / record.direction[0])
                            .atan()
                            .to_degrees();
            let point = Point {
                time: time,
                range: range as f32,
                theta: theta as f32,
                x: (record.origin[0] + record.direction[0] * range) as f32,
                y: (record.origin[1] + record.direction[1] * range) as f32,
                z: (record.origin[2] + record.direction[2] * range) as f32,
                peak: peak,
                high_channel: block.channel == Channel::High,
            };
            points.push(point);
        }
    }

    Ok(points)
}

fn timestamp(peak: &Peak<u16>, block: &Block, file_info: &FileInfo) -> f64 {
    block.time_sosbl + peak.index as f64 * file_info.sampling_time
}

/// A 3D point in the scanner's own coordiante frame.
#[derive(Clone, Copy, Debug)]
pub struct Point {
    time: f64,
    range: f32,
    theta: f32,
    x: f32,
    y: f32,
    z: f32,
    peak: Peak<u16>,
    high_channel: bool,
}

impl File {
    /// Writes all points from an .sdf file to an .sdc file.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use sdf::file::File;
    /// File::convert("110630_174316.sdf", "110630_174316.sdc").unwrap();
    /// ```
    pub fn convert<T: Into<Vec<u8>>, P: AsRef<Path>>(sdf_path: T, sdc_path: P) -> Result<()> {
        let mut sdf_file = try!(File::open(sdf_path));
        let ref file_info = try!(sdf_file.info());
        let mut sdc_file = try!(sdc::File::create(sdc_path));
        for (i, record) in sdf_file.into_iter().enumerate() {
            let points = match discretize(&record, file_info) {
                Ok(points) => points,
                Err(SdfError::NeedSingleReferencePeak(_)) => {
                    warn!("No reference peak detected for pulse {}, skipping", i);
                    continue;
                }
                Err(err) => return Err(err),
            };
            for (i, p) in points.iter().enumerate() {
                let ref point = sdc::Point {
                    time: p.time,
                    range: p.range,
                    theta: p.theta,
                    x: p.x,
                    y: p.y,
                    z: p.z,
                    amplitude: p.peak.amplitude,
                    // FIXME actually calculate this value
                    width: 1,
                    target_type: sdc::TargetType::Peak,
                    // Riegl one-indexes its target counts. Bah.
                    target: (i + 1) as u8,
                    num_target: points.len() as u8,
                    // FIXME I have no idea what this means
                    rg_index: 1,
                    facet_number: record.facet as u8,
                    high_channel: p.high_channel,
                };
                try!(sdc_file.write_point(point));
            }
        }
        Ok(())
    }
}

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

    use file::File;

    #[test]
    fn first_point() {
        let mut file = File::open("data/110630_174316.sdf").unwrap();
        file.reindex().unwrap();
        let ref file_info = file.info().unwrap();
        let ref record = file.read().unwrap();
        let points = discretize(record, file_info).unwrap();
        assert_eq!(4, points.len());
    }
}
<commit_msg>Make timestamp a closure<commit_after>//! Convert sdf files to other formats.

use std::iter::repeat;
use std::path::Path;

use peakbag::{PeakDetector, Peak};
use sdc;

use error::SdfError;
use file::{Block, Channel, File, FileInfo, Record};
use result::Result;

const HIGH_WIDTH: usize = 2;
const HIGH_FLOOR: u16 = 15;
const HIGH_CEILING: u16 = 255;
const LOW_WIDTHS: (usize, usize) = (3, 2);
const LOW_FLOOR: u16 = 15;
const LOW_CEILINGS: (u16, u16) = (250, 255); // heh
const MIN_HEIGHT_ABOVE_BACKGROUND: f64 = 5.0;
const MAX_KURTOSIS: f64 = 0.04;

/// Turns a single sdf record into zero or more `Point`s.
///
/// At this point, we assume that the timestamps are absolute. TODO make this smarter to handle the
/// case when the user has called `File::set_sosbl_mode(SosblMode::Relative)`.
///
/// # Panics
///
/// Panics if there are zero or more than one reference blocks in the record.
///
/// # Examples
///
/// ```
/// use sdf::convert::discretize;
/// use sdf::file::File;
/// let mut file = File::open("data/110630_174316.sdf").unwrap();
/// let ref file_info = file.info().unwrap();
/// file.reindex().unwrap();
/// let ref record = file.read().unwrap();
/// let points = discretize(record, file_info).unwrap();
/// ```
pub fn discretize(record: &Record, file_info: &FileInfo) -> Result<Vec<Point>> {
    let mut high_blocks = Vec::new();
    let mut low_blocks = Vec::new();
    let mut reference_block = None;
    for block in &record.blocks {
        match block.channel {
            Channel::High => high_blocks.push(block),
            Channel::Low => low_blocks.push(block),
            Channel::Reference => {
                if reference_block.is_some() {
                    panic!("More than one reference block in this record");
                } else {
                    reference_block = Some(block);
                }
            }
            _ => {}
        }
    }
    let reference_block = reference_block.unwrap();
    let high_detector = PeakDetector::new(HIGH_WIDTH, HIGH_FLOOR, HIGH_CEILING)
                            .min_height_above_background(MIN_HEIGHT_ABOVE_BACKGROUND)
                            .max_kurtosis(MAX_KURTOSIS);
    let (low_width, low_ceiling) = match high_blocks.len() {
        0 => (LOW_WIDTHS.0, LOW_CEILINGS.0),
        _ => (LOW_WIDTHS.1, LOW_CEILINGS.1),
    };
    let low_detector = PeakDetector::new(low_width, LOW_FLOOR, low_ceiling)
                           .min_height_above_background(MIN_HEIGHT_ABOVE_BACKGROUND)
                           .max_kurtosis(MAX_KURTOSIS)
                           .saturation(LOW_CEILINGS.1);
    let reference_detector = high_detector;

    let reference_peaks = reference_detector.detect_peaks(&reference_block.samples[..]);
    if reference_peaks.len() != 1 {
        debug!("Could not get a single reference peak out of: {:?}",
               reference_block.samples);
        return Err(SdfError::NeedSingleReferencePeak(reference_peaks.len()));
    }
    let ref reference_peak = reference_peaks[0];

    let timestamp = |peak: &Peak<_>, block: &Block| {
        block.time_sosbl + peak.index as f64 * file_info.sampling_time
    };

    let t_ref = timestamp(reference_peak, &reference_block);

    let mut points = Vec::new();
    for (block, detector) in low_blocks.iter()
                                       .zip(repeat(low_detector))
                                       .chain(high_blocks.iter().zip(repeat(high_detector))) {
        let peaks = detector.detect_peaks(&block.samples[..]);
        for peak in peaks {
            let time = timestamp(&peak, block);
            let range = file_info.v_group / 2.0 * (time - t_ref);
            // x is straight out of the scanner, and the mirror pans it along the
            // z axis.
            let theta = (record.direction[2] / record.direction[0])
                            .atan()
                            .to_degrees();
            let point = Point {
                time: time,
                range: range as f32,
                theta: theta as f32,
                x: (record.origin[0] + record.direction[0] * range) as f32,
                y: (record.origin[1] + record.direction[1] * range) as f32,
                z: (record.origin[2] + record.direction[2] * range) as f32,
                peak: peak,
                high_channel: block.channel == Channel::High,
            };
            points.push(point);
        }
    }

    Ok(points)
}

/// A 3D point in the scanner's own coordiante frame.
#[derive(Clone, Copy, Debug)]
pub struct Point {
    time: f64,
    range: f32,
    theta: f32,
    x: f32,
    y: f32,
    z: f32,
    peak: Peak<u16>,
    high_channel: bool,
}

impl File {
    /// Writes all points from an .sdf file to an .sdc file.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use sdf::file::File;
    /// File::convert("110630_174316.sdf", "110630_174316.sdc").unwrap();
    /// ```
    pub fn convert<T: Into<Vec<u8>>, P: AsRef<Path>>(sdf_path: T, sdc_path: P) -> Result<()> {
        let mut sdf_file = try!(File::open(sdf_path));
        let ref file_info = try!(sdf_file.info());
        let mut sdc_file = try!(sdc::File::create(sdc_path));
        for (i, record) in sdf_file.into_iter().enumerate() {
            let points = match discretize(&record, file_info) {
                Ok(points) => points,
                Err(SdfError::NeedSingleReferencePeak(_)) => {
                    warn!("No reference peak detected for pulse {}, skipping", i);
                    continue;
                }
                Err(err) => return Err(err),
            };
            for (i, p) in points.iter().enumerate() {
                let ref point = sdc::Point {
                    time: p.time,
                    range: p.range,
                    theta: p.theta,
                    x: p.x,
                    y: p.y,
                    z: p.z,
                    amplitude: p.peak.amplitude,
                    // FIXME actually calculate this value
                    width: 1,
                    target_type: sdc::TargetType::Peak,
                    // Riegl one-indexes its target counts. Bah.
                    target: (i + 1) as u8,
                    num_target: points.len() as u8,
                    // FIXME I have no idea what this means
                    rg_index: 1,
                    facet_number: record.facet as u8,
                    high_channel: p.high_channel,
                };
                try!(sdc_file.write_point(point));
            }
        }
        Ok(())
    }
}

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

    use file::File;

    #[test]
    fn first_point() {
        let mut file = File::open("data/110630_174316.sdf").unwrap();
        file.reindex().unwrap();
        let ref file_info = file.info().unwrap();
        let ref record = file.read().unwrap();
        let points = discretize(record, file_info).unwrap();
        assert_eq!(4, points.len());
    }
}
<|endoftext|>


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

use angle::{Rad, acos};
use approx::ApproxEq;
use matrix::Matrix;
use matrix::{Matrix2, ToMatrix2};
use matrix::{Matrix3, ToMatrix3};
use num::{BaseNum, BaseFloat};
use point::{Point, Point2, Point3};
use quaternion::{Quaternion, ToQuaternion};
use ray::Ray;
use vector::{Vector, Vector2, Vector3};

/// A trait for a generic rotation. A rotation is a transformation that
/// creates a circular motion, and preserves at least one point in the space.
pub trait Rotation<S: BaseNum, V: Vector<S>, P: Point<S, V>>: PartialEq + ApproxEq<S> + Sized {
    /// Create the identity transform (causes no transformation).
    fn identity() -> Self;

    /// Create a rotation to a given direction with an 'up' vector
    fn look_at(dir: &V, up: &V) -> Self;

    /// Create a shortest rotation to transform vector 'a' into 'b'.
    /// Both given vectors are assumed to have unit length.
    fn between_vectors(a: &V, b: &V) -> Self;

    /// Rotate a vector using this rotation.
    fn rotate_vector(&self, vec: &V) -> V;

    /// Rotate a point using this rotation, by converting it to its
    /// representation as a vector.
    #[inline]
    fn rotate_point(&self, point: &P) -> P {
        Point::from_vec( &self.rotate_vector( &point.to_vec() ) )
    }

    /// Rotate a ray using this rotation.
    #[inline]
    fn rotate_ray(&self, ray: &Ray<P, V>) -> Ray<P,V> {
        Ray::new(ray.origin.clone(), self.rotate_vector(&ray.direction))
    }

    /// Create a new rotation which combines both this rotation, and another.
    fn concat(&self, other: &Self) -> Self;

    /// Create a new rotation which "un-does" this rotation. That is,
    /// `r.concat(r.invert())` is the identity.
    fn invert(&self) -> Self;

    /// Modify this rotation in-place by combining it with another.
    #[inline]
    fn concat_self(&mut self, other: &Self) {
        *self = Rotation::concat(self, other);
    }

    /// Invert this rotation in-place.
    #[inline]
    fn invert_self(&mut self) {
        *self = self.invert();
    }
}

/// A two-dimensional rotation.
pub trait Rotation2<S>: Rotation<S, Vector2<S>, Point2<S>>
                      + ToMatrix2<S>
                      + ToBasis2<S> {
    /// Create a rotation by a given angle. Thus is a redundant case of both
    /// from_axis_angle() and from_euler() for 2D space.
    fn from_angle(theta: Rad<S>) -> Self;
}

/// A three-dimensional rotation.
pub trait Rotation3<S: BaseNum>: Rotation<S, Vector3<S>, Point3<S>>
                               + ToMatrix3<S>
                               + ToBasis3<S>
                               + ToQuaternion<S>{
    /// Create a rotation using an angle around a given axis.
    fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Self;

    /// Create a rotation from a set of euler angles.
    ///
    /// # Parameters
    ///
    /// - `x`: the angular rotation around the `x` axis (pitch).
    /// - `y`: the angular rotation around the `y` axis (yaw).
    /// - `z`: the angular rotation around the `z` axis (roll).
    fn from_euler(x: Rad<S>, y: Rad<S>, z: Rad<S>) -> Self;

    /// Create a rotation from an angle around the `x` axis (pitch).
    #[inline]
    fn from_angle_x(theta: Rad<S>) -> Self {
        Rotation3::from_axis_angle( &Vector3::unit_x(), theta )
    }

    /// Create a rotation from an angle around the `y` axis (yaw).
    #[inline]
    fn from_angle_y(theta: Rad<S>) -> Self {
        Rotation3::from_axis_angle( &Vector3::unit_y(), theta )
    }

    /// Create a rotation from an angle around the `z` axis (roll).
    #[inline]
    fn from_angle_z(theta: Rad<S>) -> Self {
        Rotation3::from_axis_angle( &Vector3::unit_z(), theta )
    }
}

/// A two-dimensional rotation matrix.
///
/// The matrix is guaranteed to be orthogonal, so some operations can be
/// implemented more efficiently than the implementations for `math::Matrix2`. To
/// enforce orthogonality at the type level the operations have been restricted
/// to a subset of those implemented on `Matrix2`.
///
/// ## Example
///
/// Suppose we want to rotate a vector that lies in the x-y plane by some
/// angle. We can accomplish this quite easily with a two-dimensional rotation
/// matrix:
///
/// ~~~ignore
/// use cgmath::rad;
/// use cgmath::Vector2;
/// use cgmath::{Matrix, ToMatrix2};
/// use cgmath::{Rotation, Rotation2, Basis2};
/// use cgmath::ApproxEq;
/// use std::f64;
///
/// // For simplicity, we will rotate the unit x vector to the unit y vector --
/// // so the angle is 90 degrees, or π/2.
/// let unit_x: Vector2<f64> = Vector2::unit_x();
/// let rot: Basis2<f64> = Rotation2::from_angle(rad(0.5f64 * f64::consts::PI));
///
/// // Rotate the vector using the two-dimensional rotation matrix:
/// let unit_y = rot.rotate_vector(&unit_x);
///
/// // Since sin(π/2) may not be exactly zero due to rounding errors, we can
/// // use cgmath's approx_eq() feature to show that it is close enough.
/// assert!(unit_y.approx_eq(&Vector2::unit_y()));
///
/// // This is exactly equivalent to using the raw matrix itself:
/// let unit_y2 = rot.to_matrix2().mul_v(&unit_x);
/// assert_eq!(unit_y2, unit_y);
///
/// // Note that we can also concatenate rotations:
/// let rot_half: Basis2<f64> = Rotation2::from_angle(rad(0.25f64 * f64::consts::PI));
/// let unit_y3 = rot_half.concat(&rot_half).rotate_vector(&unit_x);
/// assert!(unit_y3.approx_eq(&unit_y2));
/// ~~~
#[derive(PartialEq, Copy, Clone, RustcEncodable, RustcDecodable)]
pub struct Basis2<S> {
    mat: Matrix2<S>
}

impl<S: BaseFloat> Basis2<S> {
    /// Coerce to a `Matrix2`
    #[inline]
    pub fn as_matrix2<'a>(&'a self) -> &'a Matrix2<S> { &self.mat }
}

/// Represents types which can be converted to a rotation matrix.
pub trait ToBasis2<S: BaseFloat> {
    /// Convert this type to a rotation matrix.
    fn to_rot2(&self) -> Basis2<S>;
}

impl<S: BaseFloat> ToBasis2<S> for Basis2<S> {
    #[inline]
    fn to_rot2(&self) -> Basis2<S> { self.clone() }
}

impl<S: BaseFloat> ToMatrix2<S> for Basis2<S> {
    #[inline]
    fn to_matrix2(&self) -> Matrix2<S> { self.mat.clone() }
}

impl<S: BaseFloat + 'static> Rotation<S, Vector2<S>, Point2<S>> for Basis2<S> {
    #[inline]
    fn identity() -> Basis2<S> { Basis2{ mat: Matrix2::identity() } }

    #[inline]
    fn look_at(dir: &Vector2<S>, up: &Vector2<S>) -> Basis2<S> {
        Basis2 { mat: Matrix2::look_at(dir, up) }
    }

    #[inline]
    fn between_vectors(a: &Vector2<S>, b: &Vector2<S>) -> Basis2<S> {
        Rotation2::from_angle( acos(a.dot(b)) )
    }

    #[inline]
    fn rotate_vector(&self, vec: &Vector2<S>) -> Vector2<S> { self.mat.mul_v(vec) }

    #[inline]
    fn concat(&self, other: &Basis2<S>) -> Basis2<S> { Basis2 { mat: self.mat.mul_m(&other.mat) } }

    #[inline]
    fn concat_self(&mut self, other: &Basis2<S>) { self.mat.mul_self_m(&other.mat); }

    // TODO: we know the matrix is orthogonal, so this could be re-written
    // to be faster
    #[inline]
    fn invert(&self) -> Basis2<S> { Basis2 { mat: self.mat.invert().unwrap() } }

    // TODO: we know the matrix is orthogonal, so this could be re-written
    // to be faster
    #[inline]
    fn invert_self(&mut self) { self.mat.invert_self(); }
}

impl<S: BaseFloat> ApproxEq<S> for Basis2<S> {
    #[inline]
    fn approx_eq_eps(&self, other: &Basis2<S>, epsilon: &S) -> bool {
        self.mat.approx_eq_eps(&other.mat, epsilon)
    }
}

impl<S: BaseFloat + 'static> Rotation2<S> for Basis2<S> {
    fn from_angle(theta: Rad<S>) -> Basis2<S> { Basis2 { mat: Matrix2::from_angle(theta) } }
}

/// A three-dimensional rotation matrix.
///
/// The matrix is guaranteed to be orthogonal, so some operations, specifically
/// inversion, can be implemented more efficiently than the implementations for
/// `math::Matrix3`. To ensure orthogonality is maintained, the operations have
/// been restricted to a subeset of those implemented on `Matrix3`.
#[derive(PartialEq, Copy, Clone, RustcEncodable, RustcDecodable)]
pub struct Basis3<S> {
    mat: Matrix3<S>
}

impl<S: BaseFloat> Basis3<S> {
    /// Create a new rotation matrix from a quaternion.
    #[inline]
    pub fn from_quaternion(quaternion: &Quaternion<S>) -> Basis3<S> {
        Basis3 { mat: quaternion.to_matrix3() }
    }

    /// Coerce to a `Matrix3`
    #[inline]
    pub fn as_matrix3<'a>(&'a self) -> &'a Matrix3<S> { &self.mat }
}

/// Represents types which can be converted to a rotation matrix.
pub trait ToBasis3<S: BaseFloat> {
    /// Convert this type to a rotation matrix.
    fn to_rot3(&self) -> Basis3<S>;
}

impl<S: BaseFloat> ToBasis3<S> for Basis3<S> {
    #[inline]
    fn to_rot3(&self) -> Basis3<S> { self.clone() }
}

impl<S: BaseFloat> ToMatrix3<S> for Basis3<S> {
    #[inline]
    fn to_matrix3(&self) -> Matrix3<S> { self.mat.clone() }
}

impl<S: BaseFloat + 'static> ToQuaternion<S> for Basis3<S> {
    #[inline]
    fn to_quaternion(&self) -> Quaternion<S> { self.mat.to_quaternion() }
}

impl<S: BaseFloat + 'static> Rotation<S, Vector3<S>, Point3<S>> for Basis3<S> {
    #[inline]
    fn identity() -> Basis3<S> { Basis3{ mat: Matrix3::identity() } }

    #[inline]
    fn look_at(dir: &Vector3<S>, up: &Vector3<S>) -> Basis3<S> {
        Basis3 { mat: Matrix3::look_at(dir, up) }
    }

    #[inline]
    fn between_vectors(a: &Vector3<S>, b: &Vector3<S>) -> Basis3<S> {
        let q: Quaternion<S> = Rotation::between_vectors(a, b);
        q.to_rot3()
    }

    #[inline]
    fn rotate_vector(&self, vec: &Vector3<S>) -> Vector3<S> { self.mat.mul_v(vec) }

    #[inline]
    fn concat(&self, other: &Basis3<S>) -> Basis3<S> { Basis3 { mat: self.mat.mul_m(&other.mat) } }

    #[inline]
    fn concat_self(&mut self, other: &Basis3<S>) { self.mat.mul_self_m(&other.mat); }

    // TODO: we know the matrix is orthogonal, so this could be re-written
    // to be faster
    #[inline]
    fn invert(&self) -> Basis3<S> { Basis3 { mat: self.mat.invert().unwrap() } }

    // TODO: we know the matrix is orthogonal, so this could be re-written
    // to be faster
    #[inline]
    fn invert_self(&mut self) { self.mat.invert_self(); }
}

impl<S: BaseFloat> ApproxEq<S> for Basis3<S> {
    #[inline]
    fn approx_eq_eps(&self, other: &Basis3<S>, epsilon: &S) -> bool {
        self.mat.approx_eq_eps(&other.mat, epsilon)
    }
}

impl<S: BaseFloat + 'static> Rotation3<S> for Basis3<S> {
    fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Basis3<S> {
        Basis3 { mat: Matrix3::from_axis_angle(axis, angle) }
    }

    fn from_euler(x: Rad<S>, y: Rad<S>, z: Rad<S>) -> Basis3<S> {
        Basis3 { mat: Matrix3::from_euler(x, y ,z) }
    }

    fn from_angle_x(theta: Rad<S>) -> Basis3<S> {
        Basis3 { mat: Matrix3::from_angle_x(theta) }
    }

    fn from_angle_y(theta: Rad<S>) -> Basis3<S> {
        Basis3 { mat: Matrix3::from_angle_y(theta) }
    }

    fn from_angle_z(theta: Rad<S>) -> Basis3<S> {
        Basis3 { mat: Matrix3::from_angle_z(theta) }
    }
}
<commit_msg>compile the doctest in rotation.rs; use ``` instead of ~~~<commit_after>// Copyright 2014 The CGMath Developers. For a full listing of the authors,
// refer to the Cargo.toml file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use angle::{Rad, acos};
use approx::ApproxEq;
use matrix::Matrix;
use matrix::{Matrix2, ToMatrix2};
use matrix::{Matrix3, ToMatrix3};
use num::{BaseNum, BaseFloat};
use point::{Point, Point2, Point3};
use quaternion::{Quaternion, ToQuaternion};
use ray::Ray;
use vector::{Vector, Vector2, Vector3};

/// A trait for a generic rotation. A rotation is a transformation that
/// creates a circular motion, and preserves at least one point in the space.
pub trait Rotation<S: BaseNum, V: Vector<S>, P: Point<S, V>>: PartialEq + ApproxEq<S> + Sized {
    /// Create the identity transform (causes no transformation).
    fn identity() -> Self;

    /// Create a rotation to a given direction with an 'up' vector
    fn look_at(dir: &V, up: &V) -> Self;

    /// Create a shortest rotation to transform vector 'a' into 'b'.
    /// Both given vectors are assumed to have unit length.
    fn between_vectors(a: &V, b: &V) -> Self;

    /// Rotate a vector using this rotation.
    fn rotate_vector(&self, vec: &V) -> V;

    /// Rotate a point using this rotation, by converting it to its
    /// representation as a vector.
    #[inline]
    fn rotate_point(&self, point: &P) -> P {
        Point::from_vec( &self.rotate_vector( &point.to_vec() ) )
    }

    /// Rotate a ray using this rotation.
    #[inline]
    fn rotate_ray(&self, ray: &Ray<P, V>) -> Ray<P,V> {
        Ray::new(ray.origin.clone(), self.rotate_vector(&ray.direction))
    }

    /// Create a new rotation which combines both this rotation, and another.
    fn concat(&self, other: &Self) -> Self;

    /// Create a new rotation which "un-does" this rotation. That is,
    /// `r.concat(r.invert())` is the identity.
    fn invert(&self) -> Self;

    /// Modify this rotation in-place by combining it with another.
    #[inline]
    fn concat_self(&mut self, other: &Self) {
        *self = Rotation::concat(self, other);
    }

    /// Invert this rotation in-place.
    #[inline]
    fn invert_self(&mut self) {
        *self = self.invert();
    }
}

/// A two-dimensional rotation.
pub trait Rotation2<S>: Rotation<S, Vector2<S>, Point2<S>>
                      + ToMatrix2<S>
                      + ToBasis2<S> {
    /// Create a rotation by a given angle. Thus is a redundant case of both
    /// from_axis_angle() and from_euler() for 2D space.
    fn from_angle(theta: Rad<S>) -> Self;
}

/// A three-dimensional rotation.
pub trait Rotation3<S: BaseNum>: Rotation<S, Vector3<S>, Point3<S>>
                               + ToMatrix3<S>
                               + ToBasis3<S>
                               + ToQuaternion<S>{
    /// Create a rotation using an angle around a given axis.
    fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Self;

    /// Create a rotation from a set of euler angles.
    ///
    /// # Parameters
    ///
    /// - `x`: the angular rotation around the `x` axis (pitch).
    /// - `y`: the angular rotation around the `y` axis (yaw).
    /// - `z`: the angular rotation around the `z` axis (roll).
    fn from_euler(x: Rad<S>, y: Rad<S>, z: Rad<S>) -> Self;

    /// Create a rotation from an angle around the `x` axis (pitch).
    #[inline]
    fn from_angle_x(theta: Rad<S>) -> Self {
        Rotation3::from_axis_angle( &Vector3::unit_x(), theta )
    }

    /// Create a rotation from an angle around the `y` axis (yaw).
    #[inline]
    fn from_angle_y(theta: Rad<S>) -> Self {
        Rotation3::from_axis_angle( &Vector3::unit_y(), theta )
    }

    /// Create a rotation from an angle around the `z` axis (roll).
    #[inline]
    fn from_angle_z(theta: Rad<S>) -> Self {
        Rotation3::from_axis_angle( &Vector3::unit_z(), theta )
    }
}

/// A two-dimensional rotation matrix.
///
/// The matrix is guaranteed to be orthogonal, so some operations can be
/// implemented more efficiently than the implementations for `math::Matrix2`. To
/// enforce orthogonality at the type level the operations have been restricted
/// to a subset of those implemented on `Matrix2`.
///
/// ## Example
///
/// Suppose we want to rotate a vector that lies in the x-y plane by some
/// angle. We can accomplish this quite easily with a two-dimensional rotation
/// matrix:
///
/// ```no_run
/// use cgmath::rad;
/// use cgmath::Vector2;
/// use cgmath::{Matrix, ToMatrix2};
/// use cgmath::{Rotation, Rotation2, Basis2};
/// use cgmath::ApproxEq;
/// use std::f64;
///
/// // For simplicity, we will rotate the unit x vector to the unit y vector --
/// // so the angle is 90 degrees, or π/2.
/// let unit_x: Vector2<f64> = Vector2::unit_x();
/// let rot: Basis2<f64> = Rotation2::from_angle(rad(0.5f64 * f64::consts::PI));
///
/// // Rotate the vector using the two-dimensional rotation matrix:
/// let unit_y = rot.rotate_vector(&unit_x);
///
/// // Since sin(π/2) may not be exactly zero due to rounding errors, we can
/// // use cgmath's approx_eq() feature to show that it is close enough.
/// assert!(unit_y.approx_eq(&Vector2::unit_y()));
///
/// // This is exactly equivalent to using the raw matrix itself:
/// let unit_y2 = rot.to_matrix2().mul_v(&unit_x);
/// assert_eq!(unit_y2, unit_y);
///
/// // Note that we can also concatenate rotations:
/// let rot_half: Basis2<f64> = Rotation2::from_angle(rad(0.25f64 * f64::consts::PI));
/// let unit_y3 = rot_half.concat(&rot_half).rotate_vector(&unit_x);
/// assert!(unit_y3.approx_eq(&unit_y2));
/// ```
#[derive(PartialEq, Copy, Clone, RustcEncodable, RustcDecodable)]
pub struct Basis2<S> {
    mat: Matrix2<S>
}

impl<S: BaseFloat> Basis2<S> {
    /// Coerce to a `Matrix2`
    #[inline]
    pub fn as_matrix2<'a>(&'a self) -> &'a Matrix2<S> { &self.mat }
}

/// Represents types which can be converted to a rotation matrix.
pub trait ToBasis2<S: BaseFloat> {
    /// Convert this type to a rotation matrix.
    fn to_rot2(&self) -> Basis2<S>;
}

impl<S: BaseFloat> ToBasis2<S> for Basis2<S> {
    #[inline]
    fn to_rot2(&self) -> Basis2<S> { self.clone() }
}

impl<S: BaseFloat> ToMatrix2<S> for Basis2<S> {
    #[inline]
    fn to_matrix2(&self) -> Matrix2<S> { self.mat.clone() }
}

impl<S: BaseFloat + 'static> Rotation<S, Vector2<S>, Point2<S>> for Basis2<S> {
    #[inline]
    fn identity() -> Basis2<S> { Basis2{ mat: Matrix2::identity() } }

    #[inline]
    fn look_at(dir: &Vector2<S>, up: &Vector2<S>) -> Basis2<S> {
        Basis2 { mat: Matrix2::look_at(dir, up) }
    }

    #[inline]
    fn between_vectors(a: &Vector2<S>, b: &Vector2<S>) -> Basis2<S> {
        Rotation2::from_angle( acos(a.dot(b)) )
    }

    #[inline]
    fn rotate_vector(&self, vec: &Vector2<S>) -> Vector2<S> { self.mat.mul_v(vec) }

    #[inline]
    fn concat(&self, other: &Basis2<S>) -> Basis2<S> { Basis2 { mat: self.mat.mul_m(&other.mat) } }

    #[inline]
    fn concat_self(&mut self, other: &Basis2<S>) { self.mat.mul_self_m(&other.mat); }

    // TODO: we know the matrix is orthogonal, so this could be re-written
    // to be faster
    #[inline]
    fn invert(&self) -> Basis2<S> { Basis2 { mat: self.mat.invert().unwrap() } }

    // TODO: we know the matrix is orthogonal, so this could be re-written
    // to be faster
    #[inline]
    fn invert_self(&mut self) { self.mat.invert_self(); }
}

impl<S: BaseFloat> ApproxEq<S> for Basis2<S> {
    #[inline]
    fn approx_eq_eps(&self, other: &Basis2<S>, epsilon: &S) -> bool {
        self.mat.approx_eq_eps(&other.mat, epsilon)
    }
}

impl<S: BaseFloat + 'static> Rotation2<S> for Basis2<S> {
    fn from_angle(theta: Rad<S>) -> Basis2<S> { Basis2 { mat: Matrix2::from_angle(theta) } }
}

/// A three-dimensional rotation matrix.
///
/// The matrix is guaranteed to be orthogonal, so some operations, specifically
/// inversion, can be implemented more efficiently than the implementations for
/// `math::Matrix3`. To ensure orthogonality is maintained, the operations have
/// been restricted to a subeset of those implemented on `Matrix3`.
#[derive(PartialEq, Copy, Clone, RustcEncodable, RustcDecodable)]
pub struct Basis3<S> {
    mat: Matrix3<S>
}

impl<S: BaseFloat> Basis3<S> {
    /// Create a new rotation matrix from a quaternion.
    #[inline]
    pub fn from_quaternion(quaternion: &Quaternion<S>) -> Basis3<S> {
        Basis3 { mat: quaternion.to_matrix3() }
    }

    /// Coerce to a `Matrix3`
    #[inline]
    pub fn as_matrix3<'a>(&'a self) -> &'a Matrix3<S> { &self.mat }
}

/// Represents types which can be converted to a rotation matrix.
pub trait ToBasis3<S: BaseFloat> {
    /// Convert this type to a rotation matrix.
    fn to_rot3(&self) -> Basis3<S>;
}

impl<S: BaseFloat> ToBasis3<S> for Basis3<S> {
    #[inline]
    fn to_rot3(&self) -> Basis3<S> { self.clone() }
}

impl<S: BaseFloat> ToMatrix3<S> for Basis3<S> {
    #[inline]
    fn to_matrix3(&self) -> Matrix3<S> { self.mat.clone() }
}

impl<S: BaseFloat + 'static> ToQuaternion<S> for Basis3<S> {
    #[inline]
    fn to_quaternion(&self) -> Quaternion<S> { self.mat.to_quaternion() }
}

impl<S: BaseFloat + 'static> Rotation<S, Vector3<S>, Point3<S>> for Basis3<S> {
    #[inline]
    fn identity() -> Basis3<S> { Basis3{ mat: Matrix3::identity() } }

    #[inline]
    fn look_at(dir: &Vector3<S>, up: &Vector3<S>) -> Basis3<S> {
        Basis3 { mat: Matrix3::look_at(dir, up) }
    }

    #[inline]
    fn between_vectors(a: &Vector3<S>, b: &Vector3<S>) -> Basis3<S> {
        let q: Quaternion<S> = Rotation::between_vectors(a, b);
        q.to_rot3()
    }

    #[inline]
    fn rotate_vector(&self, vec: &Vector3<S>) -> Vector3<S> { self.mat.mul_v(vec) }

    #[inline]
    fn concat(&self, other: &Basis3<S>) -> Basis3<S> { Basis3 { mat: self.mat.mul_m(&other.mat) } }

    #[inline]
    fn concat_self(&mut self, other: &Basis3<S>) { self.mat.mul_self_m(&other.mat); }

    // TODO: we know the matrix is orthogonal, so this could be re-written
    // to be faster
    #[inline]
    fn invert(&self) -> Basis3<S> { Basis3 { mat: self.mat.invert().unwrap() } }

    // TODO: we know the matrix is orthogonal, so this could be re-written
    // to be faster
    #[inline]
    fn invert_self(&mut self) { self.mat.invert_self(); }
}

impl<S: BaseFloat> ApproxEq<S> for Basis3<S> {
    #[inline]
    fn approx_eq_eps(&self, other: &Basis3<S>, epsilon: &S) -> bool {
        self.mat.approx_eq_eps(&other.mat, epsilon)
    }
}

impl<S: BaseFloat + 'static> Rotation3<S> for Basis3<S> {
    fn from_axis_angle(axis: &Vector3<S>, angle: Rad<S>) -> Basis3<S> {
        Basis3 { mat: Matrix3::from_axis_angle(axis, angle) }
    }

    fn from_euler(x: Rad<S>, y: Rad<S>, z: Rad<S>) -> Basis3<S> {
        Basis3 { mat: Matrix3::from_euler(x, y ,z) }
    }

    fn from_angle_x(theta: Rad<S>) -> Basis3<S> {
        Basis3 { mat: Matrix3::from_angle_x(theta) }
    }

    fn from_angle_y(theta: Rad<S>) -> Basis3<S> {
        Basis3 { mat: Matrix3::from_angle_y(theta) }
    }

    fn from_angle_z(theta: Rad<S>) -> Basis3<S> {
        Basis3 { mat: Matrix3::from_angle_z(theta) }
    }
}
<|endoftext|>


<commit_before>pub fn new(name: &str) {
  println!("creator");
}
<commit_msg>Create the settings file.<commit_after>use std::io::File;

pub fn new(name: &str) {
  let path = format!("~/.muxed/{}", name);
  println!("{}", path);
  let mut file = File::create(&Path::new(path));
  file.write(b"This is a sample file");
}
<|endoftext|>


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

use std::io::Result as IoResult;
use std::io::Read;
use std::io::Error as IoError;
use std::io::ErrorKind;
use std::fmt;
use std::error::Error;

/// Reads HTTP chunks and sends back real data.
///
/// # Example
///
/// ```
/// use chunked_transfer::Decoder;
/// use std::io::Read;
///
/// let encoded = b"3\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n\r\n";
/// let mut decoded = String::new();
///
/// let mut decoder = Decoder::new(encoded as &[u8]);
/// decoder.read_to_string(&mut decoded);
///
/// assert_eq!(decoded, "hello world!!!");
/// ```
pub struct Decoder<R> {
    // where the chunks come from
    source: R,

    // remaining size of the chunk being read
    // none if we are not in a chunk
    remaining_chunks_size: Option<usize>,
}

impl<R> Decoder<R> where R: Read {
    pub fn new(source: R) -> Decoder<R> {
        Decoder {
            source: source,
            remaining_chunks_size: None,
        }
    }
}

impl<R> Read for Decoder<R> where R: Read {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        // first possibility: we are not in a chunk
        if self.remaining_chunks_size.is_none() {
            // trying the read the chunk size
            let mut chunk_size = Vec::new();

            loop {
                let byte = match self.source.by_ref().bytes().next() {
                    Some(b) => try!(b),
                    None => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
                };

                if byte == b'\r' {
                    break;
                }

                chunk_size.push(byte);
            }

            match self.source.by_ref().bytes().next() {
                Some(Ok(b'\n')) => (),
                _ => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
            }

            let chunk_size = match String::from_utf8(chunk_size) {
                Ok(c) => c,
                Err(_) => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError))
            };

            let chunk_size = match usize::from_str_radix(&chunk_size, 16) {
                Ok(c) => c,
                Err(_) => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError))
            };

            // if the chunk size is 0, we are at EOF
            if chunk_size == 0 {
                if try!(self.source.by_ref().bytes().next().unwrap_or(Ok(0))) != b'\r' {
                    return Err(IoError::new(ErrorKind::InvalidInput, DecoderError));
                }
                if try!(self.source.by_ref().bytes().next().unwrap_or(Ok(0))) != b'\n' {
                    return Err(IoError::new(ErrorKind::InvalidInput, DecoderError));
                }
                return Ok(0);
            }

            // now that we now the current chunk size, calling ourselves recursively
            self.remaining_chunks_size = Some(chunk_size);
            return self.read(buf);
        }

        assert!(self.remaining_chunks_size.is_some());

        // second possibility: we continue reading from a chunk
        if buf.len() < *self.remaining_chunks_size.as_ref().unwrap() {
            let read = try!(self.source.read(buf));
            *self.remaining_chunks_size.as_mut().unwrap() -= read;
            return Ok(read);
        }

        // third possibility: the read request goes further than the current chunk
        // we simply read until the end of the chunk and return
        assert!(buf.len() >= *self.remaining_chunks_size.as_ref().unwrap());

        let remaining_chunks_size = *self.remaining_chunks_size.as_ref().unwrap();

        let buf = &mut buf[.. remaining_chunks_size];
        let read = try!(self.source.read(buf));
        *self.remaining_chunks_size.as_mut().unwrap() -= read;

        if read == remaining_chunks_size {
            self.remaining_chunks_size = None;

            if try!(self.source.by_ref().bytes().next().unwrap_or(Ok(0))) != b'\r' {
                return Err(IoError::new(ErrorKind::InvalidInput, DecoderError));
            }
            if try!(self.source.by_ref().bytes().next().unwrap_or(Ok(0))) != b'\n' {
                return Err(IoError::new(ErrorKind::InvalidInput, DecoderError));
            }
        }

        return Ok(read);
    }
}

#[derive(Debug, Copy, Clone)]
struct DecoderError;

impl fmt::Display for DecoderError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "Error while decoding chunks")
    }
}

impl Error for DecoderError {
    fn description(&self) -> &str {
        "Error while decoding chunks"
    }
}

#[cfg(test)]
mod test {
    use super::Decoder;
    use std::io;
    use std::io::Read;

    #[test]
    fn test_valid_chunk_decode() {
        let source = io::Cursor::new("3\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n\r\n".to_string().into_bytes());
        let mut decoded = Decoder::new(source);

        let mut string = String::new();
        decoded.read_to_string(&mut string).unwrap();

        assert_eq!(string, "hello world!!!");
    }

    #[test]
    #[should_panic]
    fn invalid_input1() {
        let source = io::Cursor::new("2\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n".to_string().into_bytes());
        let mut decoded = Decoder::new(source);

        let mut string = String::new();
        decoded.read_to_string(&mut string).unwrap();
    }

    #[test]
    #[should_panic]
    fn invalid_input2() {
        let source = io::Cursor::new("3\rhel\r\nb\r\nlo world!!!\r\n0\r\n".to_string().into_bytes());
        let mut decoded = Decoder::new(source);

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

use std::io::Result as IoResult;
use std::io::Read;
use std::io::Error as IoError;
use std::io::ErrorKind;
use std::fmt;
use std::error::Error;

/// Reads HTTP chunks and sends back real data.
///
/// # Example
///
/// ```
/// use chunked_transfer::Decoder;
/// use std::io::Read;
///
/// let encoded = b"3\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n\r\n";
/// let mut decoded = String::new();
///
/// let mut decoder = Decoder::new(encoded as &[u8]);
/// decoder.read_to_string(&mut decoded);
///
/// assert_eq!(decoded, "hello world!!!");
/// ```
pub struct Decoder<R> {
    // where the chunks come from
    source: R,

    // remaining size of the chunk being read
    // none if we are not in a chunk
    remaining_chunks_size: Option<usize>,
}

impl<R> Decoder<R> where R: Read {
    pub fn new(source: R) -> Decoder<R> {
        Decoder {
            source: source,
            remaining_chunks_size: None,
        }
    }
}

impl<R> Read for Decoder<R> where R: Read {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        // first possibility: we are not in a chunk
        if self.remaining_chunks_size.is_none() {
            // trying the read the chunk size
            let mut chunk_size = Vec::new();

            loop {
                let byte = match self.source.by_ref().bytes().next() {
                    Some(b) => try!(b),
                    None => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
                };

                if byte == b'\r' {
                    break;
                }

                chunk_size.push(byte);
            }

            match self.source.by_ref().bytes().next() {
                Some(Ok(b'\n')) => (),
                _ => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError)),
            }

            let chunk_size = match String::from_utf8(chunk_size) {
                Ok(c) => c,
                Err(_) => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError))
            };

            let chunk_size = match usize::from_str_radix(&chunk_size, 16) {
                Ok(c) => c,
                Err(_) => return Err(IoError::new(ErrorKind::InvalidInput, DecoderError))
            };

            // if the chunk size is 0, we are at EOF
            if chunk_size == 0 {
                if try!(self.source.by_ref().bytes().next().unwrap_or(Ok(0))) != b'\r' {
                    return Err(IoError::new(ErrorKind::InvalidInput, DecoderError));
                }
                if try!(self.source.by_ref().bytes().next().unwrap_or(Ok(0))) != b'\n' {
                    return Err(IoError::new(ErrorKind::InvalidInput, DecoderError));
                }
                return Ok(0);
            }

            // now that we now the current chunk size, calling ourselves recursively
            self.remaining_chunks_size = Some(chunk_size);
            return self.read(buf);
        }

        assert!(self.remaining_chunks_size.is_some());

        // second possibility: we continue reading from a chunk
        if buf.len() < *self.remaining_chunks_size.as_ref().unwrap() {
            let read = try!(self.source.read(buf));
            *self.remaining_chunks_size.as_mut().unwrap() -= read;
            return Ok(read);
        }

        // third possibility: the read request goes further than the current chunk
        // we simply read until the end of the chunk and return
        assert!(buf.len() >= *self.remaining_chunks_size.as_ref().unwrap());

        let remaining_chunks_size = *self.remaining_chunks_size.as_ref().unwrap();

        let buf = &mut buf[.. remaining_chunks_size];
        let read = try!(self.source.read(buf));
        *self.remaining_chunks_size.as_mut().unwrap() -= read;

        if read == remaining_chunks_size {
            self.remaining_chunks_size = None;

            if try!(self.source.by_ref().bytes().next().unwrap_or(Ok(0))) != b'\r' {
                return Err(IoError::new(ErrorKind::InvalidInput, DecoderError));
            }
            if try!(self.source.by_ref().bytes().next().unwrap_or(Ok(0))) != b'\n' {
                return Err(IoError::new(ErrorKind::InvalidInput, DecoderError));
            }
        }

        return Ok(read);
    }
}

#[derive(Debug, Copy, Clone)]
struct DecoderError;

impl fmt::Display for DecoderError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "Error while decoding chunks")
    }
}

impl Error for DecoderError {
    fn description(&self) -> &str {
        "Error while decoding chunks"
    }
}

#[cfg(test)]
mod test {
    use super::Decoder;
    use std::io;
    use std::io::Read;

    #[test]
    fn test_valid_chunk_decode() {
        let source = io::Cursor::new("3\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n\r\n".to_string().into_bytes());
        let mut decoded = Decoder::new(source);

        let mut string = String::new();
        decoded.read_to_string(&mut string).unwrap();

        assert_eq!(string, "hello world!!!");
    }

    #[test]
    fn invalid_input1() {
        let source = io::Cursor::new("2\r\nhel\r\nb\r\nlo world!!!\r\n0\r\n".to_string().into_bytes());
        let mut decoded = Decoder::new(source);

        let mut string = String::new();
        decoded.read_to_string(&mut string).is_err();
    }

    #[test]
    fn invalid_input2() {
        let source = io::Cursor::new("3\rhel\r\nb\r\nlo world!!!\r\n0\r\n".to_string().into_bytes());
        let mut decoded = Decoder::new(source);

        let mut string = String::new();
        decoded.read_to_string(&mut string).is_err();
    }
}
<|endoftext|>


<commit_before>use crate::{
    ebml::{self, ebml_header, EBMLHeader, custom_error},
    elements::{
        segment, segment_element, simple_block, Cluster, Info, SeekHead, SegmentElement,
        TrackEntry, Tracks,
    },
    av_data::rational::Rational64,
};
use av_data::{packet::Packet, params::*, timeinfo::TimeInfo};
use av_format::{
    buffer::Buffered,
    common::GlobalInfo,
    demuxer::{Demuxer, Descr, Descriptor, Event},
    error::*,
    stream::Stream,
};
use log::{debug, error, trace};
use nom::{self, Err, IResult, Needed, Offset};
use std::sync::Arc;
use std::{collections::VecDeque, io::SeekFrom};

#[derive(Debug, Clone)]
pub struct MkvDemuxer {
    pub header: Option<EBMLHeader>,
    pub seek_head: Option<SeekHead>,
    pub info: Option<Info>,
    pub tracks: Option<Tracks>,
    pub queue: VecDeque<Event>,
    pub blockstream: Vec<u8>,
}

impl MkvDemuxer {
    pub fn new() -> MkvDemuxer {
        MkvDemuxer {
            header: None,
            seek_head: None,
            info: None,
            tracks: None,
            queue: VecDeque::new(),
            blockstream: Vec::new(),
        }
    }

    pub fn parse_until_tracks<'a>(
        &mut self,
        original_input: &'a [u8],
    ) -> IResult<&'a [u8], (), ebml::Error<'a>> {
        let (i1, header) = ebml_header(original_input)?;

        self.header = Some(header);

        let (mut input, _) = segment(i1)?;

        self.seek_head = None;
        self.info = None;
        self.tracks = None;

        loop {
            if self.seek_head.is_some() && self.info.is_some() && self.tracks.is_some() {
                return Ok((input, ()));
            }

            // println!("offset: {}", original_input.offset(input));

            let (i3, element) = segment_element(input)?;

            match element {
                SegmentElement::SeekHead(s) => {
                    trace!("got seek head: {:#?}", s);
                    if self.seek_head.is_some() {
                        return Err(Err::Error(custom_error(input, 1)));
                    } else {
                        self.seek_head = Some(s);
                    }
                }
                SegmentElement::Info(i) => {
                    trace!("got info: {:#?}", i);
                    if self.info.is_some() {
                        return Err(Err::Error(custom_error(input, 1)));
                    } else {
                        self.info = Some(i);
                    }
                }
                SegmentElement::Tracks(t) => {
                    trace!("got tracks: {:#?}", t);
                    if self.tracks.is_some() {
                        return Err(Err::Error(custom_error(input, 1)));
                    } else {
                        self.tracks = Some(t);
                    }
                }
                el => {
                    debug!("got element: {:#?}", el);
                }
            }

            input = i3;
        }
    }
}

impl Demuxer for MkvDemuxer {
    fn read_headers(&mut self, buf: &Box<dyn Buffered>, info: &mut GlobalInfo) -> Result<SeekFrom> {
        match self.parse_until_tracks(buf.data()) {
            Ok((i, _)) => {
                info.duration = self
                    .info
                    .as_ref()
                    .and_then(|info| info.duration)
                    .map(|d| d as u64);
                if let Some(ref mut t) = self.tracks {
                    for tr in t.tracks.iter_mut() {
                        info.add_stream(track_to_stream(self.info.as_ref().unwrap(), tr));
                        tr.stream_index = info.streams.last().unwrap().index;
                    }
                }
                Ok(SeekFrom::Current(buf.data().offset(i) as i64))
            }
            Err(Err::Incomplete(needed)) => {
                let sz = match needed {
                    Needed::Size(size) => buf.data().len() + size,
                    _ => 1024,
                };
                Err(Error::MoreDataNeeded(sz))
            }
            e => {
                error!("{:?}", e);
                Err(Error::InvalidData)
            }
        }
    }

    fn read_event(&mut self, buf: &Box<dyn Buffered>) -> Result<(SeekFrom, Event)> {
        if let Some(event) = self.queue.pop_front() {
            Ok((SeekFrom::Current(0), event))
        } else {
            // println!("no more stored packet, parsing a new one");
            match segment_element(buf.data()) {
                Ok((i, element)) => {
                    let seek = SeekFrom::Current(buf.data().offset(i) as i64);
                    match element {
                        SegmentElement::Cluster(c) => {
                            //self.clusters.push(c);
                            debug!("got cluster element at timecode: {}", c.timecode);
                            let mut packets = c.generate_packets(self.tracks.as_ref().unwrap());
                            self.queue.extend(packets.drain(..));
                            if let Some(event) = self.queue.pop_front() {
                                return Ok((seek, event));
                            }
                        }
                        _el => {
                            // println!("got element: {:#?}", el);
                        }
                    }
                    Ok((seek, Event::MoreDataNeeded(0)))
                }
                Err(Err::Incomplete(Needed::Size(size))) => Err(Error::MoreDataNeeded(size)),
                e => {
                    error!("{:?}", e);
                    Err(Error::InvalidData)
                }
            }
        }
    }
}

fn track_entry_codec_id(t: &TrackEntry) -> Option<String> {
    // TODO: Support V_QUICKTIME and V_MS/VFW/FOURCC
    match t.codec_id.as_ref() {
        "A_OPUS" => Some("opus".to_owned()),
        "A_VORBIS" => Some("vorbis".to_owned()),
        "V_AV1" => Some("av1".to_owned()),
        "V_VP8" => Some("vp8".to_owned()),
        "V_VP9" => Some("vp9".to_owned()),
        _ => None,
    }
}

fn track_entry_video_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Validate that a track::video exists for track::type video before.
    if let Some(ref video) = t.video {
        let v = VideoInfo {
            width: video.pixel_width as usize,
            height: video.pixel_height as usize,
            // TODO parse Colour and/or CodecPrivate to extract the format
            format: None,
        };
        Some(MediaKind::Video(v))
    } else {
        None
    }
}

fn track_entry_audio_kind(t: &TrackEntry) -> Option<MediaKind> {
    use av_data::audiosample::*;
    // TODO: Validate that a track::video exists for track::type video before.
    if let Some(ref audio) = t.audio {
        let rate = if let Some(r) = audio.output_sampling_frequency {
            r
        } else {
            audio.sampling_frequency
        };
        // TODO: complete it
        let map = if audio.channel_positions.is_none() {
            Some(ChannelMap::default_map(audio.channels as usize))
        } else {
            unimplemented!("Convert matroska map to rust-av map")
        };
        let a = AudioInfo {
            rate: rate as usize,
            map: map,
            format: None,
        };
        Some(MediaKind::Audio(a))
    } else {
        None
    }
}

fn track_entry_media_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Use an enum for the track type
    match t.track_type {
        0x1 => track_entry_video_kind(t),
        0x2 => track_entry_audio_kind(t),
        _ => None,
    }
}

// TODO: make sure the timecode_scale isn't 0
pub fn track_to_stream(info: &Info, t: &TrackEntry) -> Stream {
    let num = if let Some(ts) = t.track_timecode_scale {
        (ts * info.timecode_scale as f64) as i64
    } else {
        info.timecode_scale as i64
    };

    Stream {
        id: t.track_uid as isize,
        index: 0,
        start: None,
        duration: t.default_duration,
        timebase: Rational64::new(num, 1000 * 1000 * 1000),
        // TODO: Extend CodecParams and fill it with the remaining information
        params: CodecParams {
            extradata: t.codec_private.clone(),
            bit_rate: 0,
            delay: t.codec_delay.unwrap_or(0) as usize,
            convergence_window: t.seek_pre_roll.unwrap_or(0) as usize,
            codec_id: track_entry_codec_id(t),
            kind: track_entry_media_kind(t),
        },
        user_private: None,
    }
}

impl<'a> Cluster<'a> {
    pub fn generate_packets(&self, tracks: &Tracks) -> Vec<Event> {
        let mut v = Vec::new();

        for block_data in self.simple_block.iter() {
            if let Ok((i, block)) = simple_block(block_data) {
                debug!("parsing simple block: {:?}", block);
                if let Some(index) = tracks.lookup(block.track_number) {
                    let packet = Packet {
                        data: i.into(),
                        t: TimeInfo {
                            pts: Some(block.timecode as i64),
                            dts: None,
                            duration: None,
                            timebase: None,
                            user_private: None,
                        },
                        pos: None,
                        stream_index: index as isize,
                        is_key: block.keyframe,
                        is_corrupted: false,
                    };

                    v.push(Event::NewPacket(packet));
                }
            } else {
                error!("error parsing simple block");
            }
        }

        v
    }
}

struct Des {
    d: Descr,
}

impl Descriptor for Des {
    fn create(&self) -> Box<dyn Demuxer> {
        Box::new(MkvDemuxer::new())
    }
    fn describe<'a>(&'a self) -> &'a Descr {
        &self.d
    }
    fn probe(&self, data: &[u8]) -> u8 {
        match ebml_header(&data[..100]) {
            Ok(_) => 100,
            _ => 0,
        }
    }
}

pub const MKV_DESC: &dyn Descriptor = &Des {
    d: Descr {
        name: "matroska",
        demuxer: "mkv",
        description: "Nom-based Matroska demuxer",
        extensions: &["mkv", "webm", "mka"],
        mime: &["video/x-matroska", "audio/x-matroska"],
    },
};

#[cfg(test)]
#[allow(non_upper_case_globals)]
mod tests {
    use super::*;
    use av_format::{buffer::*, demuxer::Context};
    use log::info;
    use nom::Offset;
    use std::io::Cursor;

    const webm: &'static [u8] = include_bytes!("../assets/bbb-vp9-opus.webm");

    #[test]
    fn parse_headers() {
        let mut demuxer = MkvDemuxer::new();

        let res = demuxer.parse_until_tracks(webm);
        info!("got parsing res: {:?}", res);
        match res {
            Ok((i, _)) => {
                info!("offset: {} bytes", webm.offset(i));
            }
            e => {
                info!("could not parse: {:?}", e);
            }
        }

        info!("demuxer: {:#?}", demuxer);
    }

    #[test]
    fn parse_headers_incremental_buffer() {
        let mut demuxer = MkvDemuxer::new();

        for n in 100..2000 {
            let res = demuxer.parse_until_tracks(&webm[0..n]);
            match res {
                Ok(_) => info!("Size {} ok", n),
                Err(Err::Incomplete(needed)) => info!("Incomplete {} needs {:?}", n, needed),
                Err(e) => {
                    panic!("Error at size {}: {:?}", n, e);
                }
            }
        }
    }

    #[test]
    fn context() {
        let mut context = Context::new(
            Box::new(MkvDemuxer::new()),
            Box::new(AccReader::new(Cursor::new(webm))),
        );
        info!("read headers: {:?}", context.read_headers().unwrap());
        info!("streams: {:?}", context.info.streams);
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
    }
}
<commit_msg>fix stream index (#47)<commit_after>use crate::{
    ebml::{self, ebml_header, EBMLHeader, custom_error},
    elements::{
        segment, segment_element, simple_block, Cluster, Info, SeekHead, SegmentElement,
        TrackEntry, Tracks,
    },
    av_data::rational::Rational64,
};
use av_data::{packet::Packet, params::*, timeinfo::TimeInfo};
use av_format::{
    buffer::Buffered,
    common::GlobalInfo,
    demuxer::{Demuxer, Descr, Descriptor, Event},
    error::*,
    stream::Stream,
};
use log::{debug, error, trace};
use nom::{self, Err, IResult, Needed, Offset};
use std::sync::Arc;
use std::{collections::VecDeque, io::SeekFrom};

#[derive(Debug, Clone)]
pub struct MkvDemuxer {
    pub header: Option<EBMLHeader>,
    pub seek_head: Option<SeekHead>,
    pub info: Option<Info>,
    pub tracks: Option<Tracks>,
    pub queue: VecDeque<Event>,
    pub blockstream: Vec<u8>,
}

impl MkvDemuxer {
    pub fn new() -> MkvDemuxer {
        MkvDemuxer {
            header: None,
            seek_head: None,
            info: None,
            tracks: None,
            queue: VecDeque::new(),
            blockstream: Vec::new(),
        }
    }

    pub fn parse_until_tracks<'a>(
        &mut self,
        original_input: &'a [u8],
    ) -> IResult<&'a [u8], (), ebml::Error<'a>> {
        let (i1, header) = ebml_header(original_input)?;

        self.header = Some(header);

        let (mut input, _) = segment(i1)?;

        self.seek_head = None;
        self.info = None;
        self.tracks = None;

        loop {
            if self.seek_head.is_some() && self.info.is_some() && self.tracks.is_some() {
                return Ok((input, ()));
            }

            // println!("offset: {}", original_input.offset(input));

            let (i3, element) = segment_element(input)?;

            match element {
                SegmentElement::SeekHead(s) => {
                    trace!("got seek head: {:#?}", s);
                    if self.seek_head.is_some() {
                        return Err(Err::Error(custom_error(input, 1)));
                    } else {
                        self.seek_head = Some(s);
                    }
                }
                SegmentElement::Info(i) => {
                    trace!("got info: {:#?}", i);
                    if self.info.is_some() {
                        return Err(Err::Error(custom_error(input, 1)));
                    } else {
                        self.info = Some(i);
                    }
                }
                SegmentElement::Tracks(t) => {
                    trace!("got tracks: {:#?}", t);
                    if self.tracks.is_some() {
                        return Err(Err::Error(custom_error(input, 1)));
                    } else {
                        self.tracks = Some(t);
                    }
                }
                el => {
                    debug!("got element: {:#?}", el);
                }
            }

            input = i3;
        }
    }
}

impl Demuxer for MkvDemuxer {
    fn read_headers(&mut self, buf: &Box<dyn Buffered>, info: &mut GlobalInfo) -> Result<SeekFrom> {
        match self.parse_until_tracks(buf.data()) {
            Ok((i, _)) => {
                info.duration = self
                    .info
                    .as_ref()
                    .and_then(|info| info.duration)
                    .map(|d| d as u64);
                if let Some(ref mut t) = self.tracks {
                    for tr in t.tracks.iter_mut() {
                        info.add_stream(track_to_stream(self.info.as_ref().unwrap(), tr));
                        tr.stream_index = info.streams.last().unwrap().index;
                    }
                }
                Ok(SeekFrom::Current(buf.data().offset(i) as i64))
            }
            Err(Err::Incomplete(needed)) => {
                let sz = match needed {
                    Needed::Size(size) => buf.data().len() + size,
                    _ => 1024,
                };
                Err(Error::MoreDataNeeded(sz))
            }
            e => {
                error!("{:?}", e);
                Err(Error::InvalidData)
            }
        }
    }

    fn read_event(&mut self, buf: &Box<dyn Buffered>) -> Result<(SeekFrom, Event)> {
        if let Some(event) = self.queue.pop_front() {
            Ok((SeekFrom::Current(0), event))
        } else {
            // println!("no more stored packet, parsing a new one");
            match segment_element(buf.data()) {
                Ok((i, element)) => {
                    let seek = SeekFrom::Current(buf.data().offset(i) as i64);
                    match element {
                        SegmentElement::Cluster(c) => {
                            //self.clusters.push(c);
                            debug!("got cluster element at timecode: {}", c.timecode);
                            let mut packets = c.generate_packets(self.tracks.as_ref().unwrap());
                            self.queue.extend(packets.drain(..));
                            if let Some(event) = self.queue.pop_front() {
                                return Ok((seek, event));
                            }
                        }
                        _el => {
                            // println!("got element: {:#?}", el);
                        }
                    }
                    Ok((seek, Event::MoreDataNeeded(0)))
                }
                Err(Err::Incomplete(Needed::Size(size))) => Err(Error::MoreDataNeeded(size)),
                e => {
                    error!("{:?}", e);
                    Err(Error::InvalidData)
                }
            }
        }
    }
}

fn track_entry_codec_id(t: &TrackEntry) -> Option<String> {
    // TODO: Support V_QUICKTIME and V_MS/VFW/FOURCC
    match t.codec_id.as_ref() {
        "A_OPUS" => Some("opus".to_owned()),
        "A_VORBIS" => Some("vorbis".to_owned()),
        "V_AV1" => Some("av1".to_owned()),
        "V_VP8" => Some("vp8".to_owned()),
        "V_VP9" => Some("vp9".to_owned()),
        _ => None,
    }
}

fn track_entry_video_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Validate that a track::video exists for track::type video before.
    if let Some(ref video) = t.video {
        let v = VideoInfo {
            width: video.pixel_width as usize,
            height: video.pixel_height as usize,
            // TODO parse Colour and/or CodecPrivate to extract the format
            format: None,
        };
        Some(MediaKind::Video(v))
    } else {
        None
    }
}

fn track_entry_audio_kind(t: &TrackEntry) -> Option<MediaKind> {
    use av_data::audiosample::*;
    // TODO: Validate that a track::video exists for track::type video before.
    if let Some(ref audio) = t.audio {
        let rate = if let Some(r) = audio.output_sampling_frequency {
            r
        } else {
            audio.sampling_frequency
        };
        // TODO: complete it
        let map = if audio.channel_positions.is_none() {
            Some(ChannelMap::default_map(audio.channels as usize))
        } else {
            unimplemented!("Convert matroska map to rust-av map")
        };
        let a = AudioInfo {
            rate: rate as usize,
            map: map,
            format: None,
        };
        Some(MediaKind::Audio(a))
    } else {
        None
    }
}

fn track_entry_media_kind(t: &TrackEntry) -> Option<MediaKind> {
    // TODO: Use an enum for the track type
    match t.track_type {
        0x1 => track_entry_video_kind(t),
        0x2 => track_entry_audio_kind(t),
        _ => None,
    }
}

// TODO: make sure the timecode_scale isn't 0
pub fn track_to_stream(info: &Info, t: &TrackEntry) -> Stream {
    let num = if let Some(ts) = t.track_timecode_scale {
        (ts * info.timecode_scale as f64) as i64
    } else {
        info.timecode_scale as i64
    };

    Stream {
        id: t.track_uid as isize,
        index: t.stream_index,
        start: None,
        duration: t.default_duration,
        timebase: Rational64::new(num, 1000 * 1000 * 1000),
        // TODO: Extend CodecParams and fill it with the remaining information
        params: CodecParams {
            extradata: t.codec_private.clone(),
            bit_rate: 0,
            delay: t.codec_delay.unwrap_or(0) as usize,
            convergence_window: t.seek_pre_roll.unwrap_or(0) as usize,
            codec_id: track_entry_codec_id(t),
            kind: track_entry_media_kind(t),
        },
        user_private: None,
    }
}

impl<'a> Cluster<'a> {
    pub fn generate_packets(&self, tracks: &Tracks) -> Vec<Event> {
        let mut v = Vec::new();

        for block_data in self.simple_block.iter() {
            if let Ok((i, block)) = simple_block(block_data) {
                debug!("parsing simple block: {:?}", block);
                if let Some(index) = tracks.lookup(block.track_number) {
                    let packet = Packet {
                        data: i.into(),
                        t: TimeInfo {
                            pts: Some(block.timecode as i64),
                            dts: None,
                            duration: None,
                            timebase: None,
                            user_private: None,
                        },
                        pos: None,
                        stream_index: index as isize,
                        is_key: block.keyframe,
                        is_corrupted: false,
                    };

                    v.push(Event::NewPacket(packet));
                }
            } else {
                error!("error parsing simple block");
            }
        }

        v
    }
}

struct Des {
    d: Descr,
}

impl Descriptor for Des {
    fn create(&self) -> Box<dyn Demuxer> {
        Box::new(MkvDemuxer::new())
    }
    fn describe<'a>(&'a self) -> &'a Descr {
        &self.d
    }
    fn probe(&self, data: &[u8]) -> u8 {
        match ebml_header(&data[..100]) {
            Ok(_) => 100,
            _ => 0,
        }
    }
}

pub const MKV_DESC: &dyn Descriptor = &Des {
    d: Descr {
        name: "matroska",
        demuxer: "mkv",
        description: "Nom-based Matroska demuxer",
        extensions: &["mkv", "webm", "mka"],
        mime: &["video/x-matroska", "audio/x-matroska"],
    },
};

#[cfg(test)]
#[allow(non_upper_case_globals)]
mod tests {
    use super::*;
    use av_format::{buffer::*, demuxer::Context};
    use log::info;
    use nom::Offset;
    use std::io::Cursor;

    const webm: &'static [u8] = include_bytes!("../assets/bbb-vp9-opus.webm");

    #[test]
    fn parse_headers() {
        let mut demuxer = MkvDemuxer::new();

        let res = demuxer.parse_until_tracks(webm);
        info!("got parsing res: {:?}", res);
        match res {
            Ok((i, _)) => {
                info!("offset: {} bytes", webm.offset(i));
            }
            e => {
                info!("could not parse: {:?}", e);
            }
        }

        info!("demuxer: {:#?}", demuxer);
    }

    #[test]
    fn parse_headers_incremental_buffer() {
        let mut demuxer = MkvDemuxer::new();

        for n in 100..2000 {
            let res = demuxer.parse_until_tracks(&webm[0..n]);
            match res {
                Ok(_) => info!("Size {} ok", n),
                Err(Err::Incomplete(needed)) => info!("Incomplete {} needs {:?}", n, needed),
                Err(e) => {
                    panic!("Error at size {}: {:?}", n, e);
                }
            }
        }
    }

    #[test]
    fn context() {
        let mut context = Context::new(
            Box::new(MkvDemuxer::new()),
            Box::new(AccReader::new(Cursor::new(webm))),
        );
        info!("read headers: {:?}", context.read_headers().unwrap());
        info!("streams: {:?}", context.info.streams);
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
        info!("event: {:?}", context.read_event().unwrap());
    }
}
<|endoftext|>