<commit_before>//! Contains types used in this library
use std::convert::From;
use std::ops::{ Add, Mul, Sub };

pub use math::{ self, Matrix2d, Scalar, Vec2d };

/// The size of a shape.
#[derive(Clone, Copy, Debug)]
pub struct Size {
    /// The horizontal length of the shape (width).
    pub w: Scalar,
    /// The vertical length of the shape (height).
    pub h: Scalar,
}

impl From<Vec2d> for Size {
    fn from(v: Vec2d) -> Size {
        Size { w: v[0], h: v[1] }
    }
}

impl From<(Scalar, Scalar)> for Size {
    fn from((w, h): (Scalar, Scalar)) -> Size {
        Size { w: w, h: h }
    }
}

impl Size {
    /// Convert size to a vector.
    pub fn to_array(self) -> Vec2d {
        [self.w, self.h]
    }
}

impl<T: Into<Size>> Mul<T> for Size {
    type Output = Size;

    fn mul(self, v: T) -> Size {
        let v: Size = v.into();
        Size { w: self.w * v.w, h: self.h * v.h }
    }
}

impl Mul<Scalar> for Size {
    type Output = Size;

    fn mul(self, s: Scalar) -> Size {
        Size { w: self.w * s, h: self.h * s }
    }
}

/// A point in the Cartesian plane.
#[derive(Clone, Copy, Debug)]
pub struct Point {
    /// The x coordinate.
    pub x: Scalar,
    /// The y coordinate.
    pub y: Scalar,
}

impl Add<Scalar> for Point {
    type Output = Point;

    fn add(self, s: Scalar) -> Point {
        Point { x: self.x + s, y: self.y + s }
    }
}

impl<T: Into<Point>> Add<T> for Point {
    type Output = Point;

    fn add(self, v: T) -> Point {
        let v: Point = v.into();
        Point { x: self.x + v.x, y: self.y + v.y }
    }
}

impl From<Vec2d> for Point {
    fn from(v: Vec2d) -> Point {
        Point { x: v[0], y: v[1] }
    }
}

impl From<(Scalar, Scalar)> for Point {
    fn from((x, y): (Scalar, Scalar)) -> Point {
        Point { x: x, y: y }
    }
}

impl Sub<Scalar> for Point {
    type Output = Point;

    fn sub(self, s: Scalar) -> Point {
        Point { x: self.x - s, y: self.y - s }
    }
}

impl<T: Into<Point>> Sub<T> for Point {
    type Output = Point;

    fn sub(self, v: T) -> Point {
        let v = v.into();
        Point { x: self.x - v.x, y: self.y - v.y }
    }
}

impl Point {
    /// Convert the point to a vector.
    pub fn to_array(self) -> Vec2d {
        [self.x, self.y]
    }
}

/// A rectangle.
#[derive(Clone, Copy, Debug)]
pub struct Rect {
    /// The position of the top left corner of the rectangle.
    pub pos: Point,
    /// The width and height of the rectangle.
    pub size: Size,
}

impl<P: Into<Point>, S: Into<Size>> From<(P, S)> for Rect {
    /// Creates a rectangle from the position of its top left corner and its size.
    fn from((pos, size): (P, S)) -> Rect {
        let (pos, size): (Point, Size) = (pos.into(), size.into());
        Rect { pos: pos, size: size }
    }
}

impl From<[Scalar; 4]> for Rect {
    /// Creates a rectangle from an array.
    fn from(v: [Scalar; 4]) -> Rect {
        Rect {
            pos: Point { x: v[0], y: v[1] },
            size: Size { w: v[2], h: v[3] },
        }
    }
}

impl From<(Scalar, Scalar, Scalar, Scalar)> for Rect {
    fn from((x, y, w, h): (Scalar, Scalar, Scalar, Scalar)) -> Rect {
        Rect {
            pos: Point { x: x, y: y },
            size: Size { w: w, h: h },
        }
    }
}

impl Rect {
    /// Returns the position of the bottom side of the rectangle.
    pub fn bottom(&self) -> Scalar {
        self.pos.y + self.size.h
    }

    /// Computes a rectangle with quadruple the surface area of self and with center
    /// (self.x, self.y).
    pub fn centered(self) -> Rect {
        Rect {
            pos: Point {
                 x: self.pos.x - self.size.w,
                 y: self.pos.y - self.size.h,
            },
            size: self.size * 2.0,
        }
    }

    /// Compute whether or not the point is inside the rectangle.
    #[inline(always)]
    pub fn contains<T: Into<Point>>(&self, point: T) -> bool {
        let point: Point = point.into();
        self.left() < point.x && point.x < self.right() &&
        self.top() < point.y && point.y < self.bottom()
    }

    /// Create a rectangle that circumscribes the given circle.
    pub fn new_circle<T: Into<Point>>(center: T, radius: Scalar) -> Rect {
        let center: Point = center.into();
        Rect {
            pos: Point {
                x: center.x - radius,
                y: center.y - radius,
            },
            size: Size {
                w: 2.0 * radius,
                h: 2.0 * radius,
            },
        }
    }

    /// Create a square rectangle with sides of length len and top left corner at pos.
    pub fn new_square<T: Into<Point>>(pos: T, len: Scalar) -> Rect {
        let pos: Point = pos.into();
        Rect {
            pos: pos,
            size: Size { w: len, h: len },
        }
    }

    /// Returns the position of the left side of the rectangle.
    pub fn left(&self) -> Scalar {
        self.pos.x
    }

    /// Computes a rectangle whose perimeter forms the inside edge of margin with size m for self.
    #[inline(always)]
    pub fn margin(self, m: Scalar) -> Rect {
        math::margin_rectangle(self.to_array(), m).into()
    }

    /// Computes a rectangle translated (slid) in the direction of the vector a distance relative
    /// to the size of the rectangle. For example, self.relative([1.0, 1.0]) returns a rectangle
    /// one rectangle to the right and down from the original.
    #[inline(always)]
    pub fn relative<T: Into<Point>>(self, v: T) -> Rect {
        let v: Point = v.into();
        Rect {
            pos: Point {
                x: self.pos.x + self.size.w * v.x,
                y: self.pos.y + self.size.h * v.y,
            },
            size: self.size,
        }
    }

    /// Returns the position of the right side of the rectangle.
    pub fn right(&self) -> Scalar {
        self.pos.x + self.size.w
    }

    /// Computes a scaled rectangle with the same position as self.
    pub fn scaled<T: Into<Size>>(self, v: T) -> Rect {
        let v: Size = v.into();
        Rect {
            pos: self.pos,
            size: self.size * v,
        }
    }

    /// Converts a rectangle to [x, y, w, h].
    pub fn to_array(self) -> [Scalar; 4] {
        [self.pos.x, self.pos.y, self.size.w, self.size.h]
    }

    /// Returns the position of the top side of the rectangle.
    pub fn top(&self) -> Scalar {
        self.pos.y
    }
}
<commit_msg>Added conversion impls to arrays<commit_after>//! Contains types used in this library
use std::convert::From;
use std::ops::{ Add, Mul, Sub };

pub use math::{ self, Matrix2d, Scalar, Vec2d };

/// The size of a shape.
#[derive(Clone, Copy, Debug)]
pub struct Size {
    /// The horizontal length of the shape (width).
    pub w: Scalar,
    /// The vertical length of the shape (height).
    pub h: Scalar,
}

impl From<Size> for Vec2d {
    fn from(size: Size) -> Vec2d {
        [size.w, size.h]
    }
}

impl From<Vec2d> for Size {
    fn from(v: Vec2d) -> Size {
        Size { w: v[0], h: v[1] }
    }
}

impl From<(Scalar, Scalar)> for Size {
    fn from((w, h): (Scalar, Scalar)) -> Size {
        Size { w: w, h: h }
    }
}

impl<T: Into<Size>> Mul<T> for Size {
    type Output = Size;

    fn mul(self, v: T) -> Size {
        let v: Size = v.into();
        Size { w: self.w * v.w, h: self.h * v.h }
    }
}

impl Mul<Scalar> for Size {
    type Output = Size;

    fn mul(self, s: Scalar) -> Size {
        Size { w: self.w * s, h: self.h * s }
    }
}

/// A point in the Cartesian plane.
#[derive(Clone, Copy, Debug)]
pub struct Point {
    /// The x coordinate.
    pub x: Scalar,
    /// The y coordinate.
    pub y: Scalar,
}

impl Add<Scalar> for Point {
    type Output = Point;

    fn add(self, s: Scalar) -> Point {
        Point { x: self.x + s, y: self.y + s }
    }
}

impl<T: Into<Point>> Add<T> for Point {
    type Output = Point;

    fn add(self, v: T) -> Point {
        let v: Point = v.into();
        Point { x: self.x + v.x, y: self.y + v.y }
    }
}

impl From<Point> for Vec2d {
    fn from(point: Point) -> Vec2d {
        [point.x, point.y]
    }
}

impl From<Vec2d> for Point {
    fn from(v: Vec2d) -> Point {
        Point { x: v[0], y: v[1] }
    }
}

impl From<(Scalar, Scalar)> for Point {
    fn from((x, y): (Scalar, Scalar)) -> Point {
        Point { x: x, y: y }
    }
}

impl Sub<Scalar> for Point {
    type Output = Point;

    fn sub(self, s: Scalar) -> Point {
        Point { x: self.x - s, y: self.y - s }
    }
}

impl<T: Into<Point>> Sub<T> for Point {
    type Output = Point;

    fn sub(self, v: T) -> Point {
        let v = v.into();
        Point { x: self.x - v.x, y: self.y - v.y }
    }
}

/// A rectangle.
#[derive(Clone, Copy, Debug)]
pub struct Rect {
    /// The position of the top left corner of the rectangle.
    pub pos: Point,
    /// The width and height of the rectangle.
    pub size: Size,
}

impl<P: Into<Point>, S: Into<Size>> From<(P, S)> for Rect {
    /// Creates a rectangle from the position of its top left corner and its size.
    fn from((pos, size): (P, S)) -> Rect {
        let (pos, size): (Point, Size) = (pos.into(), size.into());
        Rect { pos: pos, size: size }
    }
}

