<commit_before>use cairo;
use core::ops::Range;

use crate::float_eq_cairo::ApproxEqCairo;

pub trait RectangleExt {
    fn new(x: f64, y: f64, width: f64, height: f64) -> cairo::Rectangle;
    fn from_size(width: f64, height: f64) -> cairo::Rectangle;
    fn is_empty(&self) -> bool;
    fn intersection(&self, rect: &cairo::Rectangle) -> Option<cairo::Rectangle>;
    fn union(&self, rect: &cairo::Rectangle) -> cairo::Rectangle;
    fn transform(&self, affine: &cairo::Matrix) -> cairo::Rectangle;
    fn outer(&self) -> cairo::Rectangle;
}

impl RectangleExt for cairo::Rectangle {
    fn new(x: f64, y: f64, width: f64, height: f64) -> cairo::Rectangle {
        cairo::Rectangle {
            x,
            y,
            width,
            height,
        }
    }

    fn from_size(width: f64, height: f64) -> cairo::Rectangle {
        cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width,
            height,
        }
    }

    fn is_empty(&self) -> bool {
        self.width.approx_eq_cairo(0.0) || self.height.approx_eq_cairo(0.0)
    }

    fn intersection(&self, rect: &cairo::Rectangle) -> Option<cairo::Rectangle> {
        let (x1, y1, x2, y2) = (
            self.x.max(rect.x),
            self.y.max(rect.y),
            (self.x + self.width).min(rect.x + rect.width),
            (self.y + self.height).min(rect.y + rect.height),
        );

        if x2 > x1 && y2 > y1 {
            Some(cairo::Rectangle {
                x: x1,
                y: y1,
                width: x2 - x1,
                height: y2 - y1,
            })
        } else {
            None
        }
    }

    fn union(&self, rect: &cairo::Rectangle) -> cairo::Rectangle {
        let (x1, y1, x2, y2) = (
            self.x.min(rect.x),
            self.y.min(rect.y),
            (self.x + self.width).max(rect.x + rect.width),
            (self.y + self.height).max(rect.y + rect.height),
        );

        cairo::Rectangle {
            x: x1,
            y: y1,
            width: x2 - x1,
            height: y2 - y1,
        }
    }

    fn transform(&self, affine: &cairo::Matrix) -> cairo::Rectangle {
        let points = vec![
            affine.transform_point(self.x, self.y),
            affine.transform_point(self.x + self.width, self.y),
            affine.transform_point(self.x, self.y + self.height),
            affine.transform_point(self.x + self.width, self.y + self.height),
        ];

        let (mut xmin, mut ymin, mut xmax, mut ymax) = {
            let (x, y) = points[0];

            (x, y, x, y)
        };

        for &(x, y) in points.iter().take(4).skip(1) {
            if x < xmin {
                xmin = x;
            }

            if x > xmax {
                xmax = x;
            }

            if y < ymin {
                ymin = y;
            }

            if y > ymax {
                ymax = y;
            }
        }

        cairo::Rectangle {
            x: xmin,
            y: ymin,
            width: xmax - xmin,
            height: ymax - ymin,
        }
    }

    fn outer(&self) -> cairo::Rectangle {
        let (x, y) = (self.x.floor(), self.y.floor());

        cairo::Rectangle {
            x,
            y,
            width: (self.x + self.width).ceil() - x,
            height: (self.y + self.height).ceil() - y,
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IRect {
    pub x0: i32,
    pub y0: i32,
    pub x1: i32,
    pub y1: i32,
}

impl IRect {
    #[inline]
    pub fn new(x0: i32, y0: i32, x1: i32, y1: i32) -> IRect {
        IRect { x0, y0, x1, y1 }
    }

    #[inline]
    pub fn from_size(w: i32, h: i32) -> IRect {
        IRect {
            x0: 0,
            y0: 0,
            x1: w,
            y1: h,
        }
    }

    #[inline]
    pub fn x_range(&self) -> Range<i32> {
        self.x0..self.x1
    }

    #[inline]
    pub fn y_range(&self) -> Range<i32> {
        self.y0..self.y1
    }

    /// Returns true if the `IRect` contains the given coordinates.
    #[inline]
    pub fn contains(self, x: i32, y: i32) -> bool {
        x >= self.x0 && x < self.x1 && y >= self.y0 && y < self.y1
    }

    /// Returns an `IRect` scaled by the given amounts.
    ///
    /// The returned `IRect` encompasses all, even partially covered, pixels after the scaling.
    #[inline]
    pub fn scale(self, x: f64, y: f64) -> IRect {
        IRect {
            x0: (f64::from(self.x0) * x).floor() as i32,
            y0: (f64::from(self.y0) * y).floor() as i32,
            x1: (f64::from(self.x1) * x).ceil() as i32,
            y1: (f64::from(self.y1) * y).ceil() as i32,
        }
    }

    /// Returns an `IRect` translated by the given amounts.
    #[inline]
    pub fn translate(&self, by: (i32, i32)) -> IRect {
        IRect {
            x0: self.x0 + by.0,
            y0: self.y0 + by.1,
            x1: self.x1 + by.0,
            y1: self.y1 + by.1,
        }
    }

    #[inline]
    pub fn intersection(&self, rect: &Self) -> Option<IRect> {
        let (x0, y0, x1, y1) = (
            self.x0.max(rect.x0),
            self.y0.max(rect.y0),
            self.x1.min(rect.x1),
            self.y1.min(rect.y1),
        );

        if x1 > x0 && y1 > y0 {
            Some(IRect { x0, y0, x1, y1 })
        } else {
            None
        }
    }
}

impl From<cairo::Rectangle> for IRect {
    #[inline]
    fn from(
        cairo::Rectangle {
            x,
            y,
            width,
            height,
        }: cairo::Rectangle,
    ) -> Self {
        Self {
            x0: x.floor() as i32,
            y0: y.floor() as i32,
            x1: (x + width).ceil() as i32,
            y1: (y + height).ceil() as i32,
        }
    }
}

impl From<IRect> for cairo::Rectangle {
    #[inline]
    fn from(IRect { x0, y0, x1, y1 }: IRect) -> Self {
        Self {
            x: f64::from(x0),
            y: f64::from(y0),
            width: f64::from(x1 - x0),
            height: f64::from(y1 - y0),
        }
    }
}

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

    #[test]
    fn empty_rect() {
        let empty = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 0.0,
            height: 0.0,
        };
        let not_empty = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };

        assert!(empty.is_empty());
        assert!(!not_empty.is_empty());
    }

    #[test]
    fn intersect_rects() {
        let r1 = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 4.14,
            height: 4.14,
        };
        let r2 = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };
        let r3 = cairo::Rectangle {
            x: 10.0,
            y: 10.0,
            width: 3.14,
            height: 3.14,
        };

        let r = r1.intersection(&r2).unwrap();
        assert_approx_eq_cairo!(0.42_f64, r.x);
        assert_approx_eq_cairo!(0.42_f64, r.y);
        assert_approx_eq_cairo!(2.94_f64, r.width);
        assert_approx_eq_cairo!(2.94_f64, r.height);

        let r = r1.intersection(&r3);
        assert!(r.is_none());
    }

    #[test]
    fn union_rects() {
        let r1 = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 4.14,
            height: 4.14,
        };
        let r2 = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };

        let r = r1.union(&r2);
        assert_approx_eq_cairo!(0.22_f64, r.x);
        assert_approx_eq_cairo!(0.22_f64, r.y);
        assert_approx_eq_cairo!(4.34_f64, r.width);
        assert_approx_eq_cairo!(4.34_f64, r.height);
    }

    #[test]
    fn transform_rect() {
        let r = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 3.14,
            height: 3.14,
        };

        let m = cairo::Matrix::identity();
        let tr = r.transform(&m);
        assert_eq!(tr, r);

        let m = cairo::Matrix::new(2.0, 0.0, 0.0, 2.0, 1.5, 1.5);
        let tr = r.transform(&m);
        assert_approx_eq_cairo!(2.34_f64, tr.x);
        assert_approx_eq_cairo!(2.34_f64, tr.y);
        assert_approx_eq_cairo!(6.28_f64, tr.width);
        assert_approx_eq_cairo!(6.28_f64, tr.height);
    }

    #[test]
    fn outer_rect() {
        let r = cairo::Rectangle {
            x: 1.42,
            y: 1.42,
            width: 3.14,
            height: 3.14,
        };

        let or = r.outer();
        assert_eq!(1.0, or.x);
        assert_eq!(1.0, or.y);
        assert_eq!(4.0, or.width);
        assert_eq!(4.0, or.height);
    }
}
<commit_msg>rect: add translate method<commit_after>use cairo;
use core::ops::Range;

use crate::float_eq_cairo::ApproxEqCairo;

pub trait RectangleExt {
    fn new(x: f64, y: f64, width: f64, height: f64) -> cairo::Rectangle;
    fn from_size(width: f64, height: f64) -> cairo::Rectangle;
    fn is_empty(&self) -> bool;
    fn intersection(&self, rect: &cairo::Rectangle) -> Option<cairo::Rectangle>;
    fn union(&self, rect: &cairo::Rectangle) -> cairo::Rectangle;
    fn transform(&self, affine: &cairo::Matrix) -> cairo::Rectangle;
    fn translate(&self, by: (f64, f64)) -> cairo::Rectangle;
    fn outer(&self) -> cairo::Rectangle;
}

impl RectangleExt for cairo::Rectangle {
    fn new(x: f64, y: f64, width: f64, height: f64) -> cairo::Rectangle {
        cairo::Rectangle {
            x,
            y,
            width,
            height,
        }
    }

