<commit_before>use gfx;
use gfx::traits::{IntoCanvas, Factory, FactoryExt, Stream};
use gfx::device::handle::Texture;
use gfx::extra::canvas::Canvas;
use gfx_device_gl as dgl;
use gfx_window_glutin as gfxw;
use glutin::{CreationError, Window, WindowBuilder, Event, VirtualKeyCode, ElementState};
use ::ivf;
use ::vpx;

pub type Error = CreationError;

#[vertex_format]
#[derive(Clone, Copy)]
struct Vertex {
    #[as_float]
    #[name = "a_Pos"]
    pos: [i8; 2],
    #[as_float]
    #[name = "a_TexCoord"]
    tex: [u8; 2],
}

#[shader_param]
struct ShaderParams<R: gfx::Resources> {
    #[name = "t_Color"]
    color: gfx::shade::TextureParam<R>,
}

static VERTEX_SRC: &'static [u8] = b"
    #version 120

    attribute vec4 a_Pos;
    attribute vec2 a_TexCoord;
    varying vec2 v_TexCoord;

    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = a_Pos;
    }
";

static FRAGMENT_SRC: &'static [u8] = b"
    #version 120

    varying vec2 v_TexCoord;
    uniform sampler2D t_Color;

    void main() {
        gl_FragColor = texture2D(t_Color, v_TexCoord);
    }
";

const VERTEX_DATA: &'static [Vertex] = &[
    // 1
    // |\
    // | \
    // 2--3
    Vertex {pos: [-1,  1], tex: [0, 0]},
    Vertex {pos: [-1, -1], tex: [0, 1]},
    Vertex {pos: [ 1, -1], tex: [1, 1]},
    // 1--3
    //  \ |
    //   \|
    //    2
    Vertex {pos: [-1,  1], tex: [0, 0]},
    Vertex {pos: [ 1, -1], tex: [1, 1]},
    Vertex {pos: [ 1,  1], tex: [1, 0]},
];

// TODO(Kagami): Process all errors.
// TODO(Kagami): Fullscreen.
pub fn run(reader: &mut ivf::Reader, decoder: &mut vpx::Decoder) -> Result<(), Error> {
    let mut canvas = {
        let window = try!(WindowBuilder::new()
            .with_dimensions(reader.get_width() as u32, reader.get_height() as u32)
            // Use simple initial title to allow to match the window in tiling
            // window managers.
            .with_title(format!("vpxview"))
            .build());
        gfxw::init(window).into_canvas()
    };
    let batch = {
        let mesh = canvas.factory.create_mesh(VERTEX_DATA);
        let program = canvas.factory.link_program(VERTEX_SRC, FRAGMENT_SRC).unwrap();
        let texture = canvas.factory.create_texture_rgba8(
            reader.get_width(),
            reader.get_height()).unwrap();
        let param = ShaderParams {color: (texture, None)};
        gfx::batch::OwnedBatch::new(mesh, program, param).unwrap()
    };
    let texture = &batch.param.color.0;

    show_frame(reader, decoder, &mut canvas, texture);
    'main: loop {
        // We need to pass mutable reference to canvas to `show_frame` so we
        // need to grab all events first.
        let events: Vec<Event> = canvas.output.window.poll_events().collect();
        for event in events {
            match event {
                Event::Closed => break 'main,
                Event::KeyboardInput(_, _, Some(VirtualKeyCode::Escape)) => break 'main,
                Event::KeyboardInput(_, _, Some(VirtualKeyCode::Q)) => break 'main,
                Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::Left)) => {
                    // TODO(Kagami).
                },
                Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::Right)) => {
                    show_frame(reader, decoder, &mut canvas, texture);
                },
                _ => {},
            }
        }
        canvas.clear(gfx::ClearData {color: [0.0, 0.0, 0.0, 1.0], depth: 1.0, stencil: 0});
        canvas.draw(&batch).unwrap();
        canvas.present();
    }
    Ok(())
}

type CanvasT = Canvas<gfxw::Output<dgl::Resources>, dgl::Device, dgl::Factory>;
type TextureT = Texture<dgl::Resources>;

fn show_frame(reader: &mut ivf::Reader,
              decoder: &mut vpx::Decoder,
              canvas: &mut CanvasT,
              texture: &TextureT) {
    let maybe_frame = reader.next();
    update_title(reader, &canvas.output.window);
    let ivf_frame = try_print!(maybe_frame, "End of file");
    match decoder.decode_many(&ivf_frame) {
        Ok(mut iter) => {
            let image = try_print!(iter.next(), "No VPx frames in this IVF frame");
            // TODO(Kagami): IVF frame may consist of several VPx frames, we
            // correctly display only 1 IVF <-> 1 VPx case as for now.
            let remaining = iter.count();
            if remaining != 0 {
                printerr!("Skipping {} other VPx frames", remaining);
            }
            // TODO(Kagami): Dimensions of decoded VPx image can vary from
            // frame to frame, we can adjust texture size accordingly.
            assert_eq!(image.get_display_width(), texture.get_info().width);
            assert_eq!(image.get_display_height(), texture.get_info().height);
            canvas.factory.update_texture_raw(
                texture,
                &texture.get_info().to_image_info(),
                &image.get_rgba8(),
                None).unwrap();
        },
        Err(err) => {
            printerr!("Cannot decode IVF frame: {}", err);
        },
    };
}

fn update_title(reader: &ivf::Reader, window: &Window) {
    let frame_count = reader.get_frame_count()
                            .map_or_else(|| "?".to_string(), |v| v.to_string());
    let title = format!("vpxview - {} - {}/{}",
                        reader.get_filename(),
                        reader.get_frame_pos(),
                        frame_count);
    println!("Frame {}/{}", reader.get_frame_pos(), frame_count);
    window.set_title(&title);
}
<commit_msg>gui: skip pending events<commit_after>use gfx;
use gfx::traits::{IntoCanvas, Factory, FactoryExt, Stream};
use gfx::device::handle::Texture;
use gfx::extra::canvas::Canvas;
use gfx_device_gl as dgl;
use gfx_window_glutin as gfxw;
use glutin::{CreationError, Window, WindowBuilder};
use glutin::Event::{Closed, KeyboardInput};
use glutin::ElementState::Pressed;
use glutin::VirtualKeyCode as Key;
use ::ivf;
use ::vpx;

pub type Error = CreationError;

#[vertex_format]
#[derive(Clone, Copy)]
struct Vertex {
    #[as_float]
    #[name = "a_Pos"]
    pos: [i8; 2],
    #[as_float]
    #[name = "a_TexCoord"]
    tex: [u8; 2],
}

#[shader_param]
struct ShaderParams<R: gfx::Resources> {
    #[name = "t_Color"]
    color: gfx::shade::TextureParam<R>,
}

static VERTEX_SRC: &'static [u8] = b"
    #version 120

    attribute vec4 a_Pos;
    attribute vec2 a_TexCoord;
    varying vec2 v_TexCoord;

    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = a_Pos;
    }
";

static FRAGMENT_SRC: &'static [u8] = b"
    #version 120

    varying vec2 v_TexCoord;
    uniform sampler2D t_Color;

    void main() {
        gl_FragColor = texture2D(t_Color, v_TexCoord);
    }
";

const VERTEX_DATA: &'static [Vertex] = &[
    // 1
    // |\
    // | \
    // 2--3
    Vertex {pos: [-1,  1], tex: [0, 0]},
    Vertex {pos: [-1, -1], tex: [0, 1]},
    Vertex {pos: [ 1, -1], tex: [1, 1]},
    // 1--3
    //  \ |
    //   \|
    //    2
    Vertex {pos: [-1,  1], tex: [0, 0]},
    Vertex {pos: [ 1, -1], tex: [1, 1]},
    Vertex {pos: [ 1,  1], tex: [1, 0]},
];