impl From<Rect> for [Scalar; 4] {
    fn from(rect: Rect) -> [Scalar; 4] {
        [rect.pos.x, rect.pos.y, rect.size.w, rect.size.h]
    }
}

impl From<[Scalar; 4]> for Rect {
    /// Creates a rectangle from an array.
    fn from(v: [Scalar; 4]) -> Rect {
        Rect {
            pos: Point { x: v[0], y: v[1] },
            size: Size { w: v[2], h: v[3] },
        }
    }
}

impl From<(Scalar, Scalar, Scalar, Scalar)> for Rect {
    fn from((x, y, w, h): (Scalar, Scalar, Scalar, Scalar)) -> Rect {
        Rect {
            pos: Point { x: x, y: y },
            size: Size { w: w, h: h },
        }
    }
}

impl Rect {
    /// Returns the position of the bottom side of the rectangle.
    pub fn bottom(&self) -> Scalar {
        self.pos.y + self.size.h
    }

    /// Computes a rectangle with quadruple the surface area of self and with center
    /// (self.x, self.y).
    pub fn centered(self) -> Rect {
        Rect {
            pos: Point {
                 x: self.pos.x - self.size.w,
                 y: self.pos.y - self.size.h,
            },
            size: self.size * 2.0,
        }
    }

    /// Compute whether or not the point is inside the rectangle.
    #[inline(always)]
    pub fn contains<T: Into<Point>>(&self, point: T) -> bool {
        let point: Point = point.into();
        self.left() < point.x && point.x < self.right() &&
        self.top() < point.y && point.y < self.bottom()
    }

    /// Create a rectangle that circumscribes the given circle.
    pub fn new_circle<T: Into<Point>>(center: T, radius: Scalar) -> Rect {
        let center: Point = center.into();
        Rect {
            pos: Point {
                x: center.x - radius,
                y: center.y - radius,
            },
            size: Size {
                w: 2.0 * radius,
                h: 2.0 * radius,
            },
        }
    }

    /// Create a square rectangle with sides of length len and top left corner at pos.
    pub fn new_square<T: Into<Point>>(pos: T, len: Scalar) -> Rect {
        let pos: Point = pos.into();
        Rect {
            pos: pos,
            size: Size { w: len, h: len },
        }
    }

    /// Returns the position of the left side of the rectangle.
    pub fn left(&self) -> Scalar {
        self.pos.x
    }

    /// Computes a rectangle whose perimeter forms the inside edge of margin with size m for self.
    #[inline(always)]
    pub fn margin(self, m: Scalar) -> Rect {
        math::margin_rectangle(self.into(), m).into()
    }

    /// Computes a rectangle translated (slid) in the direction of the vector a distance relative
    /// to the size of the rectangle. For example, self.relative([1.0, 1.0]) returns a rectangle
    /// one rectangle to the right and down from the original.
    #[inline(always)]
    pub fn relative<T: Into<Point>>(self, v: T) -> Rect {
        let v: Point = v.into();
        Rect {
            pos: Point {
                x: self.pos.x + self.size.w * v.x,
                y: self.pos.y + self.size.h * v.y,
            },
            size: self.size,
        }
    }

    /// Returns the position of the right side of the rectangle.
    pub fn right(&self) -> Scalar {
        self.pos.x + self.size.w
    }

    /// Computes a scaled rectangle with the same position as self.
    pub fn scaled<T: Into<Size>>(self, v: T) -> Rect {
        let v: Size = v.into();
        Rect {
            pos: self.pos,
            size: self.size * v,
        }
    }

    /// Returns the position of the top side of the rectangle.
    pub fn top(&self) -> Scalar {
        self.pos.y
    }
}
<|endoftext|>


<commit_before>#![crate_id(name="uniq", vers="1.0.0", author="Chirag B. Jadwani")]
/*
 * 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.
 *
 */

#![feature(macro_rules)]

extern crate getopts;

use std::ascii::OwnedStrAsciiExt;
use std::cmp::min;
use std::from_str::FromStr;
use std::io;

#[path = "../common/util.rs"]
mod util;

static NAME: &'static str = "uniq";
static VERSION: &'static str = "1.0.0";

struct Uniq {
    repeats_only: bool,
    uniques_only: bool,
    all_repeated: bool,
    delimiters: String,
    show_counts: bool,
    slice_start: Option<uint>,
    slice_stop: Option<uint>,
    ignore_case: bool,
}

impl Uniq {
    pub fn print_uniq<R: Reader, W: Writer>(&self, reader: &mut io::BufferedReader<R>, writer: &mut io::BufferedWriter<W>) {
        let mut lines: Vec<String> = vec!();
        let mut first_line_printed = false;
        let delimiters = self.delimiters.as_slice();

        for io_line in reader.lines() {
            let line = crash_if_err!(1, io_line);
            if !lines.is_empty() && self.cmp_key(&lines[0]) != self.cmp_key(&line) {
                let print_delimiter = delimiters == "prepend" || (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 == "prepend" || (delimiters == "separate" && first_line_printed);
            self.print_lines(writer, &lines, print_delimiter);
        }
    }

    fn cmp_key(&self, line: &String) -> String {
        let len = line.len();
        if len > 0 {
            let slice_start = match self.slice_start {
                Some(i) => min(i, len - 1),
                None => 0
            };
            let slice_stop = match self.slice_stop {
                Some(i) => min(slice_start + i, len),
                None => len
            };
            let sliced = line.as_slice().slice(slice_start, slice_stop).into_string();
            if self.ignore_case {
                sliced.into_ascii_upper()
            } else {
                sliced
            }
        } else {
            line.clone()
        }
    }

    fn print_lines<W: Writer>(&self, writer: &mut io::BufferedWriter<W>, lines: &Vec<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.tail().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: Writer>(&self, writer: &mut io::BufferedWriter<W>, line: &String, count: uint, print_delimiter: bool) {
        let output_line = if self.show_counts {
            format!("{:7} {}", count, line)
        } else {
            line.clone()
        };
        if print_delimiter {
            crash_if_err!(1, writer.write_line(""));
        }
        crash_if_err!(1, writer.write_str(output_line.as_slice()));
    }
}

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

pub fn uumain(args: Vec<String>) -> int {
    let program_path = Path::new(args[0].clone());
    let program = program_path.filename_str().unwrap_or(NAME);

    let opts = [
        getopts::optflag("c", "count", "prefix lines by the number of occurrences"),
        getopts::optflag("d", "repeated", "only print duplicate lines"),
        getopts::optflagopt(
            "D",
            "all-repeated",
            "print all duplicate lines delimit-method={none(default),prepend,separate} Delimiting is done with blank lines",
            "delimit-method"
        ),
        getopts::optopt("s", "skip-chars", "avoid comparing the first N characters", "N"),
        getopts::optopt("w", "check-chars", "compare no more than N characters in lines", "N"),
        getopts::optflag("i", "ignore-case", "ignore differences in case when comparing"),
        getopts::optflag("u", "unique", "only print unique lines"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit")
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f)
    };

    if matches.opt_present("help") {
        println!("{} {}", NAME, VERSION);
        println!("");
        println!("Usage:");
        println!("  {0:s} [OPTION]... [FILE]...", program);
        println!("");
        print!("{}", getopts::usage("Filter adjacent matching lines from INPUT (or standard input),\n\
                                    writing to OUTPUT (or standard output).", opts));
        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", program);
    } else if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
    } else {
        let (in_file_name, out_file_name) = match matches.free.len() {
            0 => ("-".into_string(), "-".into_string()),
            1 => (matches.free[0].clone(), "-".into_string()),
            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.as_slice() != "none" => {
                    let rep_args = ["prepend".to_string(), "separate".to_string()];
                    if !rep_args.contains(opt_arg) {
                        crash!(1, "Incorrect argument for all-repeated: {}", opt_arg.clone());
                    }
                    opt_arg.clone()
                },
                _ => "".to_string()
            },
            show_counts: matches.opt_present("count"),
            slice_start: opt_parsed("skip-chars", &matches),
            slice_stop: opt_parsed("check-chars", &matches),
            ignore_case: matches.opt_present("ignore-case"),
        };
        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) -> io::BufferedReader<Box<Reader+'static>> {
    let in_file = if in_file_name.as_slice() == "-" {
        box io::stdio::stdin_raw() as Box<Reader>
    } else {
        let path = Path::new(in_file_name);
        let in_file = io::File::open(&path);
        box crash_if_err!(1, in_file) as Box<Reader>
    };
    io::BufferedReader::new(in_file)
}

fn open_output_file(out_file_name: String) -> io::BufferedWriter<Box<Writer+'static>> {
    let out_file = if out_file_name.as_slice() == "-" {
        box io::stdio::stdout_raw() as Box<Writer>
    } else {
        let path = Path::new(out_file_name);
        let in_file = io::File::create(&path);
        box crash_if_err!(1, in_file) as Box<Writer>
    };
    io::BufferedWriter::new(out_file)
}
<commit_msg>uniq: crate_id -> crate_name<commit_after>#![crate_name = "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.
 *
 */

#![feature(macro_rules)]

extern crate getopts;

use std::ascii::OwnedStrAsciiExt;
use std::cmp::min;
use std::from_str::FromStr;
use std::io;

#[path = "../common/util.rs"]
mod util;

static NAME: &'static str = "uniq";
static VERSION: &'static str = "1.0.0";

struct Uniq {
    repeats_only: bool,
    uniques_only: bool,
    all_repeated: bool,
    delimiters: String,
    show_counts: bool,
    slice_start: Option<uint>,
    slice_stop: Option<uint>,
    ignore_case: bool,
}

