<commit_before>// Copyright (c) 2019 Chef Software Inc. and/or applicable 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::fs::create_dir_all;
use std::fs::{File, read_to_string};
use std::io::{Write};
use std::path::Path;
use serde_json::{self, json, Value as Json};
use toml::Value;

use crate::common::templating::TemplateRenderer;
use crate::common::ui::{Status, UIWriter, UI};
use crate::error::Result;

pub fn start(
    ui: &mut UI,
    template_path: &Path,
    default_toml_path: &Path,
    user_toml_path: Option<&Path>,
    mock_data_path: Option<&Path>,
    print: bool,
    no_render_dir: bool,
    render_dir: &Path,
    quiet: bool,
) -> Result<()> {
    // Strip the file name out of our passed template
    let file_name = match Path::new(&template_path).file_name() {
        Some(name) => name.to_str().clone().unwrap(),
        None => panic!(format!("Something went wrong getting filename of {:?}", &template_path)),
    };

    if !(quiet) {
      ui.begin(format!("Rendering: {:?} into: {:?} as: {:?}", template_path, render_dir, file_name))?;
      ui.br()?;
    }

    // read our template from file
    let template = read_to_string(&template_path)?;

    // create a "data" json struct
    let mut data = json!({});

    if !(quiet) {
        // import default.toml values, convert to JSON
        ui.begin(format!("Importing default.toml: {:?}", &default_toml_path))?;
    }

    // we should always have a default.toml, would be nice to "autodiscover" based on package name,
    // for now assume we're working in the plan dir if --default-toml not passed
    let default_toml = read_to_string(&default_toml_path)?;

    // merge default into data struct
    merge(&mut data, toml_to_json(&default_toml));

    // import default.toml values, convert to JSON
    let user_toml = match user_toml_path {
        Some(path) => {
            if !(quiet) {
              // print helper message, maybe only print if '--verbose'? how?
              ui.begin(format!("Importing user.toml: {:?}", path))?;
            }
            read_to_string(path)?
        },
        None => String::new(),
    };
    // merge default into data struct
    merge(&mut data, toml_to_json(&user_toml));

    // read mock data if provided
    let mock_data = match mock_data_path {
        Some(path) => {
            if !(quiet) {
                // print helper message, maybe only print if '--verbose'? how?
                ui.begin(format!("Importing override file: {:?}", path))?;
            }
            read_to_string(path)?
        },
        // return an empty json block if '--mock-data' isn't defined.
        // this allows us to merge an empty JSON block
        None => "{}".to_string(),
    };
    // merge mock data into data
    merge(&mut data, serde_json::from_str(&mock_data).unwrap());

    // create a template renderer
    let mut renderer = TemplateRenderer::new();
    // register our template
    renderer
        .register_template_string(&template, &template)
        .expect("Could not register template content");
    // render our JSON override in our template.
    let rendered_template = renderer.render(&template, &data).ok().unwrap();

    if print {
        if !(quiet) {
          ui.br()?;
          ui.warn(format!("###======== Rendered template: {:?}", &template_path))?;
        }

        println!("{}", rendered_template);

        if !(quiet) {
          ui.warn(format!("========### End rendered template: {:?}", &template_path))?;
        }
    }

    // if not no render dir (aka "unless no_render_dir == true")
    if !(no_render_dir) {
      // Render our template file
      create_with_template(ui, &Path::new(render_dir).join(file_name), &rendered_template, quiet)?;
    }

    if !(quiet) {
      ui.br()?;
    }
    // not really sure this is correct...
    Ok(())
}