// TODO(Kagami): Process all errors.
// TODO(Kagami): Fullscreen.
pub fn run(reader: &mut ivf::Reader, decoder: &mut vpx::Decoder) -> Result<(), Error> {
    let mut canvas = {
        let window = try!(WindowBuilder::new()
            .with_dimensions(reader.get_width() as u32, reader.get_height() as u32)
            // Use simple initial title to allow to match the window in tiling
            // window managers.
            .with_title(format!("vpxview"))
            .build());
        gfxw::init(window).into_canvas()
    };
    let batch = {
        let mesh = canvas.factory.create_mesh(VERTEX_DATA);
        let program = canvas.factory.link_program(VERTEX_SRC, FRAGMENT_SRC).unwrap();
        let texture = canvas.factory.create_texture_rgba8(
            reader.get_width(),
            reader.get_height()).unwrap();
        let param = ShaderParams {color: (texture, None)};
        gfx::batch::OwnedBatch::new(mesh, program, param).unwrap()
    };
    let texture = &batch.param.color.0;

    show_frame(reader, decoder, &mut canvas, texture);
    loop {
        // Skip all pending events except the first because in some cases frame
        // decoding may take too long so interface will be brozen because of
        // big events queue.
        let maybe_event = {
            let mut iter = canvas.output.window.poll_events();
            let ev = iter.next();
            iter.count();  // Consume entire iterator
            ev
        };
        match maybe_event {
            Some(Closed) => break,
            Some(KeyboardInput(Pressed, _, Some(Key::Escape))) => break,
            Some(KeyboardInput(Pressed, _, Some(Key::Q))) => break,
            Some(KeyboardInput(Pressed, _, Some(Key::Left))) => {
                // TODO(Kagami).
            },
            Some(KeyboardInput(Pressed, _, Some(Key::Right))) => {
                show_frame(reader, decoder, &mut canvas, texture);
            },
            _ => {},
        }
        canvas.clear(gfx::ClearData {color: [0.0, 0.0, 0.0, 1.0], depth: 1.0, stencil: 0});
        match canvas.draw(&batch) {
            Err(err) => printerr!("Error occured while drawing the frame: {:?}", err),
            Ok(_) => {},
        }
        canvas.present();
    }
    Ok(())
}

type CanvasT = Canvas<gfxw::Output<dgl::Resources>, dgl::Device, dgl::Factory>;
type TextureT = Texture<dgl::Resources>;

fn show_frame(reader: &mut ivf::Reader,
              decoder: &mut vpx::Decoder,
              canvas: &mut CanvasT,
              texture: &TextureT) {
    let maybe_frame = reader.next();
    update_title(reader, &canvas.output.window);
    let ivf_frame = try_print!(maybe_frame, "End of file");
    match decoder.decode_many(&ivf_frame) {
        Ok(mut iter) => {
            let image = try_print!(iter.next(), "No VPx frames in this IVF frame");
            // TODO(Kagami): IVF frame may consist of several VPx frames, we
            // correctly display only 1 IVF <-> 1 VPx case as for now.
            let remaining = iter.count();
            if remaining != 0 {
                printerr!("Skipping {} other VPx frames", remaining);
            }
            // TODO(Kagami): Dimensions of decoded VPx image can vary from
            // frame to frame, we can adjust texture size accordingly.
            assert_eq!(image.get_display_width(), texture.get_info().width);
            assert_eq!(image.get_display_height(), texture.get_info().height);
            canvas.factory.update_texture_raw(
                texture,
                &texture.get_info().to_image_info(),
                &image.get_rgba8(),
                None).unwrap();
        },
        Err(err) => {
            printerr!("Cannot decode IVF frame: {}", err);
        },
    };
}

fn update_title(reader: &ivf::Reader, window: &Window) {
    let frame_count = reader.get_frame_count()
                            .map_or_else(|| "?".to_string(), |v| v.to_string());
    let title = format!("vpxview - {} - {}/{}",
                        reader.get_filename(),
                        reader.get_frame_pos(),
                        frame_count);
    println!("Frame {}/{}", reader.get_frame_pos(), frame_count);
    window.set_title(&title);
}
<|endoftext|>


<commit_before>
use vertex::{RawVertex, Vertex};
use edge::{Edge, EdgeProxy};
use graph::TraversableToVertex;
use path::{Path, Element};

// use std::iter::Iterator;

// define a traversal as a series of stages

pub struct GraphQuery {
	// many paths
    pub paths: Vec<Path>
}

impl GraphQuery {
    pub fn new(vertices: Vec<Vertex>) -> GraphQuery {
        // create a new path for each proxy, add the proxy
        let mut paths = Vec::new();
        for p in vertices {
			let mut path = Path::new(p);
            paths.push(path)
        }
        GraphQuery{paths:paths}
    }

    pub fn empty() -> GraphQuery {
        // return an empty graph query
        GraphQuery{paths:Vec::new()}
    }

	pub fn get_paths(&self) -> &Vec<Path> {
		&self.paths
	}
	pub fn push(&mut self, path:Path) {
		self.paths.push(path)
	}

	/*
	generic mapper for our queries
	future this may use worker threads to perform
	traversals
	 */
    fn map<F: Fn(&Path) -> &[Element]>(&self, closure: F) -> GraphQuery  {
        let mut result = GraphQuery::empty(); // result
		for path in self.paths.iter() {
			let mut tmp = closure(path);
            // currently gets back a Vec<Path> but what if it gets Elements?
            let new_elements = path.permute(tmp);
            result.paths.push_all(&new_elements);
        }
		result
    }

    pub fn outV(&self) -> GraphQuery {
        // needs to be modified to return a Vec of elements or a slice?
        // map can figure out the rest
		let f = |path: &Path| {
			println!("applying outV");
			//take the final element in the path
			let element = path.last().unwrap();

			let result : &[Element] = match element {
				&Element::Vertex(ref v) => {
					let tmp = v.outV().iter().map(|&v| Element::Vertex(v)).collect();
                    &tmp
				},
				&Element::Edge(ref e) => {
                    &[]
				}
			};
			// apply outV
			result
		};
		self.map(f)
    }

//	pub fn inV(&self) -> GraphQuery {
//		let g = GraphQuery::empty();
//		let f = |element: &Element| {
//			element.inV()
//		};
//		self.map(f)
//	}
}
<commit_msg>trying poorly to get mapping working right<commit_after>
use vertex::{RawVertex, Vertex};
use edge::{Edge, EdgeProxy};
use graph::TraversableToVertex;
use path::{Path, Element};

// use std::iter::Iterator;

// define a traversal as a series of stages

pub struct GraphQuery {
	// many paths
    pub paths: Vec<Path>
}

impl GraphQuery {
    pub fn new(vertices: Vec<Vertex>) -> GraphQuery {
        // create a new path for each proxy, add the proxy
        let mut paths = Vec::new();
        for p in vertices {
			let mut path = Path::new(p);
            paths.push(path)
        }
        GraphQuery{paths:paths}
    }

    pub fn empty() -> GraphQuery {
        // return an empty graph query
        GraphQuery{paths:Vec::new()}
    }

	pub fn get_paths(&self) -> &Vec<Path> {
		&self.paths
	}
	pub fn push(&mut self, path:Path) {
		self.paths.push(path)
	}

	/*
	generic mapper for our queries
	future this may use worker threads to perform
	traversals
	 */
    fn map<F: Fn(&Path) -> &[Element]>(&self, closure: F) -> GraphQuery  {
        let mut result = GraphQuery::empty(); // result
		for path in self.paths.iter() {
			let mut tmp = closure(path);
            // currently gets back a Vec<Path> but what if it gets Elements?
            let new_elements = path.permute(tmp);
            result.paths.push_all(&new_elements);
        }
		result
    }

    pub fn outV(&self) -> GraphQuery {
        // needs to be modified to return a Vec of elements or a slice?
        // map can figure out the rest
		let f = |path: &Path| {
			println!("applying outV");
			//take the final element in the path
			let element = path.last().unwrap();

			let result : &[Element] = match element {
				&Element::Vertex(ref v) => {
					let tmp : &[Element] = v.outV().iter().map(|&v| Element::Vertex(v));
                    &tmp
				},
				&Element::Edge(ref e) => {
                    &[]
				}
			};
			// apply outV
			result
		};
		self.map(f)
    }

//	pub fn inV(&self) -> GraphQuery {
//		let g = GraphQuery::empty();
//		let f = |element: &Element| {
//			element.inV()
//		};
//		self.map(f)
//	}
}
<|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/.

use std::path::PathBuf;

// self
use math::{
    Size,
    Rect,
};
use super::attribute::*;
use super::NodeId;

#[allow(missing_docs)]
pub enum NodeKind {
    Svg(Svg),
    Defs,
    LinearGradient(LinearGradient),
    RadialGradient(RadialGradient),
    Stop(Stop),
    ClipPath(ClipPath),
    Pattern(Pattern),
    Path(Path),
    Text(Text),
    TextChunk(TextChunk),
    TSpan(TSpan),
    Image(Image),
    Group(Group),
}