impl Uniq {
    pub fn print_uniq<R: Reader, W: Writer>(&self, reader: &mut io::BufferedReader<R>, writer: &mut io::BufferedWriter<W>) {
        let mut lines: Vec<String> = vec!();
        let mut first_line_printed = false;
        let delimiters = self.delimiters.as_slice();

        for io_line in reader.lines() {
            let line = crash_if_err!(1, io_line);
            if !lines.is_empty() && self.cmp_key(&lines[0]) != self.cmp_key(&line) {
                let print_delimiter = delimiters == "prepend" || (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 == "prepend" || (delimiters == "separate" && first_line_printed);
            self.print_lines(writer, &lines, print_delimiter);
        }
    }

    fn cmp_key(&self, line: &String) -> String {
        let len = line.len();
        if len > 0 {
            let slice_start = match self.slice_start {
                Some(i) => min(i, len - 1),
                None => 0
            };
            let slice_stop = match self.slice_stop {
                Some(i) => min(slice_start + i, len),
                None => len
            };
            let sliced = line.as_slice().slice(slice_start, slice_stop).into_string();
            if self.ignore_case {
                sliced.into_ascii_upper()
            } else {
                sliced
            }
        } else {
            line.clone()
        }
    }

    fn print_lines<W: Writer>(&self, writer: &mut io::BufferedWriter<W>, lines: &Vec<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.tail().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: Writer>(&self, writer: &mut io::BufferedWriter<W>, line: &String, count: uint, print_delimiter: bool) {
        let output_line = if self.show_counts {
            format!("{:7} {}", count, line)
        } else {
            line.clone()
        };
        if print_delimiter {
            crash_if_err!(1, writer.write_line(""));
        }
        crash_if_err!(1, writer.write_str(output_line.as_slice()));
    }
}

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

pub fn uumain(args: Vec<String>) -> int {
    let program_path = Path::new(args[0].clone());
    let program = program_path.filename_str().unwrap_or(NAME);

    let opts = [
        getopts::optflag("c", "count", "prefix lines by the number of occurrences"),
        getopts::optflag("d", "repeated", "only print duplicate lines"),
        getopts::optflagopt(
            "D",
            "all-repeated",
            "print all duplicate lines delimit-method={none(default),prepend,separate} Delimiting is done with blank lines",
            "delimit-method"
        ),
        getopts::optopt("s", "skip-chars", "avoid comparing the first N characters", "N"),
        getopts::optopt("w", "check-chars", "compare no more than N characters in lines", "N"),
        getopts::optflag("i", "ignore-case", "ignore differences in case when comparing"),
        getopts::optflag("u", "unique", "only print unique lines"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit")
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f)
    };

    if matches.opt_present("help") {
        println!("{} {}", NAME, VERSION);
        println!("");
        println!("Usage:");
        println!("  {0:s} [OPTION]... [FILE]...", program);
        println!("");
        print!("{}", getopts::usage("Filter adjacent matching lines from INPUT (or standard input),\n\
                                    writing to OUTPUT (or standard output).", opts));
        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", program);
    } else if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
    } else {
        let (in_file_name, out_file_name) = match matches.free.len() {
            0 => ("-".into_string(), "-".into_string()),
            1 => (matches.free[0].clone(), "-".into_string()),
            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.as_slice() != "none" => {
                    let rep_args = ["prepend".to_string(), "separate".to_string()];
                    if !rep_args.contains(opt_arg) {
                        crash!(1, "Incorrect argument for all-repeated: {}", opt_arg.clone());
                    }
                    opt_arg.clone()
                },
                _ => "".to_string()
            },
            show_counts: matches.opt_present("count"),
            slice_start: opt_parsed("skip-chars", &matches),
            slice_stop: opt_parsed("check-chars", &matches),
            ignore_case: matches.opt_present("ignore-case"),
        };
        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) -> io::BufferedReader<Box<Reader+'static>> {
    let in_file = if in_file_name.as_slice() == "-" {
        box io::stdio::stdin_raw() as Box<Reader>
    } else {
        let path = Path::new(in_file_name);
        let in_file = io::File::open(&path);
        box crash_if_err!(1, in_file) as Box<Reader>
    };
    io::BufferedReader::new(in_file)
}

fn open_output_file(out_file_name: String) -> io::BufferedWriter<Box<Writer+'static>> {
    let out_file = if out_file_name.as_slice() == "-" {
        box io::stdio::stdout_raw() as Box<Writer>
    } else {
        let path = Path::new(out_file_name);
        let in_file = io::File::create(&path);
        box crash_if_err!(1, in_file) as Box<Writer>
    };
    io::BufferedWriter::new(out_file)
}
<|endoftext|>


<commit_before>//! Users interface

use {Github, Result};

/// User information
#[derive(Debug, Deserialize)]
pub struct User {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    // type (keyword)
    pub site_admin: bool,
}

/// Information about current authenticated user
#[derive(Debug, Deserialize)]
pub struct AuthenticatedUser {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    // type (keyword)
    pub site_admin: bool,

    // extend over `User`:
    pub name: String,
    pub company: String,
    pub blog: String,
    pub location: String,
    pub email: String,
    pub hireable: Option<bool>,
    pub bio: String,
    pub public_repos: u64,
    pub public_gists: u64,
    pub followers: u64,
    pub following: u64,
    pub created_at: String, // TODO: change to `DateTime`?
    pub updated_at: String, // TODO: change to `DateTime`?
}

/// Query user information
pub struct Users<'a> {
    github: &'a Github,
}

impl<'a> Users<'a> {
    pub fn new(github: &'a Github) -> Users<'a> {
        Users {
            github: github,
        }
    }

    /// Information about current authenticated user
    pub fn authenticated(&self) -> Result<AuthenticatedUser> {
        self.github.get::<AuthenticatedUser>(&"/user")
    }
}
<commit_msg>Fix `AuthenticatedUser::company` field type<commit_after>//! Users interface

use {Github, Result};

/// User information
#[derive(Debug, Deserialize)]
pub struct User {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    // type (keyword)
    pub site_admin: bool,
}

/// Information about current authenticated user
#[derive(Debug, Deserialize)]
pub struct AuthenticatedUser {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    // type (keyword)
    pub site_admin: bool,

    // extend over `User`:
    pub name: String,
    pub company: Option<String>,
    pub blog: String,
    pub location: String,
    pub email: String,
    pub hireable: Option<bool>,
    pub bio: String,
    pub public_repos: u64,
    pub public_gists: u64,
    pub followers: u64,
    pub following: u64,
    pub created_at: String, // TODO: change to `DateTime`?
    pub updated_at: String, // TODO: change to `DateTime`?
}

/// Query user information
pub struct Users<'a> {
    github: &'a Github,
}

impl<'a> Users<'a> {
    pub fn new(github: &'a Github) -> Users<'a> {
        Users {
            github: github,
        }
    }

    /// Information about current authenticated user
    pub fn authenticated(&self) -> Result<AuthenticatedUser> {
        self.github.get::<AuthenticatedUser>(&"/user")
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The HTML5 for Rust Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use phf::PhfMap;

use std::mem::replace;

static static_atom_map: PhfMap<uint> = static_atom_map!();
static static_atom_array: &'static [&'static str] = static_atom_array!();

// Assume that a string which can be interned always is.
// FIXME: Revisit this assumption when we have dynamic interning.
/// Interned string.
///
/// Don't pattern-match this directly! Use the `atom!()` pattern macro.
#[deriving(Clone, Show, PartialEq, Eq)]
pub enum Atom {
    Static(uint),
    // dynamic interning goes here
    Owned(String),
}

impl Atom {
    pub fn from_str(s: &str) -> Atom {
        match static_atom_map.find(&s) {
            Some(&k) => Static(k),
            None => Owned(s.to_string()),
        }
    }

    pub fn from_buf(s: String) -> Atom {
        match static_atom_map.find(&s.as_slice()) {
            Some(&k) => Static(k),
            None => Owned(s),
        }
    }

    /// Like `Atom::from_buf(replace(s, String::new()))` but avoids
    /// allocating a new `String` when the string is interned --
    /// just truncates the old one.
    pub fn take_from_buf(s: &mut String) -> Atom {
        match static_atom_map.find(&s.as_slice()) {
            Some(&k) => {
                s.truncate(0);
                Static(k)
            }
            None => {
                Owned(replace(s, String::new()))
            }
        }
    }

    #[inline(always)]
    fn fast_partial_eq(&self, other: &Atom) -> Option<bool> {
        match (self, other) {
            (&Static(x), &Static(y)) => Some(x == y),
            _ => None,
        }
    }
}

fn get_static(i: uint) -> &'static str {
    *static_atom_array.get(i).expect("bad static atom")
}

impl Str for Atom {
    fn as_slice<'t>(&'t self) -> &'t str {
        match *self {
            Static(i) => get_static(i),
            Owned(ref s) => s.as_slice(),
        }
    }
}

impl StrAllocating for Atom {
    fn into_string(self) -> String {
        match self {
            Static(i) => get_static(i).to_string(),
            Owned(s) => s.into_string(),
        }
    }

    fn to_string(&self) -> String {
        match *self {
            Static(i) => get_static(i).to_string(),
            Owned(ref s) => s.clone(),
        }
    }

    fn into_owned(self) -> String {
        match self {
            Static(i) => get_static(i).to_string(),
            Owned(s) => s,
        }
    }
}

impl PartialOrd for Atom {
    fn partial_cmp(&self, other: &Atom) -> Option<Ordering> {
        match self.fast_partial_eq(other) {
            Some(true) => Some(Equal),
            _ => self.as_slice().partial_cmp(&other.as_slice()),
        }
    }
}

impl Ord for Atom {
    fn cmp(&self, other: &Atom) -> Ordering {
        match self.fast_partial_eq(other) {
            Some(true) => Equal,
            _ => self.as_slice().cmp(&other.as_slice()),
        }
    }
}

#[cfg(test)]
#[allow(non_snake_case_functions)]
mod test {
    use super::*; // public items
    use super::{get_static}; // private items

    #[test]
    fn interned() {
        match Atom::from_str("body") {
            Static(i) => assert_eq!(get_static(i), "body"),
            _ => fail!("wrong interning"),
        }
    }

    #[test]
    fn not_interned() {
        match Atom::from_str("asdfghjk") {
            Owned(b) => assert_eq!(b.as_slice(), "asdfghjk"),
            _ => fail!("wrong interning"),
        }
    }

