<commit_before>
#[cfg(test)]
mod rasterization {
    use cgmath::{Point2, Point3};
    use rasterization::triangle;
    use shader::{Shader, MAX_OUT_VALUES};

    fn triangle_test(a_screen: Point2<f32>, b_screen: Point2<f32>, c_screen: Point2<f32>, buffer_except: Vec<u32>) {
        let a = Point3::new(a_screen.x, a_screen.y, 0.5_f32);
        let b = Point3::new(b_screen.x, b_screen.y, 0.5_f32);
        let c = Point3::new(c_screen.x, c_screen.y, 0.5_f32);
        let x_size: usize = 7;
        let y_size: usize = 5;
        let mut cbuffer: Vec<u32> = vec![0; x_size * y_size];
        let mut zbuffer: Vec<f32> = vec![0.0_f32; x_size * y_size];
        let mut shader = Shader::new();
        triangle(&mut cbuffer, &mut zbuffer, x_size, y_size, [a, b, c], [[0.0_f32;MAX_OUT_VALUES]; 3], 0, &mut shader);

        println!("");
        println!("real: ");
        for y in (0..y_size) {
            print!("   ");
            for x in (0..x_size) {
                print!("{}",if cbuffer[(y_size - y - 1) * x_size + x]==0 {0} else {1});
            }
            println!("");
        }
        println!("except: ");
        for y in (0..y_size) {
            print!("   ");
            for x in (0..x_size) {
                print!("{}",if buffer_except[y * x_size + x]==0 {0} else {1});
            }
            println!("");
        }
        for y in 0..y_size {
            for x in 0..x_size {
                let val_real = cbuffer[y * x_size + x];
                let val_except = buffer_except[(y_size - y - 1) * x_size + x];
                debug_assert!((val_real==0) == (val_except==0),
                              "real = {}, except = {}, x = {} y = {}",
                              val_real, val_except, x, y);
            }
        }
    }