impl NodeKind {
    /// Returns node's ID.
    ///
    /// If a current node doesn't support ID - an empty string
    /// will be returned.
    pub fn id(&self) -> &str {
        match *self {
            NodeKind::Svg(_) => "",
            NodeKind::Defs => "",
            NodeKind::LinearGradient(ref e) => e.id.as_str(),
            NodeKind::RadialGradient(ref e) => e.id.as_str(),
            NodeKind::Stop(_) => "",
            NodeKind::ClipPath(ref e) => e.id.as_str(),
            NodeKind::Pattern(ref e) => e.id.as_str(),
            NodeKind::Path(ref e) => e.id.as_str(),
            NodeKind::Text(ref e) => e.id.as_str(),
            NodeKind::TextChunk(_) => "",
            NodeKind::TSpan(_) => "",
            NodeKind::Image(ref e) => e.id.as_str(),
            NodeKind::Group(ref e) => e.id.as_str(),
        }
    }

    /// Returns node's transform.
    ///
    /// If a current node doesn't support transformation - a default
    /// transform will be returned.
    pub fn transform(&self) -> Transform {
        match *self {
            NodeKind::Svg(_) => Transform::default(),
            NodeKind::Defs => Transform::default(),
            NodeKind::LinearGradient(ref e) => e.d.transform,
            NodeKind::RadialGradient(ref e) => e.d.transform,
            NodeKind::Stop(_) => Transform::default(),
            NodeKind::ClipPath(ref e) => e.transform,
            NodeKind::Pattern(ref e) => e.transform,
            NodeKind::Path(ref e) => e.transform,
            NodeKind::Text(ref e) => e.transform,
            NodeKind::TextChunk(_) => Transform::default(),
            NodeKind::TSpan(_) => Transform::default(),
            NodeKind::Image(ref e) => e.transform,
            NodeKind::Group(ref e) => e.transform,
        }
    }
}

/// An SVG root element.
pub struct Svg {
    /// Image size.
    ///
    /// Size of an image that should be created to fit the S
    pub size: Size,
    /// SVG viewbox.
    ///
    /// Specifies which part of the SVG image should be rendered.
    pub view_box: Rect,
}

/// A path element.
pub struct Path {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Isn't automatically generated.
    /// Can be empty.
    ///
    /// Currently, used only for SVG dump purposes.
    pub id: String,
    /// Element transform.
    pub transform: Transform,
    /// Fill style.
    pub fill: Option<Fill>,
    /// Stroke style.
    pub stroke: Option<Stroke>,
    /// Segments list.
    ///
    /// All segments are in absolute coordinates.
    pub segments: Vec<PathSegment>,
}

/// A text element.
///
/// `text` element in the SVG.
pub struct Text {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Isn't automatically generated.
    /// Can be empty.
    ///
    /// Currently, used only for SVG dump purposes.
    pub id: String,
    /// Element transform.
    pub transform: Transform,
}

/// A text chunk.
///
/// Contains position and anchor of the next
/// [text chunk](https://www.w3.org/TR/SVG11/text.html#TextChunk).
///
/// Doesn't represented in the SVG directly. Usually, it's a first `tspan` or text node
/// and any `tspan` that defines either `x` or `y` coordinate and/or have `text-anchor`.
pub struct TextChunk {
    /// An absolute position on the X-axis.
    pub x: f64,
    /// An absolute position on the Y-axis.
    pub y: f64,
    /// A text anchor/align.
    pub anchor: TextAnchor,
}

// TODO: dx, dy
/// A text span.
///
/// `tspan` element in the SVG.
#[derive(Clone)]
pub struct TSpan {
    /// Fill style.
    pub fill: Option<Fill>,
    /// Stroke style.
    pub stroke: Option<Stroke>,
    /// Font description.
    pub font: Font,
    /// Text decoration.
    ///
    /// Unlike `text-decoration` attribute from the SVG, this one has all styles resolved.
    /// Basically, by the SVG `text-decoration` attribute can be defined on `tspan` element
    /// and on any parent element. And all definitions should be combined.
    /// The one that was defined by `tspan` uses the `tspan` style itself.
    /// The one that was defined by any parent node uses the `text` element style.
    /// So it's pretty hard to resolve.
    ///
    /// This property has all this stuff resolved.
    pub decoration: TextDecoration,
    /// An actual text line.
    ///
    /// SVG doesn't support multiline text, so this property doesn't have a new line inside of it.
    /// All the spaces are already trimmed or preserved, depending on the `xml:space` attribute.
    /// All characters references are already resolved, so there is no `>` or `P`.
    /// So this text should be rendered as is, without any postprocessing.
    pub text: String,
}

/// A raster image element.
///
/// `image` element in the SVG.
pub struct Image {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Isn't automatically generated.
    /// Can be empty.
    ///
    /// Currently, used only for SVG dump purposes.
    pub id: String,
    /// Element transform.
    pub transform: Transform,
    /// An image rectangle in which it should be fit.
    pub rect: Rect,
    /// Image data.
    pub data: ImageData,
}

/// A raster image container.
pub enum ImageData {
    /// Path to the image.
    ///
    /// Preprocessor checks that file exists, but because it can be removed later,
    /// there is no guarantee that this path is valid.
    Path(PathBuf),
    /// An image raw data.
    ///
    /// It's not a decoded image data, but the data that was decoded from base64.
    /// So you still need a PNG and a JPEG decoding library.
    Raw(Vec<u8>, ImageDataKind),
}

/// An image codec.
#[allow(missing_docs)]
#[derive(Copy,Clone,PartialEq)]
pub enum ImageDataKind {
    PNG,
    JPEG,
}

// TODO: no need for a separate vector
/// A group container.
///
/// The preprocessor will remove all groups that don't impact rendering.
/// Those that left is just an indicator that a new canvas should be created.
///
/// Currently, it's needed only for `opacity`.
///
/// `g` element in the SVG.
pub struct Group {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Isn't automatically generated.
    /// Can be empty.
    ///
    /// Currently, used only for SVG dump purposes.
    pub id: String,
    /// Element transform.
    pub transform: Transform,
    /// Group opacity.
    ///
    /// After the group is rendered we should combine
    /// it with a parent group using the specified opacity.
    pub opacity: Option<f64>,
    /// Element clip path.
    ///
    /// The value is an index from the `Document::defs` list.
    /// Use it via `Document::get_defs()` method.
    pub clip_path: Option<NodeId>,
}

/// A generic gradient.
pub struct BaseGradient {
    /// Coordinate system units.
    ///
    /// `gradientUnits` in the SVG.
    pub units: Units,
    /// Gradient transform.
    ///
    /// `gradientTransform` in the SVG.
    pub transform: Transform,
    /// Gradient spreading method.
    ///
    /// `spreadMethod` in the SVG.
    pub spread_method: SpreadMethod,
}

/// A linear gradient.
///
/// `linearGradient` element in the SVG.
#[allow(missing_docs)]
pub struct LinearGradient {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Can't be empty.
    ///
    /// Currently, used only for SVG dump purposes.
    ///
    /// It isn't used for referencing itself, because we use indexes for that.
    pub id: String,
    pub x1: f64,
    pub y1: f64,
    pub x2: f64,
    pub y2: f64,
    /// Base gradient data.
    pub d: BaseGradient,
}

/// A radial gradient.
///
/// `radialGradient` element in the SVG.
#[allow(missing_docs)]
pub struct RadialGradient {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Can't be empty.
    ///
    /// Currently, used only for SVG dump purposes.
    ///
    /// It isn't used for referencing itself, because we use indexes for that.
    pub id: String,
    pub cx: f64,
    pub cy: f64,
    pub r: f64,
    pub fx: f64,
    pub fy: f64,
    /// Base gradient data.
    pub d: BaseGradient,
}

/// Gradient's stop element.
///
/// `stop` element in the SVG.
#[derive(Clone, Copy)]
#[allow(missing_docs)]
pub struct Stop {
    pub offset: f64,
    pub color: Color,
    pub opacity: f64,
}

/// A clip-path element.
///
/// `clipPath` element in the SVG.
pub struct ClipPath {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Can't be empty.
    ///
    /// Currently, used only for SVG dump purposes.
    ///
    /// It isn't used for referencing itself, because we use indexes for that.
    pub id: String,
    /// Coordinate system units.
    ///
    /// `clipPathUnits` in the SVG.
    pub units: Units,
    /// Clip path transform.
    ///
    /// `transform` in the SVG.
    pub transform: Transform,
}