    #[test]
    fn as_slice() {
        assert_eq!(Atom::from_str("").as_slice(), "");
        assert_eq!(Atom::from_str("body").as_slice(), "body");
        assert_eq!(Atom::from_str("asdfghjk").as_slice(), "asdfghjk");
    }

    #[test]
    fn into_string() {
        assert_eq!(Atom::from_str("").into_string(), "".to_string());
        assert_eq!(Atom::from_str("body").into_string(), "body".to_string());
        assert_eq!(Atom::from_str("asdfghjk").into_string(), "asdfghjk".to_string());
    }

    #[test]
    fn to_string() {
        assert_eq!(Atom::from_str("").to_string(), "".to_string());
        assert_eq!(Atom::from_str("body").to_string(), "body".to_string());
        assert_eq!(Atom::from_str("asdfghjk").to_string(), "asdfghjk".to_string());
    }

    #[test]
    fn take_from_buf_interned() {
        let mut b = "body".to_string();
        let a = Atom::take_from_buf(&mut b);
        assert_eq!(a, Atom::from_str("body"));
        assert_eq!(b, String::new());
    }

    #[test]
    fn take_from_buf_not_interned() {
        let mut b = "asdfghjk".to_string();
        let a = Atom::take_from_buf(&mut b);
        assert_eq!(a, Atom::from_str("asdfghjk"));
        assert_eq!(b, String::new());
    }

    #[test]
    fn ord() {
        fn check(x: &str, y: &str) {
            assert_eq!(x < y, Atom::from_str(x) < Atom::from_str(y));
            assert_eq!(x.cmp(&y), Atom::from_str(x).cmp(&Atom::from_str(y)));
        }

        check("a", "body");
        check("asdf", "body");
        check("zasdf", "body");
        check("z", "body");

        check("a", "bbbbb");
        check("asdf", "bbbbb");
        check("zasdf", "bbbbb");
        check("z", "bbbbb");
    }

    #[test]
    fn atom_macro() {
        assert_eq!(atom!(body), Atom::from_str("body"));
        assert_eq!(atom!("body"), Atom::from_str("body"));
        assert_eq!(atom!("font-weight"), Atom::from_str("font-weight"));
    }

    #[test]
    fn match_atom() {
        assert_eq!(2u, match Atom::from_str("head") {
            atom!(br) => 1u,
            atom!(html) | atom!(head) => 2u,
            _ => 3u,
        });

        assert_eq!(3u, match Atom::from_str("body") {
            atom!(br) => 1u,
            atom!(html) | atom!(head) => 2u,
            _ => 3u,
        });

        assert_eq!(3u, match Atom::from_str("zzzzzz") {
            atom!(br) => 1u,
            atom!(html) | atom!(head) => 2u,
            _ => 3u,
        });
    }
}
<commit_msg>Show atoms as atom!() invocations<commit_after>// Copyright 2014 The HTML5 for Rust Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use phf::PhfMap;

use std::mem::replace;
use std::fmt::{Show, Formatter, FormatError};

static static_atom_map: PhfMap<uint> = static_atom_map!();
static static_atom_array: &'static [&'static str] = static_atom_array!();

// Assume that a string which can be interned always is.
// FIXME: Revisit this assumption when we have dynamic interning.
/// Interned string.
///
/// Don't pattern-match this directly! Use the `atom!()` pattern macro.
#[deriving(Clone, PartialEq, Eq)]
pub enum Atom {
    Static(uint),
    // dynamic interning goes here
    Owned(String),
}

impl Atom {
    pub fn from_str(s: &str) -> Atom {
        match static_atom_map.find(&s) {
            Some(&k) => Static(k),
            None => Owned(s.to_string()),
        }
    }

    pub fn from_buf(s: String) -> Atom {
        match static_atom_map.find(&s.as_slice()) {
            Some(&k) => Static(k),
            None => Owned(s),
        }
    }

    /// Like `Atom::from_buf(replace(s, String::new()))` but avoids
    /// allocating a new `String` when the string is interned --
    /// just truncates the old one.
    pub fn take_from_buf(s: &mut String) -> Atom {
        match static_atom_map.find(&s.as_slice()) {
            Some(&k) => {
                s.truncate(0);
                Static(k)
            }
            None => {
                Owned(replace(s, String::new()))
            }
        }
    }

    #[inline(always)]
    fn fast_partial_eq(&self, other: &Atom) -> Option<bool> {
        match (self, other) {
            (&Static(x), &Static(y)) => Some(x == y),
            _ => None,
        }
    }
}

fn get_static(i: uint) -> &'static str {
    *static_atom_array.get(i).expect("bad static atom")
}

impl Str for Atom {
    fn as_slice<'t>(&'t self) -> &'t str {
        match *self {
            Static(i) => get_static(i),
            Owned(ref s) => s.as_slice(),
        }
    }
}

impl StrAllocating for Atom {
    fn into_string(self) -> String {
        match self {
            Static(i) => get_static(i).to_string(),
            Owned(s) => s.into_string(),
        }
    }

    fn to_string(&self) -> String {
        match *self {
            Static(i) => get_static(i).to_string(),
            Owned(ref s) => s.clone(),
        }
    }

    fn into_owned(self) -> String {
        match self {
            Static(i) => get_static(i).to_string(),
            Owned(s) => s,
        }
    }
}

impl PartialOrd for Atom {
    fn partial_cmp(&self, other: &Atom) -> Option<Ordering> {
        match self.fast_partial_eq(other) {
            Some(true) => Some(Equal),
            _ => self.as_slice().partial_cmp(&other.as_slice()),
        }
    }
}

impl Ord for Atom {
    fn cmp(&self, other: &Atom) -> Ordering {
        match self.fast_partial_eq(other) {
            Some(true) => Equal,
            _ => self.as_slice().cmp(&other.as_slice()),
        }
    }
}

impl Show for Atom {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FormatError> {
        try!("atom!(".fmt(fmt));
        try!(self.as_slice().fmt(fmt));
        ")".fmt(fmt)
    }
}

#[cfg(test)]
#[allow(non_snake_case_functions)]
mod test {
    use super::*; // public items
    use super::{get_static}; // private items

    #[test]
    fn interned() {
        match Atom::from_str("body") {
            Static(i) => assert_eq!(get_static(i), "body"),
            _ => fail!("wrong interning"),
        }
    }

    #[test]
    fn not_interned() {
        match Atom::from_str("asdfghjk") {
            Owned(b) => assert_eq!(b.as_slice(), "asdfghjk"),
            _ => fail!("wrong interning"),
        }
    }

    #[test]
    fn as_slice() {
        assert_eq!(Atom::from_str("").as_slice(), "");
        assert_eq!(Atom::from_str("body").as_slice(), "body");
        assert_eq!(Atom::from_str("asdfghjk").as_slice(), "asdfghjk");
    }

    #[test]
    fn into_string() {
        assert_eq!(Atom::from_str("").into_string(), "".to_string());
        assert_eq!(Atom::from_str("body").into_string(), "body".to_string());
        assert_eq!(Atom::from_str("asdfghjk").into_string(), "asdfghjk".to_string());
    }

    #[test]
    fn to_string() {
        assert_eq!(Atom::from_str("").to_string(), "".to_string());
        assert_eq!(Atom::from_str("body").to_string(), "body".to_string());
        assert_eq!(Atom::from_str("asdfghjk").to_string(), "asdfghjk".to_string());
    }

    #[test]
    fn take_from_buf_interned() {
        let mut b = "body".to_string();
        let a = Atom::take_from_buf(&mut b);
        assert_eq!(a, Atom::from_str("body"));
        assert_eq!(b, String::new());
    }

    #[test]
    fn take_from_buf_not_interned() {
        let mut b = "asdfghjk".to_string();
        let a = Atom::take_from_buf(&mut b);
        assert_eq!(a, Atom::from_str("asdfghjk"));
        assert_eq!(b, String::new());
    }

    #[test]
    fn ord() {
        fn check(x: &str, y: &str) {
            assert_eq!(x < y, Atom::from_str(x) < Atom::from_str(y));
            assert_eq!(x.cmp(&y), Atom::from_str(x).cmp(&Atom::from_str(y)));
        }

        check("a", "body");
        check("asdf", "body");
        check("zasdf", "body");
        check("z", "body");

        check("a", "bbbbb");
        check("asdf", "bbbbb");
        check("zasdf", "bbbbb");
        check("z", "bbbbb");
    }

    #[test]
    fn atom_macro() {
        assert_eq!(atom!(body), Atom::from_str("body"));
        assert_eq!(atom!("body"), Atom::from_str("body"));
        assert_eq!(atom!("font-weight"), Atom::from_str("font-weight"));
    }

    #[test]
    fn match_atom() {
        assert_eq!(2u, match Atom::from_str("head") {
            atom!(br) => 1u,
            atom!(html) | atom!(head) => 2u,
            _ => 3u,
        });

        assert_eq!(3u, match Atom::from_str("body") {
            atom!(br) => 1u,
            atom!(html) | atom!(head) => 2u,
            _ => 3u,
        });

        assert_eq!(3u, match Atom::from_str("zzzzzz") {
            atom!(br) => 1u,
            atom!(html) | atom!(head) => 2u,
            _ => 3u,
        });
    }
}
<|endoftext|>


<commit_before>/// evaluates a polynomial at `z` where `coeff` are the coeffecients
/// to a polynomial of order `k` where `k` is the length of `coeff` and the coeffecient
/// to the `k`th power is the `k`th element in coeff. E.g. [3,-1,2] equates to
/// `2z^2 - z + 3`
pub fn polynomial(z: f64, coeff: &[f64]) -> f64 {
    let mut sum = coeff[coeff.len() - 1];
    for i in (0..coeff.len() - 1).rev() {
        sum *= z;
        sum += coeff[i];
    }
    sum
}