    fn from_size(width: f64, height: f64) -> cairo::Rectangle {
        cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width,
            height,
        }
    }

    fn is_empty(&self) -> bool {
        self.width.approx_eq_cairo(0.0) || self.height.approx_eq_cairo(0.0)
    }

    fn intersection(&self, rect: &cairo::Rectangle) -> Option<cairo::Rectangle> {
        let (x1, y1, x2, y2) = (
            self.x.max(rect.x),
            self.y.max(rect.y),
            (self.x + self.width).min(rect.x + rect.width),
            (self.y + self.height).min(rect.y + rect.height),
        );

        if x2 > x1 && y2 > y1 {
            Some(cairo::Rectangle {
                x: x1,
                y: y1,
                width: x2 - x1,
                height: y2 - y1,
            })
        } else {
            None
        }
    }

    fn union(&self, rect: &cairo::Rectangle) -> cairo::Rectangle {
        let (x1, y1, x2, y2) = (
            self.x.min(rect.x),
            self.y.min(rect.y),
            (self.x + self.width).max(rect.x + rect.width),
            (self.y + self.height).max(rect.y + rect.height),
        );

        cairo::Rectangle {
            x: x1,
            y: y1,
            width: x2 - x1,
            height: y2 - y1,
        }
    }

    fn transform(&self, affine: &cairo::Matrix) -> cairo::Rectangle {
        let points = vec![
            affine.transform_point(self.x, self.y),
            affine.transform_point(self.x + self.width, self.y),
            affine.transform_point(self.x, self.y + self.height),
            affine.transform_point(self.x + self.width, self.y + self.height),
        ];

        let (mut xmin, mut ymin, mut xmax, mut ymax) = {
            let (x, y) = points[0];

            (x, y, x, y)
        };

        for &(x, y) in points.iter().take(4).skip(1) {
            if x < xmin {
                xmin = x;
            }

            if x > xmax {
                xmax = x;
            }

            if y < ymin {
                ymin = y;
            }

            if y > ymax {
                ymax = y;
            }
        }

        cairo::Rectangle {
            x: xmin,
            y: ymin,
            width: xmax - xmin,
            height: ymax - ymin,
        }
    }

    fn translate(&self, by: (f64, f64)) -> cairo::Rectangle {
        cairo::Rectangle {
            x: self.x + by.0,
            y: self.y + by.1,
            width: self.width,
            height: self.height,
        }
    }

    fn outer(&self) -> cairo::Rectangle {
        let (x, y) = (self.x.floor(), self.y.floor());

        cairo::Rectangle {
            x,
            y,
            width: (self.x + self.width).ceil() - x,
            height: (self.y + self.height).ceil() - y,
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IRect {
    pub x0: i32,
    pub y0: i32,
    pub x1: i32,
    pub y1: i32,
}

impl IRect {
    #[inline]
    pub fn new(x0: i32, y0: i32, x1: i32, y1: i32) -> IRect {
        IRect { x0, y0, x1, y1 }
    }

    #[inline]
    pub fn from_size(w: i32, h: i32) -> IRect {
        IRect {
            x0: 0,
            y0: 0,
            x1: w,
            y1: h,
        }
    }

    #[inline]
    pub fn x_range(&self) -> Range<i32> {
        self.x0..self.x1
    }

    #[inline]
    pub fn y_range(&self) -> Range<i32> {
        self.y0..self.y1
    }

    /// Returns true if the `IRect` contains the given coordinates.
    #[inline]
    pub fn contains(self, x: i32, y: i32) -> bool {
        x >= self.x0 && x < self.x1 && y >= self.y0 && y < self.y1
    }

    /// Returns an `IRect` scaled by the given amounts.
    ///
    /// The returned `IRect` encompasses all, even partially covered, pixels after the scaling.
    #[inline]
    pub fn scale(self, x: f64, y: f64) -> IRect {
        IRect {
            x0: (f64::from(self.x0) * x).floor() as i32,
            y0: (f64::from(self.y0) * y).floor() as i32,
            x1: (f64::from(self.x1) * x).ceil() as i32,
            y1: (f64::from(self.y1) * y).ceil() as i32,
        }
    }

    /// Returns an `IRect` translated by the given amounts.
    #[inline]
    pub fn translate(&self, by: (i32, i32)) -> IRect {
        IRect {
            x0: self.x0 + by.0,
            y0: self.y0 + by.1,
            x1: self.x1 + by.0,
            y1: self.y1 + by.1,
        }
    }

    #[inline]
    pub fn intersection(&self, rect: &Self) -> Option<IRect> {
        let (x0, y0, x1, y1) = (
            self.x0.max(rect.x0),
            self.y0.max(rect.y0),
            self.x1.min(rect.x1),
            self.y1.min(rect.y1),
        );

        if x1 > x0 && y1 > y0 {
            Some(IRect { x0, y0, x1, y1 })
        } else {
            None
        }
    }
}

impl From<cairo::Rectangle> for IRect {
    #[inline]
    fn from(
        cairo::Rectangle {
            x,
            y,
            width,
            height,
        }: cairo::Rectangle,
    ) -> Self {
        Self {
            x0: x.floor() as i32,
            y0: y.floor() as i32,
            x1: (x + width).ceil() as i32,
            y1: (y + height).ceil() as i32,
        }
    }
}

impl From<IRect> for cairo::Rectangle {
    #[inline]
    fn from(IRect { x0, y0, x1, y1 }: IRect) -> Self {
        Self {
            x: f64::from(x0),
            y: f64::from(y0),
            width: f64::from(x1 - x0),
            height: f64::from(y1 - y0),
        }
    }
}

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

    #[test]
    fn empty_rect() {
        let empty = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 0.0,
            height: 0.0,
        };
        let not_empty = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };

        assert!(empty.is_empty());
        assert!(!not_empty.is_empty());
    }

    #[test]
    fn intersect_rects() {
        let r1 = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 4.14,
            height: 4.14,
        };
        let r2 = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };
        let r3 = cairo::Rectangle {
            x: 10.0,
            y: 10.0,
            width: 3.14,
            height: 3.14,
        };

        let r = r1.intersection(&r2).unwrap();
        assert_approx_eq_cairo!(0.42_f64, r.x);
        assert_approx_eq_cairo!(0.42_f64, r.y);
        assert_approx_eq_cairo!(2.94_f64, r.width);
        assert_approx_eq_cairo!(2.94_f64, r.height);

        let r = r1.intersection(&r3);
        assert!(r.is_none());
    }

    #[test]
    fn union_rects() {
        let r1 = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 4.14,
            height: 4.14,
        };
        let r2 = cairo::Rectangle {
            x: 0.22,
            y: 0.22,
            width: 3.14,
            height: 3.14,
        };

        let r = r1.union(&r2);
        assert_approx_eq_cairo!(0.22_f64, r.x);
        assert_approx_eq_cairo!(0.22_f64, r.y);
        assert_approx_eq_cairo!(4.34_f64, r.width);
        assert_approx_eq_cairo!(4.34_f64, r.height);
    }

    #[test]
    fn transform_rect() {
        let r = cairo::Rectangle {
            x: 0.42,
            y: 0.42,
            width: 3.14,
            height: 3.14,
        };

        let m = cairo::Matrix::identity();
        let tr = r.transform(&m);
        assert_eq!(tr, r);

        let m = cairo::Matrix::new(2.0, 0.0, 0.0, 2.0, 1.5, 1.5);
        let tr = r.transform(&m);
        assert_approx_eq_cairo!(2.34_f64, tr.x);
        assert_approx_eq_cairo!(2.34_f64, tr.y);
        assert_approx_eq_cairo!(6.28_f64, tr.width);
        assert_approx_eq_cairo!(6.28_f64, tr.height);
    }

    #[test]
    fn outer_rect() {
        let r = cairo::Rectangle {
            x: 1.42,
            y: 1.42,
            width: 3.14,
            height: 3.14,
        };

        let or = r.outer();
        assert_eq!(1.0, or.x);
        assert_eq!(1.0, or.y);
        assert_eq!(4.0, or.width);
        assert_eq!(4.0, or.height);
    }
}
<|endoftext|>


<commit_before>extern crate gcc;
extern crate pkg_config;

use std::process::Command;
use std::path::Path;
use std::env;