/// A pattern element.
///
/// `pattern` element in the SVG.
pub struct Pattern {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Can't be empty.
    ///
    /// Currently, used only for SVG dump purposes.
    ///
    /// It isn't used for referencing itself, because we use indexes for that.
    pub id: String,
    /// Coordinate system units.
    ///
    /// `patternUnits` in the SVG.
    pub units: Units,
    /// Content coordinate system units.
    ///
    /// `patternContentUnits` in the SVG.
    pub content_units: Units,
    /// Pattern transform.
    ///
    /// `patternTransform` in the SVG.
    pub transform: Transform,
    /// Pattern rectangle.
    pub rect: Rect,
    /// Pattern viewbox.
    pub view_box: Option<Rect>,
}
<commit_msg>Documentation fixes.<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/.

use std::path::PathBuf;

// self
use math::{
    Size,
    Rect,
};
use super::attribute::*;
use super::NodeId;

#[allow(missing_docs)]
pub enum NodeKind {
    Svg(Svg),
    Defs,
    LinearGradient(LinearGradient),
    RadialGradient(RadialGradient),
    Stop(Stop),
    ClipPath(ClipPath),
    Pattern(Pattern),
    Path(Path),
    Text(Text),
    TextChunk(TextChunk),
    TSpan(TSpan),
    Image(Image),
    Group(Group),
}

impl NodeKind {
    /// Returns node's ID.
    ///
    /// If a current node doesn't support ID - an empty string
    /// will be returned.
    pub fn id(&self) -> &str {
        match *self {
            NodeKind::Svg(_) => "",
            NodeKind::Defs => "",
            NodeKind::LinearGradient(ref e) => e.id.as_str(),
            NodeKind::RadialGradient(ref e) => e.id.as_str(),
            NodeKind::Stop(_) => "",
            NodeKind::ClipPath(ref e) => e.id.as_str(),
            NodeKind::Pattern(ref e) => e.id.as_str(),
            NodeKind::Path(ref e) => e.id.as_str(),
            NodeKind::Text(ref e) => e.id.as_str(),
            NodeKind::TextChunk(_) => "",
            NodeKind::TSpan(_) => "",
            NodeKind::Image(ref e) => e.id.as_str(),
            NodeKind::Group(ref e) => e.id.as_str(),
        }
    }

    /// Returns node's transform.
    ///
    /// If a current node doesn't support transformation - a default
    /// transform will be returned.
    pub fn transform(&self) -> Transform {
        match *self {
            NodeKind::Svg(_) => Transform::default(),
            NodeKind::Defs => Transform::default(),
            NodeKind::LinearGradient(ref e) => e.d.transform,
            NodeKind::RadialGradient(ref e) => e.d.transform,
            NodeKind::Stop(_) => Transform::default(),
            NodeKind::ClipPath(ref e) => e.transform,
            NodeKind::Pattern(ref e) => e.transform,
            NodeKind::Path(ref e) => e.transform,
            NodeKind::Text(ref e) => e.transform,
            NodeKind::TextChunk(_) => Transform::default(),
            NodeKind::TSpan(_) => Transform::default(),
            NodeKind::Image(ref e) => e.transform,
            NodeKind::Group(ref e) => e.transform,
        }
    }
}

/// An SVG root element.
pub struct Svg {
    /// Image size.
    ///
    /// Size of an image that should be created to fit the S
    pub size: Size,
    /// SVG viewbox.
    ///
    /// Specifies which part of the SVG image should be rendered.
    pub view_box: Rect,
}

/// A path element.
pub struct Path {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Isn't automatically generated.
    /// Can be empty.
    pub id: String,
    /// Element transform.
    pub transform: Transform,
    /// Fill style.
    pub fill: Option<Fill>,
    /// Stroke style.
    pub stroke: Option<Stroke>,
    /// Segments list.
    ///
    /// All segments are in absolute coordinates.
    pub segments: Vec<PathSegment>,
}

/// A text element.
///
/// `text` element in the SVG.
pub struct Text {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Isn't automatically generated.
    /// Can be empty.
    pub id: String,
    /// Element transform.
    pub transform: Transform,
}

/// A text chunk.
///
/// Contains position and anchor of the next
/// [text chunk](https://www.w3.org/TR/SVG11/text.html#TextChunk).
///
/// Doesn't represented in the SVG directly. Usually, it's a first `tspan` or text node
/// and any `tspan` that defines either `x` or `y` coordinate and/or have `text-anchor`.
pub struct TextChunk {
    /// An absolute position on the X-axis.
    pub x: f64,
    /// An absolute position on the Y-axis.
    pub y: f64,
    /// A text anchor/align.
    pub anchor: TextAnchor,
}

// TODO: dx, dy
/// A text span.
///
/// `tspan` element in the SVG.
#[derive(Clone)]
pub struct TSpan {
    /// Fill style.
    pub fill: Option<Fill>,
    /// Stroke style.
    pub stroke: Option<Stroke>,
    /// Font description.
    pub font: Font,
    /// Text decoration.
    ///
    /// Unlike `text-decoration` attribute from the SVG, this one has all styles resolved.
    /// Basically, by the SVG `text-decoration` attribute can be defined on `tspan` element
    /// and on any parent element. And all definitions should be combined.
    /// The one that was defined by `tspan` uses the `tspan` style itself.
    /// The one that was defined by any parent node uses the `text` element style.
    /// So it's pretty hard to resolve.
    ///
    /// This property has all this stuff resolved.
    pub decoration: TextDecoration,
    /// An actual text line.
    ///
    /// SVG doesn't support multiline text, so this property doesn't have a new line inside of it.
    /// All the spaces are already trimmed or preserved, depending on the `xml:space` attribute.
    /// All characters references are already resolved, so there is no `>` or `P`.
    /// So this text should be rendered as is, without any postprocessing.
    pub text: String,
}

/// A raster image element.
///
/// `image` element in the SVG.
pub struct Image {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Isn't automatically generated.
    /// Can be empty.
    pub id: String,
    /// Element transform.
    pub transform: Transform,
    /// An image rectangle in which it should be fit.
    pub rect: Rect,
    /// Image data.
    pub data: ImageData,
}

/// A raster image container.
pub enum ImageData {
    /// Path to the image.
    ///
    /// Preprocessor checks that file exists, but because it can be removed later,
    /// there is no guarantee that this path is valid.
    Path(PathBuf),
    /// An image raw data.
    ///
    /// It's not a decoded image data, but the data that was decoded from base64.
    /// So you still need a PNG and a JPEG decoding library.
    Raw(Vec<u8>, ImageDataKind),
}

/// An image codec.
#[allow(missing_docs)]
#[derive(Copy,Clone,PartialEq)]
pub enum ImageDataKind {
    PNG,
    JPEG,
}

/// A group container.
///
/// The preprocessor will remove all groups that don't impact rendering.
/// Those that left is just an indicator that a new canvas should be created.
///
/// Currently, it's needed only for `opacity`.
///
/// `g` element in the SVG.
pub struct Group {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Isn't automatically generated.
    /// Can be empty.
    pub id: String,
    /// Element transform.
    pub transform: Transform,
    /// Group opacity.
    ///
    /// After the group is rendered we should combine
    /// it with a parent group using the specified opacity.
    pub opacity: Option<f64>,
    /// Element clip path.
    pub clip_path: Option<NodeId>,
}

/// A generic gradient.
pub struct BaseGradient {
    /// Coordinate system units.
    ///
    /// `gradientUnits` in the SVG.
    pub units: Units,
    /// Gradient transform.
    ///
    /// `gradientTransform` in the SVG.
    pub transform: Transform,
    /// Gradient spreading method.
    ///
    /// `spreadMethod` in the SVG.
    pub spread_method: SpreadMethod,
}

/// A linear gradient.
///
/// `linearGradient` element in the SVG.
#[allow(missing_docs)]
pub struct LinearGradient {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Can't be empty.
    pub id: String,
    pub x1: f64,
    pub y1: f64,
    pub x2: f64,
    pub y2: f64,
    /// Base gradient data.
    pub d: BaseGradient,
}

/// A radial gradient.
///
/// `radialGradient` element in the SVG.
#[allow(missing_docs)]
pub struct RadialGradient {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Can't be empty.
    pub id: String,
    pub cx: f64,
    pub cy: f64,
    pub r: f64,
    pub fx: f64,
    pub fy: f64,
    /// Base gradient data.
    pub d: BaseGradient,
}