/// Evaluates a numerically stable
/// series summation where `next` returns the
/// next summand in the series
pub fn series<F>(mut next: F) -> f64
    where F: FnMut() -> f64
{
    let factor = (1 << 16) as f64;
    let mut comp = 0.0;
    let mut sum = next();

    loop {
        let cur = next();
        let y = cur - comp;
        let t = sum + y;
        comp = t - sum - y;
        sum = t;
        if sum.abs() >= (factor * cur).abs() {
            break;
        }
    }
    sum
}
<commit_msg>implement polynomial test<commit_after>/// evaluates a polynomial at `z` where `coeff` are the coeffecients
/// to a polynomial of order `k` where `k` is the length of `coeff` and the coeffecient
/// to the `k`th power is the `k`th element in coeff. E.g. [3,-1,2] equates to
/// `2z^2 - z + 3`
///
/// # Remarks
///
/// Returns 0 for a 0 length coefficient slice
pub fn polynomial(z: f64, coeff: &[f64]) -> f64 {
    let n = coeff.len();
    if n == 0 {
        return 0.0
    }

    unsafe {
        let mut sum = *coeff.get_unchecked(n - 1);
        for i in (0..n - 1).rev() {
            sum *= z;
            sum += *coeff.get_unchecked(i);
        }
        sum
    }
}

/// Evaluates a numerically stable
/// series summation where `next` returns the
/// next summand in the series
pub fn series<F>(mut next: F) -> f64
    where F: FnMut() -> f64
{
    let factor = (1 << 16) as f64;
    let mut comp = 0.0;
    let mut sum = next();

    loop {
        let cur = next();
        let y = cur - comp;
        let t = sum + y;
        comp = t - sum - y;
        sum = t;
        if sum.abs() >= (factor * cur).abs() {
            break;
        }
    }
    sum
}

#[cfg_attr(rustfmt, rustfmt_skip)]
#[cfg(test)]
mod test {
    use std::f64;

    // these tests probably could be more robust
    #[test]
    fn test_polynomial() {
        let empty: [f64; 0] = [];
        assert_eq!(super::polynomial(2.0, &empty), 0.0);

        let zero = [0.0];
        assert_eq!(super::polynomial(2.0, &zero), 0.0);

        let mut coeff = [1.0, 0.0, 5.0];
        assert_eq!(super::polynomial(2.0, &coeff), 21.0);

        coeff = [-5.0, -2.0, 3.0];
        assert_eq!(super::polynomial(2.0, &coeff), 3.0);
        assert_eq!(super::polynomial(-2.0, &coeff), 11.0);

        coeff = [f64::INFINITY, -2.0, 3.0];
        assert_eq!(super::polynomial(2.0, &coeff), f64::INFINITY);
        assert_eq!(super::polynomial(-2.0, &coeff), f64::INFINITY);

        coeff = [f64::NEG_INFINITY, -2.0, 3.0];
        assert_eq!(super::polynomial(2.0, &coeff), f64::NEG_INFINITY);
        assert_eq!(super::polynomial(-2.0, &coeff), f64::NEG_INFINITY);

        coeff = [f64::NAN, -2.0, 3.0];
        assert!(super::polynomial(2.0, &coeff).is_nan());
        assert!(super::polynomial(-2.0, &coeff).is_nan());
    }
}
<|endoftext|>


<commit_before>
use super::Database;
use super::options::{ReadOptions,WriteOptions};
use super::error::Error;
use serialize::{json, Encodable};
use serialize::json::Json;
use serialize::json::Encoder;
use serialize::json::from_reader;
use std::io::BufReader;

pub trait Interface<'a, T:Encodable<json::Encoder<'a>>> {
  fn put(&mut self,
         options: WriteOptions,
         key: &T,
         value: &T)
        -> Result<(), Error>;
  fn delete(&mut self,
           options: WriteOptions,
           key: &T) -> Result<(), Error>;
  fn get(&mut self,
         options: ReadOptions,
         key: &T) -> Result<Option<Json>, Error>;
}

impl<'a, T: Encodable<json::Encoder<'a>>> Interface<'a, T> for Database {
  fn put(&mut self,
        options: WriteOptions,
        key: &T,
        value: &T) -> Result<(), Error> {
    let encoded_key = json::Encoder::buffer_encode(&key);
    let encoded_val = json::Encoder::buffer_encode(&value);
    self.put_binary(options, encoded_key, encoded_val)
  }
  fn delete(&mut self,
            options: WriteOptions,
            key: &T) -> Result<(), Error> {
    let encoded_key = json::Encoder::buffer_encode(&key);
    self.delete_binary(options, encoded_key)
  }
  fn get(&mut self,
         options: ReadOptions,
         key: &T) -> Result<Option<Json>, Error> {
    let encoded_key = json::Encoder::buffer_encode(&key);
    let result = self.get_binary(options, encoded_key);
    match result {
      Err(error) => { Err (error) },
      Ok(opt) => {
        match opt {
          None => { Ok(None) },
          Some(binary) => {
            let mut reader = BufReader::new(binary);
            match from_reader(&mut reader) {
              Ok(json) => { Ok(Some(json)) },
              Err(_) => { Err( Error { message: ~"json parsing failed" } ) }
            }
          }
        }
      }
    }
  }
}
<commit_msg>Add IoError as the error type of JSON errors<commit_after>
use super::Database;
use super::options::{ReadOptions,WriteOptions};
use super::error::Error;
use serialize::{json, Encodable};
use serialize::json::Json;
use serialize::json::Encoder;
use serialize::json::from_reader;
use std::io::BufReader;
use std::io;

pub trait Interface<'a, T:Encodable<json::Encoder<'a>,io::IoError>> {
  fn put(&mut self,
         options: WriteOptions,
         key: &T,
         value: &T)
        -> Result<(), Error>;
  fn delete(&mut self,
           options: WriteOptions,
           key: &T) -> Result<(), Error>;
  fn get(&mut self,
         options: ReadOptions,
         key: &T) -> Result<Option<Json>, Error>;
}