fn toml_to_json(cfg: &str) -> Json {
    // parse TOML string to Value
    let toml_value = cfg.parse::<Value>().expect("Error parsing TOML");
    // convert toml to json string
    let toml_string = serde_json::to_string(&toml_value).expect("Error encoding JSON");
    // convert to Json::Value
    serde_json::from_str(&format!(r#"{{ "cfg": {} }}"#, &toml_string)).unwrap()
}

// merge two Json structs
fn merge(a: &mut Json, b: Json) {
    match (a, b) {
        // not sure I understand this...
        (a @ &mut Json::Object(_), Json::Object(b)) => {
            // not sure I understand why we unwrap this
            let a = a.as_object_mut().unwrap();
            // Iterate through key/values in Json object b,
            // merge with Json object b
            for (k, v) in b {
                merge(a.entry(k).or_insert(Json::Null), v);
            }
        }
        // or this...
        (a, b) => *a = b,
    }
}

// This is almost a dupe of the method in plan/init, except we don't care if the file exists and go
// ahead and overwite it.  I feel like maybe a different name would be good?
fn create_with_template(ui: &mut UI, location: &std::path::PathBuf, template: &str, quiet: bool) -> Result<()> {
    let path = Path::new(&location);
    if !(quiet) {
        ui.status(Status::Creating, format!("file: {:?}", location))?;
    }
    // If the directory doesn't exist we need to make it.
    if let Some(directory) = path.parent() {
        create_dir_all(directory)?;
    }
    // Write file to disk
    File::create(path).and_then(|mut file| file.write(template.as_bytes()))?;
    Ok(())
}
<commit_msg>remove unneeded comments<commit_after>// Copyright (c) 2019 Chef Software Inc. and/or applicable 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::fs::create_dir_all;
use std::fs::{File, read_to_string};
use std::io::{Write};
use std::path::Path;
use serde_json::{self, json, Value as Json};
use toml::Value;

use crate::common::templating::TemplateRenderer;
use crate::common::ui::{Status, UIWriter, UI};
use crate::error::Result;

pub fn start(
    ui: &mut UI,
    template_path: &Path,
    default_toml_path: &Path,
    user_toml_path: Option<&Path>,
    mock_data_path: Option<&Path>,
    print: bool,
    no_render_dir: bool,
    render_dir: &Path,
    quiet: bool,
) -> Result<()> {
    // Strip the file name out of our passed template
    let file_name = match Path::new(&template_path).file_name() {
        Some(name) => name.to_str().clone().unwrap(),
        None => panic!(format!("Something went wrong getting filename of {:?}", &template_path)),
    };

    if !(quiet) {
      ui.begin(format!("Rendering: {:?} into: {:?} as: {:?}", template_path, render_dir, file_name))?;
      ui.br()?;
    }

    // read our template from file
    let template = read_to_string(&template_path)?;

    // create a "data" json struct
    let mut data = json!({});

    if !(quiet) {
        // import default.toml values, convert to JSON
        ui.begin(format!("Importing default.toml: {:?}", &default_toml_path))?;
    }

    // we should always have a default.toml, would be nice to "autodiscover" based on package name,
    // for now assume we're working in the plan dir if --default-toml not passed
    let default_toml = read_to_string(&default_toml_path)?;

    // merge default into data struct
    merge(&mut data, toml_to_json(&default_toml));

    // import default.toml values, convert to JSON
    let user_toml = match user_toml_path {
        Some(path) => {
            if !(quiet) {
              // print helper message, maybe only print if '--verbose'? how?
              ui.begin(format!("Importing user.toml: {:?}", path))?;
            }
            read_to_string(path)?
        },
        None => String::new(),
    };
    // merge default into data struct
    merge(&mut data, toml_to_json(&user_toml));

    // read mock data if provided
    let mock_data = match mock_data_path {
        Some(path) => {
            if !(quiet) {
                // print helper message, maybe only print if '--verbose'? how?
                ui.begin(format!("Importing override file: {:?}", path))?;
            }
            read_to_string(path)?
        },
        // return an empty json block if '--mock-data' isn't defined.
        // this allows us to merge an empty JSON block
        None => "{}".to_string(),
    };
    // merge mock data into data
    merge(&mut data, serde_json::from_str(&mock_data).unwrap());

    // create a template renderer
    let mut renderer = TemplateRenderer::new();
    // register our template
    renderer
        .register_template_string(&template, &template)
        .expect("Could not register template content");
    // render our JSON override in our template.
    let rendered_template = renderer.render(&template, &data).ok().unwrap();

    if print {
        if !(quiet) {
          ui.br()?;
          ui.warn(format!("###======== Rendered template: {:?}", &template_path))?;
        }

        println!("{}", rendered_template);

        if !(quiet) {
          ui.warn(format!("========### End rendered template: {:?}", &template_path))?;
        }
    }

    // if not no render dir (aka "unless no_render_dir == true")
    if !(no_render_dir) {
      // Render our template file
      create_with_template(ui, &Path::new(render_dir).join(file_name), &rendered_template, quiet)?;
    }

    if !(quiet) {
      ui.br()?;
    }
    // not really sure this is correct...
    Ok(())
}

fn toml_to_json(cfg: &str) -> Json {
    let toml_value = cfg.parse::<Value>().expect("Error parsing TOML");
    let toml_string = serde_json::to_string(&toml_value).expect("Error encoding JSON");
    serde_json::from_str(&format!(r#"{{ "cfg": {} }}"#, &toml_string)).unwrap()
}

// merge two Json structs
fn merge(a: &mut Json, b: Json) {
    match (a, b) {
        // not sure I understand this...
        (a @ &mut Json::Object(_), Json::Object(b)) => {
            // not sure I understand why we unwrap this
            let a = a.as_object_mut().unwrap();
            // Iterate through key/values in Json object b,
            // merge with Json object b
            for (k, v) in b {
                merge(a.entry(k).or_insert(Json::Null), v);
            }
        }
        // or this...
        (a, b) => *a = b,
    }
}

// This is almost a dupe of the method in plan/init, except we don't care if the file exists and go
// ahead and overwite it.  I feel like maybe a different name would be good?
fn create_with_template(ui: &mut UI, location: &std::path::PathBuf, template: &str, quiet: bool) -> Result<()> {
    let path = Path::new(&location);
    if !(quiet) {
        ui.status(Status::Creating, format!("file: {:?}", location))?;
    }
    // If the directory doesn't exist we need to make it.
    if let Some(directory) = path.parent() {
        create_dir_all(directory)?;
    }
    // Write file to disk
    File::create(path).and_then(|mut file| file.write(template.as_bytes()))?;
    Ok(())
}
<|endoftext|>


<commit_before>//!Types for interpolation between multiple colors.

use std::cmp::max;

use Mix;

///A linear interpolation between colors.
#[derive(Clone)]
pub struct Gradient<C: Mix + Clone>(Vec<(f32, C)>);

impl<C: Mix + Clone> Gradient<C> {
    ///Create a gradient of evenly spaced colors with the domain [0.0, 1.0].
    ///There must be at least one color.
    pub fn new<I: IntoIterator<Item=C>>(colors: I) -> Gradient<C> {
        let mut points: Vec<_> = colors.into_iter().map(|c| (0.0, c)).collect();
        assert!(points.len() > 0);
        let step_size = 1.0 / max(points.len() - 1, 1) as f32;

        for (i, &mut (ref mut p, _)) in points.iter_mut().enumerate() {
            *p = i as f32 * step_size;
        }

        Gradient(points)
    }

    ///Create a gradient of colors with custom spacing and domain. There must be
    ///at least one color and they are expected to be ordered by their
    ///position value.
    pub fn with_domain(colors: Vec<(f32, C)>) -> Gradient<C> {
        assert!(colors.len() > 0);

        //Maybe sort the colors?
        Gradient(colors)
    }

    ///Get a color from the gradient. The nearest color will be returned if `i`
    ///is outside the domain.
    pub fn get(&self, i: f32) -> C {
        let &(mut min, ref min_color) = self.0.get(0).expect("a Gradient must contain at least one color");
        let mut min_color = min_color;
        let mut min_index = 0;

        if i <= min {
            return min_color.clone();
        }

        let &(mut max, ref max_color) = self.0.last().expect("a Gradient must contain at least one color");
        let mut max_color = max_color;
        let mut max_index = self.0.len() - 1;

        if i >= max {
            return max_color.clone();
        }

        while min_index < max_index - 1 {
            let index = min_index + (max_index - min_index) / 2;

            let (p, ref color) = self.0[index];

            if i <= p {
                max = p;
                max_color = color;
                max_index = index;
            } else {
                min = p;
                min_color = color;
                min_index = index;
            }
        }

        let factor = (i - min) / (max - min);

        min_color.mix(max_color, factor)
    }

    ///Take `n` evenly spaced colors from the gradient.
    pub fn take(&self, n: usize) -> Take<C> {
        let &(min, _) = self.0.get(0).expect("a Gradient must contain at least one color");
        let &(max, _) = self.0.last().expect("a Gradient must contain at least one color");

        Take {
            gradient: self,
            from: min,
            diff: max - min,
            len: n,
            current: 0,
        }
    }
}

///An iterator over interpolated colors.
pub struct Take<'a, C: Mix + Clone + 'a> {
    gradient: &'a Gradient<C>,
    from: f32,
    diff: f32,
    len: usize,
    current: usize,
}

impl<'a, C: Mix + Clone> Iterator for Take<'a, C> {
    type Item = C;

    fn next(&mut self) -> Option<C> {
        if self.current < self.len {
            let i = self.from + self.current as f32 * (self.diff / self.len as f32);
            self.current += 1;
            Some(self.gradient.get(i))
        } else {
            None
        }
    }
}
<commit_msg>Describe gradients some more<commit_after>//!Types for interpolation between multiple colors.

use std::cmp::max;

use Mix;

///A linear interpolation between colors.
///
///It's used to smoothly transition between a series of colors, that can be
///either evenly spaced or have customized positions. The gradient is
///continuous between the control points, but it's possible to iterate over a
///number of evenly spaced points using the `take` method. Any point outside
///the domain of the gradient will have the same color as the closest control
///point.
#[derive(Clone)]
pub struct Gradient<C: Mix + Clone>(Vec<(f32, C)>);

impl<C: Mix + Clone> Gradient<C> {
    ///Create a gradient of evenly spaced colors with the domain [0.0, 1.0].
    ///There must be at least one color.
    pub fn new<I: IntoIterator<Item=C>>(colors: I) -> Gradient<C> {
        let mut points: Vec<_> = colors.into_iter().map(|c| (0.0, c)).collect();
        assert!(points.len() > 0);
        let step_size = 1.0 / max(points.len() - 1, 1) as f32;

        for (i, &mut (ref mut p, _)) in points.iter_mut().enumerate() {
            *p = i as f32 * step_size;
        }

        Gradient(points)
    }

    ///Create a gradient of colors with custom spacing and domain. There must be
    ///at least one color and they are expected to be ordered by their
    ///position value.
    pub fn with_domain(colors: Vec<(f32, C)>) -> Gradient<C> {
        assert!(colors.len() > 0);

        //Maybe sort the colors?
        Gradient(colors)
    }

    ///Get a color from the gradient. The color of the closest control point
    ///will be returned if `i` is outside the domain.
    pub fn get(&self, i: f32) -> C {
        let &(mut min, ref min_color) = self.0.get(0).expect("a Gradient must contain at least one color");
        let mut min_color = min_color;
        let mut min_index = 0;

        if i <= min {
            return min_color.clone();
        }

        let &(mut max, ref max_color) = self.0.last().expect("a Gradient must contain at least one color");
        let mut max_color = max_color;
        let mut max_index = self.0.len() - 1;

        if i >= max {
            return max_color.clone();
        }

        while min_index < max_index - 1 {
            let index = min_index + (max_index - min_index) / 2;

            let (p, ref color) = self.0[index];

            if i <= p {
                max = p;
                max_color = color;
                max_index = index;
            } else {
                min = p;
                min_color = color;
                min_index = index;
            }
        }

        let factor = (i - min) / (max - min);

        min_color.mix(max_color, factor)
    }

    ///Take `n` evenly spaced colors from the gradient, as an iterator.
    pub fn take(&self, n: usize) -> Take<C> {
        let &(min, _) = self.0.get(0).expect("a Gradient must contain at least one color");
        let &(max, _) = self.0.last().expect("a Gradient must contain at least one color");

        Take {
            gradient: self,
            from: min,
            diff: max - min,
            len: n,
            current: 0,
        }
    }
}

///An iterator over interpolated colors.
pub struct Take<'a, C: Mix + Clone + 'a> {
    gradient: &'a Gradient<C>,
    from: f32,
    diff: f32,
    len: usize,
    current: usize,
}

impl<'a, C: Mix + Clone> Iterator for Take<'a, C> {
    type Item = C;

    fn next(&mut self) -> Option<C> {
        if self.current < self.len {
            let i = self.from + self.current as f32 * (self.diff / self.len as f32);
            self.current += 1;
            Some(self.gradient.get(i))
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>
extern crate sdl2;
extern crate rand;

use self::sdl2::rect::{Point, Rect};
use self::sdl2::pixels::Color;
use self::sdl2::EventPump;
use self::sdl2::event::Event;
use self::sdl2::mouse::MouseButton;
use self::sdl2::keyboard::Keycode;
use self::sdl2::VideoSubsystem;
use self::sdl2::video::{Window, WindowContext};
use self::sdl2::render::{Canvas, Texture, TextureCreator, WindowCanvas};
// use game_of_life::{SQUARE_SIZE, PLAYGROUND_WIDTH, PLAYGROUND_HEIGHT};

use ::domain::Point as myPoint;
use ::domain::terrain::Terrain;
use ::domain::person::Person;

use std::time::{Duration, Instant};

use self::rand::{Rng, SeedableRng, StdRng};

pub fn test_disp() {

    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window : Window = video_subsystem
        .window("rust-sdl2 demo: Window", 800, 600)
        .resizable()
        .build()
        .unwrap();

    let mut canvas = window.into_canvas().present_vsync().build().unwrap();

    let mut tick = 0;

    let now = Instant::now();
    while now.elapsed().as_secs() < 1_u64 { // displays the window for 1 second

    let mut event_pump = sdl_context.event_pump().unwrap();
        {
            // Update the window title.
            let mut window = canvas.window_mut();

            let position = window.position();
            let size = window.size();
            let title = format!("Window - pos({}x{}), size({}x{}): {}",
                                position.0,
                                position.1,
                                size.0,
                                size.1,
                                tick);
            window.set_title(&title).unwrap();

            tick += 1;

        }

        canvas.set_draw_color(Color::RGB(0, 0, 0));
        //canvas
        canvas.clear();
        canvas.present();
    }
}

pub fn initialize_windows(terrain : &Terrain) -> (WindowCanvas, Vec<u8>,  TextureCreator<WindowContext> , EventPump) {
    let data_array = terrain.get_data_ref();
    let x_size = terrain.xsize;
    let y_size = terrain.ysize;
    let mut pixels : Vec<u8> = vec![0;x_size * y_size * 3];

    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window: Window = video_subsystem
        .window("rust-sdl2 demo: Window", 800, 600)
        .opengl()
       // .resizable()
        .build()
        .unwrap();

    let mut canvas: WindowCanvas = window.into_canvas().accelerated().build().unwrap();
    println!("Using SDL_Renderer \"{}\"", canvas.info().name);
    let mut tick = 0;
    let mut event_pump = sdl_context.event_pump().unwrap();

    let mut text_creator: TextureCreator<WindowContext> = canvas.texture_creator();

    //texture.alpha_mod();
    //let texture = graphics::sdl2::render::Texture;
    return (canvas, pixels, text_creator, event_pump)
}

pub fn create_texture(text_creator : & TextureCreator<WindowContext>, width : usize, height : usize) -> Texture {
        text_creator.create_texture_streaming(
            sdl2::pixels::PixelFormatEnum::ARGB8888,
            width as u32,
            height as u32).unwrap()
    }

pub fn check_quit(event_pump : &mut EventPump) -> bool{
    for event in event_pump.poll_iter() {
        match event {
            Event::Quit { .. } |
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => return true,
            _ => {}
        }
    }
    false
}

pub fn update_texture(pixels :&mut Vec<u8>, terrain : &Terrain, canvas : &mut WindowCanvas, texture : &mut Texture) {
    let data = terrain.get_data_ref();
    let x_size = terrain.xsize;
    let y_size = terrain.ysize;
    assert_eq!(pixels.len(), x_size*y_size);

    {
        // Update the window title.
        let mut window = canvas.window_mut();

        let position = window.position();
        let size = window.size();
        let title = format!("Window - pos({}x{}), size({}x{})",
                            position.0,
                            position.1,
                            size.0,
                            size.1,
                            );
        window.set_title(&title).unwrap();
    }

    // -----
    // update texture
    //canvas.set_draw_color(Color::RGBA(0,0,0,0));
    texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
        for idx in 0..(x_size * y_size) {
            let offset = idx * 4;
            unsafe{
            buffer[offset + 0] = *data.get_unchecked(idx) as u8; // b
            buffer[offset + 1] = *data.get_unchecked(idx) as u8;//(data.get_unchecked(idx)*100_isize) as u8; // g
            buffer[offset + 2] = *data.get_unchecked(idx) as u8; // r
            buffer[offset + 3] = 255_u8; // a (opaque)
            }
        }

//        for x in 0..x_size {
//            for y in 0..y_size {
//                let offset = ( x_size * 4 * y ) + x * 4;
//                buffer[offset + 0] = (data[x][y]*50_isize) as u8; // b
//                buffer[offset + 1] = (data[x][y]*100_isize) as u8; // g
//                buffer[offset + 2] = data[x][y] as u8; // r
//                buffer[offset + 3] = 255_u8; // a (opaque)
//            }
//        }

//        // graph running indicator (changes color at each frame)
//        buffer[0] = rng.next_u32() as u8; // b
//        buffer[1] = rng.next_u32()  as u8; // g
//        buffer[2] = rng.next_u32()  as u8; // r
//        buffer[3] = 255_u8; // a
    });
}

/// this function keeps on drawing *the same* terrain over and over again.
pub fn graph_loop(terrain: &Terrain){

    let (mut canvas,
        mut pixels,
       // mut texture,
        mut text_creator,
        mut event_pump) = initialize_windows(terrain);

    let data_array = terrain.get_data_ref();
    let x_size = terrain.xsize;
    let y_size = terrain.ysize;

    let mut texture = create_texture(&text_creator, x_size, y_size);

    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit { .. } |
                Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'running,
                _ => {}
            }
        }

        {
            update_texture(&mut pixels, terrain, &mut canvas, &mut texture);
        }

        canvas.copy(&texture,
                    None,
                    None).unwrap();

        canvas.set_draw_color(Color::RGB(0, 0, 0));
        //canvas.clear();
        canvas.present();
    }

}
<commit_msg>FIX bug with assertions and pixel array size<commit_after>
extern crate sdl2;
extern crate rand;

use self::sdl2::rect::{Point, Rect};
use self::sdl2::pixels::Color;
use self::sdl2::EventPump;
use self::sdl2::event::Event;
use self::sdl2::mouse::MouseButton;
use self::sdl2::keyboard::Keycode;
use self::sdl2::VideoSubsystem;
use self::sdl2::video::{Window, WindowContext};
use self::sdl2::render::{Canvas, Texture, TextureCreator, WindowCanvas};
// use game_of_life::{SQUARE_SIZE, PLAYGROUND_WIDTH, PLAYGROUND_HEIGHT};

use ::domain::Point as myPoint;
use ::domain::terrain::Terrain;
use ::domain::person::Person;

use std::time::{Duration, Instant};

use self::rand::{Rng, SeedableRng, StdRng};

pub fn test_disp() {

    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window : Window = video_subsystem
        .window("rust-sdl2 demo: Window", 800, 600)
        .resizable()
        .build()
        .unwrap();

    let mut canvas = window.into_canvas().present_vsync().build().unwrap();

    let mut tick = 0;

    let now = Instant::now();
    while now.elapsed().as_secs() < 1_u64 { // displays the window for 1 second

    let mut event_pump = sdl_context.event_pump().unwrap();
        {
            // Update the window title.
            let mut window = canvas.window_mut();

            let position = window.position();
            let size = window.size();
            let title = format!("Window - pos({}x{}), size({}x{}): {}",
                                position.0,
                                position.1,
                                size.0,
                                size.1,
                                tick);
            window.set_title(&title).unwrap();

            tick += 1;

        }

        canvas.set_draw_color(Color::RGB(0, 0, 0));
        //canvas
        canvas.clear();
        canvas.present();
    }
}

pub fn initialize_windows(terrain : &Terrain) -> (WindowCanvas, Vec<u8>,  TextureCreator<WindowContext> , EventPump) {
    let data_array = terrain.get_data_ref();
    let x_size = terrain.xsize;
    let y_size = terrain.ysize;
    let num_px = sdl2::pixels::PixelFormatEnum::ARGB8888.byte_size_of_pixels(x_size * y_size);

    let mut pixels : Vec<u8> = vec![0; num_px];

    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window: Window = video_subsystem
        .window("rust-sdl2 demo: Window", 800, 600)
        .opengl()
       // .resizable()
        .build()
        .unwrap();

    let mut canvas: WindowCanvas = window.into_canvas().accelerated().build().unwrap();
    println!("Using SDL_Renderer \"{}\"", canvas.info().name);
    let mut tick = 0;
    let mut event_pump = sdl_context.event_pump().unwrap();

    let mut text_creator: TextureCreator<WindowContext> = canvas.texture_creator();

    return (canvas, pixels, text_creator, event_pump)
}

pub fn create_texture(text_creator : & TextureCreator<WindowContext>, width : usize, height : usize) -> Texture {
        text_creator.create_texture_streaming(
            sdl2::pixels::PixelFormatEnum::ARGB8888,
            width as u32,
            height as u32).unwrap()
    }

pub fn check_quit(event_pump : &mut EventPump) -> bool{
    for event in event_pump.poll_iter() {
        match event {
            Event::Quit { .. } |
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => return true,
            _ => {}
        }
    }
    false
}

pub fn update_texture(pixels :&mut Vec<u8>, terrain : &Terrain, canvas : &mut WindowCanvas, texture : &mut Texture) {
    let data = terrain.get_data_ref();
    let x_size = terrain.xsize;
    let y_size = terrain.ysize;
    let num_px = sdl2::pixels::PixelFormatEnum::ARGB8888.byte_size_of_pixels(x_size * y_size);
    assert_eq!(pixels.len() as usize, num_px);

    {
        // Update the window title.
        let mut window = canvas.window_mut();

        let position = window.position();
        let size = window.size();
        let title = format!("Window - pos({}x{}), size({}x{})",
                            position.0,
                            position.1,
                            size.0,
                            size.1,
                            );
        window.set_title(&title).unwrap();
    }

    // -----
    // update texture
    texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
        for idx in 0..(x_size * y_size) {
            let offset = idx * 4;
            unsafe{
            buffer[offset + 0] = *data.get_unchecked(idx) as u8; // b
            buffer[offset + 1] = *data.get_unchecked(idx) as u8;//(data.get_unchecked(idx)*100_isize) as u8; // g
            buffer[offset + 2] = *data.get_unchecked(idx) as u8; // r
            buffer[offset + 3] = 255_u8; // a (opaque)
            }
        }
    });
}