/// Gradient's stop element.
///
/// `stop` element in the SVG.
#[derive(Clone, Copy)]
#[allow(missing_docs)]
pub struct Stop {
    pub offset: f64,
    pub color: Color,
    pub opacity: f64,
}

/// A clip-path element.
///
/// `clipPath` element in the SVG.
pub struct ClipPath {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Can't be empty.
    pub id: String,
    /// Coordinate system units.
    ///
    /// `clipPathUnits` in the SVG.
    pub units: Units,
    /// Clip path transform.
    ///
    /// `transform` in the SVG.
    pub transform: Transform,
}

/// A pattern element.
///
/// `pattern` element in the SVG.
pub struct Pattern {
    /// Element's ID.
    ///
    /// Taken from the SVG itself.
    /// Can't be empty.
    pub id: String,
    /// Coordinate system units.
    ///
    /// `patternUnits` in the SVG.
    pub units: Units,
    /// Content coordinate system units.
    ///
    /// `patternContentUnits` in the SVG.
    pub content_units: Units,
    /// Pattern transform.
    ///
    /// `patternTransform` in the SVG.
    pub transform: Transform,
    /// Pattern rectangle.
    ///
    /// `x`, `y`, `width` and `height` in the SVG.
    pub rect: Rect,
    /// Pattern viewbox.
    pub view_box: Option<Rect>,
}
<|endoftext|>


<commit_before>pub struct Node<V> {
    c: char,
    left:  Option<Box<Node<V>>>,
    mid:   Option<Box<Node<V>>>,
    right: Option<Box<Node<V>>>,
    val: Option<V>,
}

impl<V> Node<V> {
    fn new(c: char) -> Node<V> {
        Node {
            c: c,
            left: None,
            mid: None,
            right: None,
            val: None
        }
    }

    fn put(mut x: Option<Box<Node<V>>>, key: &str, val: V, d: usize) -> (Option<Box<Node<V>>>, Option<V>) {
        let replaced;
        let c = key.char_at(d);
        x = x.or_else(|| Some(Box::new(Node::new(c))));
        let xc = x.as_ref().unwrap().c;
        if c < xc {
            let (left, repl) = Node::put(x.as_mut().unwrap().left.take(), key, val, d);
            x.as_mut().map(|n| n.left = left);
            replaced = repl;
        } else if c > xc {
            let (right, repl) = Node::put(x.as_mut().unwrap().right.take(), key, val, d);
            x.as_mut().map(|n| n.right = right);
            replaced = repl;
        } else if d < key.len()-1 {
            let (mid, repl) = Node::put(x.as_mut().unwrap().mid.take(), key, val, d+1);
            x.as_mut().map(|n| n.mid = mid);
            replaced = repl;
        } else {
            replaced = x.as_mut().unwrap().val.take();
            x.as_mut().map(|n| n.val = Some(val));
        }
        (x, replaced)
    }

    fn get<'a>(x: Option<&'a Box<Node<V>>>, key: &str, d: usize) -> Option<&'a Box<Node<V>>> {
        if x.is_none() {
            return None;
        }
        let c = key.char_at(d);
        let xc = x.unwrap().c;
        if c < xc {
            Node::get(x.unwrap().left.as_ref(), key, d)
        } else if c > xc {
            Node::get(x.unwrap().right.as_ref(), key, d)
        } else if d < key.len()-1 {
            Node::get(x.unwrap().mid.as_ref(), key, d+1)
        } else {
            x
        }
    }
}

/// Symbol table with string keys, implemented using a ternary search trie (TST).
pub struct TernarySearchTrie<V> {
    root: Option<Box<Node<V>>>,
    n: usize
}

impl<V> TernarySearchTrie<V>  {
    pub fn new() -> TernarySearchTrie<V> {
        TernarySearchTrie { root: None, n: 0 }
    }

    pub fn put(&mut self, key: &str, val: V) {
        let (root, replaced) = Node::put(self.root.take(), key, val, 0);
        self.root = root;
        // replace old val? or insert new?
        if replaced.is_none() {
            self.n += 1;
        }
    }

    pub fn get(&self, key: &str) -> Option<&V> {
        assert!(key.len() > 0, "key must have length >= 1");
        Node::get(self.root.as_ref(), key, 0).map_or(None, |n| n.val.as_ref())
    }

    pub fn delete(&mut self, key: &str) {
        unimplemented!()
    }

    pub fn size(&self) -> usize {
        self.n
    }

    pub fn is_empty(&self) -> bool {
        self.n == 0
    }

    pub fn contains(&self, key: &str) -> bool {
        self.get(key).is_some()
    }
}

#[test]
fn test_tst() {
    let mut t = TernarySearchTrie::new();
    assert_eq!(t.size(), 0);
    t.put("name", "Andelf");
    assert_eq!(t.size(), 1);
    t.put("name", "Fledna");
    assert_eq!(t.size(), 1);
    t.put("language", "Rust");
    assert_eq!(t.size(), 2);

    assert_eq!(t.get("name"), Some(&"Fledna"));
    assert_eq!(t.get("whatever"), None);
}
<commit_msg>tries/tst: implement delete() using put() for TernarySearchTrie<commit_after>pub struct Node<V> {
    c: char,
    left:  Option<Box<Node<V>>>,
    mid:   Option<Box<Node<V>>>,
    right: Option<Box<Node<V>>>,
    val: Option<V>,
}

impl<V> Node<V> {
    fn new(c: char) -> Node<V> {
        Node {
            c: c,
            left: None,
            mid: None,
            right: None,
            val: None
        }
    }

    fn put(mut x: Option<Box<Node<V>>>, key: &str, val: Option<V>, d: usize) -> (Option<Box<Node<V>>>, Option<V>) {
        let replaced;
        let c = key.char_at(d);
        if x.is_none() {
            if val.is_none() {  // no need to call put further
                return (x, None);
            }
            x = Some(Box::new(Node::new(c)));
        }
        let xc = x.as_ref().unwrap().c;
        if c < xc {
            let (left, repl) = Node::put(x.as_mut().unwrap().left.take(), key, val, d);
            x.as_mut().map(|n| n.left = left);
            replaced = repl;
        } else if c > xc {
            let (right, repl) = Node::put(x.as_mut().unwrap().right.take(), key, val, d);
            x.as_mut().map(|n| n.right = right);
            replaced = repl;
        } else if d < key.len()-1 {
            let (mid, repl) = Node::put(x.as_mut().unwrap().mid.take(), key, val, d+1);
            x.as_mut().map(|n| n.mid = mid);
            replaced = repl;
        } else {
            replaced = x.as_mut().unwrap().val.take();
            x.as_mut().map(|n| n.val = val);
        }
        (x, replaced)
    }

    fn get<'a>(x: Option<&'a Box<Node<V>>>, key: &str, d: usize) -> Option<&'a Box<Node<V>>> {
        if x.is_none() {
            return None;
        }
        let c = key.char_at(d);
        let xc = x.unwrap().c;
        if c < xc {
            Node::get(x.unwrap().left.as_ref(), key, d)
        } else if c > xc {
            Node::get(x.unwrap().right.as_ref(), key, d)
        } else if d < key.len()-1 {
            Node::get(x.unwrap().mid.as_ref(), key, d+1)
        } else {
            x
        }
    }
}

/// Symbol table with string keys, implemented using a ternary search trie (TST).
pub struct TernarySearchTrie<V> {
    root: Option<Box<Node<V>>>,
    n: usize
}

impl<V> TernarySearchTrie<V>  {
    pub fn new() -> TernarySearchTrie<V> {
        TernarySearchTrie { root: None, n: 0 }
    }

    pub fn put(&mut self, key: &str, val: V) {
        let (root, replaced) = Node::put(self.root.take(), key, Some(val), 0);
        self.root = root;
        // replace old val? or insert new?
        if replaced.is_none() {
            self.n += 1;
        }
    }

    pub fn get(&self, key: &str) -> Option<&V> {
        assert!(key.len() > 0, "key must have length >= 1");
        Node::get(self.root.as_ref(), key, 0).map_or(None, |n| n.val.as_ref())
    }

    pub fn delete(&mut self, key: &str) {
        let (root, replaced) = Node::put(self.root.take(), key, None, 0);
        self.root = root;
        // deleted?
        if replaced.is_some() {
            self.n -= 1;
        }
    }

    pub fn size(&self) -> usize {
        self.n
    }

    pub fn is_empty(&self) -> bool {
        self.n == 0
    }