impl<'a, T: Encodable<json::Encoder<'a>, io::IoError>> Interface<'a, T> for Database {
  fn put(&mut self,
        options: WriteOptions,
        key: &T,
        value: &T) -> Result<(), Error> {
    let encoded_key = json::Encoder::buffer_encode(&key);
    let encoded_val = json::Encoder::buffer_encode(&value);
    self.put_binary(options, encoded_key, encoded_val)
  }
  fn delete(&mut self,
            options: WriteOptions,
            key: &T) -> Result<(), Error> {
    let encoded_key = json::Encoder::buffer_encode(&key);
    self.delete_binary(options, encoded_key)
  }
  fn get(&mut self,
         options: ReadOptions,
         key: &T) -> Result<Option<Json>, Error> {
    let encoded_key = json::Encoder::buffer_encode(&key);
    let result = self.get_binary(options, encoded_key);
    match result {
      Err(error) => { Err (error) },
      Ok(opt) => {
        match opt {
          None => { Ok(None) },
          Some(binary) => {
            let mut reader = BufReader::new(binary);
            match from_reader(&mut reader) {
              Ok(json) => { Ok(Some(json)) },
              Err(_) => { Err( Error { message: ~"json parsing failed" } ) }
            }
          }
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use std::time::Duration;

use embedded_hal::digital;
use embedded_hal::Pwm;

use super::{InputPin, IoPin, Level, OutputPin, Pin};

impl digital::InputPin for Pin {
    fn is_high(&self) -> bool {
        Pin::read(self) == Level::High
    }

    fn is_low(&self) -> bool {
        Pin::read(self) == Level::Low
    }
}

impl digital::InputPin for InputPin {
    fn is_high(&self) -> bool {
        InputPin::is_high(self)
    }

    fn is_low(&self) -> bool {
        InputPin::is_low(self)
    }
}

impl digital::InputPin for IoPin {
    fn is_high(&self) -> bool {
        IoPin::is_high(self)
    }

    fn is_low(&self) -> bool {
        IoPin::is_low(self)
    }
}

impl digital::InputPin for OutputPin {
    fn is_high(&self) -> bool {
        OutputPin::is_set_high(self)
    }

    fn is_low(&self) -> bool {
        OutputPin::is_set_low(self)
    }
}

impl digital::StatefulOutputPin for IoPin {
    fn is_set_high(&self) -> bool {
        IoPin::is_high(self)
    }

    fn is_set_low(&self) -> bool {
        IoPin::is_low(self)
    }
}

impl digital::StatefulOutputPin for OutputPin {
    fn is_set_high(&self) -> bool {
        OutputPin::is_set_high(self)
    }

    fn is_set_low(&self) -> bool {
        OutputPin::is_set_low(self)
    }
}

impl digital::ToggleableOutputPin for IoPin {
    fn toggle(&mut self) {
        IoPin::toggle(self);
    }
}

impl digital::ToggleableOutputPin for OutputPin {
    fn toggle(&mut self) {
        OutputPin::toggle(self);
    }
}

impl Pwm for OutputPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`
    fn disable(&mut self, _channel: Self::Channel) {
        let _ = self.clear_pwm();
    }

    /// Enables a PWM `channel`
    fn enable(&mut self, _channel: Self::Channel) {
        let _ = self.set_pwm_frequency(self.frequency, self.duty_cycle);
    }

    /// Returns the current PWM period
    fn get_period(&self) -> Self::Time {
        Duration::from_nanos(if self.frequency == 0.0 {
            0
        } else {
            ((1.0 / self.frequency) * 1_000_000_000.0) as u64
        })
    }

    /// Returns the current duty cycle
    fn get_duty(&self, _channel: Self::Channel) -> Self::Duty {
        self.duty_cycle
    }

    /// Returns the maximum duty cycle value
    fn get_max_duty(&self) -> Self::Duty {
        1.0
    }

    /// Sets a new duty cycle
    fn set_duty(&mut self, _channel: Self::Channel, duty: Self::Duty) {
        self.duty_cycle = duty.max(0.0).min(1.0);

        if self.soft_pwm.is_some() {
            let _ = self.set_pwm_frequency(self.frequency, self.duty_cycle);
        }
    }

    /// Sets a new PWM period
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let period = period.into();
        self.frequency =
            1.0 / (period.as_secs() as f64 + (f64::from(period.subsec_nanos()) / 1_000_000_000.0));

        if self.soft_pwm.is_some() {
            let _ = self.set_pwm_frequency(self.frequency, self.duty_cycle);
        }
    }
}

impl Pwm for IoPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`
    fn disable(&mut self, _channel: Self::Channel) {
        let _ = self.clear_pwm();
    }

    /// Enables a PWM `channel`
    fn enable(&mut self, _channel: Self::Channel) {
        let _ = self.set_pwm_frequency(self.frequency, self.duty_cycle);
    }

    /// Returns the current PWM period
    fn get_period(&self) -> Self::Time {
        Duration::from_nanos(if self.frequency == 0.0 {
            0
        } else {
            ((1.0 / self.frequency) * 1_000_000_000.0) as u64
        })
    }

    /// Returns the current duty cycle
    fn get_duty(&self, _channel: Self::Channel) -> Self::Duty {
        self.duty_cycle
    }

    /// Returns the maximum duty cycle value
    fn get_max_duty(&self) -> Self::Duty {
        1.0
    }

    /// Sets a new duty cycle
    fn set_duty(&mut self, _channel: Self::Channel, duty: Self::Duty) {
        self.duty_cycle = duty.max(0.0).min(1.0);

        if self.soft_pwm.is_some() {
            let _ = self.set_pwm_frequency(self.frequency, self.duty_cycle);
        }
    }

    /// Sets a new PWM period
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let period = period.into();
        self.frequency =
            1.0 / (period.as_secs() as f64 + (f64::from(period.subsec_nanos()) / 1_000_000_000.0));

        if self.soft_pwm.is_some() {
            let _ = self.set_pwm_frequency(self.frequency, self.duty_cycle);
        }
    }
}
<commit_msg>Upgrade to v2::{InputPin, StatefulOutputPin}<commit_after>// Copyright (c) 2017-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use std::time::Duration;

use embedded_hal::digital::v2;
use embedded_hal::Pwm;

use super::{Error, InputPin, IoPin, Level, OutputPin, Pin, Result};

impl v2::InputPin for Pin {
    type Error = Error;

    fn is_high(&self) -> Result<bool> {
        Ok(Pin::read(self) == Level::High)
    }

    fn is_low(&self) -> Result<bool> {
        Ok(Pin::read(self) == Level::Low)
    }
}

impl v2::InputPin for InputPin {
    type Error = Error;

    fn is_high(&self) -> Result<bool> {
        Ok(InputPin::is_high(self))
    }

    fn is_low(&self) -> Result<bool> {
        Ok(InputPin::is_low(self))
    }
}

impl v2::InputPin for IoPin {
    type Error = Error;

    fn is_high(&self) -> Result<bool> {
        Ok(IoPin::is_high(self))
    }

    fn is_low(&self) -> Result<bool> {
        Ok(IoPin::is_low(self))
    }
}

impl v2::InputPin for OutputPin {
    type Error = Error;

    fn is_high(&self) -> Result<bool> {
        Ok(OutputPin::is_set_high(self))
    }

    fn is_low(&self) -> Result<bool> {
        Ok(OutputPin::is_set_low(self))
    }
}

impl v2::StatefulOutputPin for IoPin {
    fn is_set_high(&self) -> Result<bool> {
        Ok(IoPin::is_high(self))
    }

    fn is_set_low(&self) -> Result<bool> {
        Ok(IoPin::is_low(self))
    }
}

impl v2::StatefulOutputPin for OutputPin {
    fn is_set_high(&self) -> Result<bool> {
        Ok(OutputPin::is_set_high(self))
    }

    fn is_set_low(&self) -> Result<bool> {
        Ok(OutputPin::is_set_low(self))
    }
}

impl v2::ToggleableOutputPin for IoPin {
    type Error = Error;

    fn toggle(&mut self) -> Result<()> {
        IoPin::toggle(self);

        Ok(())
    }
}

impl v2::ToggleableOutputPin for OutputPin {
    type Error = Error;

    fn toggle(&mut self) -> Result<()> {
        OutputPin::toggle(self);

        Ok(())
    }
}

impl Pwm for OutputPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`
    fn disable(&mut self, _channel: Self::Channel) {
        let _ = self.clear_pwm();
    }

    /// Enables a PWM `channel`
    fn enable(&mut self, _channel: Self::Channel) {
        let _ = self.set_pwm_frequency(self.frequency, self.duty_cycle);
    }

    /// Returns the current PWM period
    fn get_period(&self) -> Self::Time {
        Duration::from_nanos(if self.frequency == 0.0 {
            0
        } else {
            ((1.0 / self.frequency) * 1_000_000_000.0) as u64
        })
    }

    /// Returns the current duty cycle
    fn get_duty(&self, _channel: Self::Channel) -> Self::Duty {
        self.duty_cycle
    }

    /// Returns the maximum duty cycle value
    fn get_max_duty(&self) -> Self::Duty {
        1.0
    }

    /// Sets a new duty cycle
    fn set_duty(&mut self, _channel: Self::Channel, duty: Self::Duty) {
        self.duty_cycle = duty.max(0.0).min(1.0);

        if self.soft_pwm.is_some() {
            let _ = self.set_pwm_frequency(self.frequency, self.duty_cycle);
        }
    }

    /// Sets a new PWM period
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let period = period.into();
        self.frequency =
            1.0 / (period.as_secs() as f64 + (f64::from(period.subsec_nanos()) / 1_000_000_000.0));

        if self.soft_pwm.is_some() {
            let _ = self.set_pwm_frequency(self.frequency, self.duty_cycle);
        }
    }
}

impl Pwm for IoPin {
    type Duty = f64;
    type Channel = ();
    type Time = Duration;

    /// Disables a PWM `channel`
    fn disable(&mut self, _channel: Self::Channel) {
        let _ = self.clear_pwm();
    }

    /// Enables a PWM `channel`
    fn enable(&mut self, _channel: Self::Channel) {
        let _ = self.set_pwm_frequency(self.frequency, self.duty_cycle);
    }

    /// Returns the current PWM period
    fn get_period(&self) -> Self::Time {
        Duration::from_nanos(if self.frequency == 0.0 {
            0
        } else {
            ((1.0 / self.frequency) * 1_000_000_000.0) as u64
        })
    }

    /// Returns the current duty cycle
    fn get_duty(&self, _channel: Self::Channel) -> Self::Duty {
        self.duty_cycle
    }

    /// Returns the maximum duty cycle value
    fn get_max_duty(&self) -> Self::Duty {
        1.0
    }

    /// Sets a new duty cycle
    fn set_duty(&mut self, _channel: Self::Channel, duty: Self::Duty) {
        self.duty_cycle = duty.max(0.0).min(1.0);

        if self.soft_pwm.is_some() {
            let _ = self.set_pwm_frequency(self.frequency, self.duty_cycle);
        }
    }

    /// Sets a new PWM period
    fn set_period<P>(&mut self, period: P)
    where
        P: Into<Self::Time>,
    {
        let period = period.into();
        self.frequency =
            1.0 / (period.as_secs() as f64 + (f64::from(period.subsec_nanos()) / 1_000_000_000.0));

        if self.soft_pwm.is_some() {
            let _ = self.set_pwm_frequency(self.frequency, self.duty_cycle);
        }
    }
}
<|endoftext|>


<commit_before>use fool::BoolExt as _;
use indexmap::{indexset, IndexSet};
use itertools::Itertools;
use std::borrow::Borrow;
use std::collections::HashSet;
use std::marker::PhantomData;

use crate::graph::borrow::Reborrow;
use crate::graph::geometry::GraphGeometry;
use crate::graph::mutation::Consistent;
use crate::graph::storage::alias::*;
use crate::graph::storage::key::{ArcKey, VertexKey};
use crate::graph::storage::payload::{ArcPayload, VertexPayload};
use crate::graph::storage::{AsStorage, AsStorageMut};
use crate::graph::view::edge::ArcView;
use crate::graph::view::vertex::VertexView;
use crate::graph::view::{FromKeyedSource, IntoView};
use crate::graph::{GraphError, OptionExt as _, Selector};
use crate::IteratorExt as _;

// TODO: It would probably better for `PathView` to behave as a double-ended
//       queue. That would avoid the need for `pop_swap` and allow paths to be
//       re-rooted (the initiating vertex could be changed). This would not
//       work well with `IndexSet`.

/// View of a path in a graph.
///
/// Provides a representation of **non-intersecting** paths in a graph. A path
/// is conceptually an ordered set of vertices that are joined by arcs. A path
/// over vertices $A$, $B$, and $C$ is notated $\overrightarrow{\\{A, B,
/// C\\}}$.
///
/// Paths have no associated payload and do not directly expose geometry
/// (`PathView` does not implement `Deref` or expose a `geometry` field). See
/// the module documentation for more information about topological views.
#[derive(Clone)]
pub struct PathView<M, G>
where
    M: Reborrow,
    M::Target: AsStorage<ArcPayload<G>> + AsStorage<VertexPayload<G>> + Consistent,
    G: GraphGeometry,
{
    // Paths are represented using a head and tail, where the head is the
    // initiating vertex key and the tail is an ordered set of vertex keys. It
    // is possible for the first and last (that is, the head and terminating
    // element of the tail) to be the same vertex key, in which case the path
    // is closed.
    head: VertexKey,
    tail: IndexSet<VertexKey>,
    storage: M,
    phantom: PhantomData<G>,
}

impl<M, G> PathView<M, G>
where
    M: Reborrow,
    M::Target: AsStorage<ArcPayload<G>> + AsStorage<VertexPayload<G>> + Consistent,
    G: GraphGeometry,
{
    /// Pushes a vertex onto the path.
    pub fn push(&mut self, destination: Selector<VertexKey>) -> Result<ArcKey, GraphError> {
        self.is_open()
            .ok_or_else(|| GraphError::TopologyMalformed)?;
        let a = self.last();
        let b = match destination {
            Selector::ByKey(b) => {
                self.storage
                    .reborrow()
                    .as_vertex_storage()
                    .contains_key(&b)
                    .ok_or_else(|| GraphError::TopologyNotFound)?;
                self.storage
                    .reborrow()
                    .as_arc_storage()
                    .contains_key(&(a, b).into())
                    .ok_or_else(|| GraphError::TopologyMalformed)?;
                b
            }
            Selector::ByIndex(index) => {
                let storage = self.storage.reborrow();
                let vertex = VertexView::from_keyed_source((a, storage)).expect_consistent();
                let vertex = vertex
                    .neighboring_vertices()
                    .nth(index)
                    .ok_or_else(|| GraphError::TopologyNotFound)?;
                vertex.key()
            }
        };
        // Do not allow intersections unless they form a loop with the first
        // vertex in the path.
        //
        // Note that resolving the key `b` above already implicitly prohibits
        // `a == b`, so there is no need to test that here.
        (!self.tail.contains(&b)).ok_or_else(|| GraphError::TopologyMalformed)?;
        Ok(self.push_unchecked(b))
    }

    /// Pops the terminating vertex from the path.
    pub fn pop(&mut self) -> Option<ArcKey> {
        if self.tail.len() > 1 {
            Some(self.pop_unchecked())
        }
        else {
            None
        }
    }

    /// Exchanges the terminating vertex of the path.
    ///
    /// Unlike `pop`, this function allows an existing path's originating arc
    /// to be changed by exchanging the destination vertex.
    pub fn pop_swap(&mut self, destination: Selector<VertexKey>) -> Option<ArcKey> {
        if !self.tail.is_empty() {
            // This pop operation may exhaust the tail and must be followed by
            // a push.
            let ab = self.pop_unchecked();
            let (_, b) = ab.into();
            match self.push(destination) {
                Ok(ab) => Some(ab),
                _ => {
                    // Restore the original path.
                    self.push_unchecked(b);
                    None
                }
            }
        }
        else {
            None
        }
    }

    /// Gets an iterator over the keys of the vertices in the path.
    pub fn keys(&self) -> impl Iterator<Item = &VertexKey> {
        let head = Some(&self.head);
        head.into_iter().chain(self.tail.iter())
    }

    /// Gets the initiating vertex of the path.
    pub fn first(&self) -> VertexKey {
        self.head
    }

    /// Gets the terminating vertex of the path.
    pub fn last(&self) -> VertexKey {
        self.tail.iter().cloned().last().expect("path tail empty")
    }

    /// Gets an iterator over the vertices in the path.
    pub fn vertices(&self) -> impl Iterator<Item = VertexView<&M::Target, G>> {
        let storage = self.storage.reborrow();
        self.keys()
            .cloned()
            .map(move |key| (key, storage).into_view().expect_consistent())
    }

    /// Gets an iterator over the arcs in the path.
    pub fn arcs(&self) -> impl Iterator<Item = ArcView<&M::Target, G>> {
        // Get the outgoing arc of each vertex, but skip the terminating
        // vertex.
        self.vertices()
            .tuple_windows()
            .map(|(vertex, _)| vertex.into_outgoing_arc())
    }

    /// Returns `true` if the path is open.
    ///
    /// An _open path_ is a path that does **not** form a loop.
    pub fn is_open(&self) -> bool {
        !self.is_closed()
    }

    /// Returns `true` if the path is closed.
    ///
    /// A _closed path_ is a path that forms a loop by starting and ending at
    /// the same vertex. Note that this exludes paths that self-intersect and
    /// include arcs that do not participate in loops. `PathView` disallows
    /// such paths.
    pub fn is_closed(&self) -> bool {
        self.first() == self.last()
    }

    fn push_unchecked(&mut self, b: VertexKey) -> ArcKey {
        let a = self.last();
        self.tail.insert(b);
        (a, b).into()
    }

    fn pop_unchecked(&mut self) -> ArcKey {
        let a = self.head;
        let b = self.tail.pop().expect("path tail empty");
        (a, b).into()
    }
}

impl<'a, M, G> PathView<&'a mut M, G>
where
    M: 'a
        + AsStorage<ArcPayload<G>>
        + AsStorage<VertexPayload<G>>
        + AsStorageMut<ArcPayload<G>>
        + AsStorageMut<VertexPayload<G>>
        + Consistent,
    G: 'a + GraphGeometry,
{
    /// Converts a mutable view into an immutable view.
    ///
    /// This is useful when mutations are not (or no longer) needed and mutual
    /// access is desired.
    pub fn into_ref(self) -> PathView<&'a M, G> {
        let PathView {
            head,
            tail,
            storage,
            ..
        } = self;
        PathView {
            head,
            tail,
            storage: &*storage,
            phantom: PhantomData,
        }
    }
}

// TODO: Do not implement `FromKeyedSource`. Instead, provide an
//       explicit/inherent mechanism to construct paths and report errors.
impl<I, M, G> FromKeyedSource<(I, M)> for PathView<M, G>
where
    I: IntoIterator,
    I::Item: Borrow<VertexKey>,
    M: Reborrow,
    M::Target: AsStorage<ArcPayload<G>> + AsStorage<VertexPayload<G>> + Consistent,
    G: GraphGeometry,
{
    fn from_keyed_source(source: (I, M)) -> Option<Self> {
        let (keys, storage) = source;
        let mut keys = keys.into_iter().map(|key| *key.borrow());
        let head = keys.next()?;
        let tail = keys.next()?;
        let mut path = PathView {
            head,
            tail: indexset![tail],
            storage,
            phantom: PhantomData,
        };
        for key in keys {
            path.push(Selector::ByKey(key)).ok()?;
        }
        Some(path)
    }
}

impl<M, G> PartialEq for PathView<M, G>
where
    M: Reborrow,
    M::Target: AsStorage<ArcPayload<G>> + AsStorage<VertexPayload<G>> + Consistent,
    G: GraphGeometry,
{
    fn eq(&self, other: &Self) -> bool {
        let keys = |path: &Self| path.arcs().keys().collect::<HashSet<_>>();
        keys(self) == keys(other)
    }
}

#[cfg(test)]
mod tests {}
<commit_msg>Emit views instead of keys in `PathView`.<commit_after>use fool::BoolExt as _;
use indexmap::{indexset, IndexSet};
use itertools::Itertools;
use std::borrow::Borrow;
use std::collections::HashSet;
use std::marker::PhantomData;

use crate::graph::borrow::Reborrow;
use crate::graph::geometry::GraphGeometry;
use crate::graph::mutation::Consistent;
use crate::graph::storage::alias::*;
use crate::graph::storage::key::{ArcKey, VertexKey};
use crate::graph::storage::payload::{ArcPayload, VertexPayload};
use crate::graph::storage::{AsStorage, AsStorageMut};
use crate::graph::view::edge::ArcView;
use crate::graph::view::vertex::VertexView;
use crate::graph::view::{FromKeyedSource, IntoView};
use crate::graph::{GraphError, OptionExt as _, Selector};
use crate::IteratorExt as _;

// TODO: It would probably better for `PathView` to behave as a double-ended
//       queue. That would avoid the need for `pop_swap` and allow paths to be
//       re-rooted (the initiating vertex could be changed). This would not
//       work well with `IndexSet`.

/// View of a path in a graph.
///
/// Provides a representation of **non-intersecting** paths in a graph. A path
/// is conceptually an ordered set of vertices that are joined by arcs. A path
/// over vertices $A$, $B$, and $C$ is notated $\overrightarrow{\\{A, B,
/// C\\}}$.
///
/// Paths have no associated payload and do not directly expose geometry
/// (`PathView` does not implement `Deref` or expose a `geometry` field). See
/// the module documentation for more information about topological views.
#[derive(Clone)]
pub struct PathView<M, G>
where
    M: Reborrow,
    M::Target: AsStorage<ArcPayload<G>> + AsStorage<VertexPayload<G>> + Consistent,
    G: GraphGeometry,
{
    // Paths are represented using a head and tail, where the head is the
    // initiating vertex key and the tail is an ordered set of vertex keys. It
    // is possible for the first and last (that is, the head and terminating
    // element of the tail) to be the same vertex key, in which case the path
    // is closed.
    head: VertexKey,
    tail: IndexSet<VertexKey>,
    storage: M,
    phantom: PhantomData<G>,
}

impl<M, G> PathView<M, G>
where
    M: Reborrow,
    M::Target: AsStorage<ArcPayload<G>> + AsStorage<VertexPayload<G>> + Consistent,
    G: GraphGeometry,
{
    fn keys(&self) -> impl Iterator<Item = &VertexKey> {
        let head = Some(&self.head);
        head.into_iter().chain(self.tail.iter())
    }

    fn span(&self) -> (VertexKey, VertexKey) {
        (
            self.head,
            self.tail.iter().cloned().last().expect("path tail empty"),
        )
    }

    /// Pushes a vertex onto the path.
    pub fn push(&mut self, destination: Selector<VertexKey>) -> Result<ArcKey, GraphError> {
        self.is_open()
            .ok_or_else(|| GraphError::TopologyMalformed)?;
        let (a, _) = self.span();
        let b = match destination {
            Selector::ByKey(b) => {
                self.storage
                    .reborrow()
                    .as_vertex_storage()
                    .contains_key(&b)
                    .ok_or_else(|| GraphError::TopologyNotFound)?;
                self.storage
                    .reborrow()
                    .as_arc_storage()
                    .contains_key(&(a, b).into())
                    .ok_or_else(|| GraphError::TopologyMalformed)?;
                b
            }
            Selector::ByIndex(index) => {
                let storage = self.storage.reborrow();
                let vertex = VertexView::from_keyed_source((a, storage)).expect_consistent();
                let vertex = vertex
                    .neighboring_vertices()
                    .nth(index)
                    .ok_or_else(|| GraphError::TopologyNotFound)?;
                vertex.key()
            }
        };
        // Do not allow intersections unless they form a loop with the first
        // vertex in the path.
        //
        // Note that resolving the key `b` above already implicitly prohibits
        // `a == b`, so there is no need to test that here.
        (!self.tail.contains(&b)).ok_or_else(|| GraphError::TopologyMalformed)?;
        Ok(self.push_unchecked(b))
    }

    /// Pops the terminating vertex from the path.
    pub fn pop(&mut self) -> Option<ArcKey> {
        if self.tail.len() > 1 {
            Some(self.pop_unchecked())
        }
        else {
            None
        }
    }

    /// Exchanges the terminating vertex of the path.
    ///
    /// Unlike `pop`, this function allows an existing path's originating arc
    /// to be changed by exchanging the destination vertex.
    pub fn pop_swap(&mut self, destination: Selector<VertexKey>) -> Option<ArcKey> {
        if !self.tail.is_empty() {
            // This pop operation may exhaust the tail and must be followed by
            // a push.
            let ab = self.pop_unchecked();
            let (_, b) = ab.into();
            match self.push(destination) {
                Ok(ab) => Some(ab),
                _ => {
                    // Restore the original path.
                    self.push_unchecked(b);
                    None
                }
            }
        }
        else {
            None
        }
    }

    /// Gets the initiating vertex of the path.
    pub fn first(&self) -> VertexView<&M::Target, G> {
        let (key, _) = self.span();
        let storage = self.storage.reborrow();
        (key, storage).into_view().expect_consistent()
    }

    /// Gets the terminating vertex of the path.
    pub fn last(&self) -> VertexView<&M::Target, G> {
        let (_, key) = self.span();
        let storage = self.storage.reborrow();
        (key, storage).into_view().expect_consistent()
    }

    /// Gets an iterator over the vertices in the path.
    pub fn vertices(&self) -> impl Iterator<Item = VertexView<&M::Target, G>> {
        let storage = self.storage.reborrow();
        self.keys()
            .cloned()
            .map(move |key| (key, storage).into_view().expect_consistent())
    }

    /// Gets an iterator over the arcs in the path.
    pub fn arcs(&self) -> impl Iterator<Item = ArcView<&M::Target, G>> {
        // Get the outgoing arc of each vertex, but skip the terminating
        // vertex.
        self.vertices()
            .tuple_windows()
            .map(|(vertex, _)| vertex.into_outgoing_arc())
    }

    /// Returns `true` if the path is open.
    ///
    /// An _open path_ is a path that does **not** form a loop.
    pub fn is_open(&self) -> bool {
        !self.is_closed()
    }

    /// Returns `true` if the path is closed.
    ///
    /// A _closed path_ is a path that forms a loop by starting and ending at
    /// the same vertex. Note that this exludes paths that self-intersect and
    /// include arcs that do not participate in loops. `PathView` disallows
    /// such paths.
    pub fn is_closed(&self) -> bool {
        let (a, b) = self.span();
        a == b
    }

    fn push_unchecked(&mut self, b: VertexKey) -> ArcKey {
        let (_, a) = self.span();
        self.tail.insert(b);
        (a, b).into()
    }

    fn pop_unchecked(&mut self) -> ArcKey {
        let a = self.head;
        let b = self.tail.pop().expect("path tail empty");
        (a, b).into()
    }
}

impl<'a, M, G> PathView<&'a mut M, G>
where
    M: 'a
        + AsStorage<ArcPayload<G>>
        + AsStorage<VertexPayload<G>>
        + AsStorageMut<ArcPayload<G>>
        + AsStorageMut<VertexPayload<G>>
        + Consistent,
    G: 'a + GraphGeometry,
{
    /// Converts a mutable view into an immutable view.
    ///
    /// This is useful when mutations are not (or no longer) needed and mutual
    /// access is desired.
    pub fn into_ref(self) -> PathView<&'a M, G> {
        let PathView {
            head,
            tail,
            storage,
            ..
        } = self;
        PathView {
            head,
            tail,
            storage: &*storage,
            phantom: PhantomData,
        }
    }
}

// TODO: Do not implement `FromKeyedSource`. Instead, provide an
//       explicit/inherent mechanism to construct paths and report errors.
impl<I, M, G> FromKeyedSource<(I, M)> for PathView<M, G>
where
    I: IntoIterator,
    I::Item: Borrow<VertexKey>,
    M: Reborrow,
    M::Target: AsStorage<ArcPayload<G>> + AsStorage<VertexPayload<G>> + Consistent,
    G: GraphGeometry,
{
    fn from_keyed_source(source: (I, M)) -> Option<Self> {
        let (keys, storage) = source;
        let mut keys = keys.into_iter().map(|key| *key.borrow());
        let head = keys.next()?;
        let tail = keys.next()?;
        let mut path = PathView {
            head,
            tail: indexset![tail],
            storage,
            phantom: PhantomData,
        };
        for key in keys {
            path.push(Selector::ByKey(key)).ok()?;
        }
        Some(path)
    }
}

impl<M, G> PartialEq for PathView<M, G>
where
    M: Reborrow,
    M::Target: AsStorage<ArcPayload<G>> + AsStorage<VertexPayload<G>> + Consistent,
    G: GraphGeometry,
{
    fn eq(&self, other: &Self) -> bool {
        let keys = |path: &Self| path.arcs().keys().collect::<HashSet<_>>();
        keys(self) == keys(other)
    }
}

#[cfg(test)]
mod tests {}
<|endoftext|>


<commit_before>use collision::{Aabb, Aabb3, Union};
use point_viewer::data_provider::DataProviderFactory;
use point_viewer::errors::*;
use point_viewer::iterator::{ParallelIterator, PointQuery};
use point_viewer::octree::Octree;
use point_viewer::{PointsBatch, NUM_POINTS_PER_BATCH};

pub struct PointCloudClient {
    octrees: Vec<Octree>,
    aabb: Aabb3<f64>,
    pub num_points_per_batch: usize,
    pub num_threads: usize,
    pub buffer_size: usize,
}

impl PointCloudClient {
    pub fn new(locations: &[String], data_provider_factory: DataProviderFactory) -> Result<Self> {
        let octrees = locations
            .iter()
            .map(|location| {
                data_provider_factory
                    .generate_data_provider(location)
                    .and_then(|provider| Octree::from_data_provider(provider))
            })
            .collect::<Result<Vec<Octree>>>()?;
        let mut aabb = Aabb3::zero();
        if let Some((first_octree, remaining_octrees)) = octrees.split_first() {
            aabb = *first_octree.bounding_box();
            for octree in remaining_octrees {
                aabb = aabb.union(octree.bounding_box());
            }
        }
        Ok(PointCloudClient {
            octrees,
            aabb,
            num_points_per_batch: NUM_POINTS_PER_BATCH,
            num_threads: num_cpus::get() - 1,
            buffer_size: 4,
        })
    }

    pub fn bounding_box(&self) -> &Aabb3<f64> {
        &self.aabb
    }

    pub fn for_each_point_data<F>(&self, point_location: &PointQuery, mut func: F) -> Result<()>
    where
        F: FnMut(PointsBatch) -> Result<()>,
    {
        let mut parallel_iterator = ParallelIterator::new(
            &self.octrees,
            point_location,
            self.num_points_per_batch,
            self.num_threads,
            self.buffer_size,
        );
        parallel_iterator.try_for_each_batch(&mut func)?;
        Ok(())
    }
}
<commit_msg>Point cloud client for s2 without bounding box. (#364)<commit_after>use collision::{Aabb, Aabb3, Union};
use point_viewer::data_provider::{DataProvider, DataProviderFactory};
use point_viewer::errors::*;
use point_viewer::iterator::{ParallelIterator, PointQuery};
use point_viewer::octree::Octree;
use point_viewer::s2_cells::S2Cells;
use point_viewer::{PointsBatch, NUM_POINTS_PER_BATCH};

enum PointClouds {
    Octrees(Vec<Octree>),
    S2Cells(Vec<S2Cells>),
}

pub struct PointCloudClient {
    point_clouds: PointClouds,
    aabb: Aabb3<f64>,
    pub num_points_per_batch: usize,
    pub num_threads: usize,
    pub buffer_size: usize,
}

impl PointCloudClient {
    pub fn new(locations: &[String], data_provider_factory: DataProviderFactory) -> Result<Self> {
        if locations.is_empty() {
            return Err("No locations specified for point cloud client.".into());
        }
        let data_providers = locations
            .iter()
            .map(|location| data_provider_factory.generate_data_provider(location))
            .collect::<Result<Vec<Box<dyn DataProvider>>>>()?;
        let point_clouds = if data_providers[0].meta_proto()?.has_octree() {
            PointClouds::Octrees(
                data_providers
                    .into_iter()
                    .map(|provider| Octree::from_data_provider(provider))
                    .collect::<Result<Vec<Octree>>>()?,
            )
        } else {
            PointClouds::S2Cells(
                data_providers
                    .into_iter()
                    .map(|provider| S2Cells::from_data_provider(provider))
                    .collect::<Result<Vec<S2Cells>>>()?,
            )
        };
        let mut aabb = Aabb3::zero();
        match &point_clouds {
            PointClouds::Octrees(octrees) => {
                if let Some((first_octree, remaining_octrees)) = octrees.split_first() {
                    aabb = *first_octree.bounding_box();
                    for octree in remaining_octrees {
                        aabb = aabb.union(octree.bounding_box());
                    }
                }
            }
            PointClouds::S2Cells(_s2_cells) => {
                // TODO(feuerste): Add bounding box to s2 meta.
                unimplemented!();
            }
        }

        Ok(PointCloudClient {
            point_clouds,
            aabb,
            num_points_per_batch: NUM_POINTS_PER_BATCH,
            num_threads: num_cpus::get() - 1,
            buffer_size: 4,
        })
    }

    pub fn bounding_box(&self) -> &Aabb3<f64> {
        &self.aabb
    }

    pub fn for_each_point_data<F>(&self, point_location: &PointQuery, mut func: F) -> Result<()>
    where
        F: FnMut(PointsBatch) -> Result<()>,
    {
        match &self.point_clouds {
            PointClouds::Octrees(octrees) => {
                let mut parallel_iterator = ParallelIterator::new(
                    octrees,
                    point_location,
                    self.num_points_per_batch,
                    self.num_threads,
                    self.buffer_size,
                );
                parallel_iterator.try_for_each_batch(&mut func)?;
            }
            PointClouds::S2Cells(s2_cells) => {
                let mut parallel_iterator = ParallelIterator::new(
                    s2_cells,
                    point_location,
                    self.num_points_per_batch,
                    self.num_threads,
                    self.buffer_size,
                );
                parallel_iterator.try_for_each_batch(&mut func)?;
            }
        }
        Ok(())
    }
}
<|endoftext|>