fn main() {
    let out_dir_str = env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(&out_dir_str);

    match pkg_config::find_library("mad") {
        Ok(_) => return,
        Err(..) => {}
    };

    if cfg!(windows) {
    panic!("Building libmad on Windows not implemented yet. Please install libmad manually.");
    }
    match env::set_current_dir("libmad-src") {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    match Command::new("mkdir").arg("temp").output() {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    match Command::new("tar").arg("-xzf")
                             .arg("libmad-0.15.1b.patched.tar.gz")
                             .arg("-C")
                             .arg("temp")
                             .output() {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    match env::set_current_dir("temp/libmad-0.15.1b/") {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    gcc::Config::new()
                .file("bit.c")
                .file("decoder.c")
                .file("fixed.c")
                .file("frame.c")
                .file("huffman.c")
                .file("layer3.c")
                .file("layer12.c")
                .file("stream.c")
                .file("synth.c")
                .file("timer.c")
                .file("version.c")
                .define("FPM_DEFAULT", None)
                .compile("libmad.a");

    match env::set_current_dir("../..") {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    match Command::new("rm").arg("-rf").arg("temp").output() {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    let out_str = out_dir.to_str().unwrap();
    println!("cargo:rustc-flags=-L native={}/lib -l static=mad", out_str);
    println!("cargo:rustdoc-flags=-L native={}/lib -l static=mad", out_str);
}
<commit_msg>Switched from gcc to manual build for now<commit_after>extern crate gcc;
extern crate pkg_config;

use std::process::Command;
use std::path::Path;
use std::env;

fn main() {
    let out_dir_str = env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(&out_dir_str);

    match pkg_config::find_library("mad") {
        Ok(_) => return,
        Err(..) => {}
    };

    if cfg!(windows) {
    panic!("Building libmad on Windows not implemented yet. Please install libmad manually.");
    }

    match env::set_current_dir("libmad-src") {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    match Command::new("mkdir").arg("temp").output() {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    match Command::new("tar").arg("-xzf")
                             .arg("libmad-0.15.1b.patched.tar.gz")
                             .arg("-C")
                             .arg("temp")
                             .output() {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    match env::set_current_dir("temp/libmad-0.15.1b/") {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    Command::new("./configure")
        .args(&["--disable-shared", "--enable-static"]) // Only build static lib
        .args(&["--prefix", out_dir.to_str().unwrap()]) // Install on the outdir
        .arg("--with-pic") // Build position-independent code (required by Rust)
        .output()
        .unwrap();

    match Command::new("make").output() {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    match Command::new("make").arg("install").output() {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    match env::set_current_dir("../..") {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    match Command::new("rm").arg("-rf").arg("temp").output() {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    }

    let out_str = out_dir.to_str().unwrap();
    println!("cargo:rustc-flags=-L native={}/lib -l static=mad", out_str);
    println!("cargo:rustdoc-flags=-L native={}/lib -l static=mad", out_str);
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate serde_json;

use request;

pub use types::{Account, CreateAccountResponse, EditAccountResponse};

impl Account {
    pub fn new(short_name: &str, author_name: &str, author_url: &str) -> Account {
        Account {
            short_name: short_name.to_string(),
            author_name: author_name.to_string(),
            author_url: author_url.to_string(),
            access_token: "".to_string(),
            auth_url: "".to_string(),
            page_count: 0,
        }
    }

    pub fn set_short_name(&mut self, short_name: &str) -> &mut Account {
        self.short_name = short_name.to_string();
        self
    }

    pub fn set_author_name(&mut self, author_name: &str) -> &mut Account {
        self.author_name = author_name.to_string();
        self
    }

    pub fn set_author_url(&mut self, author_url: &str) -> &mut Account {
        self.author_url = author_url.to_string();
        self
    }

    pub fn set_auth_url(&mut self, auth_url: &str) -> &mut Account {
        self.auth_url = auth_url.to_string();
        self
    }

    pub fn set_page_count(&mut self, page_count: &i32) -> &mut Account {
        self.page_count = page_count.clone();
        self
    }

    pub fn set_access_token(&mut self, access_token: &str) -> &mut Account {
        self.access_token = access_token.to_string();
        self
    }

    fn update(&mut self, new_acc: &Account) -> &mut Account {
        self.set_short_name(&new_acc.short_name);
        self.set_author_name(&new_acc.author_name);
        self.set_author_url(&new_acc.author_url);

        self
    }

    pub fn create_account(&mut self) -> Result<CreateAccountResponse, &str> {
        let url = format!(
            "https://api.telegra.ph/createAccount?short_name={}&author_name={}",
            self.short_name,
            self.author_name
        );
        let res_json = request::get(&url);
        let decoded: CreateAccountResponse = serde_json::from_str(&res_json).unwrap();

        self.set_access_token(&decoded.result.access_token)
            .set_auth_url(&decoded.result.auth_url);

        Ok(decoded)
    }

    pub fn edit_account_info(&mut self, acc: &Account) -> Result<EditAccountResponse, &str> {
        let url = String::from("https://api.telegra.ph/editAccountInfo?");
        let mut params: Vec<String> = vec![];

        let access_token = "access_token=".to_string() + &if acc.access_token.len() == 0 {
                self.access_token.clone()
            } else {
                acc.access_token.clone()
            };
        params.push(access_token);

        if acc.short_name.len() > 0 {
            let short_name = "short_name=".to_string() + &acc.short_name;
            params.push(short_name);
        }
        if acc.author_name.len() > 0 {
            let author_name = "author_name=".to_string() + &acc.author_name;
            params.push(author_name);
        }
        if acc.author_url.len() > 0 {
            let author_url = "author_url=".to_string() + &acc.author_url;
            params.push(author_url);
        }

        let url = url + &params.join("&");
        let res_json = request::get(&url);
        let decoded: EditAccountResponse = serde_json::from_str(&res_json).unwrap();

        self.update(&decoded.result);

        Ok(decoded)
    }

    pub fn get_account_info<'a>(&self, fields_list: &Vec<&str>) -> Result<EditAccountResponse, &'a str> {
        let fields = fields_list.iter()
            .map(|&field| "\"".to_string() + field + "\"")
            .collect::<Vec<String>>()
            .join(",");
        let fields = "[".to_string() + &fields + "]";
        let url = format!(
            "https://api.telegra.ph/getAccountInfo?access_token={}&fields={}",
            self.access_token,
            fields
        );
        let res_json = request::get(&url);
        let decoded: EditAccountResponse = serde_json::from_str(&res_json).unwrap();

        Ok(decoded)
    }

    pub fn revoke_access_token(&mut self) -> Result<EditAccountResponse, &str> {
        let url = format!(
            "https://api.telegra.ph/revokeAccessToken?access_token={}",
            self.access_token
        );
        let res_json = request::get(&url);
        let decoded: EditAccountResponse = serde_json::from_str(&res_json).unwrap();

        self.set_access_token(&decoded.result.access_token);

        Ok(decoded)
    }

}
<commit_msg>added create_page method<commit_after>extern crate hyper;
extern crate serde_json;

use request;

pub use types::*;

impl Account {
    pub fn new(short_name: &str, author_name: &str, author_url: &str) -> Account {
        Account {
            short_name: short_name.to_string(),
            author_name: author_name.to_string(),
            author_url: author_url.to_string(),
            access_token: "".to_string(),
            auth_url: "".to_string(),
            page_count: 0,
        }
    }

    pub fn set_short_name(&mut self, short_name: &str) -> &mut Account {
        self.short_name = short_name.to_string();
        self
    }

    pub fn set_author_name(&mut self, author_name: &str) -> &mut Account {
        self.author_name = author_name.to_string();
        self
    }

    pub fn set_author_url(&mut self, author_url: &str) -> &mut Account {
        self.author_url = author_url.to_string();
        self
    }

    pub fn set_auth_url(&mut self, auth_url: &str) -> &mut Account {
        self.auth_url = auth_url.to_string();
        self
    }

    pub fn set_page_count(&mut self, page_count: &i32) -> &mut Account {
        self.page_count = page_count.clone();
        self
    }

    pub fn set_access_token(&mut self, access_token: &str) -> &mut Account {
        self.access_token = access_token.to_string();
        self
    }

    fn update(&mut self, new_acc: &Account) -> &mut Account {
        self.set_short_name(&new_acc.short_name);
        self.set_author_name(&new_acc.author_name);
        self.set_author_url(&new_acc.author_url);

        self
    }

    pub fn create_account(&mut self) -> Result<CreateAccountResponse, &str> {
        let url = format!(
            "https://api.telegra.ph/createAccount?short_name={}&author_name={}",
            self.short_name,
            self.author_name
        );
        let res_json = request::get(&url);
        let decoded: CreateAccountResponse = serde_json::from_str(&res_json).unwrap();

        self.set_access_token(&decoded.result.access_token)
            .set_auth_url(&decoded.result.auth_url);

        Ok(decoded)
    }

    pub fn edit_account_info(&mut self, acc: &Account) -> Result<EditAccountResponse, &str> {
        let url = String::from("https://api.telegra.ph/editAccountInfo?");
        let mut params: Vec<String> = vec![];

        let access_token = "access_token=".to_string() + &if acc.access_token.len() == 0 {
                self.access_token.clone()
            } else {
                acc.access_token.clone()
            };
        params.push(access_token);

        if acc.short_name.len() > 0 {
            let short_name = "short_name=".to_string() + &acc.short_name;
            params.push(short_name);
        }
        if acc.author_name.len() > 0 {
            let author_name = "author_name=".to_string() + &acc.author_name;
            params.push(author_name);
        }
        if acc.author_url.len() > 0 {
            let author_url = "author_url=".to_string() + &acc.author_url;
            params.push(author_url);
        }

        let url = url + &params.join("&");
        let res_json = request::get(&url);
        let decoded: EditAccountResponse = serde_json::from_str(&res_json).unwrap();

        self.update(&decoded.result);

        Ok(decoded)
    }

    pub fn get_account_info<'a>(&self, fields_list: &Vec<&str>) -> Result<EditAccountResponse, &'a str> {
        let fields = fields_list.iter()
            .map(|&field| "\"".to_string() + field + "\"")
            .collect::<Vec<String>>()
            .join(",");
        let fields = "[".to_string() + &fields + "]";
        let url = format!(
            "https://api.telegra.ph/getAccountInfo?access_token={}&fields={}",
            self.access_token,
            fields
        );
        let res_json = request::get(&url);
        let decoded: EditAccountResponse = serde_json::from_str(&res_json).unwrap();

        Ok(decoded)
    }

    pub fn revoke_access_token(&mut self) -> Result<EditAccountResponse, &str> {
        let url = format!(
            "https://api.telegra.ph/revokeAccessToken?access_token={}",
            self.access_token
        );
        let res_json = request::get(&url);
        let decoded: EditAccountResponse = serde_json::from_str(&res_json).unwrap();

        self.set_access_token(&decoded.result.access_token);

        Ok(decoded)
    }

    pub fn create_page(&mut self, page: &Page, return_content: bool) -> Result<CreatePageResponse, &str> {
        let mut url = format!("https://api.telegra.ph/createPage?");
        let mut params: Vec<String> = vec![];

        params.push("access_token=".to_string() + &self.access_token);
        params.push("title=".to_string() + &page.title);
        params.push("content=".to_string() + &page.content.to_string());
        params.push("return_content=".to_string() + &return_content.to_string());

        url = url + &params.join("&");

        let res_json = request::get(&url);
        let decoded: CreatePageResponse = serde_json::from_str(&res_json).unwrap();

        Ok(decoded)
    }
}
<|endoftext|>


<commit_before>use std::str::Chars;

const NUMERICAL: [char; 11] = ['-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];

fn main() {
    let input = include_str!("day12.txt");

    let result = calculate(input);

    println!("{}", result);
}

fn calculate(input: &str) -> i32 {
    calculate_recursive(&mut input.chars())
}

fn calculate_recursive(input: &mut Chars) -> i32 {
    let mut reading_number = false;
    let mut buff = String::new();
    let mut total = 0;

    let mut red = Red::new();

    while let Some(c) = input.next() {
        red.input(c);

        if !red.check() {
            let mut stack = 1;
            // read until close current structure
            while let Some(c) = input.next() {
                if stack == 0 {
                    break
                } else if c == '{' {
                    stack += 1;
                } else if c == '}' {
                    stack -= 1;
                }
            }

            total = 0;
            break
        }

        if NUMERICAL.contains(&c) {
            reading_number = true;
            buff.push(c);
        } else if reading_number {
            reading_number = false;
            total += buff.parse().expect("Could not parse value");
            buff.clear();
        }

        if c == '{' {
            total += calculate_recursive(input);
        } else if c == '}' {
            return total
        }
    }

    total
}

struct Red {
    pub level: u32,
}

impl Red {
    fn new() -> Self {
        Red {
            level: 0,
        }
    }

    pub fn input(&mut self, c: char) {
        if self.level == 6 {
            return
        }

        if c == ':' && self.level == 0
            || c == '"' && self.level == 1
            || c == 'r' && self.level == 2
            || c == 'e' && self.level == 3
            || c == 'd' && self.level == 4
            || c == '"' && self.level == 5
        {
            self.level += 1;
        } else if self.level < 6 {
            self.level = 0;
        }
    }

    pub fn check(&self) -> bool {
        self.level < 5
    }
}

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

    #[test]
    fn test_1() {
        assert_eq!(6, calculate("[1,2,3]"));
    }

    #[test]
    fn test_2() {
        assert_eq!(6, calculate(r#"{"a":2,"b":4}"#));
    }

    #[test]
    fn test_3() {
        assert_eq!(3, calculate(r#"[[[3]]]"#));
    }

    #[test]
    fn test_4() {
        assert_eq!(3, calculate(r#"{"a":{"b":4},"c":-1}"#));
    }

    #[test]
    fn test_5() {
        assert_eq!(0, calculate(r#"{"a":[-1,1]}"#));
    }

    #[test]
    fn test_6() {
        assert_eq!(0, calculate(r#"[-1,{"a":1}]"#));
    }

    #[test]
    fn test_7() {
        assert_eq!(0, calculate(r#"[]"#));
    }

    #[test]
    fn test_8() {
        assert_eq!(0, calculate(r#"{}"#));
    }

    #[test]
    fn test_red_1() {
        assert_eq!(4, calculate(r#"[1,{"c":"red","b":2},3]"#));
    }

    #[test]
    fn test_red_2() {
        assert_eq!(0, calculate(r#"{"d":"red","e":[1,2,3,4],"f":5}"#));
    }

    #[test]
    fn test_red_3() {
        assert_eq!(0, calculate(r#"[1,"red",5]"#));
    }
}
<commit_msg>fix test for day 12 part 2<commit_after>use std::str::Chars;

const NUMERICAL: [char; 11] = ['-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];

fn main() {
    let input = include_str!("day12.txt");

    let result = calculate(input);

    println!("{}", result);
}

fn calculate(input: &str) -> i32 {
    calculate_recursive(&mut input.chars())
}

fn calculate_recursive(input: &mut Chars) -> i32 {
    let mut reading_number = false;
    let mut buff = String::new();
    let mut total = 0;

    let mut red = Red::new();

    while let Some(c) = input.next() {
        red.input(c);

        if !red.check() {
            let mut stack = 1;
            // read until close current structure
            while let Some(c) = input.next() {
                if stack == 0 {
                    break
                } else if c == '{' {
                    stack += 1;
                } else if c == '}' {
                    stack -= 1;
                }
            }

            total = 0;
            break
        }

        if NUMERICAL.contains(&c) {
            reading_number = true;
            buff.push(c);
        } else if reading_number {
            reading_number = false;
            total += buff.parse().expect("Could not parse value");
            buff.clear();
        }

        if c == '{' {
            total += calculate_recursive(input);
        } else if c == '}' {
            return total
        }
    }

    total
}

struct Red {
    pub level: u32,
}

impl Red {
    fn new() -> Self {
        Red {
            level: 0,
        }
    }

    pub fn input(&mut self, c: char) {
        if self.level == 6 {
            return
        }

        if c == ':' && self.level == 0
            || c == '"' && self.level == 1
            || c == 'r' && self.level == 2
            || c == 'e' && self.level == 3
            || c == 'd' && self.level == 4
            || c == '"' && self.level == 5
        {
            self.level += 1;
        } else if self.level < 6 {
            self.level = 0;
        }
    }

    pub fn check(&self) -> bool {
        self.level < 5
    }
}

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

    #[test]
    fn test_1() {
        assert_eq!(6, calculate("[1,2,3]"));
    }

    #[test]
    fn test_2() {
        assert_eq!(6, calculate(r#"{"a":2,"b":4}"#));
    }

    #[test]
    fn test_3() {
        assert_eq!(3, calculate(r#"[[[3]]]"#));
    }

    #[test]
    fn test_4() {
        assert_eq!(3, calculate(r#"{"a":{"b":4},"c":-1}"#));
    }

    #[test]
    fn test_5() {
        assert_eq!(0, calculate(r#"{"a":[-1,1]}"#));
    }

    #[test]
    fn test_6() {
        assert_eq!(0, calculate(r#"[-1,{"a":1}]"#));
    }

    #[test]
    fn test_7() {
        assert_eq!(0, calculate(r#"[]"#));
    }

    #[test]
    fn test_8() {
        assert_eq!(0, calculate(r#"{}"#));
    }

    #[test]
    fn test_red_1() {
        assert_eq!(4, calculate(r#"[1,{"c":"red","b":2},3]"#));
    }

    #[test]
    fn test_red_2() {
        assert_eq!(0, calculate(r#"{"d":"red","e":[1,2,3,4],"f":5}"#));
    }

    #[test]
    fn test_red_3() {
        assert_eq!(6, calculate(r#"[1,"red",5]"#));
    }
}
<|endoftext|>


<commit_before>#[allow(unused)]
pub mod response;
pub mod entity;
pub mod http;

use std;
use std::option::Option;
use std::result::Result;
use hyper;
use hyper::client;
use std::collections::HashMap;
use std::fmt::Debug;
use std::io::Read;
use serde_json;
use std::process::exit;

#[derive(Debug)]
pub struct Api {
    base_uri: &'static str,
    api_key: String,
    login_token: String,
    client: hyper::client::Client,
    user_agent: String,
}

#[allow(unused)]
impl Api {

    /// Create a new api client
    pub fn new(api_key: String) -> Api {
        let crates_version = &std::env::var("CARGO_PKG_VERSION")
            .unwrap_or("unknown".to_string());
        let crates_name = std::env::var("CARGO_PKG_NAME").
            unwrap_or("unknown".to_string());

        let ua = format!("libproxer-rust({}/v{})", crates_name, crates_version);

        Api {
            base_uri:    "http://proxer.me/api/v1/",
            api_key:     api_key,
            login_token: "None".to_string(),
            client:      hyper::client::Client::new(),
            user_agent:  ua,
        }
    }

    pub fn info_get_full_info(self, id: u32) -> Result<client::response::Response, hyper::Error> {
        use api::entity::response::*;
        let url = "info/fullentry";

        response::Response::new::<info::fullinfo::FullInfo>(self.http_req(url))
    }

    fn http_req(self, url: &str) -> Result<client::response::Response, hyper::Error> {
        let uri = self.base_uri.to_string()+url;
        let hyper_url = hyper::Url::parse(&uri).unwrap();
        header! {(ProxerApiKeyHeader, "proxer-api-key") => [String]}
        header! {(UserAgent, "User-Agent") => [String]}

        let mut headers = hyper::header::Headers::new();
        headers.set(ProxerApiKeyHeader(self.api_key));
        headers.set(ProxerApiKeyHeader(self.user_agent));

        self.client
            .post(hyper_url)
            .headers(headers)
            .send()
    }

    pub fn read_json(json: String) -> std::result::Result<serde_json::Value, serde_json::Error> {
        serde_json::from_str(&json)
    }
}

fn hashmap_to_encoded_url(params: HashMap<String, String>) -> String{
    "foobar".to_string()
}
<commit_msg>improve typing<commit_after>#[allow(unused)]
pub mod response;
pub mod entity;
pub mod http;

use std;
use std::option::Option;
use std::result::Result;
use hyper;
use hyper::client;
use std::collections::HashMap;
use std::fmt::Debug;
use std::io::Read;
use serde_json;
use std::process::exit;

#[derive(Debug)]
pub struct Api {
    base_uri: &'static str,
    api_key: String,
    login_token: String,
    client: hyper::client::Client,
    user_agent: String,
}

#[allow(unused)]
impl Api {

    /// Create a new api client
    pub fn new(api_key: String) -> Api {
        let crates_version = &std::env::var("CARGO_PKG_VERSION")
            .unwrap_or("unknown".to_string());
        let crates_name = std::env::var("CARGO_PKG_NAME").
            unwrap_or("unknown".to_string());

        let ua = format!("libproxer-rust({}/v{})", crates_name, crates_version);

        Api {
            base_uri:    "http://proxer.me/api/v1/",
            api_key:     api_key,
            login_token: "None".to_string(),
            client:      hyper::client::Client::new(),
            user_agent:  ua,
        }
    }

    pub fn info_get_full_info(self, id: u32) -> Result<client::response::Response, hyper::Error> {
        use api::entity::response::*;
        let url = "info/fullentry";

        response::Response::new::<info::fullinfo::FullInfo>(self.http_req(url))
    }

    fn http_req<T: ToString>(self, url: &str, data: T) -> Result<client::response::Response, hyper::Error> {
        let uri = self.base_uri.to_string()+url;
        let hyper_url = hyper::Url::parse(&uri).unwrap();

        let mut headers = hyper::header::Headers::new();
        header! {(ProxerApiKeyHeader, "proxer-api-key") => [String]}
        header! {(UserAgent, "User-Agent") => [String]}
        headers.set(ProxerApiKeyHeader(self.api_key));
        headers.set(UserAgent(self.user_agent));
        headers.set(hyper::header::ContentType::form_url_encoded());

        self.client
            .post(hyper_url)
            .headers(headers)
            .body(&data.to_string())
            .send()
    }

    pub fn read_json(json: String) -> std::result::Result<serde_json::Value, serde_json::Error> {
        serde_json::from_str(&json)
    }
}

fn hashmap_to_encoded_url(params: HashMap<String, String>) -> String{
    "foobar".to_string()
}
<|endoftext|>


<commit_before>extern crate robots;

use robots::actors::{Actor,ActorCell};
use std::sync::Mutex;
use std::any::Any;
use std::thread;
use std::time;
use super::super::gpioaccess::{DirectionProxied,PinProxyContract,PwmProxyContract};
use super::super::gpioaccess::proxyimpl::{PinProxy,PwmProxy};

#[derive(Copy, Clone, PartialEq,Debug)]
pub enum PinCommands {
	Blink(u64),
	Switch,
}

pub struct PinActor {
	pinproxy :  Mutex<PinProxy>,
}

impl Actor for PinActor {
	fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		if let Ok(_message) = Box::<Any>::downcast::<PinCommands>(_message){
			match *_message {
				PinCommands::Blink(times) => {
					let pin = self.pinproxy.lock().unwrap();
					match pin.export() {
						Ok(()) => {
							println!("Pin exported");
							for _ in 1..times {
								pin.set_direction(DirectionProxied::Out);
								pin.set_direction(DirectionProxied::High);
								thread::sleep(time::Duration::from_millis(400));
								pin.set_direction(DirectionProxied::Low);
								thread::sleep(time::Duration::from_millis(400));
								println!("Blink");
							}
							match pin.unexport() {
								Ok(()) => {
									println!("Pin unexported");
								}
								_ => {}
							}
						}
						_ => {}
					}
				},
				PinCommands::Switch => { }
			}
		}
	}
}

impl PinActor{
	pub fn new(pin_number: u64) -> PinActor {
		PinActor{ pinproxy : Mutex::new(PinProxy::new(pin_number)) }
	}
}

#[derive(Copy, Clone, PartialEq,Debug)]
pub enum PwmCommands {
	MoveToDegree(u16)
}

pub struct PwmActor {
	pwmproxy :  Result<Mutex<PwmProxy>,()>,
}

impl Actor for PwmActor {
	fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		println!("pwm received message");
		if let Ok(_message) = Box::<Any>::downcast::<PwmCommands>(_message){
			println!("pwm recognized command");
			match *_message {
				PwmCommands::MoveToDegree(degree) => {
					println!("pwm movetodegree");
					match self.pwmproxy {
						Ok(ref pwmproxyresult) =>
						{
							let pwm = pwmproxyresult.lock().unwrap();
							match pwm.export() {
								Ok(()) => {
									println!("Pwm exported");
									match pwm.set_period_ns(10_000_000)
									{
										Ok(()) => {
											println!("Pwm setting period");
											match pwm.enable(true)
											{
												Ok(()) => {
													println!("Pwm enable");
													for x in 1..10 {
														println!("Pwm {}",x);
														pwm.increase_to_max(1000, 20);
														pwm.decrease_to_minimum(1000, 20);
													}
													match pwm.enable(false)
													{
														Ok(()) => {
															println!("Pwm disable");
														}
														_ => println!("Pwm disabled failed")
													}
												}
												_ => println!("Pwm enabled failed")
											}
										}
										_ => println!("Pwm set period failed")
									}
									match pwm.unexport() {
										Ok(()) => {
											println!("Pwm unexported");
										}
										_ => println!("Pwm unexport failed")
									}
								}
								_ => println!("Pwm export failed")
							}
						}
						_ => println!("No Pwm")
					}

					println!("pwm done");
				}
			}
		}
	}
}

impl PwmActor{
	pub fn new(number: u32) -> PwmActor {
		match PwmProxy::new(0,number)
		{
			Ok(pwmproxy) =>  PwmActor{ pwmproxy : Ok(Mutex::new(pwmproxy)) },
			_ => PwmActor{ pwmproxy : Err(()) },
		}
	}
}<commit_msg>frequency<commit_after>extern crate robots;

use robots::actors::{Actor,ActorCell};
use std::sync::Mutex;
use std::any::Any;
use std::thread;
use std::time;
use super::super::gpioaccess::{DirectionProxied,PinProxyContract,PwmProxyContract};
use super::super::gpioaccess::proxyimpl::{PinProxy,PwmProxy};

#[derive(Copy, Clone, PartialEq,Debug)]
pub enum PinCommands {
	Blink(u64),
	Switch,
}

pub struct PinActor {
	pinproxy :  Mutex<PinProxy>,
}

impl Actor for PinActor {
	fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		if let Ok(_message) = Box::<Any>::downcast::<PinCommands>(_message){
			match *_message {
				PinCommands::Blink(times) => {
					let pin = self.pinproxy.lock().unwrap();
					match pin.export() {
						Ok(()) => {
							println!("Pin exported");
							for _ in 1..times {
								pin.set_direction(DirectionProxied::Out);
								pin.set_direction(DirectionProxied::High);
								thread::sleep(time::Duration::from_millis(400));
								pin.set_direction(DirectionProxied::Low);
								thread::sleep(time::Duration::from_millis(400));
								println!("Blink");
							}
							match pin.unexport() {
								Ok(()) => {
									println!("Pin unexported");
								}
								_ => {}
							}
						}
						_ => {}
					}
				},
				PinCommands::Switch => { }
			}
		}
	}
}

impl PinActor{
	pub fn new(pin_number: u64) -> PinActor {
		PinActor{ pinproxy : Mutex::new(PinProxy::new(pin_number)) }
	}
}

#[derive(Copy, Clone, PartialEq,Debug)]
pub enum PwmCommands {
	MoveToDegree(u16)
}

pub struct PwmActor {
	pwmproxy :  Result<Mutex<PwmProxy>,()>,
}

impl Actor for PwmActor {
	fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		println!("pwm received message");
		if let Ok(_message) = Box::<Any>::downcast::<PwmCommands>(_message){
			println!("pwm recognized command");
			match *_message {
				PwmCommands::MoveToDegree(degree) => {
					println!("pwm movetodegree");
					match self.pwmproxy {
						Ok(ref pwmproxyresult) =>
						{
							let pwm = pwmproxyresult.lock().unwrap();
							match pwm.export() {
								Ok(()) => {
									println!("Pwm exported");
									match pwm.set_period_ns(3_000_000)
									{
										Ok(()) => {
											println!("Pwm setting period");
											match pwm.enable(true)
											{
												Ok(()) => {
													println!("Pwm enable");
													for x in 1..10 {
														println!("Pwm {}",x);
														pwm.increase_to_max(1000, 20);
														pwm.decrease_to_minimum(1000, 20);
													}
													match pwm.enable(false)
													{
														Ok(()) => {
															println!("Pwm disable");
														}
														_ => println!("Pwm disabled failed")
													}
												}
												_ => println!("Pwm enabled failed")
											}
										}
										_ => println!("Pwm set period failed")
									}
									match pwm.unexport() {
										Ok(()) => {
											println!("Pwm unexported");
										}
										_ => println!("Pwm unexport failed")
									}
								}
								_ => println!("Pwm export failed")
							}
						}
						_ => println!("No Pwm")
					}

					println!("pwm done");
				}
			}
		}
	}
}

impl PwmActor{
	pub fn new(number: u32) -> PwmActor {
		match PwmProxy::new(0,number)
		{
			Ok(pwmproxy) =>  PwmActor{ pwmproxy : Ok(Mutex::new(pwmproxy)) },
			_ => PwmActor{ pwmproxy : Err(()) },
		}
	}
}<|endoftext|>


<commit_before>// Implementation adapted from Python version:
// https://github.com/commonsmachinery/blockhash-python/blob/e8b009d/blockhash.py
// Main site: http://blockhash.io
use image::{GenericImageView, Pixel};

use {BitSet, Image, HashBytes};

use std::cmp::Ordering;
use std::ops::AddAssign;
use std::mem;

const FLOAT_EQ_MARGIN: f32 = 0.001;

pub fn blockhash<I: Image, B: HashBytes>(img: &I, width: u32, height: u32) -> B {
    assert_eq!(width % 4, 0, "width must be multiple of 4");
    assert_eq!(height % 4, 0, "height must be multiple of 4");

    let (iwidth, iheight) = img.dimensions();

    // Skip the floating point math if it's unnecessary
    if iwidth % width == 0 && iheight % height == 0 {
        blockhash_fast(img, width, height)
    } else {
        blockhash_slow(img, width, height)
    }
}

macro_rules! gen_hash {
    ($imgty:ty, $valty:ty, $blocks: expr, $width:expr, $block_width:expr, $block_height:expr, $eq_fn:expr) => ({
        let channel_count = <<$imgty as GenericImageView>::Pixel as Pixel>::channel_count() as u32;

        let group_len = ($width * 4) as usize;

        let block_area = $block_width * $block_height;

        let cmp_factor = match channel_count {
            3 | 4 => 255u32 as $valty * 3u32 as $valty,
            2 | 1 => 255u32 as $valty,
            _ => panic!("Unrecognized channel count from Image: {}", channel_count),
        }
            * block_area
            / (2u32 as $valty);

        let medians: Vec<$valty> = $blocks.chunks(group_len).map(get_median).collect();

        BitSet::from_bools(
            $blocks.chunks(group_len).zip(medians)
            .flat_map(|(blocks, median)|
                blocks.iter().map(move |&block|
                    block > median ||
                        ($eq_fn(block, median) && median > cmp_factor)
                )
            )
        )
    })
}

//noinspection RsNeedlessLifetimes
// false positive
fn block_adder<'a, T: AddAssign + 'a>(blocks: &'a mut [T], width: u32) -> impl FnMut(u32, u32, T) + 'a {
    move |x, y, add| (blocks[(y as usize) * (width as usize) + (x as usize)] += add)
}

fn blockhash_slow<I: Image, B: HashBytes>(img: &I, hwidth: u32, hheight: u32) -> B {
    let mut blocks = vec![0f32; (hwidth * hheight) as usize];

    let (iwidth, iheight) = img.dimensions();

    // Block dimensions, in pixels
    let (block_width, block_height) = (iwidth as f32 / hwidth as f32, iheight as f32 / hheight as f32);

    img.foreach_pixel8(|x, y, px| {
        let mut add_to_block = block_adder(&mut blocks, hwidth);

        let px_sum = sum_px(px) as f32;

        let (x, y) = (x as f32, y as f32);

        let block_x = x / block_width;
        let block_y = y / block_height;

        let x_mod = x + 1. % block_width;
        let y_mod = y + 1. % block_height;

        // terminology is mostly arbitrary as long as we're consistent
        // if `x` evenly divides `block_height`, this weight will be 0
        // so we don't double the sum as `block_top` will equal `block_bottom`
        let weight_left = x_mod.fract();
        let weight_right = 1. - weight_left;
        let weight_top = y_mod.fract();
        let weight_bottom = 1. - weight_top;

        let block_left = block_x.floor() as u32;
        let block_top = block_y.floor() as u32;

        let block_right = if x_mod.trunc() == 0. {
            block_x.ceil() as u32
        } else {
            block_left
        };

        let block_bottom = if y_mod.trunc() == 0. {
            block_y.ceil() as u32
        } else {
            block_top
        };

        add_to_block(block_left, block_top, px_sum * weight_left * weight_top);
        add_to_block(block_left, block_bottom, px_sum * weight_left * weight_bottom);
        add_to_block(block_right, block_top, px_sum * weight_right * weight_top);
        add_to_block(block_right, block_bottom, px_sum * weight_right * weight_bottom);
    });

    gen_hash!(I, f32, blocks, hwidth, block_width, block_height,
        |l: f32, r: f32| (l - r).abs() < FLOAT_EQ_MARGIN)
}

fn blockhash_fast<I: Image, B: HashBytes>(img: &I, hwidth: u32, hheight: u32) -> B {
    let mut blocks = vec![0u32; (hwidth * hheight) as usize];
    let (iwidth, iheight) = img.dimensions();

    let (block_width, block_height) = (iwidth / hwidth, iheight / hheight);

    img.foreach_pixel8(|x, y, px| {
        let mut add_to_block = block_adder(&mut blocks, hwidth);

        let px_sum = sum_px(px);

        let block_x = x / block_width;
        let block_y = y / block_width;

        add_to_block(block_x, block_y, px_sum);
    });

    gen_hash!(I, u32, blocks, hwidth, block_width, block_height, |l, r| l == r)
}

#[inline(always)]
fn sum_px(chans: &[u8]) -> u32 {
    // Branch prediction should eliminate the match after a few iterations
    match chans.len() {
        4 => if chans[3] == 0 { 255 * 3 } else { sum_px(&chans[..3]) },
        3 => chans.iter().map(|&x| x as u32).sum(),
        2 => if chans[1] == 0 { 255 } else { chans[0] as u32 },
        1 => chans[0] as u32,
        channels => panic!("Unsupported channel count in image: {}", channels),
    }
}

fn get_median<T: PartialOrd + Copy>(data: &[T]) -> T {
    let mut scratch = data.to_owned();
    let median = scratch.len() / 2;
    *qselect_inplace(&mut scratch, median)
}

const SORT_THRESH: usize = 8;

fn qselect_inplace<T: PartialOrd>(data: &mut [T], k: usize) -> &mut T {
    let len = data.len();

    assert!(k < len, "Called qselect_inplace with k = {} and data length: {}", k, len);

    if len < SORT_THRESH {
        data.sort_by(|left, right| left.partial_cmp(right).unwrap_or(Ordering::Less));
        return &mut data[k];
    }

    let pivot_idx = partition(data);

    if k == pivot_idx {
        &mut data[pivot_idx]
    } else if k < pivot_idx {
        qselect_inplace(&mut data[..pivot_idx], k)
    } else {
        qselect_inplace(&mut data[pivot_idx + 1..], k - pivot_idx - 1)
    }
}

fn partition<T: PartialOrd>(data: &mut [T]) -> usize {
    let len = data.len();

    let pivot_idx = {
        let first = (&data[0], 0);
        let mid = (&data[len / 2], len / 2);
        let last = (&data[len - 1], len - 1);

        median_of_3(&first, &mid, &last).1
    };

    data.swap(pivot_idx, len - 1);

    let mut curr = 0;

    for i in 0 .. len - 1 {
        if &data[i] < &data[len - 1] {
            data.swap(i, curr);
            curr += 1;
        }
    }

    data.swap(curr, len - 1);

    curr
}

fn median_of_3<T: PartialOrd>(mut x: T, mut y: T, mut z: T) -> T {
    if x > y {
        mem::swap(&mut x, &mut y);
    }

    if x > z {
        mem::swap(&mut x, &mut z);
    }

    if x > z {
        mem::swap(&mut y, &mut z);
    }

    y
}
<commit_msg>IntelliJ-Rust fixed this false-positive<commit_after>// Implementation adapted from Python version:
// https://github.com/commonsmachinery/blockhash-python/blob/e8b009d/blockhash.py
// Main site: http://blockhash.io
use image::{GenericImageView, Pixel};

use {BitSet, Image, HashBytes};

use std::cmp::Ordering;
use std::ops::AddAssign;
use std::mem;

const FLOAT_EQ_MARGIN: f32 = 0.001;

pub fn blockhash<I: Image, B: HashBytes>(img: &I, width: u32, height: u32) -> B {
    assert_eq!(width % 4, 0, "width must be multiple of 4");
    assert_eq!(height % 4, 0, "height must be multiple of 4");

    let (iwidth, iheight) = img.dimensions();

    // Skip the floating point math if it's unnecessary
    if iwidth % width == 0 && iheight % height == 0 {
        blockhash_fast(img, width, height)
    } else {
        blockhash_slow(img, width, height)
    }
}

macro_rules! gen_hash {
    ($imgty:ty, $valty:ty, $blocks: expr, $width:expr, $block_width:expr, $block_height:expr, $eq_fn:expr) => ({
        let channel_count = <<$imgty as GenericImageView>::Pixel as Pixel>::channel_count() as u32;

        let group_len = ($width * 4) as usize;

        let block_area = $block_width * $block_height;

        let cmp_factor = match channel_count {
            3 | 4 => 255u32 as $valty * 3u32 as $valty,
            2 | 1 => 255u32 as $valty,
            _ => panic!("Unrecognized channel count from Image: {}", channel_count),
        }
            * block_area
            / (2u32 as $valty);

        let medians: Vec<$valty> = $blocks.chunks(group_len).map(get_median).collect();

        BitSet::from_bools(
            $blocks.chunks(group_len).zip(medians)
            .flat_map(|(blocks, median)|
                blocks.iter().map(move |&block|
                    block > median ||
                        ($eq_fn(block, median) && median > cmp_factor)
                )
            )
        )
    })
}

fn block_adder<'a, T: AddAssign + 'a>(blocks: &'a mut [T], width: u32) -> impl FnMut(u32, u32, T) + 'a {
    move |x, y, add| (blocks[(y as usize) * (width as usize) + (x as usize)] += add)
}

fn blockhash_slow<I: Image, B: HashBytes>(img: &I, hwidth: u32, hheight: u32) -> B {
    let mut blocks = vec![0f32; (hwidth * hheight) as usize];

    let (iwidth, iheight) = img.dimensions();

    // Block dimensions, in pixels
    let (block_width, block_height) = (iwidth as f32 / hwidth as f32, iheight as f32 / hheight as f32);

    img.foreach_pixel8(|x, y, px| {
        let mut add_to_block = block_adder(&mut blocks, hwidth);

        let px_sum = sum_px(px) as f32;

        let (x, y) = (x as f32, y as f32);

        let block_x = x / block_width;
        let block_y = y / block_height;

        let x_mod = x + 1. % block_width;
        let y_mod = y + 1. % block_height;

        // terminology is mostly arbitrary as long as we're consistent
        // if `x` evenly divides `block_height`, this weight will be 0
        // so we don't double the sum as `block_top` will equal `block_bottom`
        let weight_left = x_mod.fract();
        let weight_right = 1. - weight_left;
        let weight_top = y_mod.fract();
        let weight_bottom = 1. - weight_top;

        let block_left = block_x.floor() as u32;
        let block_top = block_y.floor() as u32;

        let block_right = if x_mod.trunc() == 0. {
            block_x.ceil() as u32
        } else {
            block_left
        };

        let block_bottom = if y_mod.trunc() == 0. {
            block_y.ceil() as u32
        } else {
            block_top
        };

        add_to_block(block_left, block_top, px_sum * weight_left * weight_top);
        add_to_block(block_left, block_bottom, px_sum * weight_left * weight_bottom);
        add_to_block(block_right, block_top, px_sum * weight_right * weight_top);
        add_to_block(block_right, block_bottom, px_sum * weight_right * weight_bottom);
    });

    gen_hash!(I, f32, blocks, hwidth, block_width, block_height,
        |l: f32, r: f32| (l - r).abs() < FLOAT_EQ_MARGIN)
}

fn blockhash_fast<I: Image, B: HashBytes>(img: &I, hwidth: u32, hheight: u32) -> B {
    let mut blocks = vec![0u32; (hwidth * hheight) as usize];
    let (iwidth, iheight) = img.dimensions();

    let (block_width, block_height) = (iwidth / hwidth, iheight / hheight);

    img.foreach_pixel8(|x, y, px| {
        let mut add_to_block = block_adder(&mut blocks, hwidth);

        let px_sum = sum_px(px);

        let block_x = x / block_width;
        let block_y = y / block_width;

        add_to_block(block_x, block_y, px_sum);
    });

    gen_hash!(I, u32, blocks, hwidth, block_width, block_height, |l, r| l == r)
}

#[inline(always)]
fn sum_px(chans: &[u8]) -> u32 {
    // Branch prediction should eliminate the match after a few iterations
    match chans.len() {
        4 => if chans[3] == 0 { 255 * 3 } else { sum_px(&chans[..3]) },
        3 => chans.iter().map(|&x| x as u32).sum(),
        2 => if chans[1] == 0 { 255 } else { chans[0] as u32 },
        1 => chans[0] as u32,
        channels => panic!("Unsupported channel count in image: {}", channels),
    }
}

fn get_median<T: PartialOrd + Copy>(data: &[T]) -> T {
    let mut scratch = data.to_owned();
    let median = scratch.len() / 2;
    *qselect_inplace(&mut scratch, median)
}

const SORT_THRESH: usize = 8;

fn qselect_inplace<T: PartialOrd>(data: &mut [T], k: usize) -> &mut T {
    let len = data.len();

    assert!(k < len, "Called qselect_inplace with k = {} and data length: {}", k, len);

    if len < SORT_THRESH {
        data.sort_by(|left, right| left.partial_cmp(right).unwrap_or(Ordering::Less));
        return &mut data[k];
    }

    let pivot_idx = partition(data);

    if k == pivot_idx {
        &mut data[pivot_idx]
    } else if k < pivot_idx {
        qselect_inplace(&mut data[..pivot_idx], k)
    } else {
        qselect_inplace(&mut data[pivot_idx + 1..], k - pivot_idx - 1)
    }
}

fn partition<T: PartialOrd>(data: &mut [T]) -> usize {
    let len = data.len();

    let pivot_idx = {
        let first = (&data[0], 0);
        let mid = (&data[len / 2], len / 2);
        let last = (&data[len - 1], len - 1);

        median_of_3(&first, &mid, &last).1
    };

    data.swap(pivot_idx, len - 1);

    let mut curr = 0;

    for i in 0 .. len - 1 {
        if &data[i] < &data[len - 1] {
            data.swap(i, curr);
            curr += 1;
        }
    }

    data.swap(curr, len - 1);

    curr
}

fn median_of_3<T: PartialOrd>(mut x: T, mut y: T, mut z: T) -> T {
    if x > y {
        mem::swap(&mut x, &mut y);
    }

    if x > z {
        mem::swap(&mut x, &mut z);
    }

    if x > z {
        mem::swap(&mut y, &mut z);
    }

    y
}
<|endoftext|>


<commit_before>use fake_tty::FakeIO;
use tty::IO;

pub struct Ansi<'a> {
    pub io: Box<(IO + 'a)>,
}

impl <'a> Ansi<'a> {
    pub fn escape(&mut self, message: &str) {
        let out = Ansi::esc(message);
        self.io.write(out.as_slice());
    }

    fn esc(input: &str) -> String {
        format!("\x1b[{}", input)
    }

    pub fn clear(&mut self) {
        self.escape("2J");
    }

    pub fn hide_cursor(&mut self) {
        self.escape("?251");
    }

    pub fn show_cursor(&mut self) {
        self.escape("?25h");
    }

    pub fn set_position(&mut self, line: usize, column: usize) {
        let message = format!("{};{}H", line + 1, column + 1);
        self.escape(message.as_slice());
    }

    fn invert(&mut self) {
        self.escape("7m");
    }

    fn reset(&mut self) {
        self.escape("0m");
    }

    pub fn inverted(&mut self, line: &str) {
        let compound = format!("{}{}{}", Ansi::esc("7m"), line, Ansi::esc("0m"));
        self.io.write(compound.as_slice());
    }

    pub fn print(&mut self, line: &str) {
        self.io.write(line);
    }

    pub fn blank_line(&mut self, line: usize) {
        self.set_position(line, 0);
        self.escape("2K");
    }
}

#[cfg(test)]

#[test]
fn it_escapes_a_str() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.escape("something");
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[something");
}

#[test]
fn it_clears_the_screen() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.clear();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[2J");
}

#[test]
fn it_hides_the_cursos() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.hide_cursor();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[?251");
}

#[test]
fn it_shows_the_cursor() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.show_cursor();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[?25h");
}

#[test]
fn it_sets_the_position() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.set_position(8,12);
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[9;13H");
}

#[test]
fn it_inverts() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.invert();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[7m");
}

fn it_prints_inverted() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.inverted("test");
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[7mtest\x1b[0m");
}

#[test]
fn it_resets() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.reset();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[0m");
}
<commit_msg>Annotate a test function as such<commit_after>use fake_tty::FakeIO;
use tty::IO;

pub struct Ansi<'a> {
    pub io: Box<(IO + 'a)>,
}

impl <'a> Ansi<'a> {
    pub fn escape(&mut self, message: &str) {
        let out = Ansi::esc(message);
        self.io.write(out.as_slice());
    }

    fn esc(input: &str) -> String {
        format!("\x1b[{}", input)
    }

    pub fn clear(&mut self) {
        self.escape("2J");
    }

    pub fn hide_cursor(&mut self) {
        self.escape("?251");
    }

    pub fn show_cursor(&mut self) {
        self.escape("?25h");
    }

    pub fn set_position(&mut self, line: usize, column: usize) {
        let message = format!("{};{}H", line + 1, column + 1);
        self.escape(message.as_slice());
    }

    fn invert(&mut self) {
        self.escape("7m");
    }

    fn reset(&mut self) {
        self.escape("0m");
    }

    pub fn inverted(&mut self, line: &str) {
        let compound = format!("{}{}{}", Ansi::esc("7m"), line, Ansi::esc("0m"));
        self.io.write(compound.as_slice());
    }

    pub fn print(&mut self, line: &str) {
        self.io.write(line);
    }

    pub fn blank_line(&mut self, line: usize) {
        self.set_position(line, 0);
        self.escape("2K");
    }
}

#[cfg(test)]

#[test]
fn it_escapes_a_str() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.escape("something");
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[something");
}

#[test]
fn it_clears_the_screen() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.clear();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[2J");
}

#[test]
fn it_hides_the_cursos() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.hide_cursor();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[?251");
}

#[test]
fn it_shows_the_cursor() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.show_cursor();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[?25h");
}

#[test]
fn it_sets_the_position() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.set_position(8,12);
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[9;13H");
}

#[test]
fn it_inverts() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.invert();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[7m");
}

#[test]
fn it_prints_inverted() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.inverted("test");
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[7mtest\x1b[0m");
}

#[test]
fn it_resets() {
    let mut ansi = Ansi { io: Box::new(FakeIO::new()) };

    ansi.reset();
    let inner_box = ansi.io;
    assert_eq!(inner_box.last(), "\x1b[0m");
}
<|endoftext|>


<commit_before>use style::{Colour, Style};

use std::fmt;

use write::AnyWrite;

// ---- generating ANSI codes ----

impl Style {

    /// Write any ANSI codes that go *before* a piece of text. These should be
    /// the codes to set the terminal to a different colour or font style.
    fn write_prefix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {

        // If there are actually no styles here, then don’t write *any* codes
        // as the prefix. An empty ANSI code may not affect the terminal
        // output at all, but a user may just want a code-free string.
        if self.is_plain() {
            return Ok(());
        }

        // Write the codes’ prefix, then write numbers, separated by
        // semicolons, for each text style we want to apply.
        write!(f, "\x1B[")?;
        let mut written_anything = false;

        {
            let mut write_char = |c| {
                if written_anything { write!(f, ";")?; }
                written_anything = true;
                write!(f, "{}", c)?;
                Ok(())
            };

            if self.is_bold           { write_char('1')? }
            if self.is_dimmed         { write_char('2')? }
            if self.is_italic         { write_char('3')? }
            if self.is_underline      { write_char('4')? }
            if self.is_blink          { write_char('5')? }
            if self.is_reverse        { write_char('7')? }
            if self.is_hidden         { write_char('8')? }
            if self.is_strikethrough  { write_char('9')? }
        }

        // The foreground and background colours, if specified, need to be
        // handled specially because the number codes are more complicated.
        // (see `write_background_code` and `write_foreground_code`)
        if let Some(bg) = self.background {
            if written_anything { write!(f, ";")?; }
            written_anything = true;
            bg.write_background_code(f)?;
        }

        if let Some(fg) = self.foreground {
            if written_anything { write!(f, ";")?; }
            fg.write_foreground_code(f)?;
        }

        // All the codes end with an `m`, because reasons.
        write!(f, "m")?;

        Ok(())
    }

    /// Write any ANSI codes that go *after* a piece of text. These should be
    /// the codes to *reset* the terminal back to its normal colour and style.
    fn write_suffix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
        if self.is_plain() {
            Ok(())
        }
        else {
            write!(f, "{}", RESET)
        }
    }
}

/// The code to send to reset all styles and return to `Style::default()`.
pub static RESET: &str = "\x1B[0m";

impl Colour {
    fn write_foreground_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
        match *self {
            Colour::Black      => write!(f, "30"),
            Colour::Red        => write!(f, "31"),
            Colour::Green      => write!(f, "32"),
            Colour::Yellow     => write!(f, "33"),
            Colour::Blue       => write!(f, "34"),
            Colour::Purple     => write!(f, "35"),
            Colour::Cyan       => write!(f, "36"),
            Colour::White      => write!(f, "37"),
            Colour::Fixed(num) => write!(f, "38;5;{}", &num),
            Colour::RGB(r,g,b) => write!(f, "38;2;{};{};{}", &r, &g, &b),
        }
    }

    fn write_background_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
        match *self {
            Colour::Black      => write!(f, "40"),
            Colour::Red        => write!(f, "41"),
            Colour::Green      => write!(f, "42"),
            Colour::Yellow     => write!(f, "43"),
            Colour::Blue       => write!(f, "44"),
            Colour::Purple     => write!(f, "45"),
            Colour::Cyan       => write!(f, "46"),
            Colour::White      => write!(f, "47"),
            Colour::Fixed(num) => write!(f, "48;5;{}", &num),
            Colour::RGB(r,g,b) => write!(f, "48;2;{};{};{}", &r, &g, &b),
        }
    }
}

/// Like `ANSIString`, but only displays the style prefix.
#[derive(Clone, Copy, Debug)]
pub struct Prefix(Style);

/// Like `ANSIString`, but only displays the difference between two
/// styles.
#[derive(Clone, Copy, Debug)]
pub struct Infix(Style, Style);

/// Like `ANSIString`, but only displays the style suffix.
#[derive(Clone, Copy, Debug)]
pub struct Suffix(Style);

impl Style {

    /// The prefix for this style.
    pub fn prefix(self) -> Prefix {
        Prefix(self)
    }

    /// The infix between this style and another.
    pub fn infix(self, other: Style) -> Infix {
        Infix(self, other)
    }

    /// The suffix for this style.
    pub fn suffix(self) -> Suffix {
        Suffix(self)
    }
}

impl Colour {

    /// The prefix for this colour.
    pub fn prefix(self) -> Prefix {
        Prefix(self.normal())
    }

    /// The infix between this colour and another.
    pub fn infix(self, other: Colour) -> Infix {
        Infix(self.normal(), other.normal())
    }

    /// The suffix for this colour.
    pub fn suffix(self) -> Suffix {
        Suffix(self.normal())
    }
}

impl fmt::Display for Prefix {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let f: &mut fmt::Write = f;
        self.0.write_prefix(f)
    }
}

impl fmt::Display for Infix {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use difference::Difference;

        match Difference::between(&self.0, &self.1) {
            Difference::ExtraStyles(style) => {
                let f: &mut fmt::Write = f;
                style.write_prefix(f)
            },
            Difference::Reset => {
                let f: &mut fmt::Write = f;
                write!(f, "{}{}", RESET, self.0.prefix())
            },
            Difference::NoDifference => {
                Ok(())   // nothing to write
            },
        }
    }
}

impl fmt::Display for Suffix {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let f: &mut fmt::Write = f;
        self.0.write_suffix(f)
    }
}

#[cfg(test)]
mod test {
    use style::Style;
    use style::Colour::*;

    macro_rules! test {
        ($name: ident: $style: expr; $input: expr => $result: expr) => {
            #[test]
            fn $name() {
                assert_eq!($style.paint($input).to_string(), $result.to_string());

                let mut v = Vec::new();
                $style.paint($input.as_bytes()).write_to(&mut v).unwrap();
                assert_eq!(v.as_slice(), $result.as_bytes());
            }
        };
    }

    test!(plain:                 Style::default();                  "text/plain" => "text/plain");
    test!(red:                   Red;                               "hi" => "\x1B[31mhi\x1B[0m");
    test!(black:                 Black.normal();                    "hi" => "\x1B[30mhi\x1B[0m");
    test!(yellow_bold:           Yellow.bold();                     "hi" => "\x1B[1;33mhi\x1B[0m");
    test!(yellow_bold_2:         Yellow.normal().bold();            "hi" => "\x1B[1;33mhi\x1B[0m");
    test!(blue_underline:        Blue.underline();                  "hi" => "\x1B[4;34mhi\x1B[0m");
    test!(green_bold_ul:         Green.bold().underline();          "hi" => "\x1B[1;4;32mhi\x1B[0m");
    test!(green_bold_ul_2:       Green.underline().bold();          "hi" => "\x1B[1;4;32mhi\x1B[0m");
    test!(purple_on_white:       Purple.on(White);                  "hi" => "\x1B[47;35mhi\x1B[0m");
    test!(purple_on_white_2:     Purple.normal().on(White);         "hi" => "\x1B[47;35mhi\x1B[0m");
    test!(yellow_on_blue:        Style::new().on(Blue).fg(Yellow);  "hi" => "\x1B[44;33mhi\x1B[0m");
    test!(yellow_on_blue_2:      Cyan.on(Blue).fg(Yellow);          "hi" => "\x1B[44;33mhi\x1B[0m");
    test!(cyan_bold_on_white:    Cyan.bold().on(White);             "hi" => "\x1B[1;47;36mhi\x1B[0m");
    test!(cyan_ul_on_white:      Cyan.underline().on(White);        "hi" => "\x1B[4;47;36mhi\x1B[0m");
    test!(cyan_bold_ul_on_white: Cyan.bold().underline().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
    test!(cyan_ul_bold_on_white: Cyan.underline().bold().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
    test!(fixed:                 Fixed(100);                        "hi" => "\x1B[38;5;100mhi\x1B[0m");
    test!(fixed_on_purple:       Fixed(100).on(Purple);             "hi" => "\x1B[45;38;5;100mhi\x1B[0m");
    test!(fixed_on_fixed:        Fixed(100).on(Fixed(200));         "hi" => "\x1B[48;5;200;38;5;100mhi\x1B[0m");
    test!(rgb:                   RGB(70,130,180);                   "hi" => "\x1B[38;2;70;130;180mhi\x1B[0m");
    test!(rgb_on_blue:           RGB(70,130,180).on(Blue);          "hi" => "\x1B[44;38;2;70;130;180mhi\x1B[0m");
    test!(blue_on_rgb:           Blue.on(RGB(70,130,180));          "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m");
    test!(rgb_on_rgb:            RGB(70,130,180).on(RGB(5,10,15));  "hi" => "\x1B[48;2;5;10;15;38;2;70;130;180mhi\x1B[0m");
    test!(bold:                  Style::new().bold();               "hi" => "\x1B[1mhi\x1B[0m");
    test!(underline:             Style::new().underline();          "hi" => "\x1B[4mhi\x1B[0m");
    test!(bunderline:            Style::new().bold().underline();   "hi" => "\x1B[1;4mhi\x1B[0m");
    test!(dimmed:                Style::new().dimmed();             "hi" => "\x1B[2mhi\x1B[0m");
    test!(italic:                Style::new().italic();             "hi" => "\x1B[3mhi\x1B[0m");
    test!(blink:                 Style::new().blink();              "hi" => "\x1B[5mhi\x1B[0m");
    test!(reverse:               Style::new().reverse();            "hi" => "\x1B[7mhi\x1B[0m");
    test!(hidden:                Style::new().hidden();             "hi" => "\x1B[8mhi\x1B[0m");
    test!(stricken:              Style::new().strikethrough();      "hi" => "\x1B[9mhi\x1B[0m");

}
<commit_msg>Documentation improvements for ansi bytes<commit_after>use style::{Colour, Style};

use std::fmt;

use write::AnyWrite;

// ---- generating ANSI codes ----

impl Style {

    /// Write any bytes that go *before* a piece of text to the given writer.
    fn write_prefix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {

        // If there are actually no styles here, then don’t write *any* codes
        // as the prefix. An empty ANSI code may not affect the terminal
        // output at all, but a user may just want a code-free string.
        if self.is_plain() {
            return Ok(());
        }

        // Write the codes’ prefix, then write numbers, separated by
        // semicolons, for each text style we want to apply.
        write!(f, "\x1B[")?;
        let mut written_anything = false;

        {
            let mut write_char = |c| {
                if written_anything { write!(f, ";")?; }
                written_anything = true;
                write!(f, "{}", c)?;
                Ok(())
            };

            if self.is_bold           { write_char('1')? }
            if self.is_dimmed         { write_char('2')? }
            if self.is_italic         { write_char('3')? }
            if self.is_underline      { write_char('4')? }
            if self.is_blink          { write_char('5')? }
            if self.is_reverse        { write_char('7')? }
            if self.is_hidden         { write_char('8')? }
            if self.is_strikethrough  { write_char('9')? }
        }

        // The foreground and background colours, if specified, need to be
        // handled specially because the number codes are more complicated.
        // (see `write_background_code` and `write_foreground_code`)
        if let Some(bg) = self.background {
            if written_anything { write!(f, ";")?; }
            written_anything = true;
            bg.write_background_code(f)?;
        }

        if let Some(fg) = self.foreground {
            if written_anything { write!(f, ";")?; }
            fg.write_foreground_code(f)?;
        }

        // All the codes end with an `m`, because reasons.
        write!(f, "m")?;

        Ok(())
    }

    /// Write any bytes that go *after* a piece of text to the given writer.
    fn write_suffix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
        if self.is_plain() {
            Ok(())
        }
        else {
            write!(f, "{}", RESET)
        }
    }
}

/// The code to send to reset all styles and return to `Style::default()`.
pub static RESET: &str = "\x1B[0m";

impl Colour {
    fn write_foreground_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
        match *self {
            Colour::Black      => write!(f, "30"),
            Colour::Red        => write!(f, "31"),
            Colour::Green      => write!(f, "32"),
            Colour::Yellow     => write!(f, "33"),
            Colour::Blue       => write!(f, "34"),
            Colour::Purple     => write!(f, "35"),
            Colour::Cyan       => write!(f, "36"),
            Colour::White      => write!(f, "37"),
            Colour::Fixed(num) => write!(f, "38;5;{}", &num),
            Colour::RGB(r,g,b) => write!(f, "38;2;{};{};{}", &r, &g, &b),
        }
    }

    fn write_background_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
        match *self {
            Colour::Black      => write!(f, "40"),
            Colour::Red        => write!(f, "41"),
            Colour::Green      => write!(f, "42"),
            Colour::Yellow     => write!(f, "43"),
            Colour::Blue       => write!(f, "44"),
            Colour::Purple     => write!(f, "45"),
            Colour::Cyan       => write!(f, "46"),
            Colour::White      => write!(f, "47"),
            Colour::Fixed(num) => write!(f, "48;5;{}", &num),
            Colour::RGB(r,g,b) => write!(f, "48;2;{};{};{}", &r, &g, &b),
        }
    }
}

/// Like `ANSIString`, but only displays the style prefix.
///
/// This type implements the `Display` trait, meaning it can be written to a
/// `std::fmt` formatting without doing any extra allocation, and written to a
/// string with the `.to_string()` method. For examples, see
/// [`Style::prefix`](struct.Style.html#method.prefix).
#[derive(Clone, Copy, Debug)]
pub struct Prefix(Style);

/// Like `ANSIString`, but only displays the difference between two
/// styles.
///
/// This type implements the `Display` trait, meaning it can be written to a
/// `std::fmt` formatting without doing any extra allocation, and written to a
/// string with the `.to_string()` method. For examples, see
/// [`Style::infix`](struct.Style.html#method.infix).
#[derive(Clone, Copy, Debug)]
pub struct Infix(Style, Style);

/// Like `ANSIString`, but only displays the style suffix.
///
/// This type implements the `Display` trait, meaning it can be written to a
/// `std::fmt` formatting without doing any extra allocation, and written to a
/// string with the `.to_string()` method. For examples, see
/// [`Style::suffix`](struct.Style.html#method.suffix).
#[derive(Clone, Copy, Debug)]
pub struct Suffix(Style);

impl Style {

    /// The prefix bytes for this style. These are the bytes that tell the
    /// terminal to use a different colour or font style.
    ///
    /// # Examples
    ///
    /// ```
    /// use ansi_term::{Style, Colour::Blue};
    ///
    /// let style = Style::default().bold();
    /// assert_eq!("\x1b[1m",
    ///            style.prefix().to_string());
    ///
    /// let style = Blue.bold();
    /// assert_eq!("\x1b[1;34m",
    ///            style.prefix().to_string());
    ///
    /// let style = Style::default();
    /// assert_eq!("",
    ///            style.prefix().to_string());
    /// ```
    pub fn prefix(self) -> Prefix {
        Prefix(self)
    }

    /// The infix bytes between this style and another. These are the bytes
    /// that tell the terminal to either use a different colour or font style
    /// _or_ to reset entirely, depending on the two styles.
    ///
    /// # Examples
    ///
    /// ```
    /// use ansi_term::{Style, Colour::Green};
    ///
    /// let style = Style::default().bold();
    /// assert_eq!("\x1b[32m",
    ///            style.infix(Green.bold()).to_string());
    ///
    /// let style = Green.normal();
    /// assert_eq!("\x1b[1m",
    ///            style.infix(Green.bold()).to_string());
    ///
    /// let style = Style::default();
    /// assert_eq!("",
    ///            style.infix(style).to_string());
    /// ```
    pub fn infix(self, other: Style) -> Infix {
        Infix(self, other)
    }

    /// The suffix for this style. These are the bytes that tell the terminal
    /// to reset back to its normal colour and font style.
    ///
    /// # Examples
    ///
    /// ```
    /// use ansi_term::{Style, Colour::Green};
    ///
    /// let style = Style::default().bold();
    /// assert_eq!("\x1b[0m",
    ///            style.suffix().to_string());
    ///
    /// let style = Green.normal().bold();
    /// assert_eq!("\x1b[0m",
    ///            style.suffix().to_string());
    ///
    /// let style = Style::default();
    /// assert_eq!("",
    ///            style.suffix().to_string());
    /// ```
    pub fn suffix(self) -> Suffix {
        Suffix(self)
    }
}

impl Colour {

    /// The prefix bytes for this colour as a `Style`. These are the bytes
    /// that tell the terminal to use a different colour or font style.
    ///
    /// See also [`Style::prefix`](struct.Style.html#method.prefix).
    ///
    /// # Examples
    ///
    /// ```
    /// use ansi_term::Colour::Green;
    ///
    /// assert_eq!("\x1b[0m",
    ///            Green.suffix().to_string());
    /// ```
    pub fn prefix(self) -> Prefix {
        Prefix(self.normal())
    }

    /// The infix bytes between this style and another. These are the bytes
    /// that tell the terminal to use the second colour, or to do nothing if
    /// the two colours are equal.
    ///
    /// See also [`Style::infix`](struct.Style.html#method.infix).
    ///
    /// # Examples
    ///
    /// ```
    /// use ansi_term::Colour::{Red, Yellow};
    ///
    /// assert_eq!("\x1b[33m",
    ///            Red.infix(Yellow).to_string());
    /// ```
    pub fn infix(self, other: Colour) -> Infix {
        Infix(self.normal(), other.normal())
    }

    /// The suffix for this colour as a `Style`. These are the bytes that
    /// tell the terminal to reset back to its normal colour and font style.
    ///
    /// See also [`Style::suffix`](struct.Style.html#method.suffix).
    ///
    /// # Examples
    ///
    /// ```
    /// use ansi_term::Colour::Purple;
    ///
    /// assert_eq!("\x1b[0m",
    ///            Purple.suffix().to_string());
    /// ```
    pub fn suffix(self) -> Suffix {
        Suffix(self.normal())
    }
}

impl fmt::Display for Prefix {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let f: &mut fmt::Write = f;
        self.0.write_prefix(f)
    }
}

impl fmt::Display for Infix {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use difference::Difference;

        match Difference::between(&self.0, &self.1) {
            Difference::ExtraStyles(style) => {
                let f: &mut fmt::Write = f;
                style.write_prefix(f)
            },
            Difference::Reset => {
                let f: &mut fmt::Write = f;
                write!(f, "{}{}", RESET, self.0.prefix())
            },
            Difference::NoDifference => {
                Ok(())   // nothing to write
            },
        }
    }
}

impl fmt::Display for Suffix {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let f: &mut fmt::Write = f;
        self.0.write_suffix(f)
    }
}

#[cfg(test)]
mod test {
    use style::Style;
    use style::Colour::*;

    macro_rules! test {
        ($name: ident: $style: expr; $input: expr => $result: expr) => {
            #[test]
            fn $name() {
                assert_eq!($style.paint($input).to_string(), $result.to_string());

                let mut v = Vec::new();
                $style.paint($input.as_bytes()).write_to(&mut v).unwrap();
                assert_eq!(v.as_slice(), $result.as_bytes());
            }
        };
    }

    test!(plain:                 Style::default();                  "text/plain" => "text/plain");
    test!(red:                   Red;                               "hi" => "\x1B[31mhi\x1B[0m");
    test!(black:                 Black.normal();                    "hi" => "\x1B[30mhi\x1B[0m");
    test!(yellow_bold:           Yellow.bold();                     "hi" => "\x1B[1;33mhi\x1B[0m");
    test!(yellow_bold_2:         Yellow.normal().bold();            "hi" => "\x1B[1;33mhi\x1B[0m");
    test!(blue_underline:        Blue.underline();                  "hi" => "\x1B[4;34mhi\x1B[0m");
    test!(green_bold_ul:         Green.bold().underline();          "hi" => "\x1B[1;4;32mhi\x1B[0m");
    test!(green_bold_ul_2:       Green.underline().bold();          "hi" => "\x1B[1;4;32mhi\x1B[0m");
    test!(purple_on_white:       Purple.on(White);                  "hi" => "\x1B[47;35mhi\x1B[0m");
    test!(purple_on_white_2:     Purple.normal().on(White);         "hi" => "\x1B[47;35mhi\x1B[0m");
    test!(yellow_on_blue:        Style::new().on(Blue).fg(Yellow);  "hi" => "\x1B[44;33mhi\x1B[0m");
    test!(yellow_on_blue_2:      Cyan.on(Blue).fg(Yellow);          "hi" => "\x1B[44;33mhi\x1B[0m");
    test!(cyan_bold_on_white:    Cyan.bold().on(White);             "hi" => "\x1B[1;47;36mhi\x1B[0m");
    test!(cyan_ul_on_white:      Cyan.underline().on(White);        "hi" => "\x1B[4;47;36mhi\x1B[0m");
    test!(cyan_bold_ul_on_white: Cyan.bold().underline().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
    test!(cyan_ul_bold_on_white: Cyan.underline().bold().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
    test!(fixed:                 Fixed(100);                        "hi" => "\x1B[38;5;100mhi\x1B[0m");
    test!(fixed_on_purple:       Fixed(100).on(Purple);             "hi" => "\x1B[45;38;5;100mhi\x1B[0m");
    test!(fixed_on_fixed:        Fixed(100).on(Fixed(200));         "hi" => "\x1B[48;5;200;38;5;100mhi\x1B[0m");
    test!(rgb:                   RGB(70,130,180);                   "hi" => "\x1B[38;2;70;130;180mhi\x1B[0m");
    test!(rgb_on_blue:           RGB(70,130,180).on(Blue);          "hi" => "\x1B[44;38;2;70;130;180mhi\x1B[0m");
    test!(blue_on_rgb:           Blue.on(RGB(70,130,180));          "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m");
    test!(rgb_on_rgb:            RGB(70,130,180).on(RGB(5,10,15));  "hi" => "\x1B[48;2;5;10;15;38;2;70;130;180mhi\x1B[0m");
    test!(bold:                  Style::new().bold();               "hi" => "\x1B[1mhi\x1B[0m");
    test!(underline:             Style::new().underline();          "hi" => "\x1B[4mhi\x1B[0m");
    test!(bunderline:            Style::new().bold().underline();   "hi" => "\x1B[1;4mhi\x1B[0m");
    test!(dimmed:                Style::new().dimmed();             "hi" => "\x1B[2mhi\x1B[0m");
    test!(italic:                Style::new().italic();             "hi" => "\x1B[3mhi\x1B[0m");
    test!(blink:                 Style::new().blink();              "hi" => "\x1B[5mhi\x1B[0m");
    test!(reverse:               Style::new().reverse();            "hi" => "\x1B[7mhi\x1B[0m");
    test!(hidden:                Style::new().hidden();             "hi" => "\x1B[8mhi\x1B[0m");
    test!(stricken:              Style::new().strikethrough();      "hi" => "\x1B[9mhi\x1B[0m");

}
<|endoftext|>