    pub fn contains(&self, key: &str) -> bool {
        self.get(key).is_some()
    }
}

#[test]
fn test_tst() {
    let mut t = TernarySearchTrie::new();
    assert_eq!(t.size(), 0);
    t.put("name", "Andelf");
    assert_eq!(t.size(), 1);
    t.put("name", "Fledna");
    assert_eq!(t.size(), 1);
    t.put("language", "Rust");
    assert_eq!(t.size(), 2);

    assert_eq!(t.get("name"), Some(&"Fledna"));
    assert_eq!(t.get("whatever"), None);

    t.delete("name");
    assert_eq!(t.size(), 1);
    assert_eq!(t.get("name"), None);
}
<|endoftext|>


<commit_before>extern crate aprs;
use aprs::fcs;

extern crate data_encoding;
use data_encoding::HEXLOWER as HEX;

#[path="../tests/test_constants.rs"]
mod test_constants;

#[test]
//#[ignore]
fn test_fcs_checksum() {
}

#[test]
#[ignore]
fn test_fcs_validate() {
}
<commit_msg>Tests: missed commented ignore<commit_after>extern crate aprs;
use aprs::fcs;

extern crate data_encoding;
use data_encoding::HEXLOWER as HEX;

#[path="../tests/test_constants.rs"]
mod test_constants;

#[test]
#[ignore]
fn test_fcs_checksum() {
}

#[test]
#[ignore]
fn test_fcs_validate() {
}
<|endoftext|>


<commit_before>#![crate_name = "uu_uniq"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Chirag B Jadwani <chirag.jadwani@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 */

extern crate getopts;

#[macro_use]
extern crate uucore;

use getopts::{Matches, Options};
use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Write};
use std::path::Path;
use std::str::FromStr;

static NAME: &'static str = "uniq";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(PartialEq)]
enum Delimiters {
    Prepend,
    Separate,
    None,
}

struct Uniq {
    repeats_only: bool,
    uniques_only: bool,
    all_repeated: bool,
    delimiters: Delimiters,
    show_counts: bool,
    skip_fields: Option<usize>,
    slice_start: Option<usize>,
    slice_stop: Option<usize>,
    ignore_case: bool,
    zero_terminated: bool,
}

fn iter_ne<'a>(lhs: Box<Iterator<Item = char> + 'a>, rhs: Box<Iterator<Item = char> + 'a>) -> bool {
    lhs.ne(rhs)
}

impl Uniq {
    pub fn print_uniq<R: Read, W: Write>(
        &self,
        reader: &mut BufReader<R>,
        writer: &mut BufWriter<W>,
    ) {
        let mut lines: Vec<String> = vec![];
        let mut first_line_printed = false;
        let delimiters = &self.delimiters;
        let line_terminator = self.get_line_terminator();

        for io_line in reader.split(line_terminator) {
            let line = String::from_utf8(crash_if_err!(1, io_line)).unwrap();
            if !lines.is_empty() && self.cmp_keys(&lines[0], &line) {
                let print_delimiter = delimiters == &Delimiters::Prepend
                    || (delimiters == &Delimiters::Separate && first_line_printed);
                first_line_printed |= self.print_lines(writer, &lines, print_delimiter);
                lines.truncate(0);
            }
            lines.push(line);
        }
        if !lines.is_empty() {
            let print_delimiter = delimiters == &Delimiters::Prepend
                || (delimiters == &Delimiters::Separate && first_line_printed);
            self.print_lines(writer, &lines, print_delimiter);
        }
    }

    fn skip_fields<'a>(&self, line: &'a str) -> &'a str {
        if let Some(skip_fields) = self.skip_fields {
            if line.split_whitespace().count() > skip_fields {
                let mut field = 0;
                let mut i = 0;
                while field < skip_fields && i < line.len() {
                    while i < line.len() && line.chars().nth(i).unwrap().is_whitespace() {
                        i = i + 1;
                    }
                    while i < line.len() && !line.chars().nth(i).unwrap().is_whitespace() {
                        i = i + 1;
                    }
                    field = field + 1;
                }
                &line[i..]
            } else {
                ""
            }
        } else {
            line
        }
    }

    fn get_line_terminator(&self) -> u8 {
        if self.zero_terminated {
            0
        } else {
            '\n' as u8
        }
    }

    fn cmp_key<'a>(&'a self, line: &'a str) -> Box<Iterator<Item = char> + 'a> {
        let fields_to_check = self.skip_fields(line);
        let len = fields_to_check.len();
        if len > 0 {
            Box::new(
                fields_to_check
                    .chars()
                    .skip(self.slice_start.unwrap_or(0))
                    .take(self.slice_stop.unwrap_or(len))
                    .map(move |c| match c {
                        'a'...'z' if self.ignore_case => ((c as u8) - 32) as char,
                        _ => c,
                    }),
            )
        } else {
            Box::new(fields_to_check.chars())
        }
    }

    fn print_lines<W: Write>(
        &self,
        writer: &mut BufWriter<W>,
        lines: &[String],
        print_delimiter: bool,
    ) -> bool {
        let mut first_line_printed = false;
        let mut count = if self.all_repeated { 1 } else { lines.len() };
        if lines.len() == 1 && !self.repeats_only || lines.len() > 1 && !self.uniques_only {
            self.print_line(writer, &lines[0], count, print_delimiter);
            first_line_printed = true;
            count += 1;
        }
        if self.all_repeated {
            for line in lines[1..].iter() {
                self.print_line(writer, line, count, print_delimiter && !first_line_printed);
                first_line_printed = true;
                count += 1;
            }
        }
        first_line_printed
    }

    fn print_line<W: Write>(
        &self,
        writer: &mut BufWriter<W>,
        line: &str,
        count: usize,
        print_delimiter: bool,
    ) {
        let line_terminator = self.get_line_terminator();

        if print_delimiter {
            crash_if_err!(1, writer.write_all(&[line_terminator]));
        }

        crash_if_err!(
            1,
            if self.show_counts {
                writer.write_all(format!("{:7} {}", count, line).as_bytes())
            } else {
                writer.write_all(line.as_bytes())
            }
        );
        crash_if_err!(1, writer.write_all(&[line_terminator]));
    }
}

fn opt_parsed<T: FromStr>(opt_name: &str, matches: &Matches) -> Option<T> {
    matches.opt_str(opt_name).map(|arg_str| {
        let opt_val: Option<T> = arg_str.parse().ok();
        opt_val.unwrap_or_else(|| crash!(1, "Invalid argument for {}: {}", opt_name, arg_str))
    })
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();

    opts.optflag("c", "count", "prefix lines by the number of occurrences");
    opts.optflag("d", "repeated", "only print duplicate lines");
    opts.optflagopt(
        "D",
        "all-repeated",
        "print all duplicate lines delimit-method={none(default),prepend,separate} Delimiting is done with blank lines",
        "delimit-method"
    );
    opts.optopt(
        "f",
        "skip-fields",
        "avoid comparing the first N fields",
        "N",
    );
    opts.optopt(
        "s",
        "skip-chars",
        "avoid comparing the first N characters",
        "N",
    );
    opts.optopt(
        "w",
        "check-chars",
        "compare no more than N characters in lines",
        "N",
    );
    opts.optflag(
        "i",
        "ignore-case",
        "ignore differences in case when comparing",
    );
    opts.optflag("u", "unique", "only print unique lines");
    opts.optflag("z", "zero-terminated", "end lines with 0 byte, not newline");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f),
    };

    if matches.opt_present("help") {
        println!("{} {}", NAME, VERSION);
        println!("");
        println!("Usage:");
        println!("  {0} [OPTION]... [FILE]...", NAME);
        println!("");
        print!(
            "{}",
            opts.usage(
                "Filter adjacent matching lines from INPUT (or standard input),\n\
                 writing to OUTPUT (or standard output)."
            )
        );
        println!("");
        println!(
            "Note: '{0}' does not detect repeated lines unless they are adjacent.\n\
             You may want to sort the input first, or use 'sort -u' without '{0}'.\n",
            NAME
        );
    } else if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
    } else {
        let (in_file_name, out_file_name) = match matches.free.len() {
            0 => ("-".to_owned(), "-".to_owned()),
            1 => (matches.free[0].clone(), "-".to_owned()),
            2 => (matches.free[0].clone(), matches.free[1].clone()),
            _ => {
                crash!(1, "Extra operand: {}", matches.free[2]);
            }
        };
        let uniq = Uniq {
            repeats_only: matches.opt_present("repeated") || matches.opt_present("all-repeated"),
            uniques_only: matches.opt_present("unique"),
            all_repeated: matches.opt_present("all-repeated"),
            delimiters: match matches.opt_default("all-repeated", "none") {
                Some(ref opt_arg) if opt_arg != "none" => match &(*opt_arg.as_str()) {
                    "prepend" => Delimiters::Prepend,
                    "separate" => Delimiters::Separate,
                    _ => crash!(1, "Incorrect argument for all-repeated: {}", opt_arg),
                },
                _ => Delimiters::None,
            },
            show_counts: matches.opt_present("count"),
            skip_fields: opt_parsed("skip-fields", &matches),
            slice_start: opt_parsed("skip-chars", &matches),
            slice_stop: opt_parsed("check-chars", &matches),
            ignore_case: matches.opt_present("ignore-case"),
            zero_terminated: matches.opt_present("zero-terminated"),
        };
        uniq.print_uniq(
            &mut open_input_file(in_file_name),
            &mut open_output_file(out_file_name),
        );
    }
    0
}