/// this function keeps on drawing *the same* terrain over and over again.
pub fn graph_loop(terrain: &Terrain){

    let (mut canvas,
        mut pixels,
       // mut texture,
        mut text_creator,
        mut event_pump) = initialize_windows(terrain);

    let data_array = terrain.get_data_ref();
    let x_size = terrain.xsize;
    let y_size = terrain.ysize;

    let mut texture = create_texture(&text_creator, x_size, y_size);

    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit { .. } |
                Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'running,
                _ => {}
            }
        }

        {
            update_texture(&mut pixels, terrain, &mut canvas, &mut texture);
        }

        canvas.copy(&texture,
                    None,
                    None).unwrap();

        canvas.set_draw_color(Color::RGB(0, 0, 0));
        //canvas.clear();
        canvas.present();
    }

}
<|endoftext|>


<commit_before>#[crate_id = "http#0.1-pre"];

#[comment = "Rust HTTP server"];
#[license = "MIT/ASL2"];
#[crate_type = "dylib"];
#[crate_type = "rlib"];

#[deny(non_camel_case_types)];
//#[deny(missing_doc)];

#[feature(macro_rules)];
#[macro_escape];

extern crate extra;
extern crate collections;

pub mod buffer;
pub mod client;
pub mod common;
pub mod connecter;
pub mod server;
pub mod method;
pub mod headers;
pub mod rfc2616;
#[path = "generated/status.rs"]
pub mod status;  // Getting an error? It's generated; use ``make`` or see the ``Makefile``

/// TODO: submit upstream
#[cfg(test)]
pub mod memstream;
<commit_msg>Made the library announce the location of its documentation<commit_after>#[crate_id = "http#0.1-pre"];

#[comment = "Rust HTTP server"];
#[license = "MIT/ASL2"];
#[crate_type = "dylib"];
#[crate_type = "rlib"];

#[doc(html_root_url = "http://www.rust-ci.org/chris-morgan/rust-http/doc/")];

#[deny(non_camel_case_types)];
//#[deny(missing_doc)];

#[feature(macro_rules)];
#[macro_escape];

extern crate extra;
extern crate collections;

pub mod buffer;
pub mod client;
pub mod common;
pub mod connecter;
pub mod server;
pub mod method;
pub mod headers;
pub mod rfc2616;
#[path = "generated/status.rs"]
pub mod status;  // Getting an error? It's generated; use ``make`` or see the ``Makefile``

/// TODO: submit upstream
#[cfg(test)]
pub mod memstream;
<|endoftext|>


<commit_before>//! Basic types to build the parsers

use self::IResult::*;

/*
/// (Experimental) Closure used to hold the temporary state of resumable parsing
pub type IResultClosure<'a,I,O> = Box<FnMut(I) -> IResult<I,O> +'a>;

//cf libcore/fmt/mod.rs:674
impl<'a,I,O> Debug for IResultClosure<'a,I,O> {
  fn fmt(&self, f: &mut Formatter) -> Result {
    Display::fmt("closure", f)
  }
}

impl<'a,I:PartialEq,O:PartialEq> PartialEq for IResultClosure<'a,I,O> {
  #[allow(unused_variables)]
  fn eq<'b>(&self, other: &IResultClosure<'b,I,O>) -> bool {
    false
  }

  #[allow(unused_variables)]
  fn ne<'b>(&self, other: &IResultClosure<'b,I,O>) -> bool {
    false
  }
}

impl<'a,I:Eq,O:Eq> Eq for IResultClosure<'a,I,O> {}
*/
//type IResultClosure<'a,I,O> = |I|:'a -> IResult<'a,I,O>;
//type IResultClosure<'a,I,O> = Fn<I, IResult<'a,I,O>>;