    #[test]
    fn triangle_00() {
        triangle_test(Point2::new(1.0,4.0), Point2::new(2.0,1.0), Point2::new(6.0,3.0),
                      vec![0,0,0,0,0,0,0,
                           0,1,1,0,0,0,0,
                           0,1,1,1,1,0,0,
                           0,0,1,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_01() {
        triangle_test(Point2::new(1.4,1.6), Point2::new(2.4,1.6), Point2::new(2.4,2.6),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_02() {
        triangle_test(Point2::new(3.5,1.5), Point2::new(4.5,1.5), Point2::new(4.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_03() {
        triangle_test(Point2::new(2.5,2.5), Point2::new(2.5,2.5), Point2::new(2.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_04() {
        triangle_test(Point2::new(0.0,0.0), Point2::new(4.0,0.0), Point2::new(6.0,2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,1,0,0,
                           0,1,1,1,0,0,0]);
    }

    #[test]
    fn triangle_05() {
        triangle_test(Point2::new(1.0,2.0), Point2::new(4.0,1.0), Point2::new(3.0,4.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,1,0,0,0,0,
                           0,1,1,0,0,0,0,
                           0,0,1,1,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_06() {
        triangle_test(Point2::new(5.5,2.5), Point2::new(4.0,1.0), Point2::new(3.0,4.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,1,0,0,0,
                           0,0,0,1,1,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_07() {
        triangle_test(Point2::new(1.5,0.5), Point2::new(2.5,0.5), Point2::new(1.5,-2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,1,0,0,0,0,0]);
    }

    #[test]
    fn triangle_08() {
        triangle_test(Point2::new(0.7,3.5), Point2::new(2.5,0.7), Point2::new(4.6,3.5),
                      vec![0,0,0,0,0,0,0,
                           0,1,1,1,1,0,0,
                           0,1,1,1,0,0,0,
                           0,0,1,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_09() {
        triangle_test(Point2::new(0.7,1.5), Point2::new(2.7,3.2), Point2::new(4.7,1.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,1,1,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_10() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(0.5,2.5), Point2::new(1.5,1.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_11() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(0.5,2.5), Point2::new(2.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_12() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(2.5,2.5), Point2::new(2.5,0.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,1,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_13() {
        triangle_test(Point2::new(0.5,3.5), Point2::new(1.5,2.5), Point2::new(1.5,0.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_14() {
        triangle_test(Point2::new(0.5,3.5), Point2::new(1.5,2.5), Point2::new(2.0,5.0),
                      vec![0,1,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_15() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(2.5,0.5), Point2::new(0.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_16() {
        triangle_test(Point2::new(2.5,2.5), Point2::new(2.5,0.5), Point2::new(0.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           0,1,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_17() {
        triangle_test(Point2::new(5.0,2.0), Point2::new(5.0,-2.0), Point2::new(10.0,2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,1,1,
                           0,0,0,0,0,1,1]);
    }

    #[test]
    fn triangle_18() {
        triangle_test(Point2::new(5.0,3.0), Point2::new(5.0,10.0), Point2::new(10.0,3.0),
                      vec![0,0,0,0,0,1,1,
                           0,0,0,0,0,1,1,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }
}
<commit_msg>fix tests<commit_after>
#[cfg(test)]
mod rasterization {
    use cgmath::{Point2, Point3};
    use rasterization::triangle;
    use shader::{Shader, ShaderType, MAX_OUT_VALUES};

    fn triangle_test(a_screen: Point2<f32>, b_screen: Point2<f32>, c_screen: Point2<f32>, buffer_except: Vec<u32>) {
        let a = Point3::new(a_screen.x, a_screen.y, 0.5_f32);
        let b = Point3::new(b_screen.x, b_screen.y, 0.5_f32);
        let c = Point3::new(c_screen.x, c_screen.y, 0.5_f32);
        let x_size: usize = 7;
        let y_size: usize = 5;
        let mut cbuffer: Vec<u32> = vec![0; x_size * y_size];
        let mut zbuffer: Vec<f32> = vec![0.0_f32; x_size * y_size];
        let mut shader = Shader::new(ShaderType::Default);
        triangle(&mut cbuffer, &mut zbuffer, x_size, y_size, [a, b, c], [[0.0_f32;MAX_OUT_VALUES]; 3], 0, &mut shader);

        println!("");
        println!("real: ");
        for y in (0..y_size) {
            print!("   ");
            for x in (0..x_size) {
                print!("{}",if cbuffer[(y_size - y - 1) * x_size + x]==0 {0} else {1});
            }
            println!("");
        }
        println!("except: ");
        for y in (0..y_size) {
            print!("   ");
            for x in (0..x_size) {
                print!("{}",if buffer_except[y * x_size + x]==0 {0} else {1});
            }
            println!("");
        }
        for y in 0..y_size {
            for x in 0..x_size {
                let val_real = cbuffer[y * x_size + x];
                let val_except = buffer_except[(y_size - y - 1) * x_size + x];
                debug_assert!((val_real==0) == (val_except==0),
                              "real = {}, except = {}, x = {} y = {}",
                              val_real, val_except, x, y);
            }
        }
    }

    #[test]
    fn triangle_00() {
        triangle_test(Point2::new(1.0,4.0), Point2::new(2.0,1.0), Point2::new(6.0,3.0),
                      vec![0,0,0,0,0,0,0,
                           0,1,1,0,0,0,0,
                           0,1,1,1,1,0,0,
                           0,0,1,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_01() {
        triangle_test(Point2::new(1.4,1.6), Point2::new(2.4,1.6), Point2::new(2.4,2.6),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_02() {
        triangle_test(Point2::new(3.5,1.5), Point2::new(4.5,1.5), Point2::new(4.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_03() {
        triangle_test(Point2::new(2.5,2.5), Point2::new(2.5,2.5), Point2::new(2.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_04() {
        triangle_test(Point2::new(0.0,0.0), Point2::new(4.0,0.0), Point2::new(6.0,2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,1,0,0,
                           0,1,1,1,0,0,0]);
    }

    #[test]
    fn triangle_05() {
        triangle_test(Point2::new(1.0,2.0), Point2::new(4.0,1.0), Point2::new(3.0,4.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,1,0,0,0,0,
                           0,1,1,0,0,0,0,
                           0,0,1,1,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_06() {
        triangle_test(Point2::new(5.5,2.5), Point2::new(4.0,1.0), Point2::new(3.0,4.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,1,0,0,0,
                           0,0,0,1,1,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_07() {
        triangle_test(Point2::new(1.5,0.5), Point2::new(2.5,0.5), Point2::new(1.5,-2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,1,0,0,0,0,0]);
    }

    #[test]
    fn triangle_08() {
        triangle_test(Point2::new(0.7,3.5), Point2::new(2.5,0.7), Point2::new(4.6,3.5),
                      vec![0,0,0,0,0,0,0,
                           0,1,1,1,1,0,0,
                           0,1,1,1,0,0,0,
                           0,0,1,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_09() {
        triangle_test(Point2::new(0.7,1.5), Point2::new(2.7,3.2), Point2::new(4.7,1.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,1,1,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_10() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(0.5,2.5), Point2::new(1.5,1.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_11() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(0.5,2.5), Point2::new(2.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_12() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(2.5,2.5), Point2::new(2.5,0.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,1,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_13() {
        triangle_test(Point2::new(0.5,3.5), Point2::new(1.5,2.5), Point2::new(1.5,0.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_14() {
        triangle_test(Point2::new(0.5,3.5), Point2::new(1.5,2.5), Point2::new(2.0,5.0),
                      vec![0,1,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_15() {
        triangle_test(Point2::new(0.5,0.5), Point2::new(2.5,0.5), Point2::new(0.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_16() {
        triangle_test(Point2::new(2.5,2.5), Point2::new(2.5,0.5), Point2::new(0.5,2.5),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           1,1,0,0,0,0,0,
                           0,1,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }

    #[test]
    fn triangle_17() {
        triangle_test(Point2::new(5.0,2.0), Point2::new(5.0,-2.0), Point2::new(10.0,2.0),
                      vec![0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,1,1,
                           0,0,0,0,0,1,1]);
    }

    #[test]
    fn triangle_18() {
        triangle_test(Point2::new(5.0,3.0), Point2::new(5.0,10.0), Point2::new(10.0,3.0),
                      vec![0,0,0,0,0,1,1,
                           0,0,0,0,0,1,1,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0,
                           0,0,0,0,0,0,0]);
    }
}
<|endoftext|>


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

//! The [`@font-face`][ff] at-rule.
//!
//! [ff]: https://drafts.csswg.org/css-fonts/#at-font-face-rule

#![deny(missing_docs)]

use computed_values::font_family::FontFamily;
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
use parser::{ParserContext, log_css_error, Parse};
use std::fmt;
use std::iter;
use style_traits::{ToCss, CommaSeparated};
use values::specified::url::SpecifiedUrl;

/// A source for a font-face rule.
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub enum Source {
    /// A `url()` source.
    Url(UrlSource),
    /// A `local()` source.
    Local(FontFamily),
}

impl ToCss for Source {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
        where W: fmt::Write,
    {
        match *self {
            Source::Url(ref url) => {
                try!(dest.write_str("url(\""));
                try!(url.to_css(dest));
            },
            Source::Local(ref family) => {
                try!(dest.write_str("local(\""));
                try!(family.to_css(dest));
            },
        }
        dest.write_str("\")")
    }
}

impl CommaSeparated for Source {}

/// A `UrlSource` represents a font-face source that has been specified with a
/// `url()` function.
///
/// https://drafts.csswg.org/css-fonts/#src-desc
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub struct UrlSource {
    /// The specified url.
    pub url: SpecifiedUrl,
    /// The format hints specified with the `format()` function.
    pub format_hints: Vec<String>,
}

impl ToCss for UrlSource {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
        where W: fmt::Write,
    {
        dest.write_str(self.url.as_str())
    }
}

/// Parse the block inside a `@font-face` rule.
///
/// Note that the prelude parsing code lives in the `stylesheets` module.
pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser)
                             -> Result<FontFaceRule, ()> {
    let mut rule = FontFaceRule::initial();
    {
        let parser = FontFaceRuleParser { context: context, rule: &mut rule };
        let mut iter = DeclarationListParser::new(input, parser);
        while let Some(declaration) = iter.next() {
            if let Err(range) = declaration {
                let pos = range.start;
                let message = format!("Unsupported @font-face descriptor declaration: '{}'",
                                      iter.input.slice(range));
                log_css_error(iter.input, pos, &*message, context);
            }
        }
    }
    if rule.family != FontFamily::Generic(atom!("")) && !rule.sources.is_empty() {
        Ok(rule)
    } else {
        Err(())
    }
}

/// A list of effective sources that we send over through IPC to the font cache.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
pub struct EffectiveSources(Vec<Source>);

impl FontFaceRule {
    /// Returns the list of effective sources for that font-face, that is the
    /// sources which don't list any format hint, or the ones which list at
    /// least "truetype" or "opentype".
    pub fn effective_sources(&self) -> EffectiveSources {
        EffectiveSources(self.sources.iter().rev().filter(|source| {
            if let Source::Url(ref url_source) = **source {
                let hints = &url_source.format_hints;
                // We support only opentype fonts and truetype is an alias for
                // that format. Sources without format hints need to be
                // downloaded in case we support them.
                hints.is_empty() || hints.iter().any(|hint| {
                    hint == "truetype" || hint == "opentype" || hint == "woff"
                })
            } else {
                true
            }
        }).cloned().collect())
    }
}

impl iter::Iterator for EffectiveSources {
    type Item = Source;
    fn next(&mut self) -> Option<Source> {
        self.0.pop()
    }
}

struct FontFaceRuleParser<'a, 'b: 'a> {
    context: &'a ParserContext<'b>,
    rule: &'a mut FontFaceRule,
}

/// Default methods reject all at rules.
impl<'a, 'b> AtRuleParser for FontFaceRuleParser<'a, 'b> {
    type Prelude = ();
    type AtRule = ();
}

impl Parse for Vec<Source> {
    fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        input.parse_comma_separated(|input| Source::parse(context, input))
    }
}

impl Parse for Source {
    fn parse(context: &ParserContext, input: &mut Parser) -> Result<Source, ()> {
        if input.try(|input| input.expect_function_matching("local")).is_ok() {
            return input.parse_nested_block(|input| {
                FontFamily::parse(context, input)
            }).map(Source::Local)
        }

        let url = SpecifiedUrl::parse(context, input)?;

        // Parsing optional format()
        let format_hints = if input.try(|input| input.expect_function_matching("format")).is_ok() {
            input.parse_nested_block(|input| {
                input.parse_comma_separated(|input| {
                    Ok(input.expect_string()?.into_owned())
                })
            })?
        } else {
            vec![]
        };

        Ok(Source::Url(UrlSource {
            url: url,
            format_hints: format_hints,
        }))
    }
}

macro_rules! font_face_descriptors {
    ( $( #[$doc: meta] $name: tt $ident: ident : $ty: ty = $initial: expr, )+ ) => {
        /// A `@font-face` rule.
        ///
        /// https://drafts.csswg.org/css-fonts/#font-face-rule
        #[derive(Debug, PartialEq, Eq)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub struct FontFaceRule {
            $(
                #[$doc]
                pub $ident: $ty,
            )+
        }

        impl FontFaceRule {
            fn initial() -> Self {
                FontFaceRule {
                    $(
                        $ident: $initial,
                    )+
                }
            }
        }

        impl ToCss for FontFaceRule {
            // Serialization of FontFaceRule is not specced.
            fn to_css<W>(&self, dest: &mut W) -> fmt::Result
                where W: fmt::Write,
            {
                dest.write_str("@font-face {\n")?;
                $(
                    // Because of parse_font_face_block,
                    // this condition is always true for "src" and "font-family".
                    // But it can be false for other descriptors.
                    if self.$ident != $initial {
                        dest.write_str(concat!("  ", $name, ": "))?;
                        self.$ident.to_css(dest)?;
                        dest.write_str(";\n")?;
                    }
                )+
                dest.write_str("}")
            }
        }

       impl<'a, 'b> DeclarationParser for FontFaceRuleParser<'a, 'b> {
            type Declaration = ();

            fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<(), ()> {
                match_ignore_ascii_case! { name,
                    $(
                        $name => self.rule.$ident = Parse::parse(self.context, input)?,
                    )+
                    _ => return Err(())
                }
                Ok(())
            }
        }
    }
}

/// css-name rust_identifier: Type = initial_value,
font_face_descriptors! {
    /// The specified url.
    "font-family" family: FontFamily = FontFamily::Generic(atom!("")),

    /// The format hints specified with the `format()` function.
    "src" sources: Vec<Source> = Vec::new(),
}
<commit_msg>Separate mandatory and optional descriptors in @font-face parsing macro.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The [`@font-face`][ff] at-rule.
//!
//! [ff]: https://drafts.csswg.org/css-fonts/#at-font-face-rule

#![deny(missing_docs)]

use computed_values::font_family::FontFamily;
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
use parser::{ParserContext, log_css_error, Parse};
use std::fmt;
use std::iter;
use style_traits::{ToCss, CommaSeparated};
use values::specified::url::SpecifiedUrl;

/// A source for a font-face rule.
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub enum Source {
    /// A `url()` source.
    Url(UrlSource),
    /// A `local()` source.
    Local(FontFamily),
}

impl ToCss for Source {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
        where W: fmt::Write,
    {
        match *self {
            Source::Url(ref url) => {
                try!(dest.write_str("url(\""));
                try!(url.to_css(dest));
            },
            Source::Local(ref family) => {
                try!(dest.write_str("local(\""));
                try!(family.to_css(dest));
            },
        }
        dest.write_str("\")")
    }
}

impl CommaSeparated for Source {}

/// A `UrlSource` represents a font-face source that has been specified with a
/// `url()` function.
///
/// https://drafts.csswg.org/css-fonts/#src-desc
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub struct UrlSource {
    /// The specified url.
    pub url: SpecifiedUrl,
    /// The format hints specified with the `format()` function.
    pub format_hints: Vec<String>,
}

impl ToCss for UrlSource {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
        where W: fmt::Write,
    {
        dest.write_str(self.url.as_str())
    }
}

/// Parse the block inside a `@font-face` rule.
///
/// Note that the prelude parsing code lives in the `stylesheets` module.
pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser)
                             -> Result<FontFaceRule, ()> {
    let mut rule = FontFaceRule::initial();
    {
        let parser = FontFaceRuleParser {
            context: context,
            rule: &mut rule,
            missing: MissingDescriptors::new(),
        };
        let mut iter = DeclarationListParser::new(input, parser);
        while let Some(declaration) = iter.next() {
            if let Err(range) = declaration {
                let pos = range.start;
                let message = format!("Unsupported @font-face descriptor declaration: '{}'",
                                      iter.input.slice(range));
                log_css_error(iter.input, pos, &*message, context);
            }
        }
        if iter.parser.missing.any() {
            return Err(())
        }
    }
    Ok(rule)
}

/// A list of effective sources that we send over through IPC to the font cache.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
pub struct EffectiveSources(Vec<Source>);

impl FontFaceRule {
    /// Returns the list of effective sources for that font-face, that is the
    /// sources which don't list any format hint, or the ones which list at
    /// least "truetype" or "opentype".
    pub fn effective_sources(&self) -> EffectiveSources {
        EffectiveSources(self.sources.iter().rev().filter(|source| {
            if let Source::Url(ref url_source) = **source {
                let hints = &url_source.format_hints;
                // We support only opentype fonts and truetype is an alias for
                // that format. Sources without format hints need to be
                // downloaded in case we support them.
                hints.is_empty() || hints.iter().any(|hint| {
                    hint == "truetype" || hint == "opentype" || hint == "woff"
                })
            } else {
                true
            }
        }).cloned().collect())
    }
}

impl iter::Iterator for EffectiveSources {
    type Item = Source;
    fn next(&mut self) -> Option<Source> {
        self.0.pop()
    }
}

struct FontFaceRuleParser<'a, 'b: 'a> {
    context: &'a ParserContext<'b>,
    rule: &'a mut FontFaceRule,
    missing: MissingDescriptors,
}

/// Default methods reject all at rules.
impl<'a, 'b> AtRuleParser for FontFaceRuleParser<'a, 'b> {
    type Prelude = ();
    type AtRule = ();
}

impl Parse for Vec<Source> {
    fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        input.parse_comma_separated(|input| Source::parse(context, input))
    }
}

impl Parse for Source {
    fn parse(context: &ParserContext, input: &mut Parser) -> Result<Source, ()> {
        if input.try(|input| input.expect_function_matching("local")).is_ok() {
            return input.parse_nested_block(|input| {
                FontFamily::parse(context, input)
            }).map(Source::Local)
        }

        let url = SpecifiedUrl::parse(context, input)?;

        // Parsing optional format()
        let format_hints = if input.try(|input| input.expect_function_matching("format")).is_ok() {
            input.parse_nested_block(|input| {
                input.parse_comma_separated(|input| {
                    Ok(input.expect_string()?.into_owned())
                })
            })?
        } else {
            vec![]
        };

        Ok(Source::Url(UrlSource {
            url: url,
            format_hints: format_hints,
        }))
    }
}

macro_rules! font_face_descriptors {
    (
        mandatory descriptors = [
            $( #[$m_doc: meta] $m_name: tt $m_ident: ident : $m_ty: ty = $m_initial: expr, )*
        ]
        optional descriptors = [
            $( #[$o_doc: meta] $o_name: tt $o_ident: ident : $o_ty: ty = $o_initial: expr, )*
        ]
    ) => {
        /// A `@font-face` rule.
        ///
        /// https://drafts.csswg.org/css-fonts/#font-face-rule
        #[derive(Debug, PartialEq, Eq)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub struct FontFaceRule {
            $(
                #[$m_doc]
                pub $m_ident: $m_ty,
            )*
            $(
                #[$o_doc]
                pub $o_ident: $o_ty,
            )*
        }

        struct MissingDescriptors {
            $(
                $m_ident: bool,
            )*
        }

        impl MissingDescriptors {
            fn new() -> Self {
                MissingDescriptors {
                    $(
                        $m_ident: true,
                    )*
                }
            }

            fn any(&self) -> bool {
                $(
                    self.$m_ident
                )||*
            }
        }

        impl FontFaceRule {
            fn initial() -> Self {
                FontFaceRule {
                    $(
                        $m_ident: $m_initial,
                    )*
                    $(
                        $o_ident: $o_initial,
                    )*
                }
            }
        }

        impl ToCss for FontFaceRule {
            // Serialization of FontFaceRule is not specced.
            fn to_css<W>(&self, dest: &mut W) -> fmt::Result
                where W: fmt::Write,
            {
                dest.write_str("@font-face {\n")?;
                $(
                    dest.write_str(concat!("  ", $m_name, ": "))?;
                    self.$m_ident.to_css(dest)?;
                    dest.write_str(";\n")?;
                )*
                $(
                    // Because of parse_font_face_block,
                    // this condition is always true for "src" and "font-family".
                    // But it can be false for other descriptors.
                    if self.$o_ident != $o_initial {
                        dest.write_str(concat!("  ", $o_name, ": "))?;
                        self.$o_ident.to_css(dest)?;
                        dest.write_str(";\n")?;
                    }
                )*
                dest.write_str("}")
            }
        }

       impl<'a, 'b> DeclarationParser for FontFaceRuleParser<'a, 'b> {
            type Declaration = ();

            fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<(), ()> {
                match_ignore_ascii_case! { name,
                    $(
                        $m_name => {
                            self.rule.$m_ident = Parse::parse(self.context, input)?;
                            self.missing.$m_ident = false
                        },
                    )*
                    $(
                        $o_name => self.rule.$o_ident = Parse::parse(self.context, input)?,
                    )*
                    _ => return Err(())
                }
                Ok(())
            }
        }
    }
}

/// css-name rust_identifier: Type = initial_value,
font_face_descriptors! {
    mandatory descriptors = [
        /// The specified url.
        "font-family" family: FontFamily = FontFamily::Generic(atom!("")),

        /// The format hints specified with the `format()` function.
        "src" sources: Vec<Source> = Vec::new(),
    ]
    optional descriptors = [
    ]
}
<|endoftext|>


<commit_before>use futures::{future, stream, Future, Stream, Sink, IntoFuture};
use futures::stream::MergedItem;
use futures::future::{Either, err};
use futures::sync::mpsc;
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::reactor::{Core, Handle, Timeout};
use tokio_io::AsyncRead;

use std::io;
use std::net::SocketAddr;
use std::thread;
use std::time::{SystemTime, Duration};
use std::collections::hash_map::{HashMap, Entry};
use std::error::Error as StdError;

use crypto::{gen_keypair, PublicKey, SecretKey};
use messages::{RawMessage, Any, Connect, Message};
use events::{EventHandler, Event};

use super::error::{other_error, result_ok, forget_result, into_other, log_error};
use super::codec::MessagesCodec;
use super::Node;
use super::handler::NetworkRequest;

pub fn run_node(node: Node) -> io::Result<()> {
    let (sender, receiver) = (node.channel.0, node.channel.1);
    let listen_addr = sender.listen_addr;
    // Channels
    let (events_tx, events_rx) = mpsc::channel(64);
    let (requests_tx, requests_rx) = (sender.network_sender, receiver.network_receiver);
    let (timeouts_tx, timeouts_rx) = (sender.timeout_sender, receiver.timeout_receiver);

    let events_tx = events_tx.clone();
    let requests_tx = requests_tx.clone();
    let network_thread = thread::spawn(move || {
        let mut core = Core::new().unwrap();

        // Outgoing connections handler
        let mut outgoing_connections: HashMap<SocketAddr, mpsc::Sender<RawMessage>> =
            HashMap::new();

        // Requests handler
        let handle = core.handle();
        let events_tx = events_tx.clone();
        let requests_handle = requests_rx.for_each(|request| {
            debug!("Tokio: Handle request {:?}", request);

            match request {
                NetworkRequest::ConnectWithPeer(peer) => {
                    match outgoing_connections.entry(peer) {
                        Entry::Occupied(_) => {}
                        Entry::Vacant(entry) => {
                            let (conn_tx, conn_rx) = mpsc::channel(10);
                            let socket = TcpStream::connect(&peer, &handle);

                            let events_tx = events_tx.clone();
                            let requests_tx = requests_tx.clone();
                            let connect_handle = socket
                                .and_then(move |sock| {
                                    info!("Tokio: Established connection with peer={}", peer);

                                    // Send `Connected` event
                                    // FIXME remove unwap
                                    events_tx
                                        .clone()
                                        .send(Event::Connected(peer))
                                        .wait()
                                        .unwrap();

                                    let stream = sock.framed(MessagesCodec);
                                    let (sink, stream) = stream.split();

                                    let writer = conn_rx
                                        .map_err(|_| other_error("Can't send data into socket"))
                                        .forward(sink);
                                    let reader = stream.for_each(result_ok).map_err(into_other);

                                    reader
                                        .select2(writer)
                                        .map_err(|_| other_error("Socket error"))
                                        .and_then(|res| match res {
                                            Either::A((_, _reader)) => Ok(()).into_future(),
                                            Either::B((_, _writer)) => Ok(()).into_future(),
                                        })
                                })
                                .and_then(move |_| {
                                    info!("Tokio: Connection with peer={} closed", peer);
                                    let request = NetworkRequest::DisconnectWithPeer(peer);
                                    requests_tx
                                        .clone()
                                        .send(request)
                                        .map(forget_result)
                                        .map_err(into_other)
                                })
                                .map_err(log_error);
                            handle.spawn(connect_handle);

                            entry.insert(conn_tx.clone());
                        }
                    }
                }
                NetworkRequest::SendMessage(peer, msg) => {
                    if let Some(conn_tx) = outgoing_connections.get(&peer) {
                        let send_handle = conn_tx.clone().send(msg).map(forget_result).map_err(
                            log_error,
                        );
                        handle.spawn(send_handle);
                    }
                }
                NetworkRequest::DisconnectWithPeer(peer) => {
                    outgoing_connections.remove(&peer);

                    let event = Event::Disconnected(peer);
                    let event_handle = events_tx.clone().send(event).map(forget_result).map_err(
                        log_error,
                    );
                    handle.spawn(event_handle);
                }
            }
            Ok(())
        });

        // Incoming connections handler
        let listener = TcpListener::bind(&listen_addr, &core.handle()).unwrap();
        let events_tx = events_tx.clone();
        let server = listener
            .incoming()
            .fold(events_tx, move |events_tx, (sock, addr)| {
                info!("Accepted incoming connection with peer={}", addr);

                let stream = sock.framed(MessagesCodec);
                let (_, stream) = stream.split();
                let events_tx = events_tx.clone();

                let event = Event::Disconnected(addr);
                let connect_event = events_tx.clone().send(event).map_err(into_other);

                let messages_stream = stream.for_each(move |raw| {
                    let event = Event::Incoming(raw);
                    events_tx.clone().send(event).map(forget_result).map_err(
                        into_other,
                    )
                });

                messages_stream
                    .join(connect_event)
                    .map(move |(_, stream)| stream)
                    .map_err(into_other)
            })
            .map(forget_result)
            .map_err(log_error);
        core.handle().spawn(server);

        core.run(requests_handle).unwrap();
    });

    let mut handler = node.handler;
    let mut core = node.core;
    handler.initialize();

    let events_handle = events_rx.merge(timeouts_rx).for_each(move |item| {
        match item {
            MergedItem::First(event) => {
                handler.handle_event(event);
            }
            MergedItem::Second(timeout) => {
                handler.handle_timeout(timeout);
            }
            MergedItem::Both(event, timeout) => {
                handler.handle_timeout(timeout);
                handler.handle_event(event);
            }
        }
        Ok(())
    });
    core.run(events_handle).unwrap();
    debug!("Handler thread is gone");

    network_thread.join().unwrap();
    Ok(())
}<commit_msg>Fix disconnect<commit_after>use futures::{future, stream, Future, Stream, Sink, IntoFuture};
use futures::stream::MergedItem;
use futures::future::{Either, err};
use futures::sync::mpsc;
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::reactor::{Core, Handle, Timeout};
use tokio_io::AsyncRead;

use std::io;
use std::net::SocketAddr;
use std::thread;
use std::time::{SystemTime, Duration};
use std::collections::hash_map::{HashMap, Entry};
use std::error::Error as StdError;

use crypto::{gen_keypair, PublicKey, SecretKey};
use messages::{RawMessage, Any, Connect, Message};
use events::{EventHandler, Event};

use super::error::{other_error, result_ok, forget_result, into_other, log_error};
use super::codec::MessagesCodec;
use super::Node;
use super::handler::NetworkRequest;

pub fn run_node(node: Node) -> io::Result<()> {
    let (sender, receiver) = (node.channel.0, node.channel.1);
    let listen_addr = sender.listen_addr;
    // Channels
    let (events_tx, events_rx) = mpsc::channel(64);
    let (requests_tx, requests_rx) = (sender.network_sender, receiver.network_receiver);
    let (timeouts_tx, timeouts_rx) = (sender.timeout_sender, receiver.timeout_receiver);

    let events_tx = events_tx.clone();
    let requests_tx = requests_tx.clone();
    let network_thread = thread::spawn(move || {
        let mut core = Core::new().unwrap();

        // Outgoing connections handler
        let mut outgoing_connections: HashMap<SocketAddr, mpsc::Sender<RawMessage>> =
            HashMap::new();

        // Requests handler
        let handle = core.handle();
        let events_tx = events_tx.clone();
        let requests_handle = requests_rx.for_each(|request| {
            debug!("Tokio: Handle request {:?}", request);

            match request {
                NetworkRequest::ConnectWithPeer(peer) => {
                    match outgoing_connections.entry(peer) {
                        Entry::Occupied(_) => {}
                        Entry::Vacant(entry) => {
                            let (conn_tx, conn_rx) = mpsc::channel(10);
                            let socket = TcpStream::connect(&peer, &handle);

                            let events_tx = events_tx.clone();
                            let requests_tx = requests_tx.clone();
                            let connect_handle = socket
                                .and_then(move |sock| {
                                    info!("Tokio: Established connection with peer={}", peer);

                                    // Send `Connected` event
                                    // FIXME remove unwap
                                    events_tx
                                        .clone()
                                        .send(Event::Connected(peer))
                                        .wait()
                                        .unwrap();

                                    let stream = sock.framed(MessagesCodec);
                                    let (sink, stream) = stream.split();

                                    let writer = conn_rx
                                        .map_err(|_| other_error("Can't send data into socket"))
                                        .forward(sink);
                                    let reader = stream.for_each(result_ok).map_err(into_other);

                                    reader
                                        .select2(writer)
                                        .map_err(|_| other_error("Socket error"))
                                        .and_then(|res| match res {
                                            Either::A((_, _reader)) => Ok(()).into_future(),
                                            Either::B((_, _writer)) => Ok(()).into_future(),
                                        })
                                })
                                .map_err(log_error)
                                .then(move |reason| {
                                    info!("Tokio: Connection with peer={} closed", peer);
                                    let request = NetworkRequest::DisconnectWithPeer(peer);
                                    requests_tx
                                        .clone()
                                        .send(request)
                                        .map(forget_result)
                                        .map_err(into_other)
                                })
                                .map_err(log_error);
                            handle.spawn(connect_handle);

                            entry.insert(conn_tx.clone());
                        }
                    }
                }
                NetworkRequest::SendMessage(peer, msg) => {
                    if let Some(conn_tx) = outgoing_connections.get(&peer) {
                        let send_handle = conn_tx.clone().send(msg).map(forget_result).map_err(
                            log_error,
                        );
                        handle.spawn(send_handle);
                    }
                }
                NetworkRequest::DisconnectWithPeer(peer) => {
                    outgoing_connections.remove(&peer);

                    let event = Event::Disconnected(peer);
                    let event_handle = events_tx.clone().send(event).map(forget_result).map_err(
                        log_error,
                    );
                    handle.spawn(event_handle);
                }
            }
            Ok(())
        });

        // Incoming connections handler
        let listener = TcpListener::bind(&listen_addr, &core.handle()).unwrap();
        let events_tx = events_tx.clone();
        let server = listener
            .incoming()
            .fold(events_tx, move |events_tx, (sock, addr)| {
                info!("Accepted incoming connection with peer={}", addr);

                let stream = sock.framed(MessagesCodec);
                let (_, stream) = stream.split();
                let events_tx = events_tx.clone();

                let event = Event::Disconnected(addr);
                let connect_event = events_tx.clone().send(event).map_err(into_other);

                let messages_stream = stream.for_each(move |raw| {
                    let event = Event::Incoming(raw);
                    events_tx.clone().send(event).map(forget_result).map_err(
                        into_other,
                    )
                });

                messages_stream
                    .join(connect_event)
                    .map(move |(_, stream)| stream)
                    .map_err(into_other)
            })
            .map(forget_result)
            .map_err(log_error);
        core.handle().spawn(server);

        core.run(requests_handle).unwrap();
    });

    let mut handler = node.handler;
    let mut core = node.core;
    handler.initialize();

    let events_handle = events_rx.merge(timeouts_rx).for_each(move |item| {
        match item {
            MergedItem::First(event) => {
                handler.handle_event(event);
            }
            MergedItem::Second(timeout) => {
                handler.handle_timeout(timeout);
            }
            MergedItem::Both(event, timeout) => {
                handler.handle_timeout(timeout);
                handler.handle_event(event);
            }
        }
        Ok(())
    });
    core.run(events_handle).unwrap();
    debug!("Handler thread is gone");

    network_thread.join().unwrap();
    Ok(())
}<|endoftext|>


<commit_before>extern crate euclid;
extern crate vitral;

use std::iter;
use std::cmp::max;
use euclid::{Point2D, Rect, Size2D};
use vitral::ImageBuffer;

/// Try to pack input images in a single new texture.
///
/// Will create at most `max_size` * `max_size` texture, will fail if the input images cannot be
/// fit in the maximum image.
pub fn build_atlas<F, T: Clone>(input: &[ImageBuffer],
                                max_size: u32,
                                mut f: F)
                                -> Result<Vec<vitral::ImageData<T>>, ()>
    where F: FnMut(ImageBuffer) -> T
{
    let (buf, posns) = try!(build_atlas_buffer(input, max_size));
    let x_scale = 1.0 / buf.size.width as f32;
    let y_scale = 1.0 / buf.size.height as f32;

    let t = f(buf);

    Ok(input.iter()
            .zip(posns)
            .map(|(buf, pos)| {
                let size = buf.size;
                // Texture coordinates in [0, 1] range
                let tex_pos = Point2D::new(pos.x as f32 * x_scale, pos.y as f32 * y_scale);
                let tex_size = Size2D::new(size.width as f32 * x_scale,
                                           size.height as f32 * y_scale);
                vitral::ImageData {
                    texture: t.clone(),
                    size: size,
                    tex_coords: Rect::new(tex_pos, tex_size),
                }
            })
            .collect())
}

fn build_atlas_buffer(input: &[ImageBuffer],
                      mut max_size: u32)
                      -> Result<(ImageBuffer, Vec<Point2D<u32>>), ()> {
    assert!(input.len() > 0);
    let dims: Vec<Size2D<u32>> = input.iter()
                                      .map(|i| i.size)
                                      .collect();

    let mut packing = None;
    // Keep shrinking the atlas size until things no longer pack.
    while let Some(p) = pack_rectangles(Size2D::new(max_size, max_size), &dims) {
        packing = Some(p);
        max_size /= 2;
    }

    // Undo last scaling step.
    max_size *= 2;
    if max_size == 0 {
        max_size = 1;
    }

    if let Some(packing) = packing {
        let mut atlas = ImageBuffer::new(max_size, max_size);

        for (i, pos) in packing.iter().enumerate() {
            atlas.copy_from(&input[i], pos.x, pos.y);
        }

        Ok((atlas, packing))
    } else {
        // Didn't get a packing even at the largest size, bail out.
        Err(())
    }

}

/// Try to pack several small rectangles into one large rectangle. Return
/// offsets for the subrectangles within the container if a packing was found.
fn pack_rectangles(container_dim: Size2D<u32>, dims: &[Size2D<u32>]) -> Option<Vec<Point2D<u32>>> {
    let total_area = dims.iter()
                         .map(|dim| dim.width * dim.height)
                         .fold(0, |a, b| a + b);

    // Too much rectangle area to fit in container no matter how you pack it.
    // Fail early.
    if total_area > container_dim.width * container_dim.height {
        return None;
    }

    // Take enumeration to keep the original indices around.
    let mut largest_first: Vec<(usize, &Size2D<u32>)> = dims.iter()
                                                            .enumerate()
                                                            .collect();
    largest_first.sort_by(|&(_i, a), &(_j, b)| (b.width * b.height).cmp(&(a.width * a.height)));

    let mut slots = vec![Rect::new(Point2D::new(0, 0), container_dim)];

    let mut ret: Vec<Point2D<u32>> = iter::repeat(Point2D::new(0, 0))
                                         .take(dims.len())
                                         .collect();

    for &(idx, &dim) in &largest_first {
        match place(dim, &mut slots) {
            Some(pos) => {
                ret[idx] = pos;
            }
            None => {
                return None;
            }
        }
    }

    return Some(ret);

    /// Find the smallest slot in the slot vector that will fit the given
    /// item.
    fn place(dim: Size2D<u32>, slots: &mut Vec<Rect<u32>>) -> Option<Point2D<u32>> {
        for i in 0..(slots.len()) {
            let Rect { origin: slot_pos, size: slot_dim } = slots[i];
            if fits(dim, slot_dim) {
                // Remove the original slot, it gets the item. Add the two new
                // rectangles that form around the item.
                let (new_1, new_2) = remaining_rects(dim, Rect::new(slot_pos, slot_dim));
                slots.swap_remove(i);
                slots.push(new_1);
                slots.push(new_2);
                // Sort by area from smallest to largest.
                slots.sort_by(|&a, &b| {
                    (a.size.width * a.size.height).cmp(&(b.size.width * b.size.height))
                });
                return Some(slot_pos);
            }
        }
        None
    }

    /// Return the two remaining parts of container rect when the dim-sized
    /// item is placed in the top left corner.
    fn remaining_rects(dim: Size2D<u32>,
                       Rect { origin: rect_pos, size: rect_dim }: Rect<u32>)
                       -> (Rect<u32>, Rect<u32>) {
        assert!(fits(dim, rect_dim));

        // Choose between making a vertical or a horizontal split
        // based on which leaves a bigger open rectangle.
        let vert_vol = max(rect_dim.width * (rect_dim.height - dim.height),
                           (rect_dim.width - dim.width) * dim.height);
        let horiz_vol = max(dim.width * (rect_dim.height - dim.height),
                            (rect_dim.width - dim.width) * rect_dim.height);

        if vert_vol > horiz_vol {
            //     |AA
            // ----+--
            // BBBBBBB
            // BBBBBBB
            (Rect::new(Point2D::new(rect_pos.x + dim.width, rect_pos.y),
                       Size2D::new(rect_dim.width - dim.width, dim.height)),
             Rect::new(Point2D::new(rect_pos.x, rect_pos.y + dim.height),
                       Size2D::new(rect_dim.width, rect_dim.height - dim.height)))
        } else {
            //     |BB
            // ----+BB
            // AAAA|BB
            // AAAA|BB
            (Rect::new(Point2D::new(rect_pos.x, rect_pos.y + dim.height),
                       Size2D::new(dim.width, rect_dim.height - dim.height)),
             Rect::new(Point2D::new(rect_pos.x + dim.width, rect_pos.y),
                       Size2D::new(rect_dim.width - dim.width, rect_dim.height)))
        }
    }

    fn fits(dim: Size2D<u32>, container_dim: Size2D<u32>) -> bool {
        dim.width <= container_dim.width && dim.height <= container_dim.height
    }
}
<commit_msg>Rename atlas build fn<commit_after>extern crate euclid;
extern crate vitral;

use std::iter;
use std::cmp::max;
use euclid::{Point2D, Rect, Size2D};
use vitral::ImageBuffer;

/// Try to pack input images in a single new texture.
///
/// Will create at most `max_size` * `max_size` texture, will fail if the input images cannot be
/// fit in the maximum image.
pub fn build<F, T: Clone>(input: &[ImageBuffer],
                          max_size: u32,
                          mut f: F)
                          -> Result<Vec<vitral::ImageData<T>>, ()>
    where F: FnMut(ImageBuffer) -> T
{
    let (buf, posns) = try!(build_atlas_buffer(input, max_size));
    let x_scale = 1.0 / buf.size.width as f32;
    let y_scale = 1.0 / buf.size.height as f32;

    let t = f(buf);

    Ok(input.iter()
            .zip(posns)
            .map(|(buf, pos)| {
                let size = buf.size;
                // Texture coordinates in [0, 1] range
                let tex_pos = Point2D::new(pos.x as f32 * x_scale, pos.y as f32 * y_scale);
                let tex_size = Size2D::new(size.width as f32 * x_scale,
                                           size.height as f32 * y_scale);
                vitral::ImageData {
                    texture: t.clone(),
                    size: size,
                    tex_coords: Rect::new(tex_pos, tex_size),
                }
            })
            .collect())
}

fn build_atlas_buffer(input: &[ImageBuffer],
                      mut max_size: u32)
                      -> Result<(ImageBuffer, Vec<Point2D<u32>>), ()> {
    assert!(input.len() > 0);
    let dims: Vec<Size2D<u32>> = input.iter()
                                      .map(|i| i.size)
                                      .collect();

    let mut packing = None;
    // Keep shrinking the atlas size until things no longer pack.
    while let Some(p) = pack_rectangles(Size2D::new(max_size, max_size), &dims) {
        packing = Some(p);
        max_size /= 2;
    }

    // Undo last scaling step.
    max_size *= 2;
    if max_size == 0 {
        max_size = 1;
    }

    if let Some(packing) = packing {
        let mut atlas = ImageBuffer::new(max_size, max_size);

        for (i, pos) in packing.iter().enumerate() {
            atlas.copy_from(&input[i], pos.x, pos.y);
        }

        Ok((atlas, packing))
    } else {
        // Didn't get a packing even at the largest size, bail out.
        Err(())
    }

}

/// Try to pack several small rectangles into one large rectangle. Return
/// offsets for the subrectangles within the container if a packing was found.
fn pack_rectangles(container_dim: Size2D<u32>, dims: &[Size2D<u32>]) -> Option<Vec<Point2D<u32>>> {
    let total_area = dims.iter()
                         .map(|dim| dim.width * dim.height)
                         .fold(0, |a, b| a + b);

    // Too much rectangle area to fit in container no matter how you pack it.
    // Fail early.
    if total_area > container_dim.width * container_dim.height {
        return None;
    }

    // Take enumeration to keep the original indices around.
    let mut largest_first: Vec<(usize, &Size2D<u32>)> = dims.iter()
                                                            .enumerate()
                                                            .collect();
    largest_first.sort_by(|&(_i, a), &(_j, b)| (b.width * b.height).cmp(&(a.width * a.height)));

    let mut slots = vec![Rect::new(Point2D::new(0, 0), container_dim)];

    let mut ret: Vec<Point2D<u32>> = iter::repeat(Point2D::new(0, 0))
                                         .take(dims.len())
                                         .collect();

    for &(idx, &dim) in &largest_first {
        match place(dim, &mut slots) {
            Some(pos) => {
                ret[idx] = pos;
            }
            None => {
                return None;
            }
        }
    }

    return Some(ret);

    /// Find the smallest slot in the slot vector that will fit the given
    /// item.
    fn place(dim: Size2D<u32>, slots: &mut Vec<Rect<u32>>) -> Option<Point2D<u32>> {
        for i in 0..(slots.len()) {
            let Rect { origin: slot_pos, size: slot_dim } = slots[i];
            if fits(dim, slot_dim) {
                // Remove the original slot, it gets the item. Add the two new
                // rectangles that form around the item.
                let (new_1, new_2) = remaining_rects(dim, Rect::new(slot_pos, slot_dim));
                slots.swap_remove(i);
                slots.push(new_1);
                slots.push(new_2);
                // Sort by area from smallest to largest.
                slots.sort_by(|&a, &b| {
                    (a.size.width * a.size.height).cmp(&(b.size.width * b.size.height))
                });
                return Some(slot_pos);
            }
        }
        None
    }

    /// Return the two remaining parts of container rect when the dim-sized
    /// item is placed in the top left corner.
    fn remaining_rects(dim: Size2D<u32>,
                       Rect { origin: rect_pos, size: rect_dim }: Rect<u32>)
                       -> (Rect<u32>, Rect<u32>) {
        assert!(fits(dim, rect_dim));

        // Choose between making a vertical or a horizontal split
        // based on which leaves a bigger open rectangle.
        let vert_vol = max(rect_dim.width * (rect_dim.height - dim.height),
                           (rect_dim.width - dim.width) * dim.height);
        let horiz_vol = max(dim.width * (rect_dim.height - dim.height),
                            (rect_dim.width - dim.width) * rect_dim.height);

        if vert_vol > horiz_vol {
            //     |AA
            // ----+--
            // BBBBBBB
            // BBBBBBB
            (Rect::new(Point2D::new(rect_pos.x + dim.width, rect_pos.y),
                       Size2D::new(rect_dim.width - dim.width, dim.height)),
             Rect::new(Point2D::new(rect_pos.x, rect_pos.y + dim.height),
                       Size2D::new(rect_dim.width, rect_dim.height - dim.height)))
        } else {
            //     |BB
            // ----+BB
            // AAAA|BB
            // AAAA|BB
            (Rect::new(Point2D::new(rect_pos.x, rect_pos.y + dim.height),
                       Size2D::new(dim.width, rect_dim.height - dim.height)),
             Rect::new(Point2D::new(rect_pos.x + dim.width, rect_pos.y),
                       Size2D::new(rect_dim.width - dim.width, rect_dim.height)))
        }
    }

    fn fits(dim: Size2D<u32>, container_dim: Size2D<u32>) -> bool {
        dim.width <= container_dim.width && dim.height <= container_dim.height
    }
}
<|endoftext|>


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

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

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

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

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

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

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

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

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

fn adjust_bits_per_sample(frame_header: &frame::Header,
                          channel: usize)
                          -> usize {
  let bits_per_sample = frame_header.bits_per_sample;

  match frame_header.channel_assignment {
    // Independent doesn't adjust bits per sample.
    ChannelAssignment::Independent => bits_per_sample,
    ChannelAssignment::LeftSide    => {
      if channel == 1 {
        bits_per_sample + 1
      } else {
        bits_per_sample
      }
    }
    ChannelAssignment::RightSide   => {
      if channel == 0 {
        bits_per_sample + 1
      } else {
        bits_per_sample
      }
    }
    ChannelAssignment::MiddleSide  => {
      if channel == 1 {
        bits_per_sample + 1
      } else {
        bits_per_sample
      }
    }
  }
}

pub fn subframe_parser<'a>(input: (&'a [u8], usize),
                           channel: &mut usize,
                           frame_header: &frame::Header)
                           -> IResult<'a, (&'a [u8], usize), SubFrame> {
  let block_size      = frame_header.block_size as usize;
  let bits_per_sample = adjust_bits_per_sample(frame_header, *channel);

  chain!(input,
    subframe_header: header ~
    wasted_bits: map!(
      cond!(subframe_header.1, leading_zeros),
      |option: Option<u32>| option.map_or(0, |zeros| zeros + 1)
    ) ~
    subframe_data: apply!(data,
      bits_per_sample - (wasted_bits as usize),
      block_size, subframe_header.0),
    || {
      // Iterate over the current channel being parsed. This probably should
      // be abstracted away, but for now this is the solution.
      *channel += 1;

      SubFrame {
        data: subframe_data,
        wasted_bits: wasted_bits,
      }
    }
  )
}

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

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

fn data(input: (&[u8], usize),
        bits_per_sample: usize,
        block_size: usize,
        subframe_type: usize)
        -> IResult<(&[u8], usize), subframe::Data> {
  match subframe_type {
    0b000000            => constant(input, bits_per_sample),
    0b000001            => verbatim(input, bits_per_sample, block_size),
    0b001000...0b001100 => fixed(input, subframe_type & 0b0111,
                                 bits_per_sample, block_size),
    0b100000...0b111111 => lpc(input, (subframe_type & 0b011111) + 1,
                               bits_per_sample, block_size),
    _                   => IResult::Error(Err::Position(
                             ErrorCode::Alt as u32, input.0))
  }
}

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

fn fixed(input: (&[u8], usize),
         order: usize,
         bits_per_sample: usize,
         block_size: usize)
         -> IResult<(&[u8], usize), subframe::Data> {
  let mut warmup = [0; subframe::MAX_FIXED_ORDER];

  chain!(input,
    count_slice!(take_bits!(i32, bits_per_sample), &mut warmup[0..order]) ~
    tuple: apply!(residual, order, block_size),
    || {
      let data = tuple;

      subframe::Data::Fixed(subframe::Fixed {
        entropy_coding_method: data.0,
        order: order as u8,
        warmup: warmup,
        residual: data.1,
      })
    }
  )
}

fn qlp_coefficient_precision(input: (&[u8], usize))
                             -> IResult<(&[u8], usize), u8> {
  match take_bits!(input, u8, 4) {
    IResult::Done(i, precision) => {
      if precision == 0b1111 {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      } else {
        IResult::Done(i, precision + 1)
      }
    }
    IResult::Error(error)       => IResult::Error(error),
    IResult::Incomplete(need)   => IResult::Incomplete(need),
  }
}

fn lpc(input: (&[u8], usize),
       order: usize,
       bits_per_sample: usize,
       block_size: usize)
       -> IResult<(&[u8], usize), subframe::Data> {
  let mut warmup           = [0; subframe::MAX_LPC_ORDER];
  let mut qlp_coefficients = [0; subframe::MAX_LPC_ORDER];

  chain!(input,
    count_slice!(take_bits!(i32, bits_per_sample), &mut warmup[0..order]) ~
    qlp_coeff_precision: qlp_coefficient_precision ~
    quantization_level: take_bits!(i8, 5) ~
    count_slice!(
      take_bits!(i32, qlp_coeff_precision as usize),
      &mut qlp_coefficients[0..order]
    ) ~
    tuple: apply!(residual, order, block_size),
    || {
      let data = tuple;

      subframe::Data::LPC(subframe::LPC {
        entropy_coding_method: data.0,
        order: order as u8,
        qlp_coeff_precision: qlp_coeff_precision,
        quantization_level: quantization_level,
        qlp_coefficients: qlp_coefficients,
        warmup: warmup,
        residual: data.1,
      })
    }
  )
}

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

fn coding_method(input: (&[u8], usize))
                 -> IResult<(&[u8], usize), CodingMethod> {
  match take_bits!(input, u8, 2) {
    IResult::Done(i, method)  => {
      match method {
        0 => IResult::Done(i, CodingMethod::PartitionedRice),
        1 => IResult::Done(i, CodingMethod::PartitionedRice2),
        _ => IResult::Error(Err::Position(ErrorCode::Alt as u32, input.0)),
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn residual(input: (&[u8], usize),
            predictor_order: usize,
            block_size: usize)
            -> IResult<(&[u8], usize),
                       (subframe::EntropyCodingMethod, Vec<i32>)> {
  match pair!(input, coding_method, take_bits!(u32, 4)) {
    IResult::Done(i, data)    => {
      let (method, order) = data;

      rice_partition(i, order, predictor_order, block_size, method)
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

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

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

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

  unsafe { residual.set_len(residual_size) }

  let partitions = 2_usize.pow(partition_order);

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

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

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

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

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

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

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

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

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

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

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

  *raw_bit = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

fn adjust_bits_per_sample(frame_header: &frame::Header,
                          channel: usize)
                          -> usize {
  let bits_per_sample = frame_header.bits_per_sample;

  match frame_header.channel_assignment {
    // Independent doesn't adjust bits per sample.
    ChannelAssignment::Independent => bits_per_sample,
    ChannelAssignment::LeftSide    => {
      if channel == 1 {
        bits_per_sample + 1
      } else {
        bits_per_sample
      }
    }
    ChannelAssignment::RightSide   => {
      if channel == 0 {
        bits_per_sample + 1
      } else {
        bits_per_sample
      }
    }
    ChannelAssignment::MiddleSide  => {
      if channel == 1 {
        bits_per_sample + 1
      } else {
        bits_per_sample
      }
    }
  }
}

pub fn subframe_parser<'a>(input: (&'a [u8], usize),
                           channel: &mut usize,
                           frame_header: &frame::Header)
                           -> IResult<'a, (&'a [u8], usize), SubFrame> {
  let block_size      = frame_header.block_size as usize;
  let bits_per_sample = adjust_bits_per_sample(frame_header, *channel);

  chain!(input,
    subframe_header: header ~
    wasted_bits: map!(
      cond!(subframe_header.1, leading_zeros),
      |option: Option<u32>| option.map_or(0, |zeros| zeros + 1)
    ) ~
    subframe_data: apply!(data,
      bits_per_sample - (wasted_bits as usize),
      block_size, subframe_header.0),
    || {
      // Iterate over the current channel being parsed. This probably should
      // be abstracted away, but for now this is the solution.
      *channel += 1;

      SubFrame {
        data: subframe_data,
        wasted_bits: wasted_bits,
      }
    }
  )
}

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

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

fn data(input: (&[u8], usize),
        bits_per_sample: usize,
        block_size: usize,
        subframe_type: usize)
        -> IResult<(&[u8], usize), subframe::Data> {
  match subframe_type {
    0b000000            => constant(input, bits_per_sample),
    0b000001            => verbatim(input, bits_per_sample, block_size),
    0b001000...0b001100 => fixed(input, subframe_type & 0b0111,
                                 bits_per_sample, block_size),
    0b100000...0b111111 => lpc(input, (subframe_type & 0b011111) + 1,
                               bits_per_sample, block_size),
    _                   => IResult::Error(Err::Position(
                             ErrorCode::Alt as u32, input.0))
  }
}

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

fn fixed(input: (&[u8], usize),
         order: usize,
         bits_per_sample: usize,
         block_size: usize)
         -> IResult<(&[u8], usize), subframe::Data> {
  let mut warmup = [0; subframe::MAX_FIXED_ORDER];

  chain!(input,
    count_slice!(take_bits!(i32, bits_per_sample), &mut warmup[0..order]) ~
    tuple: apply!(residual, order, block_size),
    || {
      let data = tuple;

      subframe::Data::Fixed(subframe::Fixed {
        entropy_coding_method: data.0,
        order: order as u8,
        warmup: warmup,
        residual: data.1,
      })
    }
  )
}

fn qlp_coefficient_precision(input: (&[u8], usize))
                             -> IResult<(&[u8], usize), u8> {
  match take_bits!(input, u8, 4) {
    IResult::Done(i, precision) => {
      if precision == 0b1111 {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      } else {
        IResult::Done(i, precision + 1)
      }
    }
    IResult::Error(error)       => IResult::Error(error),
    IResult::Incomplete(need)   => IResult::Incomplete(need),
  }
}

fn lpc(input: (&[u8], usize),
       order: usize,
       bits_per_sample: usize,
       block_size: usize)
       -> IResult<(&[u8], usize), subframe::Data> {
  let mut warmup           = [0; subframe::MAX_LPC_ORDER];
  let mut qlp_coefficients = [0; subframe::MAX_LPC_ORDER];

  chain!(input,
    count_slice!(take_bits!(i32, bits_per_sample), &mut warmup[0..order]) ~
    qlp_coeff_precision: qlp_coefficient_precision ~
    quantization_level: take_bits!(i8, 5) ~
    count_slice!(
      take_bits!(i32, qlp_coeff_precision as usize),
      &mut qlp_coefficients[0..order]
    ) ~
    tuple: apply!(residual, order, block_size),
    || {
      let data = tuple;

      subframe::Data::LPC(subframe::LPC {
        entropy_coding_method: data.0,
        order: order as u8,
        qlp_coeff_precision: qlp_coeff_precision,
        quantization_level: quantization_level,
        qlp_coefficients: qlp_coefficients,
        warmup: warmup,
        residual: data.1,
      })
    }
  )
}

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

fn coding_method(input: (&[u8], usize))
                 -> IResult<(&[u8], usize), CodingMethod> {
  match take_bits!(input, u8, 2) {
    IResult::Done(i, method)  => {
      match method {
        0 => IResult::Done(i, CodingMethod::PartitionedRice),
        1 => IResult::Done(i, CodingMethod::PartitionedRice2),
        _ => IResult::Error(Err::Position(ErrorCode::Alt as u32, input.0)),
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn residual(input: (&[u8], usize),
            predictor_order: usize,
            block_size: usize)
            -> IResult<(&[u8], usize),
                       (subframe::EntropyCodingMethod, Vec<i32>)> {
  match pair!(input, coding_method, take_bits!(u32, 4)) {
    IResult::Done(i, data)    => {
      let (method, order) = data;

      rice_partition(i, order, predictor_order, block_size, method)
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

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

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

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

  unsafe { residual.set_len(residual_size) }

  let partitions = 2_usize.pow(partition_order);

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

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

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

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

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

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

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

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

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

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

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

  *raw_bit = 0;

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

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

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

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

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

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

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

  #[test]
  fn test_leading_zeros() {
    let inputs  = [ (&[0b10000000][..], 0)
                  , (&[0b11000000][..], 1)
                  , (&[0b00000001][..], 0)
                  , (&[0b11111111][..], 7)
                  , (&[0b00000000, 0b10000000][..], 0)
                  , (&[0b10000000, 0b10000000][..], 1)
                  , (&[0b00000000, 0b00000001][..], 0)
                  , (&[0b11111110, 0b00000010][..], 7)
                  ];
    let results = [ IResult::Done((&inputs[0].0[..], 1), 0)
                  , IResult::Done((&inputs[1].0[..], 2), 0)
                  , IResult::Done((&[][..], 0), 7)
                  , IResult::Done((&[][..], 0), 0)
                  , IResult::Done((&inputs[4].0[1..], 1), 8)
                  , IResult::Done((&inputs[5].0[1..], 1), 7)
                  , IResult::Done((&[][..], 0), 15)
                  , IResult::Done((&inputs[7].0[1..], 7), 7)
                  ];

    assert_eq!(leading_zeros(inputs[0]), results[0]);
    assert_eq!(leading_zeros(inputs[1]), results[1]);
    assert_eq!(leading_zeros(inputs[2]), results[2]);
    assert_eq!(leading_zeros(inputs[3]), results[3]);
    assert_eq!(leading_zeros(inputs[4]), results[4]);
    assert_eq!(leading_zeros(inputs[5]), results[5]);
    assert_eq!(leading_zeros(inputs[6]), results[6]);
    assert_eq!(leading_zeros(inputs[7]), results[7]);
  }
}
<|endoftext|>


<commit_before>use header::{Header, HeaderFormat};
use std::fmt;
use std::str::FromStr;
use header::parsing::{from_comma_delimited, fmt_comma_delimited};

use self::Protocol::{WebSocket, ProtocolExt};

/// The `Upgrade` header.
#[derive(Clone, PartialEq, Debug)]
pub struct Upgrade(pub Vec<Protocol>);

deref!(Upgrade => Vec<Protocol>);

/// Protocol values that can appear in the Upgrade header.
#[derive(Clone, PartialEq, Debug)]
pub enum Protocol {
    /// The websocket protocol.
    WebSocket,
    /// Some other less common protocol.
    ProtocolExt(String),
}

impl FromStr for Protocol {
    fn from_str(s: &str) -> Option<Protocol> {
        match s {
            "websocket" => Some(WebSocket),
            s => Some(ProtocolExt(s.to_string()))
        }
    }
}

impl fmt::Display for Protocol {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}", match *self {
            WebSocket => "websocket",
            ProtocolExt(ref s) => s.as_slice()
        })
    }
}

impl Header for Upgrade {
    fn header_name() -> &'static str {
        "Upgrade"
    }

    fn parse_header(raw: &[Vec<u8>]) -> Option<Upgrade> {
        from_comma_delimited(raw).map(|vec| Upgrade(vec))
    }
}

impl HeaderFormat for Upgrade {
    fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let Upgrade(ref parts) = *self;
        fmt_comma_delimited(fmt, &parts[])
    }
}

bench_header!(bench, Upgrade, { vec![b"HTTP/2.0, RTA/x11, websocket".to_vec()] });

<commit_msg>fix(headers): make Protocol search websocket unicase<commit_after>use header::{Header, HeaderFormat};
use std::fmt;
use std::str::FromStr;
use header::parsing::{from_comma_delimited, fmt_comma_delimited};
use unicase::UniCase;

use self::Protocol::{WebSocket, ProtocolExt};

/// The `Upgrade` header.
#[derive(Clone, PartialEq, Debug)]
pub struct Upgrade(pub Vec<Protocol>);

deref!(Upgrade => Vec<Protocol>);

/// Protocol values that can appear in the Upgrade header.
#[derive(Clone, PartialEq, Debug)]
pub enum Protocol {
    /// The websocket protocol.
    WebSocket,
    /// Some other less common protocol.
    ProtocolExt(String),
}

impl FromStr for Protocol {
    fn from_str(s: &str) -> Option<Protocol> {
        if UniCase(s) == UniCase("websocket") {
            Some(WebSocket)
        }
        else {
            Some(ProtocolExt(s.to_string()))
        }
    }
}

impl fmt::Display for Protocol {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}", match *self {
            WebSocket => "websocket",
            ProtocolExt(ref s) => s.as_slice()
        })
    }
}

impl Header for Upgrade {
    fn header_name() -> &'static str {
        "Upgrade"
    }

    fn parse_header(raw: &[Vec<u8>]) -> Option<Upgrade> {
        from_comma_delimited(raw).map(|vec| Upgrade(vec))
    }
}

impl HeaderFormat for Upgrade {
    fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let Upgrade(ref parts) = *self;
        fmt_comma_delimited(fmt, &parts[])
    }
}

bench_header!(bench, Upgrade, { vec![b"HTTP/2.0, RTA/x11, websocket".to_vec()] });

<|endoftext|>