fn open_input_file(in_file_name: String) -> BufReader<Box<Read + 'static>> {
    let in_file = if in_file_name == "-" {
        Box::new(stdin()) as Box<Read>
    } else {
        let path = Path::new(&in_file_name[..]);
        let in_file = File::open(&path);
        let r = crash_if_err!(1, in_file);
        Box::new(r) as Box<Read>
    };
    BufReader::new(in_file)
}

fn open_output_file(out_file_name: String) -> BufWriter<Box<Write + 'static>> {
    let out_file = if out_file_name == "-" {
        Box::new(stdout()) as Box<Write>
    } else {
        let path = Path::new(&out_file_name[..]);
        let in_file = File::create(&path);
        let w = crash_if_err!(1, in_file);
        Box::new(w) as Box<Write>
    };
    BufWriter::new(out_file)
}
<commit_msg>uniq: avoid a upper-case map if we don't need to<commit_after>#![crate_name = "uu_uniq"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Chirag B Jadwani <chirag.jadwani@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 */

extern crate getopts;

#[macro_use]
extern crate uucore;

use getopts::{Matches, Options};
use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Write};
use std::path::Path;
use std::str::FromStr;

static NAME: &'static str = "uniq";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(PartialEq)]
enum Delimiters {
    Prepend,
    Separate,
    None,
}

struct Uniq {
    repeats_only: bool,
    uniques_only: bool,
    all_repeated: bool,
    delimiters: Delimiters,
    show_counts: bool,
    skip_fields: Option<usize>,
    slice_start: Option<usize>,
    slice_stop: Option<usize>,
    ignore_case: bool,
    zero_terminated: bool,
}

fn iter_ne<'a>(lhs: Box<Iterator<Item = char> + 'a>, rhs: Box<Iterator<Item = char> + 'a>) -> bool {
    lhs.ne(rhs)
}

impl Uniq {
    pub fn print_uniq<R: Read, W: Write>(
        &self,
        reader: &mut BufReader<R>,
        writer: &mut BufWriter<W>,
    ) {
        let mut lines: Vec<String> = vec![];
        let mut first_line_printed = false;
        let delimiters = &self.delimiters;
        let line_terminator = self.get_line_terminator();

        for io_line in reader.split(line_terminator) {
            let line = String::from_utf8(crash_if_err!(1, io_line)).unwrap();
            if !lines.is_empty() && self.cmp_keys(&lines[0], &line) {
                let print_delimiter = delimiters == &Delimiters::Prepend
                    || (delimiters == &Delimiters::Separate && first_line_printed);
                first_line_printed |= self.print_lines(writer, &lines, print_delimiter);
                lines.truncate(0);
            }
            lines.push(line);
        }
        if !lines.is_empty() {
            let print_delimiter = delimiters == &Delimiters::Prepend
                || (delimiters == &Delimiters::Separate && first_line_printed);
            self.print_lines(writer, &lines, print_delimiter);
        }
    }

    fn skip_fields<'a>(&self, line: &'a str) -> &'a str {
        if let Some(skip_fields) = self.skip_fields {
            if line.split_whitespace().count() > skip_fields {
                let mut field = 0;
                let mut i = 0;
                while field < skip_fields && i < line.len() {
                    while i < line.len() && line.chars().nth(i).unwrap().is_whitespace() {
                        i = i + 1;
                    }
                    while i < line.len() && !line.chars().nth(i).unwrap().is_whitespace() {
                        i = i + 1;
                    }
                    field = field + 1;
                }
                &line[i..]
            } else {
                ""
            }
        } else {
            line
        }
    }

    fn get_line_terminator(&self) -> u8 {
        if self.zero_terminated {
            0
        } else {
            '\n' as u8
        }
    }

    fn cmp_key<'a>(&'a self, line: &'a str) -> Box<Iterator<Item = char> + 'a> {
        let fields_to_check = self.skip_fields(line);
        let len = fields_to_check.len();
        let slice_start = self.slice_start.unwrap_or(0);
        let slice_stop = self.slice_stop.unwrap_or(len);
        if len > 0 {
            // fast path: we can avoid mapping chars to upper-case, if we don't want to ignore the case
            if !self.ignore_case {
                return Box::new(fields_to_check.chars().skip(slice_start).take(slice_stop));
            }

            Box::new(
                fields_to_check
                    .chars()
                    .skip(slice_start)
                    .take(slice_stop)
                    .map(move |c| match c {
                        'a'...'z' if self.ignore_case => ((c as u8) - 32) as char,
                        _ => c,
                    }),
            )
        } else {
            Box::new(fields_to_check.chars())
        }
    }

    fn print_lines<W: Write>(
        &self,
        writer: &mut BufWriter<W>,
        lines: &[String],
        print_delimiter: bool,
    ) -> bool {
        let mut first_line_printed = false;
        let mut count = if self.all_repeated { 1 } else { lines.len() };
        if lines.len() == 1 && !self.repeats_only || lines.len() > 1 && !self.uniques_only {
            self.print_line(writer, &lines[0], count, print_delimiter);
            first_line_printed = true;
            count += 1;
        }
        if self.all_repeated {
            for line in lines[1..].iter() {
                self.print_line(writer, line, count, print_delimiter && !first_line_printed);
                first_line_printed = true;
                count += 1;
            }
        }
        first_line_printed
    }

    fn print_line<W: Write>(
        &self,
        writer: &mut BufWriter<W>,
        line: &str,
        count: usize,
        print_delimiter: bool,
    ) {
        let line_terminator = self.get_line_terminator();

        if print_delimiter {
            crash_if_err!(1, writer.write_all(&[line_terminator]));
        }

        crash_if_err!(
            1,
            if self.show_counts {
                writer.write_all(format!("{:7} {}", count, line).as_bytes())
            } else {
                writer.write_all(line.as_bytes())
            }
        );
        crash_if_err!(1, writer.write_all(&[line_terminator]));
    }
}