#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<'a>{
  Code(u32),
  Node(u32, Box<Err<'a>>),
  Position(u32, &'a [u8]),
  NodePosition(u32, &'a [u8], Box<Err<'a>>)
}

#[derive(Debug,PartialEq,Eq)]
pub enum Needed {
  Unknown,
  Size(u32)
}

/// Holds the result of parsing functions
///
/// It depends on I, the input types, and O, the output type.
///
/// * Done indicates a correct parsing, the first field containing the rest of the unparsed data,
/// the second field contains the parsed data
///
/// * Error is currently a u32, but should be updated to indicate which parser had a problem,
/// a description, and an eventual stack of parser to know which path failed
///
/// * Incomplete will hold the closure used to restart the computation once more data is available.
/// Current attemps at implementation of Incomplete are progressing, but slowed down by lifetime problems
#[derive(Debug,PartialEq,Eq)]
pub enum IResult<'a,I,O> {
  Done(I,O),
  Error(Err<'a>),
  //Incomplete(proc(I):'a -> IResult<I,O>)
  Incomplete(Needed)
  //Incomplete(Box<FnMut(I) -> IResult<I,O>>)
  //Incomplete(IResultClosure<I,O>)
  //Incomplete(|I|:'a -> IResult<'a,I,O>)
  //Incomplete(fn(I) -> IResult<'a,I,O>)
}

impl<'a,I,O> IResult<'a,I,O> {
  pub fn is_done(&self) -> bool {
    match self {
      &Done(_,_) => true,
      _          => false
    }
  }

  pub fn is_err(&self) -> bool {
    match self {
      &Error(_) => true,
      _         => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match self {
      &Incomplete(_) => true,
      _              => false
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O> GetInput<&'a[I]> for IResult<'a,&'a[I],O> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match self {
      &Done(ref i,_) => Some(*i),
      _          => None
    }
  }
}

impl<'a,O> GetInput<()> for IResult<'a,(),O> {
  fn remaining_input(&self) -> Option<()> {
    match self {
      &Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,I,O> GetOutput<&'a[O]> for IResult<'a,I,&'a[O]> {
  fn output(&self) -> Option<&'a[O]> {
    match self {
      &Done(_, ref o) => Some(*o),
      _          => None
    }
  }
}

impl<'a,I> GetOutput<()> for IResult<'a,I,()> {
  fn output(&self) -> Option<()> {
    match self {
      &Done(_,()) => Some(()),
      _          => None
    }
  }
}

<commit_msg>Missing trait derivations<commit_after>//! Basic types to build the parsers

use self::IResult::*;

/*
/// (Experimental) Closure used to hold the temporary state of resumable parsing
pub type IResultClosure<'a,I,O> = Box<FnMut(I) -> IResult<I,O> +'a>;

//cf libcore/fmt/mod.rs:674
impl<'a,I,O> Debug for IResultClosure<'a,I,O> {
  fn fmt(&self, f: &mut Formatter) -> Result {
    Display::fmt("closure", f)
  }
}

impl<'a,I:PartialEq,O:PartialEq> PartialEq for IResultClosure<'a,I,O> {
  #[allow(unused_variables)]
  fn eq<'b>(&self, other: &IResultClosure<'b,I,O>) -> bool {
    false
  }

  #[allow(unused_variables)]
  fn ne<'b>(&self, other: &IResultClosure<'b,I,O>) -> bool {
    false
  }
}

impl<'a,I:Eq,O:Eq> Eq for IResultClosure<'a,I,O> {}
*/
//type IResultClosure<'a,I,O> = |I|:'a -> IResult<'a,I,O>;
//type IResultClosure<'a,I,O> = Fn<I, IResult<'a,I,O>>;

#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<'a>{
  Code(u32),
  Node(u32, Box<Err<'a>>),
  Position(u32, &'a [u8]),
  NodePosition(u32, &'a [u8], Box<Err<'a>>)
}

#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Needed {
  Unknown,
  Size(u32)
}

/// Holds the result of parsing functions
///
/// It depends on I, the input types, and O, the output type.
///
/// * Done indicates a correct parsing, the first field containing the rest of the unparsed data,
/// the second field contains the parsed data
///
/// * Error is currently a u32, but should be updated to indicate which parser had a problem,
/// a description, and an eventual stack of parser to know which path failed
///
/// * Incomplete will hold the closure used to restart the computation once more data is available.
/// Current attemps at implementation of Incomplete are progressing, but slowed down by lifetime problems
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<'a,I,O> {
  Done(I,O),
  Error(Err<'a>),
  //Incomplete(proc(I):'a -> IResult<I,O>)
  Incomplete(Needed)
  //Incomplete(Box<FnMut(I) -> IResult<I,O>>)
  //Incomplete(IResultClosure<I,O>)
  //Incomplete(|I|:'a -> IResult<'a,I,O>)
  //Incomplete(fn(I) -> IResult<'a,I,O>)
}

impl<'a,I,O> IResult<'a,I,O> {
  pub fn is_done(&self) -> bool {
    match self {
      &Done(_,_) => true,
      _          => false
    }
  }

  pub fn is_err(&self) -> bool {
    match self {
      &Error(_) => true,
      _         => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match self {
      &Incomplete(_) => true,
      _              => false
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O> GetInput<&'a[I]> for IResult<'a,&'a[I],O> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match self {
      &Done(ref i,_) => Some(*i),
      _          => None
    }
  }
}

impl<'a,O> GetInput<()> for IResult<'a,(),O> {
  fn remaining_input(&self) -> Option<()> {
    match self {
      &Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,I,O> GetOutput<&'a[O]> for IResult<'a,I,&'a[O]> {
  fn output(&self) -> Option<&'a[O]> {
    match self {
      &Done(_, ref o) => Some(*o),
      _          => None
    }
  }
}

impl<'a,I> GetOutput<()> for IResult<'a,I,()> {
  fn output(&self) -> Option<()> {
    match self {
      &Done(_,()) => Some(()),
      _          => None
    }
  }
}

<|endoftext|>


<commit_before>#![feature(test)]
extern crate test;
#[macro_use]
extern crate chomp;

use test::Bencher;
use chomp::prelude::*;
use chomp::buffer::InputBuf;

#[derive(Debug)]
struct Request<B> {
    method:  B,
    uri:     B,
    version: B,
}

#[derive(Debug)]
struct Header<B> {
    name:  B,
    value: Vec<B>,
}

fn is_token(c: u8) -> bool {
    match c {
        128...255 => false,
        0...31    => false,
        b'('      => false,
        b')'      => false,
        b'<'      => false,
        b'>'      => false,
        b'@'      => false,
        b','      => false,
        b';'      => false,
        b':'      => false,
        b'\\'     => false,
        b'"'      => false,
        b'/'      => false,
        b'['      => false,
        b']'      => false,
        b'?'      => false,
        b'='      => false,
        b'{'      => false,
        b'}'      => false,
        b' '      => false,
        _         => true,
    }
}

fn is_horizontal_space(c: u8) -> bool { c == b' ' || c == b'\t' }
fn is_space(c: u8)            -> bool { c == b' ' }
fn is_not_space(c: u8)        -> bool { c != b' ' }
fn is_end_of_line(c: u8)      -> bool { c == b'\r' || c == b'\n' }
fn is_http_version(c: u8)     -> bool { c >= b'0' && c <= b'9' || c == b'.' }

fn end_of_line<I: U8Input>(i: I) -> SimpleResult<I, u8> {
    parse!{i; (token(b'\r') <|> ret b'\0') >> token(b'\n')}
}

fn http_version<I: U8Input>(i: I) -> SimpleResult<I, I::Buffer> {
    parse!{i;
        string(b"HTTP/");
        take_while1(is_http_version)
    }
}

fn request_line<I: U8Input>(i: I) -> SimpleResult<I, Request<I::Buffer>> {
    parse!{i;
        let method  = take_while1(is_token);
                      take_while1(is_space);
        let uri     = take_while1(is_not_space);
                      take_while1(is_space);
        let version = http_version();

        ret Request {
            method:  method,
            uri:     uri,
            version: version,
        }
    }
}

fn message_header_line<I: U8Input>(i: I) -> SimpleResult<I, I::Buffer> {
    parse!{i;
                   take_while1(is_horizontal_space);
        let line = take_till(is_end_of_line);
                   end_of_line();

        ret line
    }
}

fn message_header<I: U8Input>(i: I) -> SimpleResult<I, Header<I::Buffer>> {
    parse!{i;
        let name  = take_while1(is_token);
                    token(b':');
        let lines = many1(message_header_line);

        ret Header {
            name:  name,
            value: lines,
        }
    }
}

#[inline(never)]
fn request<I: U8Input>(i: I) -> SimpleResult<I, (Request<I::Buffer>, Vec<Header<I::Buffer>>)> {
    parse!{i;
        let r = request_line();
                end_of_line();
        let h = many(message_header);
                end_of_line();

        ret (r, h)
    }
}

#[bench]
fn single_request(b: &mut Bencher) {
    let data = b"GET / HTTP/1.1\r
Host: www.reddit.com\r
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1\r
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r
Accept-Language: en-us,en;q=0.5\r
Accept-Encoding: gzip, deflate\r
Connection: keep-alive\r
\r
\r";

    b.iter(|| {
        parse_only(request, data)
    })
}

#[bench]
fn single_request_minimal(b: &mut Bencher) {
    let data = b"GET / HTTP/1.1\r
Host: localhost\r
\r
\r";

    b.iter(|| {
        parse_only(request, data)
    })
}

#[bench]
fn single_request_large(b: &mut Bencher) {
    let data = b"GET /i.gif?e=eyJhdiI6NjIzNTcsImF0Ijo1LCJjbSI6MTE2MzUxLCJjaCI6Nzk4NCwiY3IiOjMzNzAxNSwiZGkiOiI4NmI2Y2UzYWM5NDM0MjhkOTk2ZTg4MjYwZDE5ZTE1YyIsImRtIjoxLCJmYyI6NDE2MTI4LCJmbCI6MjEwNDY0LCJrdyI6Ii1yZWRkaXQuY29tIiwibWsiOiItcmVkZGl0LmNvbSIsIm53Ijo1MTQ2LCJwYyI6MCwicHIiOjIwMzYyLCJydCI6MSwicmYiOiJodHRwOi8vd3d3LnJlZGRpdC5jb20vIiwic3QiOjI0OTUwLCJ1ayI6InVlMS01ZWIwOGFlZWQ5YTc0MDFjOTE5NWNiOTMzZWI3Yzk2NiIsInRzIjoxNDAwODYyNTkzNjQ1fQ&s=lwlbFf2Uywt7zVBFRj_qXXu7msY HTTP/1.1\r
Host: engine.adzerk.net\r
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1\r
Accept: image/png,image/*;q=0.8,*/*;q=0.5\r
Accept-Language: en-us,en;q=0.5\r
Accept-Encoding: gzip, deflate\r
Connection: keep-alive\r
Referer: http://static.adzerk.net/reddit/ads.html?sr=-reddit.com&bust2\r
Cookie: azk=ue1-5eb08aeed9a7401c9195cb933eb7c966\r
\r
\r";

    b.iter(|| {
        parse_only(request, data)
    })
}

#[bench]
fn multiple_requests(b: &mut Bencher) {
    let data = include_bytes!("./data/http-requests.txt");

    b.iter(|| {
        let r: Result<Vec<_>, _> = parse_only(parser!{many(request)}, data);

        r
    })
}
<commit_msg>bench: Fixed compiler warning<commit_after>#![feature(test)]
extern crate test;
#[macro_use]
extern crate chomp;

use test::Bencher;
use chomp::prelude::*;

#[derive(Debug)]
struct Request<B> {
    method:  B,
    uri:     B,
    version: B,
}

#[derive(Debug)]
struct Header<B> {
    name:  B,
    value: Vec<B>,
}

fn is_token(c: u8) -> bool {
    match c {
        128...255 => false,
        0...31    => false,
        b'('      => false,
        b')'      => false,
        b'<'      => false,
        b'>'      => false,
        b'@'      => false,
        b','      => false,
        b';'      => false,
        b':'      => false,
        b'\\'     => false,
        b'"'      => false,
        b'/'      => false,
        b'['      => false,
        b']'      => false,
        b'?'      => false,
        b'='      => false,
        b'{'      => false,
        b'}'      => false,
        b' '      => false,
        _         => true,
    }
}

fn is_horizontal_space(c: u8) -> bool { c == b' ' || c == b'\t' }
fn is_space(c: u8)            -> bool { c == b' ' }
fn is_not_space(c: u8)        -> bool { c != b' ' }
fn is_end_of_line(c: u8)      -> bool { c == b'\r' || c == b'\n' }
fn is_http_version(c: u8)     -> bool { c >= b'0' && c <= b'9' || c == b'.' }

fn end_of_line<I: U8Input>(i: I) -> SimpleResult<I, u8> {
    parse!{i; (token(b'\r') <|> ret b'\0') >> token(b'\n')}
}

fn http_version<I: U8Input>(i: I) -> SimpleResult<I, I::Buffer> {
    parse!{i;
        string(b"HTTP/");
        take_while1(is_http_version)
    }
}

fn request_line<I: U8Input>(i: I) -> SimpleResult<I, Request<I::Buffer>> {
    parse!{i;
        let method  = take_while1(is_token);
                      take_while1(is_space);
        let uri     = take_while1(is_not_space);
                      take_while1(is_space);
        let version = http_version();

        ret Request {
            method:  method,
            uri:     uri,
            version: version,
        }
    }
}

fn message_header_line<I: U8Input>(i: I) -> SimpleResult<I, I::Buffer> {
    parse!{i;
                   take_while1(is_horizontal_space);
        let line = take_till(is_end_of_line);
                   end_of_line();

        ret line
    }
}

fn message_header<I: U8Input>(i: I) -> SimpleResult<I, Header<I::Buffer>> {
    parse!{i;
        let name  = take_while1(is_token);
                    token(b':');
        let lines = many1(message_header_line);

        ret Header {
            name:  name,
            value: lines,
        }
    }
}

#[inline(never)]
fn request<I: U8Input>(i: I) -> SimpleResult<I, (Request<I::Buffer>, Vec<Header<I::Buffer>>)> {
    parse!{i;
        let r = request_line();
                end_of_line();
        let h = many(message_header);
                end_of_line();

        ret (r, h)
    }
}

#[bench]
fn single_request(b: &mut Bencher) {
    let data = b"GET / HTTP/1.1\r
Host: www.reddit.com\r
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1\r
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r
Accept-Language: en-us,en;q=0.5\r
Accept-Encoding: gzip, deflate\r
Connection: keep-alive\r
\r
\r";

    b.iter(|| {
        parse_only(request, data)
    })
}

#[bench]
fn single_request_minimal(b: &mut Bencher) {
    let data = b"GET / HTTP/1.1\r
Host: localhost\r
\r
\r";

    b.iter(|| {
        parse_only(request, data)
    })
}

#[bench]
fn single_request_large(b: &mut Bencher) {
    let data = b"GET /i.gif?e=eyJhdiI6NjIzNTcsImF0Ijo1LCJjbSI6MTE2MzUxLCJjaCI6Nzk4NCwiY3IiOjMzNzAxNSwiZGkiOiI4NmI2Y2UzYWM5NDM0MjhkOTk2ZTg4MjYwZDE5ZTE1YyIsImRtIjoxLCJmYyI6NDE2MTI4LCJmbCI6MjEwNDY0LCJrdyI6Ii1yZWRkaXQuY29tIiwibWsiOiItcmVkZGl0LmNvbSIsIm53Ijo1MTQ2LCJwYyI6MCwicHIiOjIwMzYyLCJydCI6MSwicmYiOiJodHRwOi8vd3d3LnJlZGRpdC5jb20vIiwic3QiOjI0OTUwLCJ1ayI6InVlMS01ZWIwOGFlZWQ5YTc0MDFjOTE5NWNiOTMzZWI3Yzk2NiIsInRzIjoxNDAwODYyNTkzNjQ1fQ&s=lwlbFf2Uywt7zVBFRj_qXXu7msY HTTP/1.1\r
Host: engine.adzerk.net\r
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1\r
Accept: image/png,image/*;q=0.8,*/*;q=0.5\r
Accept-Language: en-us,en;q=0.5\r
Accept-Encoding: gzip, deflate\r
Connection: keep-alive\r
Referer: http://static.adzerk.net/reddit/ads.html?sr=-reddit.com&bust2\r
Cookie: azk=ue1-5eb08aeed9a7401c9195cb933eb7c966\r
\r
\r";

    b.iter(|| {
        parse_only(request, data)
    })
}

#[bench]
fn multiple_requests(b: &mut Bencher) {
    let data = include_bytes!("./data/http-requests.txt");

    b.iter(|| {
        let r: Result<Vec<_>, _> = parse_only(parser!{many(request)}, data);

        r
    })
}
<|endoftext|>


<commit_before>use criterion::{criterion_group, criterion_main};
use criterion::{BenchmarkId, Criterion, Throughput};

use std::io::{Cursor, Read, Write};

use rand::Rng;
use zip::{CompressionMethod, ZipArchive, ZipWriter};

fn generate_random_archive(size: usize, method: Option<CompressionMethod>) -> Vec<u8> {
    let data = Vec::new();
    let mut writer = ZipWriter::new(Cursor::new(data));
    let options = zip::write::FileOptions::default()
        .compression_method(method.unwrap_or(CompressionMethod::Stored));

    writer.start_file("random.dat", options).unwrap();

    // Generate some random data.
    let mut bytes = vec![0u8; size];
    rand::thread_rng().fill(bytes.as_mut_slice());

    writer.write_all(&bytes).unwrap();

    writer.finish().unwrap().into_inner()
}

fn read_entry(bench: &mut Criterion) {
    let size = 1024 * 1024;
    let bytes = generate_random_archive(size, None);

    //
    let mut group = bench.benchmark_group("read_entry");

    //
    for method in CompressionMethod::supported_methods().iter() {
        group.bench_with_input(BenchmarkId::from_parameter(method), method, |b, method| {
            b.iter(|| {
                let mut archive = ZipArchive::new(Cursor::new(bytes.as_slice())).unwrap();
                let mut file = archive.by_name("random.dat").unwrap();
                let mut buf = [0u8; 1024];

                let mut total_bytes = 0;

                loop {
                    let n = file.read(&mut buf).unwrap();
                    total_bytes += n;
                    if n == 0 {
                        return total_bytes;
                    }
                }
            });
        });
    }
}

fn write_random_archive(bench: &mut Criterion) {
    let size = 1024 * 1024;

    //
    let mut group = bench.benchmark_group("write_random_archive");

    //
    for method in CompressionMethod::supported_methods().iter() {
        group.bench_with_input(BenchmarkId::from_parameter(method), method, |b, method| {
            b.iter(|| {
                generate_random_archive(size, Some(method.clone()));
            })
        });
    }

    group.finish();
}

criterion_group!(benches, read_entry, write_random_archive);
criterion_main!(benches);
<commit_msg>Update bench tests...<commit_after>use criterion::{criterion_group, criterion_main};
use criterion::{BenchmarkId, Criterion};

use std::io::{Cursor, Read, Write};

use rand::Rng;
use zip::{CompressionMethod, ZipArchive, ZipWriter};

fn generate_random_archive(size: usize, method: Option<CompressionMethod>) -> Vec<u8> {
    let data = Vec::new();
    let mut writer = ZipWriter::new(Cursor::new(data));
    let options = zip::write::FileOptions::default()
        .compression_method(method.unwrap_or(CompressionMethod::Stored));

    writer.start_file("random.dat", options).unwrap();

    // Generate some random data.
    let mut bytes = vec![0u8; size];
    rand::thread_rng().fill(bytes.as_mut_slice());

    writer.write_all(&bytes).unwrap();

    writer.finish().unwrap().into_inner()
}

fn read_entry(bench: &mut Criterion) {
    let size = 1024 * 1024;

    //
    let mut group = bench.benchmark_group("read_entry");

    //
    for method in CompressionMethod::supported_methods().iter() {
        group.bench_with_input(BenchmarkId::from_parameter(method), method, |bench, method| {
            let bytes = generate_random_archive(size, Some(*method));

            bench.iter(|| {
                let mut archive = ZipArchive::new(Cursor::new(bytes.as_slice())).unwrap();
                let mut file = archive.by_name("random.dat").unwrap();
                let mut buf = [0u8; 1024];

                let mut total_bytes = 0;

                loop {
                    let n = file.read(&mut buf).unwrap();
                    total_bytes += n;
                    if n == 0 {
                        return total_bytes;
                    }
                }
            });
        });
    }
}

fn write_random_archive(bench: &mut Criterion) {
    let size = 1024 * 1024;

    //
    let mut group = bench.benchmark_group("write_random_archive");

    //
    for method in CompressionMethod::supported_methods().iter() {
        group.bench_with_input(BenchmarkId::from_parameter(method), method, |b, method| {
            b.iter(|| {
                generate_random_archive(size, Some(*method));
            })
        });
    }

    group.finish();
}

criterion_group!(benches, read_entry, write_random_archive);
criterion_main!(benches);
<|endoftext|>


<commit_before>use super::Backend;
use std::fs::{self, File};
use std::io;
use std::path::{Path, PathBuf};

/// Backend operating on the local filesystem.
pub struct LocalBackend {
    base_path: PathBuf,
}

impl LocalBackend {
    /// Create a new LocalBackend that operates on the given directory.
    pub fn new<P: AsRef<Path>>(path: P) -> Self {
        LocalBackend { base_path: path.as_ref().to_path_buf() }
    }
}

impl Backend for LocalBackend {
    type FileName = PathBuf;
    type FileNameIter = Vec<PathBuf>;
    type FileStream = File;

    fn get_file_names(&self) -> io::Result<Self::FileNameIter> {
        let dir = try!(fs::read_dir(self.base_path.as_path()));
        let paths = dir.filter(|entry| entry.is_ok())
                       .map(|entry| {
                           let filename = entry.unwrap().file_name();
                           let filename: &Path = filename.as_ref();
                           filename.to_path_buf()
                       })
                       .collect::<Vec<_>>();
        Ok(paths)
    }

    fn open_file(&self, name: &Path) -> io::Result<File> {
        let mut path = self.base_path.clone();
        path.push(name);
        File::open(path)
    }
}
<commit_msg>Use a lazy iterator for local backend file names<commit_after>use super::Backend;
use std::fs::{self, File};
use std::io;
use std::path::{Path, PathBuf};
use std::ffi::OsString;

/// Backend operating on the local filesystem.
pub struct LocalBackend {
    base_path: PathBuf,
}

/// Iterator over a set of file names.
pub struct FileNameIterator(fs::ReadDir);

impl LocalBackend {
    /// Create a new LocalBackend that operates on the given directory.
    pub fn new<P: AsRef<Path>>(path: P) -> Self {
        LocalBackend { base_path: path.as_ref().to_path_buf() }
    }
}

impl Backend for LocalBackend {
    type FileName = OsString;
    type FileNameIter = FileNameIterator;
    type FileStream = File;

    fn get_file_names(&self) -> io::Result<Self::FileNameIter> {
        let dir = try!(fs::read_dir(self.base_path.as_path()));
        Ok(FileNameIterator(dir))
    }

    fn open_file(&self, name: &Path) -> io::Result<File> {
        let mut path = self.base_path.clone();
        path.push(name);
        File::open(path)
    }
}

impl Iterator for FileNameIterator {
    type Item = OsString;

    fn next(&mut self) -> Option<OsString> {
        while let Some(entry) = self.0.next() {
            if let Ok(entry) = entry {
                return Some(entry.file_name());
            }
        }
        None
    }
}
<|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/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<%helpers:shorthand name="flex-flow" sub_properties="flex-direction flex-wrap" extra_prefixes="webkit"
                    spec="https://drafts.csswg.org/css-flexbox/#flex-flow-property">
    use properties::longhands::{flex_direction, flex_wrap};

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let mut direction = None;
        let mut wrap = None;
        loop {
            if direction.is_none() {
                if let Ok(value) = input.try(|input| flex_direction::parse(context, input)) {
                    direction = Some(value);
                    continue
                }
            }
            if wrap.is_none() {
                if let Ok(value) = input.try(|input| flex_wrap::parse(context, input)) {
                    wrap = Some(value);
                    continue
                }
            }
            break
        }

        if direction.is_none() && wrap.is_none() {
            return Err(())
        }
        Ok(Longhands {
            flex_direction: unwrap_or_initial!(flex_direction, direction),
            flex_wrap: unwrap_or_initial!(flex_wrap, wrap),
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            self.flex_direction.to_css(dest)?;
            dest.write_str(" ")?;
            self.flex_wrap.to_css(dest)
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="flex" sub_properties="flex-grow flex-shrink flex-basis" extra_prefixes="webkit"
                    spec="https://drafts.csswg.org/css-flexbox/#flex-property">
    use values::specified::Number;

    fn parse_flexibility(context: &ParserContext, input: &mut Parser)
                         -> Result<(Number, Option<Number>),()> {
        let grow = try!(Number::parse_non_negative(context, input));
        let shrink = input.try(|i| Number::parse_non_negative(context, i)).ok();
        Ok((grow, shrink))
    }

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let mut grow = None;
        let mut shrink = None;
        let mut basis = None;

        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
            return Ok(Longhands {
                flex_grow: Number::new(0.0),
                flex_shrink: Number::new(0.0),
                flex_basis: longhands::flex_basis::SpecifiedValue::auto(),
            })
        }
        loop {
            if grow.is_none() {
                if let Ok((flex_grow, flex_shrink)) = input.try(|i| parse_flexibility(context, i)) {
                    grow = Some(flex_grow);
                    shrink = flex_shrink;
                    continue
                }
            }
            if basis.is_none() {
                if let Ok(value) = input.try(|input| longhands::flex_basis::parse(context, input)) {
                    basis = Some(value);
                    continue
                }
            }
            break
        }

        if grow.is_none() && basis.is_none() {
            return Err(())
        }
        Ok(Longhands {
            flex_grow: grow.unwrap_or(Number::new(1.0)),
            flex_shrink: shrink.unwrap_or(Number::new(1.0)),
            flex_basis: basis.unwrap_or(longhands::flex_basis::SpecifiedValue::zero()),
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            try!(self.flex_grow.to_css(dest));
            try!(dest.write_str(" "));

            try!(self.flex_shrink.to_css(dest));
            try!(dest.write_str(" "));

            self.flex_basis.to_css(dest)
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="grid-gap" sub_properties="grid-row-gap grid-column-gap"
                    spec="https://drafts.csswg.org/css-grid/#propdef-grid-gap"
                    products="gecko">
  use properties::longhands::{grid_row_gap, grid_column_gap};

  pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
      let row_gap = grid_row_gap::parse(context, input)?;
      let column_gap = input.try(|input| grid_column_gap::parse(context, input)).unwrap_or(row_gap.clone());

      Ok(Longhands {
        grid_row_gap: row_gap,
        grid_column_gap: column_gap,
      })
  }

  impl<'a> ToCss for LonghandsToSerialize<'a>  {
      fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
          if self.grid_row_gap == self.grid_column_gap {
            self.grid_row_gap.to_css(dest)
          } else {
            self.grid_row_gap.to_css(dest)?;
            dest.write_str(" ")?;
            self.grid_column_gap.to_css(dest)
          }
      }
  }

</%helpers:shorthand>

<%helpers:shorthand name="place-content" sub_properties="align-content justify-content"
                    spec="https://drafts.csswg.org/css-align/#propdef-place-content"
                    products="gecko" disable_when_testing="True">
    use properties::longhands::align_content;
    use properties::longhands::justify_content;

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let align = align_content::parse(context, input)?;
        let justify = input.try(|input| justify_content::parse(context, input))
                           .unwrap_or(justify_content::SpecifiedValue::from(align));

        Ok(Longhands {
            align_content: align,
            justify_content: justify,
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a> {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            if self.align_content == self.justify_content {
                self.align_content.to_css(dest)
            } else {
                self.justify_content.to_css(dest)?;
                dest.write_str(" ")?;
                self.justify_content.to_css(dest)
            }
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="place-self" sub_properties="align-self justify-self"
                    spec="https://drafts.csswg.org/css-align/#place-self-property"
                    products="gecko" disable_when_testing="True">
    use values::specified::align::AlignJustifySelf;
    use parser::Parse;

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let align = AlignJustifySelf::parse(context, input)?;
        let justify = input.try(|input| AlignJustifySelf::parse(context, input)).unwrap_or(align.clone());

        Ok(Longhands {
            align_self: align,
            justify_self: justify,
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a> {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            if self.align_self == self.justify_self {
                self.align_self.to_css(dest)
            } else {
                self.align_self.to_css(dest)?;
                dest.write_str(" ")?;
                self.justify_self.to_css(dest)
            }
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="place-items" sub_properties="align-items justify-items"
                    spec="https://drafts.csswg.org/css-align/#place-items-property"
                    products="gecko" disable_when_testing="True">
    use values::specified::align::{AlignItems, JustifyItems};
    use parser::Parse;

    impl From<AlignItems> for JustifyItems {
        fn from(align: AlignItems) -> JustifyItems {
            JustifyItems(align.0)
        }
    }

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let align = AlignItems::parse(context, input)?;
        let justify = input.try(|input| JustifyItems::parse(context, input))
                           .unwrap_or(JustifyItems::from(align));

        Ok(Longhands {
            align_items: align,
            justify_items: justify,
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a> {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            if self.align_items.0 == self.justify_items.0 {
                self.align_items.to_css(dest)
            } else {
                self.align_items.to_css(dest)?;
                dest.write_str(" ")?;
                self.justify_items.to_css(dest)
            }
        }
    }
</%helpers:shorthand>
<commit_msg>Auto merge of #16443 - Wafflespeanut:grid-2, r=canaltinova<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/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<%helpers:shorthand name="flex-flow" sub_properties="flex-direction flex-wrap" extra_prefixes="webkit"
                    spec="https://drafts.csswg.org/css-flexbox/#flex-flow-property">
    use properties::longhands::{flex_direction, flex_wrap};

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let mut direction = None;
        let mut wrap = None;
        loop {
            if direction.is_none() {
                if let Ok(value) = input.try(|input| flex_direction::parse(context, input)) {
                    direction = Some(value);
                    continue
                }
            }
            if wrap.is_none() {
                if let Ok(value) = input.try(|input| flex_wrap::parse(context, input)) {
                    wrap = Some(value);
                    continue
                }
            }
            break
        }

        if direction.is_none() && wrap.is_none() {
            return Err(())
        }
        Ok(Longhands {
            flex_direction: unwrap_or_initial!(flex_direction, direction),
            flex_wrap: unwrap_or_initial!(flex_wrap, wrap),
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            self.flex_direction.to_css(dest)?;
            dest.write_str(" ")?;
            self.flex_wrap.to_css(dest)
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="flex" sub_properties="flex-grow flex-shrink flex-basis" extra_prefixes="webkit"
                    spec="https://drafts.csswg.org/css-flexbox/#flex-property">
    use values::specified::Number;

    fn parse_flexibility(context: &ParserContext, input: &mut Parser)
                         -> Result<(Number, Option<Number>),()> {
        let grow = try!(Number::parse_non_negative(context, input));
        let shrink = input.try(|i| Number::parse_non_negative(context, i)).ok();
        Ok((grow, shrink))
    }

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let mut grow = None;
        let mut shrink = None;
        let mut basis = None;

        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
            return Ok(Longhands {
                flex_grow: Number::new(0.0),
                flex_shrink: Number::new(0.0),
                flex_basis: longhands::flex_basis::SpecifiedValue::auto(),
            })
        }
        loop {
            if grow.is_none() {
                if let Ok((flex_grow, flex_shrink)) = input.try(|i| parse_flexibility(context, i)) {
                    grow = Some(flex_grow);
                    shrink = flex_shrink;
                    continue
                }
            }
            if basis.is_none() {
                if let Ok(value) = input.try(|input| longhands::flex_basis::parse(context, input)) {
                    basis = Some(value);
                    continue
                }
            }
            break
        }

        if grow.is_none() && basis.is_none() {
            return Err(())
        }
        Ok(Longhands {
            flex_grow: grow.unwrap_or(Number::new(1.0)),
            flex_shrink: shrink.unwrap_or(Number::new(1.0)),
            flex_basis: basis.unwrap_or(longhands::flex_basis::SpecifiedValue::zero()),
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            try!(self.flex_grow.to_css(dest));
            try!(dest.write_str(" "));

            try!(self.flex_shrink.to_css(dest));
            try!(dest.write_str(" "));

            self.flex_basis.to_css(dest)
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="grid-gap" sub_properties="grid-row-gap grid-column-gap"
                    spec="https://drafts.csswg.org/css-grid/#propdef-grid-gap"
                    products="gecko">
  use properties::longhands::{grid_row_gap, grid_column_gap};

  pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
      let row_gap = grid_row_gap::parse(context, input)?;
      let column_gap = input.try(|input| grid_column_gap::parse(context, input)).unwrap_or(row_gap.clone());

      Ok(Longhands {
        grid_row_gap: row_gap,
        grid_column_gap: column_gap,
      })
  }

  impl<'a> ToCss for LonghandsToSerialize<'a>  {
      fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
          if self.grid_row_gap == self.grid_column_gap {
            self.grid_row_gap.to_css(dest)
          } else {
            self.grid_row_gap.to_css(dest)?;
            dest.write_str(" ")?;
            self.grid_column_gap.to_css(dest)
          }
      }
  }

</%helpers:shorthand>

% for kind in ["row", "column"]:
<%helpers:shorthand name="grid-${kind}" sub_properties="grid-${kind}-start grid-${kind}-end"
                    spec="https://drafts.csswg.org/css-grid/#propdef-grid-${kind}"
                    products="gecko">
    use values::specified::GridLine;
    use parser::Parse;

    // NOTE: Since both the shorthands have the same code, we should (re-)use code from one to implement
    // the other. This might not be a big deal for now, but we should consider looking into this in the future
    // to limit the amount of code generated.
    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let start = input.try(|i| GridLine::parse(context, i))?;
        let end = if input.try(|i| i.expect_delim('/')).is_ok() {
            GridLine::parse(context, input)?
        } else {
            let mut line = GridLine::default();
            if start.integer.is_none() && !start.is_span {
                line.ident = start.ident.clone();       // ident from start value should be taken
            }

            line
        };

        Ok(Longhands {
            grid_${kind}_start: start,
            grid_${kind}_end: end,
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a> {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            self.grid_${kind}_start.to_css(dest)?;
            dest.write_str(" / ")?;
            self.grid_${kind}_end.to_css(dest)
        }
    }
</%helpers:shorthand>
% endfor

<%helpers:shorthand name="grid-area"
                    sub_properties="grid-row-start grid-row-end grid-column-start grid-column-end"
                    spec="https://drafts.csswg.org/css-grid/#propdef-grid-area"
                    products="gecko">
    use values::specified::GridLine;
    use parser::Parse;

    // The code is the same as `grid-{row,column}` except that this can have four values at most.
    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        fn line_with_ident_from(other: &GridLine) -> GridLine {
            let mut this = GridLine::default();
            if other.integer.is_none() && !other.is_span {
                this.ident = other.ident.clone();
            }

            this
        }

        let row_start = input.try(|i| GridLine::parse(context, i))?;
        let (column_start, row_end, column_end) = if input.try(|i| i.expect_delim('/')).is_ok() {
            let column_start = GridLine::parse(context, input)?;
            let (row_end, column_end) = if input.try(|i| i.expect_delim('/')).is_ok() {
                let row_end = GridLine::parse(context, input)?;
                let column_end = if input.try(|i| i.expect_delim('/')).is_ok() {
                    GridLine::parse(context, input)?
                } else {        // grid-column-end has not been given
                    line_with_ident_from(&column_start)
                };

                (row_end, column_end)
            } else {        // grid-row-start and grid-column-start has been given
                let row_end = line_with_ident_from(&row_start);
                let column_end = line_with_ident_from(&column_start);
                (row_end, column_end)
            };

            (column_start, row_end, column_end)
        } else {        // only grid-row-start is given
            let line = line_with_ident_from(&row_start);
            (line.clone(), line.clone(), line)
        };

        Ok(Longhands {
            grid_row_start: row_start,
            grid_row_end: row_end,
            grid_column_start: column_start,
            grid_column_end: column_end,
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a> {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            self.grid_row_start.to_css(dest)?;
            let values = [&self.grid_column_start, &self.grid_row_end, &self.grid_column_end];
            for value in &values {
                dest.write_str(" / ")?;
                value.to_css(dest)?;
            }

            Ok(())
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="place-content" sub_properties="align-content justify-content"
                    spec="https://drafts.csswg.org/css-align/#propdef-place-content"
                    products="gecko" disable_when_testing="True">
    use properties::longhands::align_content;
    use properties::longhands::justify_content;

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let align = align_content::parse(context, input)?;
        let justify = input.try(|input| justify_content::parse(context, input))
                           .unwrap_or(justify_content::SpecifiedValue::from(align));

        Ok(Longhands {
            align_content: align,
            justify_content: justify,
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a> {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            if self.align_content == self.justify_content {
                self.align_content.to_css(dest)
            } else {
                self.justify_content.to_css(dest)?;
                dest.write_str(" ")?;
                self.justify_content.to_css(dest)
            }
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="place-self" sub_properties="align-self justify-self"
                    spec="https://drafts.csswg.org/css-align/#place-self-property"
                    products="gecko" disable_when_testing="True">
    use values::specified::align::AlignJustifySelf;
    use parser::Parse;

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let align = AlignJustifySelf::parse(context, input)?;
        let justify = input.try(|input| AlignJustifySelf::parse(context, input)).unwrap_or(align.clone());

        Ok(Longhands {
            align_self: align,
            justify_self: justify,
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a> {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            if self.align_self == self.justify_self {
                self.align_self.to_css(dest)
            } else {
                self.align_self.to_css(dest)?;
                dest.write_str(" ")?;
                self.justify_self.to_css(dest)
            }
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="place-items" sub_properties="align-items justify-items"
                    spec="https://drafts.csswg.org/css-align/#place-items-property"
                    products="gecko" disable_when_testing="True">
    use values::specified::align::{AlignItems, JustifyItems};
    use parser::Parse;

    impl From<AlignItems> for JustifyItems {
        fn from(align: AlignItems) -> JustifyItems {
            JustifyItems(align.0)
        }
    }

    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
        let align = AlignItems::parse(context, input)?;
        let justify = input.try(|input| JustifyItems::parse(context, input))
                           .unwrap_or(JustifyItems::from(align));

        Ok(Longhands {
            align_items: align,
            justify_items: justify,
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a> {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            if self.align_items.0 == self.justify_items.0 {
                self.align_items.to_css(dest)
            } else {
                self.align_items.to_css(dest)?;
                dest.write_str(" ")?;
                self.justify_items.to_css(dest)
            }
        }
    }
</%helpers:shorthand>
<|endoftext|>


<commit_before>//! The metadata that describes a column family, a level, or a SST file,

use std::fmt;
use std::ops::Deref;

use crate::types::SequenceNumber;

/// The metadata that describes a column family.
pub struct ColumnFamilyMetaData {
    /// The size of this column family in bytes, which is equal to the sum of
    /// the file size of its "levels".
    pub size: u64,
    /// The number of files in this column family.
    pub file_count: usize,
    /// The name of the column family.
    pub name: String,
    /// The metadata of all levels in this column family.
    pub levels: Vec<LevelMetaData>,
}

impl fmt::Debug for ColumnFamilyMetaData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("ColumnFamily")
            .field("name", &self.name)
            .field("file_count", &self.file_count)
            .field("size", &self.size)
            .finish()?;
        write!(f, "\n")?;
        for level in &self.levels {
            write!(f, "  > {:?}\n", level)?;
        }
        Ok(())
    }
}

/// The metadata that describes a level.
pub struct LevelMetaData {
    /// The level which this meta data describes.
    pub level: u32,
    /// The size of this level in bytes, which is equal to the sum of
    /// the file size of its "files".
    pub size: u64,
    /// The metadata of all sst files in this level.
    pub files: Vec<SstFileMetaData>,
}

impl fmt::Debug for LevelMetaData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Level")
            .field("level", &self.level)
            .field("files", &self.files)
            .finish()
    }
}

/// The metadata that describes a SST file.
pub struct SstFileMetaData {
    /// File size in bytes.
    pub size: u64,
    /// The name of the file.
    pub name: String,
    /// The full path where the file locates.
    pub db_path: String,

    /// Smallest sequence number in file.
    pub smallest_seqno: SequenceNumber,
    /// Largest sequence number in file.
    pub largest_seqno: SequenceNumber,
    /// Smallest user defined key in the file.
    pub smallestkey: Vec<u8>,
    /// Largest user defined key in the file.
    pub largestkey: Vec<u8>,
    /// true if the file is currently being compacted.
    pub being_compacted: bool,
}

impl fmt::Debug for SstFileMetaData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("SstFile").field("name", &self.name).finish()
    }
}

/// The full set of metadata associated with each SST file.
pub struct LiveFileMetaData {
    pub sst_file: SstFileMetaData,
    /// Name of the column family
    pub column_family_name: String,
    /// Level at which this file resides.
    pub level: u32,
}

impl Deref for LiveFileMetaData {
    type Target = SstFileMetaData;

    fn deref(&self) -> &SstFileMetaData {
        &self.sst_file
    }
}

impl fmt::Debug for LiveFileMetaData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LiveFile")
            .field("name", &self.name)
            .field("column_family_name", &self.column_family_name)
            .field("level", &self.level)
            .field("db_path", &self.db_path)
            .field("smallestkey", &String::from_utf8_lossy(&self.smallestkey))
            .field("largestkey", &String::from_utf8_lossy(&self.largestkey))
            .field("being_compacted", &self.being_compacted)
            .field("size", &self.size)
            .finish()
    }
}
<commit_msg>style(metadata): refine metadata debug<commit_after>//! The metadata that describes a column family, a level, or a SST file,

use std::fmt;
use std::ops::Deref;

use crate::types::SequenceNumber;

/// The metadata that describes a column family.
pub struct ColumnFamilyMetaData {
    /// The size of this column family in bytes, which is equal to the sum of
    /// the file size of its "levels".
    pub size: u64,
    /// The number of files in this column family.
    pub file_count: usize,
    /// The name of the column family.
    pub name: String,
    /// The metadata of all levels in this column family.
    pub levels: Vec<LevelMetaData>,
}

impl fmt::Debug for ColumnFamilyMetaData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("ColumnFamilyMetaData")
            .field("name", &self.name)
            .field("file_count", &self.file_count)
            .field("size", &self.size)
            .finish()?;
        write!(f, "\n")?;
        for level in &self.levels {
            write!(f, "  > {:?}\n", level)?;
        }
        Ok(())
    }
}

/// The metadata that describes a level.
pub struct LevelMetaData {
    /// The level which this meta data describes.
    pub level: u32,
    /// The size of this level in bytes, which is equal to the sum of
    /// the file size of its "files".
    pub size: u64,
    /// The metadata of all sst files in this level.
    pub files: Vec<SstFileMetaData>,
}

impl fmt::Debug for LevelMetaData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LevelMetaData")
            .field("level", &self.level)
            .field("files", &self.files)
            .finish()
    }
}

/// The metadata that describes a SST file.
pub struct SstFileMetaData {
    /// File size in bytes.
    pub size: u64,
    /// The name of the file.
    pub name: String,
    /// The full path where the file locates.
    pub db_path: String,

    /// Smallest sequence number in file.
    pub smallest_seqno: SequenceNumber,
    /// Largest sequence number in file.
    pub largest_seqno: SequenceNumber,
    /// Smallest user defined key in the file.
    pub smallestkey: Vec<u8>,
    /// Largest user defined key in the file.
    pub largestkey: Vec<u8>,
    /// true if the file is currently being compacted.
    pub being_compacted: bool,
}

impl fmt::Debug for SstFileMetaData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("SstFile").field("name", &self.name).finish()
    }
}

/// The full set of metadata associated with each SST file.
pub struct LiveFileMetaData {
    pub sst_file: SstFileMetaData,
    /// Name of the column family
    pub column_family_name: String,
    /// Level at which this file resides.
    pub level: u32,
}

impl Deref for LiveFileMetaData {
    type Target = SstFileMetaData;

    fn deref(&self) -> &SstFileMetaData {
        &self.sst_file
    }
}

impl fmt::Debug for LiveFileMetaData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LiveFile")
            .field("name", &self.name)
            .field("column_family_name", &self.column_family_name)
            .field("level", &self.level)
            .field("db_path", &self.db_path)
            .field("smallestkey", &String::from_utf8_lossy(&self.smallestkey))
            .field("largestkey", &String::from_utf8_lossy(&self.largestkey))
            .field("being_compacted", &self.being_compacted)
            .field("size", &self.size)
            .finish()
    }
}
<|endoftext|>


<commit_before>use ape;
use id3;
use lewton::inside_ogg::OggStreamReader;
use metaflac;
use mp3_duration;
use regex::Regex;
use std::fs;
use std::path::Path;

use errors::*;
use utils;
use utils::AudioFormat;

#[derive(Debug, Clone, PartialEq)]
pub struct SongTags {
	pub disc_number: Option<u32>,
	pub track_number: Option<u32>,
	pub title: Option<String>,
	pub duration: Option<u32>,
	pub artist: Option<String>,
	pub album_artist: Option<String>,
	pub album: Option<String>,
	pub year: Option<i32>,
}

pub fn read(path: &Path) -> Result<SongTags> {
	match utils::get_audio_format(path) {
		Some(AudioFormat::FLAC) => read_flac(path),
		Some(AudioFormat::MP3) => read_id3(path),
		Some(AudioFormat::MPC) => read_ape(path),
		Some(AudioFormat::OGG) => read_vorbis(path),
		_ => bail!("Unsupported file format for reading metadata"),
	}
}

fn read_id3(path: &Path) -> Result<SongTags> {
	let file = fs::File::open(path)?;
	let tag = id3::Tag::read_from(&file)?;
	let duration = mp3_duration::from_file(&file).map(|d| d.as_secs() as u32).ok();

	let artist = tag.artist().map(|s| s.to_string());
	let album_artist = tag.album_artist().map(|s| s.to_string());
	let album = tag.album().map(|s| s.to_string());
	let title = tag.title().map(|s| s.to_string());
	let disc_number = tag.disc();
	let track_number = tag.track();
	let year = tag.year()
		.map(|y| y as i32)
		.or(tag.date_released().and_then(|d| Some(d.year)))
		.or(tag.date_recorded().and_then(|d| Some(d.year)));

	Ok(SongTags {
	       artist: artist,
	       album_artist: album_artist,
	       album: album,
	       title: title,
		   duration: duration,
	       disc_number: disc_number,
	       track_number: track_number,
	       year: year,
	   })
}

fn read_ape_string(item: &ape::Item) -> Option<String> {
	match item.value {
		ape::ItemValue::Text(ref s) => Some(s.clone()),
		_ => None,
	}
}

fn read_ape_i32(item: &ape::Item) -> Option<i32> {
	match item.value {
		ape::ItemValue::Text(ref s) => s.parse::<i32>().ok(),
		_ => None,
	}
}

fn read_ape_x_of_y(item: &ape::Item) -> Option<u32> {
	match item.value {
		ape::ItemValue::Text(ref s) => {
			let format = Regex::new(r#"^\d+"#).unwrap();
			if let Some(m) = format.find(s) {
				s[m.start()..m.end()].parse().ok()
			} else {
				None
			}
		}
		_ => None,
	}
}

fn read_ape(path: &Path) -> Result<SongTags> {
	let tag = ape::read(path)?;
	let artist = tag.item("Artist").and_then(read_ape_string);
	let album = tag.item("Album").and_then(read_ape_string);
	let album_artist = tag.item("Album artist").and_then(read_ape_string);
	let title = tag.item("Title").and_then(read_ape_string);
	let year = tag.item("Year").and_then(read_ape_i32);
	let disc_number = tag.item("Disc").and_then(read_ape_x_of_y);
	let track_number = tag.item("Track").and_then(read_ape_x_of_y);
	Ok(SongTags {
	       artist: artist,
	       album_artist: album_artist,
	       album: album,
	       title: title,
		   duration: None,
	       disc_number: disc_number,
	       track_number: track_number,
	       year: year,
	   })
}

fn read_vorbis(path: &Path) -> Result<SongTags> {

	let file = fs::File::open(path)?;
	let source = OggStreamReader::new(file)?;

	let mut tags = SongTags {
		artist: None,
		album_artist: None,
		album: None,
		title: None,
		duration:None,
		disc_number: None,
		track_number: None,
		year: None,
	};

	for (key, value) in source.comment_hdr.comment_list {
		match key.as_str() {
			"TITLE" => tags.title = Some(value),
			"ALBUM" => tags.album = Some(value),
			"ARTIST" => tags.artist = Some(value),
			"ALBUMARTIST" => tags.album_artist = Some(value),
			"TRACKNUMBER" => tags.track_number = value.parse::<u32>().ok(),
			"DISCNUMBER" => tags.disc_number = value.parse::<u32>().ok(),
			"DATE" => tags.year = value.parse::<i32>().ok(),
			_ => (),
		}
	}

	Ok(tags)
}

fn read_flac(path: &Path) -> Result<SongTags> {
	let tag = metaflac::Tag::read_from_path(path)?;
	let vorbis = tag.vorbis_comments().ok_or("Missing Vorbis comments")?;
	let disc_number = vorbis
		.get("DISCNUMBER")
		.and_then(|d| d[0].parse::<u32>().ok());
	let year = vorbis.get("DATE").and_then(|d| d[0].parse::<i32>().ok());
	let streaminfo = tag.get_blocks(metaflac::BlockType::StreamInfo);
	let duration = match streaminfo.first() {
        Some(&&metaflac::Block::StreamInfo(ref s)) => Some((s.total_samples as u32 / s.sample_rate) as u32),
        _ => None
	};

	Ok(SongTags {
	       artist: vorbis.artist().map(|v| v[0].clone()),
	       album_artist: vorbis.album_artist().map(|v| v[0].clone()),
	       album: vorbis.album().map(|v| v[0].clone()),
	       title: vorbis.title().map(|v| v[0].clone()),
	       duration: duration,
	       disc_number: disc_number,
	       track_number: vorbis.track(),
	       year: year,
	   })
}

#[test]
fn test_read_metadata() {
	let sample_tags = SongTags {
		disc_number: Some(3),
		track_number: Some(1),
		title: Some("TEST TITLE".into()),
		artist: Some("TEST ARTIST".into()),
		album_artist: Some("TEST ALBUM ARTIST".into()),
		album: Some("TEST ALBUM".into()),
        duration: None,
		year: Some(2016),
	};
	let flac_sample_tag = SongTags {duration: Some(0), ..sample_tags.clone()};
	let mp3_sample_tag = SongTags {duration: Some(0), ..sample_tags.clone()};
	assert_eq!(read(Path::new("test/sample.mp3")).unwrap(), mp3_sample_tag);
	assert_eq!(read(Path::new("test/sample.ogg")).unwrap(), sample_tags);
	assert_eq!(read(Path::new("test/sample.flac")).unwrap(), flac_sample_tag);
}
<commit_msg>Fixed a bug where mp3 file durations were not read<commit_after>use ape;
use id3;
use lewton::inside_ogg::OggStreamReader;
use metaflac;
use mp3_duration;
use regex::Regex;
use std::fs;
use std::path::Path;

use errors::*;
use utils;
use utils::AudioFormat;

#[derive(Debug, Clone, PartialEq)]
pub struct SongTags {
	pub disc_number: Option<u32>,
	pub track_number: Option<u32>,
	pub title: Option<String>,
	pub duration: Option<u32>,
	pub artist: Option<String>,
	pub album_artist: Option<String>,
	pub album: Option<String>,
	pub year: Option<i32>,
}

pub fn read(path: &Path) -> Result<SongTags> {
	match utils::get_audio_format(path) {
		Some(AudioFormat::FLAC) => read_flac(path),
		Some(AudioFormat::MP3) => read_id3(path),
		Some(AudioFormat::MPC) => read_ape(path),
		Some(AudioFormat::OGG) => read_vorbis(path),
		_ => bail!("Unsupported file format for reading metadata"),
	}
}

fn read_id3(path: &Path) -> Result<SongTags> {
	let tag = id3::Tag::read_from_path(&path)?;
	let duration = mp3_duration::from_path(&path).map(|d| d.as_secs() as u32).ok();

	let artist = tag.artist().map(|s| s.to_string());
	let album_artist = tag.album_artist().map(|s| s.to_string());
	let album = tag.album().map(|s| s.to_string());
	let title = tag.title().map(|s| s.to_string());
	let disc_number = tag.disc();
	let track_number = tag.track();
	let year = tag.year()
		.map(|y| y as i32)
		.or(tag.date_released().and_then(|d| Some(d.year)))
		.or(tag.date_recorded().and_then(|d| Some(d.year)));

	Ok(SongTags {
	       artist: artist,
	       album_artist: album_artist,
	       album: album,
	       title: title,
		   duration: duration,
	       disc_number: disc_number,
	       track_number: track_number,
	       year: year,
	   })
}

fn read_ape_string(item: &ape::Item) -> Option<String> {
	match item.value {
		ape::ItemValue::Text(ref s) => Some(s.clone()),
		_ => None,
	}
}

fn read_ape_i32(item: &ape::Item) -> Option<i32> {
	match item.value {
		ape::ItemValue::Text(ref s) => s.parse::<i32>().ok(),
		_ => None,
	}
}

fn read_ape_x_of_y(item: &ape::Item) -> Option<u32> {
	match item.value {
		ape::ItemValue::Text(ref s) => {
			let format = Regex::new(r#"^\d+"#).unwrap();
			if let Some(m) = format.find(s) {
				s[m.start()..m.end()].parse().ok()
			} else {
				None
			}
		}
		_ => None,
	}
}

fn read_ape(path: &Path) -> Result<SongTags> {
	let tag = ape::read(path)?;
	let artist = tag.item("Artist").and_then(read_ape_string);
	let album = tag.item("Album").and_then(read_ape_string);
	let album_artist = tag.item("Album artist").and_then(read_ape_string);
	let title = tag.item("Title").and_then(read_ape_string);
	let year = tag.item("Year").and_then(read_ape_i32);
	let disc_number = tag.item("Disc").and_then(read_ape_x_of_y);
	let track_number = tag.item("Track").and_then(read_ape_x_of_y);
	Ok(SongTags {
	       artist: artist,
	       album_artist: album_artist,
	       album: album,
	       title: title,
		   duration: None,
	       disc_number: disc_number,
	       track_number: track_number,
	       year: year,
	   })
}

fn read_vorbis(path: &Path) -> Result<SongTags> {

	let file = fs::File::open(path)?;
	let source = OggStreamReader::new(file)?;

	let mut tags = SongTags {
		artist: None,
		album_artist: None,
		album: None,
		title: None,
		duration:None,
		disc_number: None,
		track_number: None,
		year: None,
	};

	for (key, value) in source.comment_hdr.comment_list {
		match key.as_str() {
			"TITLE" => tags.title = Some(value),
			"ALBUM" => tags.album = Some(value),
			"ARTIST" => tags.artist = Some(value),
			"ALBUMARTIST" => tags.album_artist = Some(value),
			"TRACKNUMBER" => tags.track_number = value.parse::<u32>().ok(),
			"DISCNUMBER" => tags.disc_number = value.parse::<u32>().ok(),
			"DATE" => tags.year = value.parse::<i32>().ok(),
			_ => (),
		}
	}

	Ok(tags)
}

fn read_flac(path: &Path) -> Result<SongTags> {
	let tag = metaflac::Tag::read_from_path(path)?;
	let vorbis = tag.vorbis_comments().ok_or("Missing Vorbis comments")?;
	let disc_number = vorbis
		.get("DISCNUMBER")
		.and_then(|d| d[0].parse::<u32>().ok());
	let year = vorbis.get("DATE").and_then(|d| d[0].parse::<i32>().ok());
	let streaminfo = tag.get_blocks(metaflac::BlockType::StreamInfo);
	let duration = match streaminfo.first() {
        Some(&&metaflac::Block::StreamInfo(ref s)) => Some((s.total_samples as u32 / s.sample_rate) as u32),
        _ => None
	};

	Ok(SongTags {
	       artist: vorbis.artist().map(|v| v[0].clone()),
	       album_artist: vorbis.album_artist().map(|v| v[0].clone()),
	       album: vorbis.album().map(|v| v[0].clone()),
	       title: vorbis.title().map(|v| v[0].clone()),
	       duration: duration,
	       disc_number: disc_number,
	       track_number: vorbis.track(),
	       year: year,
	   })
}

#[test]
fn test_read_metadata() {
	let sample_tags = SongTags {
		disc_number: Some(3),
		track_number: Some(1),
		title: Some("TEST TITLE".into()),
		artist: Some("TEST ARTIST".into()),
		album_artist: Some("TEST ALBUM ARTIST".into()),
		album: Some("TEST ALBUM".into()),
        duration: None,
		year: Some(2016),
	};
	let flac_sample_tag = SongTags {duration: Some(0), ..sample_tags.clone()};
	let mp3_sample_tag = SongTags {duration: Some(0), ..sample_tags.clone()};
	assert_eq!(read(Path::new("test/sample.mp3")).unwrap(), mp3_sample_tag);
	assert_eq!(read(Path::new("test/sample.ogg")).unwrap(), sample_tags);
	assert_eq!(read(Path::new("test/sample.flac")).unwrap(), flac_sample_tag);
}
<|endoftext|>