fn opt_parsed<T: FromStr>(opt_name: &str, matches: &Matches) -> Option<T> {
    matches.opt_str(opt_name).map(|arg_str| {
        let opt_val: Option<T> = arg_str.parse().ok();
        opt_val.unwrap_or_else(|| crash!(1, "Invalid argument for {}: {}", opt_name, arg_str))
    })
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();

    opts.optflag("c", "count", "prefix lines by the number of occurrences");
    opts.optflag("d", "repeated", "only print duplicate lines");
    opts.optflagopt(
        "D",
        "all-repeated",
        "print all duplicate lines delimit-method={none(default),prepend,separate} Delimiting is done with blank lines",
        "delimit-method"
    );
    opts.optopt(
        "f",
        "skip-fields",
        "avoid comparing the first N fields",
        "N",
    );
    opts.optopt(
        "s",
        "skip-chars",
        "avoid comparing the first N characters",
        "N",
    );
    opts.optopt(
        "w",
        "check-chars",
        "compare no more than N characters in lines",
        "N",
    );
    opts.optflag(
        "i",
        "ignore-case",
        "ignore differences in case when comparing",
    );
    opts.optflag("u", "unique", "only print unique lines");
    opts.optflag("z", "zero-terminated", "end lines with 0 byte, not newline");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f),
    };

    if matches.opt_present("help") {
        println!("{} {}", NAME, VERSION);
        println!("");
        println!("Usage:");
        println!("  {0} [OPTION]... [FILE]...", NAME);
        println!("");
        print!(
            "{}",
            opts.usage(
                "Filter adjacent matching lines from INPUT (or standard input),\n\
                 writing to OUTPUT (or standard output)."
            )
        );
        println!("");
        println!(
            "Note: '{0}' does not detect repeated lines unless they are adjacent.\n\
             You may want to sort the input first, or use 'sort -u' without '{0}'.\n",
            NAME
        );
    } else if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
    } else {
        let (in_file_name, out_file_name) = match matches.free.len() {
            0 => ("-".to_owned(), "-".to_owned()),
            1 => (matches.free[0].clone(), "-".to_owned()),
            2 => (matches.free[0].clone(), matches.free[1].clone()),
            _ => {
                crash!(1, "Extra operand: {}", matches.free[2]);
            }
        };
        let uniq = Uniq {
            repeats_only: matches.opt_present("repeated") || matches.opt_present("all-repeated"),
            uniques_only: matches.opt_present("unique"),
            all_repeated: matches.opt_present("all-repeated"),
            delimiters: match matches.opt_default("all-repeated", "none") {
                Some(ref opt_arg) if opt_arg != "none" => match &(*opt_arg.as_str()) {
                    "prepend" => Delimiters::Prepend,
                    "separate" => Delimiters::Separate,
                    _ => crash!(1, "Incorrect argument for all-repeated: {}", opt_arg),
                },
                _ => Delimiters::None,
            },
            show_counts: matches.opt_present("count"),
            skip_fields: opt_parsed("skip-fields", &matches),
            slice_start: opt_parsed("skip-chars", &matches),
            slice_stop: opt_parsed("check-chars", &matches),
            ignore_case: matches.opt_present("ignore-case"),
            zero_terminated: matches.opt_present("zero-terminated"),
        };
        uniq.print_uniq(
            &mut open_input_file(in_file_name),
            &mut open_output_file(out_file_name),
        );
    }
    0
}

fn open_input_file(in_file_name: String) -> BufReader<Box<Read + 'static>> {
    let in_file = if in_file_name == "-" {
        Box::new(stdin()) as Box<Read>
    } else {
        let path = Path::new(&in_file_name[..]);
        let in_file = File::open(&path);
        let r = crash_if_err!(1, in_file);
        Box::new(r) as Box<Read>
    };
    BufReader::new(in_file)
}

fn open_output_file(out_file_name: String) -> BufWriter<Box<Write + 'static>> {
    let out_file = if out_file_name == "-" {
        Box::new(stdout()) as Box<Write>
    } else {
        let path = Path::new(&out_file_name[..]);
        let in_file = File::create(&path);
        let w = crash_if_err!(1, in_file);
        Box::new(w) as Box<Write>
    };
    BufWriter::new(out_file)
}
<|endoftext|>


<commit_before>/* Copyright (c) 2014, Peter Nelson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#![crate_name = "jit"]
#![allow(raw_pointer_derive, non_camel_case_types, non_upper_case_globals)]
#![deny(unused_attributes, dead_code, unused_parens, unknown_lints, unreachable_code, unused_allocation, unused_allocation, unused_must_use)]
#![feature(alloc, libc, core, convert, plugin, unboxed_closures, optin_builtin_traits, associated_consts)]
#![plugin(rustc_bitflags)]

//! This crate wraps LibJIT in an idiomatic style.
//! For example, here's a quick example which makes a multiply function using LibJIT:
//!
//! ```rust
//! #![feature(plugin)]
//! #![plugin(jit_macros)]
//! extern crate jit;
//! #[no_link] #[macro_use]
//! extern crate jit_macros;
//! use jit::{Context, get, Type};
//! fn main() {
//!     // make a new context to make functions on
//!     let mut ctx = Context::<()>::new();
//!     jit_func!(ctx, func, mul(x: isize, y: isize) -> isize, {
//!         func.insn_return(x * y);
//!     }, |mul| {
//!         assert_eq!(mul((4, 5)), 20);
//!     });
//! }
//! ```
#[no_link] #[macro_use]
extern crate rustc_bitflags;
extern crate alloc;
extern crate libc;
extern crate libjit_sys as raw;
use raw::*;
use libc::c_void;
use std::mem;
pub use compile::Compile;
pub use context::{Builder, Context};
pub use elf::*;
pub use function::{flags, Abi, UncompiledFunction, Func, CompiledFunction};
pub use function::flags::CallFlags;
pub use label::Label;
pub use insn::{Block, Instruction, InstructionIter};
pub use types::kind::TypeKind;
pub use types::{kind, get, Type, Field, Fields, Params, CowType, StaticType, Ty, TaggedType};
pub use types::consts as typecs;
pub use value::Val;

extern fn free_data<T>(data: *mut c_void) {
    unsafe {
        let actual_data:Box<T> = mem::transmute(data);
        mem::drop(actual_data);
    }
}

/// Initialise the library and prepare for operations
#[inline]
pub fn init() -> () {
    unsafe {
        jit_init()
    }
}
/// Check if the JIT is using a fallback interpreter
#[inline]
pub fn uses_interpreter() -> bool {
    unsafe {
        jit_uses_interpreter() != 0
    }
}
/// Check if the JIT supports theads
#[inline]
pub fn supports_threads() -> bool {
    unsafe {
        jit_supports_threads() != 0
    }
}
/// Check if the JIT supports virtual memory
#[inline]
pub fn supports_virtual_memory() -> bool {
    unsafe {
        jit_supports_virtual_memory() != 0
    }
}
#[macro_use]
mod macros;
mod context;
mod compile;
mod elf;
mod function;
mod insn;
mod label;
mod types;
mod util;
mod value;
<commit_msg>Remove unused `convert` feature<commit_after>/* Copyright (c) 2014, Peter Nelson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#![crate_name = "jit"]
#![allow(raw_pointer_derive, non_camel_case_types, non_upper_case_globals)]
#![deny(unused_attributes, dead_code, unused_parens, unknown_lints, unreachable_code, unused_allocation, unused_allocation, unused_must_use)]
#![feature(alloc, libc, core, plugin, unboxed_closures, optin_builtin_traits, associated_consts)]
#![plugin(rustc_bitflags)]

//! This crate wraps LibJIT in an idiomatic style.
//! For example, here's a quick example which makes a multiply function using LibJIT:
//!
//! ```rust
//! #![feature(plugin)]
//! #![plugin(jit_macros)]
//! extern crate jit;
//! #[no_link] #[macro_use]
//! extern crate jit_macros;
//! use jit::{Context, get, Type};
//! fn main() {
//!     // make a new context to make functions on
//!     let mut ctx = Context::<()>::new();
//!     jit_func!(ctx, func, mul(x: isize, y: isize) -> isize, {
//!         func.insn_return(x * y);
//!     }, |mul| {
//!         assert_eq!(mul((4, 5)), 20);
//!     });
//! }
//! ```
#[no_link] #[macro_use]
extern crate rustc_bitflags;
extern crate alloc;
extern crate libc;
extern crate libjit_sys as raw;
use raw::*;
use libc::c_void;
use std::mem;
pub use compile::Compile;
pub use context::{Builder, Context};
pub use elf::*;
pub use function::{flags, Abi, UncompiledFunction, Func, CompiledFunction};
pub use function::flags::CallFlags;
pub use label::Label;
pub use insn::{Block, Instruction, InstructionIter};
pub use types::kind::TypeKind;
pub use types::{kind, get, Type, Field, Fields, Params, CowType, StaticType, Ty, TaggedType};
pub use types::consts as typecs;
pub use value::Val;

extern fn free_data<T>(data: *mut c_void) {
    unsafe {
        let actual_data:Box<T> = mem::transmute(data);
        mem::drop(actual_data);
    }
}

/// Initialise the library and prepare for operations
#[inline]
pub fn init() -> () {
    unsafe {
        jit_init()
    }
}
/// Check if the JIT is using a fallback interpreter
#[inline]
pub fn uses_interpreter() -> bool {
    unsafe {
        jit_uses_interpreter() != 0
    }
}
/// Check if the JIT supports theads
#[inline]
pub fn supports_threads() -> bool {
    unsafe {
        jit_supports_threads() != 0
    }
}
/// Check if the JIT supports virtual memory
#[inline]
pub fn supports_virtual_memory() -> bool {
    unsafe {
        jit_supports_virtual_memory() != 0
    }
}
#[macro_use]
mod macros;
mod context;
mod compile;
mod elf;
mod function;
mod insn;
mod label;
mod types;
mod util;
mod value;
<|endoftext|>