<commit_before>extern crate image;
extern crate rand;
extern crate rayon;

use image::{Rgba, RgbaImage, Pixel};

use rand::Rng;

#[derive(Clone, Copy, Debug)]
struct Point {
    x: i32,
    y: i32,
}

impl Point {
    fn cross_product(&self, b: Point) -> i32 {
        self.x * b.y - self.y * b.x
    }
}

#[derive(Debug, Copy, Clone)]
struct BoundingBox {
    top_left: Point,
    bottom_right: Point,
}

#[derive(Debug, Copy, Clone)]
struct Triangle {
    a: Point,
    b: Point,
    c: Point,
    color: Option<Rgba<u8>>,
}

impl Triangle {
    fn new(a: Point, b: Point, c: Point) -> Triangle {
        Triangle {
            a: a,
            b: b,
            c: c,
            color: None,
        }
    }

    // fn set_color(&mut self, c: Color) {
    //     self.color = Some(c);
    // }

    // fn get_color(&)

    fn is_inside_primitive(&self, p: Point) -> bool {
        let spanA = Point { x: self.b.x - self.a.x, y: self.b.y - self.a.y };
        let spanB = Point { x: self.c.x - self.a.x, y: self.c.y - self.a.y };

        let q = Point { x: p.x - self.a.x, y: p.y - self.a.y };

        let s = q.cross_product(spanB) as f32 / spanA.cross_product(spanB) as f32;
        let t = spanA.cross_product(q) as f32 / spanA.cross_product(spanB) as f32;

        (s >= 0.0) && (t >= 0.0) && ((s + t) <= 1.0)
    }

    fn get_bounding_box(&self) -> BoundingBox {
        use std::cmp::{min, max};
        BoundingBox {
            top_left: Point {
                x: min(min(self.a.x, self.b.x), self.c.x),
                y: min(min(self.a.y, self.b.y), self.c.y),
            },
            bottom_right: Point {
                x: max(max(self.a.x, self.b.x), self.c.x),
                y: max(max(self.a.y, self.b.y), self.c.y),
            }
        }
    }
}

pub struct RandomPointGenerator {
    rng: Box<Rng>,
    width: i32,
    height: i32,
}

impl RandomPointGenerator {
    pub fn new(width: i32, height: i32) -> RandomPointGenerator {
        RandomPointGenerator {
            rng: Box::new(rand::thread_rng()),
            width: width,
            height: height,
        }
    }

    fn next_point(&mut self) -> Point {
        Point {
            x: self.rng.gen_range(0, self.width),
            y: self.rng.gen_range(0, self.height),
        }
    }
}

pub struct Geometrify {
    point_gen: RandomPointGenerator,
}

impl Geometrify {
    pub fn new(point_gen: RandomPointGenerator) -> Geometrify {
        Geometrify {
            point_gen: point_gen
        }
    }

    fn calculate_color(image: &RgbaImage, primitive: Triangle) -> Rgba<u8> {
        let bb = primitive.get_bounding_box();

        let mut count = 0u64;
        let mut cr = 0u64;
        let mut cg = 0u64;
        let mut cb = 0u64;
        let mut ca = 0u64;

        for y in bb.top_left.y..bb.bottom_right.y {
            for x in bb.top_left.x..bb.bottom_right.x {
                let (r, g, b, a) = image.get_pixel(x as u32, y as u32).channels4();
                cr += r as u64;
                cg += g as u64;
                cb += b as u64;
                ca += a as u64;
                count += 1;
            }
        }

        if count == 0 {
            Rgba::from_channels(255, 255, 255, 255)
        } else {
            Rgba::from_channels((cr / count) as u8,
                                (cg / count) as u8,
                                (cb / count) as u8,
                                (ca / count) as u8)
        }
    }

    fn generate_primitive(&mut self) -> Triangle {
        Triangle::new(self.point_gen.next_point(),
                      self.point_gen.next_point(),
                      self.point_gen.next_point())
    }

    fn add_to_image(image: &mut RgbaImage, primitive: Triangle) {
        let bb = primitive.get_bounding_box();

        for y in bb.top_left.y..bb.bottom_right.y {
            for x in bb.top_left.x..bb.bottom_right.x {
        // for y in 0..image.height() {
        //     for x in 0..image.width() {
                let p = Point {x: x as i32, y: y as i32};
                if primitive.is_inside_primitive(p) {
                    *image.get_pixel_mut(x as u32, y as u32) = Geometrify::mixColor(primitive.color.expect("color of triangle not set"), *image.get_pixel(x as u32, y as u32));
                }
            }
        }
    }

    fn mixColor(first: Rgba<u8>, second: Rgba<u8>) -> Rgba<u8> {
        let (r1, g1, b1, a1) = first.channels4();
        let (r2, g2, b2, a2) = second.channels4();

        Rgba::from_channels(
            ((((r1 as u32 + r2 as u32)) / 2) as u8),
            ((((g1 as u32 + g2 as u32)) / 2) as u8),
            ((((b1 as u32 + b2 as u32)) / 2) as u8),
            ((((a1 as u32 + a2 as u32)) / 2) as u8),
        )
    }

    fn difference(first: Rgba<u8>, second: Rgba<u8>) -> i32 {
        let (r1, g1, b1, a1) = first.channels4();
        let (r2, g2, b2, a2) = second.channels4();
        let mut d = 0i32;

        d += i32::abs((r1 as i32 - r2 as i32));
        d += i32::abs((g1 as i32 - g2 as i32));
        d += i32::abs((b1 as i32 - b2 as i32));
        d += i32::abs((a1 as i32 - a2 as i32));

        d
    }

    fn calculate_difference(original: &RgbaImage, current: &RgbaImage, primitive: Triangle) -> i32 {
        let bb = primitive.get_bounding_box();

        let mut d = 0i32;

        for y in 0..original.height() {
            for x in 0..original.width() {
                let originalRgb = original.get_pixel(x, y);
                let resultRgb = if (bb.top_left.x as u32 <= x) && (x <= bb.bottom_right.x as u32)
                    && (bb.top_left.y as u32 <= y) && (y <= bb.bottom_right.y as u32)
                    && (primitive.is_inside_primitive(Point { x: x as i32, y: y as i32 })) {
                        Geometrify::mixColor(*current.get_pixel(x, y), primitive.color.expect("triangle color not "))
                    } else {
                        *current.get_pixel(x, y)
                    };

                d += Geometrify::difference(*originalRgb, resultRgb);
            }
        }

        d
    }

    pub fn apply(&mut self, image: RgbaImage, numberOfIterations: i32, numberOfSamples: i32) -> RgbaImage {
        let mut destination = RgbaImage::new(image.width(), image.height());

        for _ in 0..numberOfIterations {
            let mut minDifference = i32::max_value();
            let mut minPrimitive = None;

            for _ in 0..numberOfSamples {
                let mut primitive = self.generate_primitive();
                let color = Geometrify::calculate_color(&image, primitive);
                primitive.color = Some(color);

                let diff = Geometrify::calculate_difference(&image, &destination, primitive);
                if (diff < minDifference) {
                    minDifference = diff;
                    minPrimitive = Some(primitive);
                }
            }

            Geometrify::add_to_image(&mut destination, minPrimitive.expect("no fitting triangle found"));
        }

        destination
    }

}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>Parallelize triangle search.<commit_after>extern crate image;
extern crate rand;
extern crate rayon;

use image::{Rgba, RgbaImage, Pixel};

use rand::Rng;

use rayon::prelude::*;

#[derive(Clone, Copy, Debug)]
struct Point {
    x: i32,
    y: i32,
}

impl Point {
    fn cross_product(&self, b: Point) -> i32 {
        self.x * b.y - self.y * b.x
    }
}

#[derive(Debug, Copy, Clone)]
struct BoundingBox {
    top_left: Point,
    bottom_right: Point,
}

#[derive(Debug, Copy, Clone)]
struct Triangle {
    a: Point,
    b: Point,
    c: Point,
    color: Option<Rgba<u8>>,
}

impl Triangle {
    fn new(a: Point, b: Point, c: Point) -> Triangle {
        Triangle {
            a: a,
            b: b,
            c: c,
            color: None,
        }
    }

    // fn set_color(&mut self, c: Color) {
    //     self.color = Some(c);
    // }

    // fn get_color(&)

    fn is_inside_primitive(&self, p: Point) -> bool {
        let spanA = Point { x: self.b.x - self.a.x, y: self.b.y - self.a.y };
        let spanB = Point { x: self.c.x - self.a.x, y: self.c.y - self.a.y };

        let q = Point { x: p.x - self.a.x, y: p.y - self.a.y };

        let s = q.cross_product(spanB) as f32 / spanA.cross_product(spanB) as f32;
        let t = spanA.cross_product(q) as f32 / spanA.cross_product(spanB) as f32;

        (s >= 0.0) && (t >= 0.0) && ((s + t) <= 1.0)
    }

    fn get_bounding_box(&self) -> BoundingBox {
        use std::cmp::{min, max};
        BoundingBox {
            top_left: Point {
                x: min(min(self.a.x, self.b.x), self.c.x),
                y: min(min(self.a.y, self.b.y), self.c.y),
            },
            bottom_right: Point {
                x: max(max(self.a.x, self.b.x), self.c.x),
                y: max(max(self.a.y, self.b.y), self.c.y),
            }
        }
    }
}

pub struct RandomPointGenerator {
    rng: Box<Rng>,
    width: i32,
    height: i32,
}

impl RandomPointGenerator {
    pub fn new(width: i32, height: i32) -> RandomPointGenerator {
        RandomPointGenerator {
            rng: Box::new(rand::thread_rng()),
            width: width,
            height: height,
        }
    }

    fn next_point(&mut self) -> Point {
        Point {
            x: self.rng.gen_range(0, self.width),
            y: self.rng.gen_range(0, self.height),
        }
    }
}

pub struct Geometrify {
    point_gen: RandomPointGenerator,
}

impl Geometrify {
    pub fn new(point_gen: RandomPointGenerator) -> Geometrify {
        Geometrify {
            point_gen: point_gen
        }
    }

    fn calculate_color(image: &RgbaImage, primitive: Triangle) -> Rgba<u8> {
        let bb = primitive.get_bounding_box();

        let mut count = 0u64;
        let mut cr = 0u64;
        let mut cg = 0u64;
        let mut cb = 0u64;
        let mut ca = 0u64;

        for y in bb.top_left.y..bb.bottom_right.y {
            for x in bb.top_left.x..bb.bottom_right.x {
                let (r, g, b, a) = image.get_pixel(x as u32, y as u32).channels4();
                cr += r as u64;
                cg += g as u64;
                cb += b as u64;
                ca += a as u64;
                count += 1;
            }
        }

        if count == 0 {
            Rgba::from_channels(255, 255, 255, 255)
        } else {
            Rgba::from_channels((cr / count) as u8,
                                (cg / count) as u8,
                                (cb / count) as u8,
                                (ca / count) as u8)
        }
    }

    fn generate_primitive(&mut self) -> Triangle {
        Triangle::new(self.point_gen.next_point(),
                      self.point_gen.next_point(),
                      self.point_gen.next_point())
    }

    fn add_to_image(image: &mut RgbaImage, primitive: Triangle) {
        let bb = primitive.get_bounding_box();

        for y in bb.top_left.y..bb.bottom_right.y {
            for x in bb.top_left.x..bb.bottom_right.x {
        // for y in 0..image.height() {
        //     for x in 0..image.width() {
                let p = Point {x: x as i32, y: y as i32};
                if primitive.is_inside_primitive(p) {
                    *image.get_pixel_mut(x as u32, y as u32) = Geometrify::mixColor(primitive.color.expect("color of triangle not set"), *image.get_pixel(x as u32, y as u32));
                }
            }
        }
    }

    fn mixColor(first: Rgba<u8>, second: Rgba<u8>) -> Rgba<u8> {
        let (r1, g1, b1, a1) = first.channels4();
        let (r2, g2, b2, a2) = second.channels4();

        Rgba::from_channels(
            ((((r1 as u32 + r2 as u32)) / 2) as u8),
            ((((g1 as u32 + g2 as u32)) / 2) as u8),
            ((((b1 as u32 + b2 as u32)) / 2) as u8),
            ((((a1 as u32 + a2 as u32)) / 2) as u8),
        )
    }

    fn difference(first: Rgba<u8>, second: Rgba<u8>) -> i32 {
        let (r1, g1, b1, a1) = first.channels4();
        let (r2, g2, b2, a2) = second.channels4();
        let mut d = 0i32;

        d += i32::abs((r1 as i32 - r2 as i32));
        d += i32::abs((g1 as i32 - g2 as i32));
        d += i32::abs((b1 as i32 - b2 as i32));
        d += i32::abs((a1 as i32 - a2 as i32));

        d
    }

    fn calculate_difference(original: &RgbaImage, current: &RgbaImage, primitive: Triangle) -> i32 {
        let bb = primitive.get_bounding_box();

        let mut d = 0i32;

        for y in 0..original.height() {
            for x in 0..original.width() {
                let originalRgb = original.get_pixel(x, y);
                let resultRgb = if (bb.top_left.x as u32 <= x) && (x <= bb.bottom_right.x as u32)
                    && (bb.top_left.y as u32 <= y) && (y <= bb.bottom_right.y as u32)
                    && (primitive.is_inside_primitive(Point { x: x as i32, y: y as i32 })) {
                        Geometrify::mixColor(*current.get_pixel(x, y), primitive.color.expect("triangle color not "))
                    } else {
                        *current.get_pixel(x, y)
                    };

                d += Geometrify::difference(*originalRgb, resultRgb);
            }
        }

        d
    }

    pub fn apply(&mut self, image: RgbaImage, numberOfIterations: i32, numberOfSamples: i32) -> RgbaImage {
        let mut destination = RgbaImage::new(image.width(), image.height());

        for _ in 0..numberOfIterations {
            let minPrimitive = (0..numberOfSamples).map(|_| {
                self.generate_primitive()
            }).collect::<Vec<Triangle>>().par_iter()
                .map(|primitive| {
                    let mut prim = *primitive;
                    prim.color = Some(Geometrify::calculate_color(&image, prim));
                    (prim, Geometrify::calculate_difference(&image, &destination, prim))
                }).min_by_key(|tup| tup.1);

            Geometrify::add_to_image(&mut destination, minPrimitive.expect("no fitting triangle found").0);
        }

        destination
    }

}

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


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

//#![feature(collections)]
//#![cfg_attr(test, feature(test))]

/// Unstable: this library is still in rapid development

extern crate byteorder;
extern crate rustc_serialize as serialize;

pub const MSGPACK_VERSION : u32 = 5;

pub mod core;

pub use core::{
    Marker,
};

pub use core::encode;

pub use core::decode::serialize::{
    Decoder,
};

pub use core::encode::serialize::{
    Encoder,
};

/// Temporary. Move to error.rs module.
pub use core::{Error, ReadError};

//#[cfg(test)]
//mod bench;

// Stage 1. Low-level decoding functions.
// Stage 2. Value decoding functions.
// Stage 3. Deserialization.
// Stage 4. Low-level encoding functions.
// Stage 5. Value encoding functions.
// Stage 6. Serialization.
<commit_msg>[Misc] Planning note.<commit_after>#![crate_name = "msgpack"]

//#![feature(collections)]
//#![cfg_attr(test, feature(test))]

/// Unstable: this library is still in rapid development

extern crate byteorder;
extern crate rustc_serialize as serialize;

pub const MSGPACK_VERSION : u32 = 5;

pub mod core;

pub use core::{
    Marker,
};

pub use core::encode;

pub use core::decode::serialize::{
    Decoder,
};

pub use core::encode::serialize::{
    Encoder,
};

/// Temporary. Move to error.rs module.
pub use core::{Error, ReadError};

//#[cfg(test)]
//mod bench;

// Stage 1. Low-level decoding functions.
// Stage 2. Value decoding functions.
// Stage 3. Deserialization.
// Stage 4. Low-level encoding functions.
// Stage 5. Value encoding functions.
// Stage 6. Serialization.

// NOTE: Write about strict integer typing. Sized integers always encoded as sized even if they are
// fit in unsized, i.e 100 -> i32 -> posfix.
<|endoftext|>


<commit_before>//! The `gettext` crate provides functionality for
//! parsing and using Gettext catalogs stored in MO files.

// https://pascalhertleif.de/artikel/good-practices-for-writing-rust-libraries/
#![deny(missing_docs, missing_debug_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code, unstable_features,
        unused_import_braces, unused_qualifications)]

use std::collections::HashMap;
use std::ops::Deref;

/// Catalog represents a set of translation strings
/// parsed out of one MO file.
#[derive(Debug)]
pub struct Catalog {
    strings: HashMap<String, Message>,
}

impl Catalog {
    fn new() -> Self {
        Catalog { strings: HashMap::new() }
    }

    fn insert(&mut self, msg: Message) {
        let key = match msg.context {
            Some(ref ctxt) => [ctxt.deref(), &*msg.id].join("\x04"),
            None => msg.id.clone(),
        };
        self.strings.insert(key, msg);
    }

    /// Returns the singular translation of `msg_id` from the given catalog
    /// or `msg_id` itself if a translation does not exist.
    pub fn gettext<'a>(&'a self, msg_id: &'a str) -> &'a str {
        self.strings.get(Into::into(msg_id)).and_then(|msg| msg.singular()).unwrap_or(msg_id)
    }
}

#[derive(Debug)]
struct Message {
    id: String,
    context: Option<String>,
    translated: Vec<String>,
}

impl Message {
    fn new<T: Into<String>>(id: T, context: Option<T>, translated: Vec<T>) -> Self {
        Message {
            id: id.into(),
            context: context.map(Into::into),
            translated: translated.into_iter().map(Into::into).collect(),
        }
    }

    fn singular(&self) -> Option<&str> {
        self.translated.get(0).map(|s| s.deref())
    }
}

#[test]
fn catalog_insert() {
    let mut cat = Catalog::new();
    cat.insert(Message::new("thisisid", None, vec![]));
    cat.insert(Message::new("anotherid", Some("context"), vec![]));
    let mut keys = cat.strings.keys().collect::<Vec<_>>();
    keys.sort();
    assert_eq!(keys, &["context\x04anotherid", "thisisid"])
}

#[test]
fn catalog_gettext() {
    let mut cat = Catalog::new();
    cat.insert(Message::new("Text", None, vec!["Tekstas"]));
    assert_eq!(cat.gettext("Text"), "Tekstas");
    assert_eq!(cat.gettext("Image"), "Image");
}
<commit_msg>ngettext()<commit_after>//! The `gettext` crate provides functionality for
//! parsing and using Gettext catalogs stored in MO files.

// https://pascalhertleif.de/artikel/good-practices-for-writing-rust-libraries/
#![deny(missing_docs, missing_debug_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code, unstable_features,
        unused_import_braces, unused_qualifications)]

use std::collections::HashMap;
use std::ops::Deref;

/// Catalog represents a set of translation strings
/// parsed out of one MO file.
#[derive(Debug)]
pub struct Catalog {
    strings: HashMap<String, Message>,
}

impl Catalog {
    fn new() -> Self {
        Catalog { strings: HashMap::new() }
    }

    fn insert(&mut self, msg: Message) {
        let key = match msg.context {
            Some(ref ctxt) => [ctxt.deref(), &*msg.id].join("\x04"),
            None => msg.id.clone(),
        };
        self.strings.insert(key, msg);
    }

    /// Returns the singular translation of `msg_id` from the given catalog
    /// or `msg_id` itself if a translation does not exist.
    pub fn gettext<'a>(&'a self, msg_id: &'a str) -> &'a str {
        self.strings.get(&msg_id.to_owned()).and_then(|msg| msg.get_translated(0)).unwrap_or(msg_id)
    }

    /// Returns the plural translation of `msg_id` from the given catalog
    /// with the correct plural form for the number `n` of objects.
    /// Returns msg_id if a translation does not exist and `n == 1`,
    /// msg_id_plural otherwise.
    ///
    /// Currently, the only supported plural formula is `n != 1`.
    pub fn ngettext<'a>(&'a self, msg_id: &'a str, msg_id_plural: &'a str, n: usize) -> &'a str {
        let form_no = if n != 1 {
            1
        } else {
            0
        };

        match self.strings.get(&msg_id.to_owned()) {
            Some(msg) => {
                msg.get_translated(form_no).unwrap_or_else(|| [msg_id, msg_id_plural][form_no])
            }
            None if form_no == 0 => msg_id,
            None if form_no == 1 => msg_id_plural,
            _ => unreachable!(),
        }
    }
}

#[derive(Debug)]
struct Message {
    id: String,
    context: Option<String>,
    translated: Vec<String>,
}

impl Message {
    fn new<T: Into<String>>(id: T, context: Option<T>, translated: Vec<T>) -> Self {
        Message {
            id: id.into(),
            context: context.map(Into::into),
            translated: translated.into_iter().map(Into::into).collect(),
        }
    }

    fn get_translated(&self, form_no: usize) -> Option<&str> {
        self.translated.get(form_no).map(|s| s.deref())
    }
}

#[test]
fn catalog_insert() {
    let mut cat = Catalog::new();
    cat.insert(Message::new("thisisid", None, vec![]));
    cat.insert(Message::new("anotherid", Some("context"), vec![]));
    let mut keys = cat.strings.keys().collect::<Vec<_>>();
    keys.sort();
    assert_eq!(keys, &["context\x04anotherid", "thisisid"])
}

#[test]
fn catalog_gettext() {
    let mut cat = Catalog::new();
    cat.insert(Message::new("Text", None, vec!["Tekstas"]));
    assert_eq!(cat.gettext("Text"), "Tekstas");
    assert_eq!(cat.gettext("Image"), "Image");
}

#[test]
fn catalog_ngettext() {
    let mut cat = Catalog::new();
    {
        // n == 1, no translation
        assert_eq!(cat.ngettext("Text", "Texts", 1), "Text");
        // n != 1, no translation
        assert_eq!(cat.ngettext("Text", "Texts", 0), "Texts");
        assert_eq!(cat.ngettext("Text", "Texts", 2), "Texts");
    }
    {
        cat.insert(Message::new("Text", None, vec!["Tekstas", "Tekstai"]));
        // n == 1, translation available
        assert_eq!(cat.ngettext("Text", "Texts", 1), "Tekstas");
        // n != 1, translation available
        assert_eq!(cat.ngettext("Text", "Texts", 0), "Tekstai");
        assert_eq!(cat.ngettext("Text", "Texts", 2), "Tekstai");
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]
#![feature(io)]
#![feature(path)]

mod just;
pub mod led;
<commit_msg>fix: update to rust nightly<commit_after>#![deny(warnings)]
#![feature(old_path)]
#![feature(old_io)]

mod just;
pub mod led;
<|endoftext|>


<commit_before>#![feature(plugin_registrar, box_syntax, rustc_private, custom_derive, quote, plugin, custom_attribute)]

#[macro_use]
extern crate rustc;
extern crate rustc_front;
extern crate rustc_plugin;
#[macro_use]
extern crate syntax;
extern crate syntax_ext;

use rustc_plugin::Registry;
use syntax::parse::token::intern;
use syntax::ext::base::MultiDecorator;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(intern("derive_From"), MultiDecorator(box expand_derive_from));
}

use std::collections::HashMap;

use syntax::ast::{Ident, Ty, VariantData, ItemKind, MetaItem, EnumDef};
use syntax::codemap::Span;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;
use syntax::print::pprust::ty_to_string;

/// Provides the hook to expand `#[derive(From)]` into an implementation of `From`
fn expand_derive_from(cx: &mut ExtCtxt, span: Span, _: &MetaItem,
                          item: &Annotatable, push: &mut FnMut(Annotatable)) {

    // Get the that is wrapped by the newtype and do some checks
    let failed = match *item {
        Annotatable::Item(ref x) => {
            match x.node {
                ItemKind::Struct(VariantData::Tuple(ref structs, _), _) => {
                    if structs.len() == 1 {
                        newtype_from(cx, x.ident, structs[0].node.ty.clone(), push);
                        false
                    }
                    else {
                        true
                    }
                },
                ItemKind::Enum(ref definition, _) => {
                    enum_from(cx, x.ident, definition, push);
                    false

                }
                _ => true,
            }
        },
        _ => true,
    };

    if failed {
        cx.span_bug(span, "only newtype structs can use `derive(From)`");
    }
}

fn newtype_from(cx: &mut ExtCtxt, ident: Ident, old_type: P<Ty>,
                push: &mut FnMut(Annotatable)) {
    let code = quote_item!(cx,
        impl ::std::convert::From<$old_type> for $ident {
            fn from(a: $old_type) -> $ident {
                $ident(a)
            }
        }
    ).unwrap();

    push(Annotatable::Item(code));
}

fn enum_from(cx: &mut ExtCtxt, enum_ident: Ident, definition: &EnumDef,
             push: &mut FnMut(Annotatable)) {
    let mut types = vec![];
    let mut idents = vec![];
    let mut type_counts = HashMap::new();

    for variant in &definition.variants {
        match variant.node.data {
            VariantData::Tuple(ref structs, _) => {
                if structs.len() == 1 {
                    let ty = structs[0].node.ty.clone();
                    idents.push(variant.node.name);
                    types.push(ty.clone());
                    let counter = type_counts.entry(ty_to_string(&*ty)).or_insert(0);
                    *counter += 1;
                }
            }
            _ => (),
        }
    }

    for (ident, old_type) in idents.iter().zip(types) {
        if *type_counts.get(&ty_to_string(&*old_type)).unwrap() != 1 {
            // If more than one newtype is present don't add automatic From, since it is
            // ambiguous.
            continue
        }

        let code = quote_item!(cx,
            impl ::std::convert::From<$old_type> for $enum_ident {
                fn from(a: $old_type) -> $enum_ident {
                    $enum_ident::$ident(a)
                }
            }
        ).unwrap();

        push(Annotatable::Item(code));
    }
}
<commit_msg>Remove some unnecessary included features<commit_after>#![feature(plugin_registrar, box_syntax, rustc_private, custom_derive, quote)]

#[macro_use]
extern crate rustc;
extern crate rustc_front;
extern crate rustc_plugin;
#[macro_use]
extern crate syntax;
extern crate syntax_ext;

use rustc_plugin::Registry;
use syntax::parse::token::intern;
use syntax::ext::base::MultiDecorator;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(intern("derive_From"), MultiDecorator(box expand_derive_from));
}

use std::collections::HashMap;

use syntax::ast::{Ident, Ty, VariantData, ItemKind, MetaItem, EnumDef};
use syntax::codemap::Span;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;
use syntax::print::pprust::ty_to_string;

/// Provides the hook to expand `#[derive(From)]` into an implementation of `From`
fn expand_derive_from(cx: &mut ExtCtxt, span: Span, _: &MetaItem,
                          item: &Annotatable, push: &mut FnMut(Annotatable)) {

    // Get the that is wrapped by the newtype and do some checks
    let failed = match *item {
        Annotatable::Item(ref x) => {
            match x.node {
                ItemKind::Struct(VariantData::Tuple(ref structs, _), _) => {
                    if structs.len() == 1 {
                        newtype_from(cx, x.ident, structs[0].node.ty.clone(), push);
                        false
                    }
                    else {
                        true
                    }
                },
                ItemKind::Enum(ref definition, _) => {
                    enum_from(cx, x.ident, definition, push);
                    false

                }
                _ => true,
            }
        },
        _ => true,
    };

    if failed {
        cx.span_bug(span, "only newtype structs can use `derive(From)`");
    }
}

fn newtype_from(cx: &mut ExtCtxt, ident: Ident, old_type: P<Ty>,
                push: &mut FnMut(Annotatable)) {
    let code = quote_item!(cx,
        impl ::std::convert::From<$old_type> for $ident {
            fn from(a: $old_type) -> $ident {
                $ident(a)
            }
        }
    ).unwrap();

    push(Annotatable::Item(code));
}

fn enum_from(cx: &mut ExtCtxt, enum_ident: Ident, definition: &EnumDef,
             push: &mut FnMut(Annotatable)) {
    let mut types = vec![];
    let mut idents = vec![];
    let mut type_counts = HashMap::new();

    for variant in &definition.variants {
        match variant.node.data {
            VariantData::Tuple(ref structs, _) => {
                if structs.len() == 1 {
                    let ty = structs[0].node.ty.clone();
                    idents.push(variant.node.name);
                    types.push(ty.clone());
                    let counter = type_counts.entry(ty_to_string(&*ty)).or_insert(0);
                    *counter += 1;
                }
            }
            _ => (),
        }
    }

    for (ident, old_type) in idents.iter().zip(types) {
        if *type_counts.get(&ty_to_string(&*old_type)).unwrap() != 1 {
            // If more than one newtype is present don't add automatic From, since it is
            // ambiguous.
            continue
        }

        let code = quote_item!(cx,
            impl ::std::convert::From<$old_type> for $enum_ident {
                fn from(a: $old_type) -> $enum_ident {
                    $enum_ident::$ident(a)
                }
            }
        ).unwrap();

        push(Annotatable::Item(code));
    }
}
<|endoftext|>


<commit_before>//! Support for Unix domain socket clients and servers.
#![feature(io, std_misc, path, core)]
#![warn(missing_docs)]
#![doc(html_root_url="https://sfackler.github.io/rust-unix-socket/doc/unix_socket")]

extern crate libc;

use std::cmp;
use std::ffi::AsOsStr;
use std::io;
use std::iter::IntoIterator;
use std::mem;
use std::num::Int;
use std::os::unix::{Fd, OsStrExt, AsRawFd};
use std::path::AsPath;

struct Inner(Fd);

impl Drop for Inner {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.0);
        }
    }
}

impl Inner {
    unsafe fn new() -> io::Result<Inner> {
        let fd = libc::socket(libc::AF_UNIX, libc::SOCK_STREAM, 0);
        if fd < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(Inner(fd))
        }
    }

}

unsafe fn sockaddr_un<P: AsPath + ?Sized>(path: &P) -> io::Result<libc::sockaddr_un> {
    let mut addr: libc::sockaddr_un = mem::zeroed();
    addr.sun_family = libc::AF_UNIX as libc::sa_family_t;

    let bytes = path.as_path().as_os_str().as_bytes();
    if bytes.len() > addr.sun_path.len() - 1 {
        return Err(io::Error::new(io::ErrorKind::InvalidInput,
                                  "path must be smaller than SUN_LEN",
                                  None));
    }
    for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
        *dst = *src as libc::c_char;
    }
    // null byte's already there because we zeroed the struct

    Ok(addr)
}

/// A stream which communicates over a Unix domain socket.
pub struct UnixStream {
    inner: Inner,
}

impl UnixStream {
    /// Connect to the socket named by `path`.
    pub fn connect<P: AsPath + ?Sized>(path: &P) -> io::Result<UnixStream> {
        unsafe {
            let inner = try!(Inner::new());
            let addr = try!(sockaddr_un(path));

            let ret = libc::connect(inner.0,
                                    &addr as *const _ as *const _,
                                    mem::size_of::<libc::sockaddr_un>() as libc::socklen_t);
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(UnixStream {
                    inner: inner,
                })
            }
        }
    }
}

fn calc_len(buf: &[u8]) -> libc::size_t {
    cmp::min(<libc::size_t as Int>::max_value() as usize, buf.len()) as libc::size_t
}

impl io::Read for UnixStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let ret = unsafe {
            libc::recv(self.inner.0, buf.as_mut_ptr() as *mut _, calc_len(buf), 0)
        };

        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(ret as usize)
        }
    }
}

impl io::Write for UnixStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let ret = unsafe {
            libc::send(self.inner.0, buf.as_ptr() as *const _, calc_len(buf), 0)
        };

        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(ret as usize)
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl AsRawFd for UnixStream {
    fn as_raw_fd(&self) -> Fd {
        self.inner.0
    }
}

/// A structure representing a Unix domain socket server.
pub struct UnixListener {
    inner: Inner,
}

impl UnixListener {
    /// Creates a new `UnixListener` which will be bound to the specified socket.
    pub fn bind<P: AsPath + ?Sized>(path: &P) -> io::Result<UnixListener> {
        unsafe {
            let inner = try!(Inner::new());
            let addr = try!(sockaddr_un(path));

            let ret = libc::bind(inner.0,
                                 &addr as *const _ as *const _,
                                 mem::size_of::<libc::sockaddr_un>() as libc::socklen_t);
            if ret < 0 {
                return Err(io::Error::last_os_error());
            }

            let ret = libc::listen(inner.0, 128);
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(UnixListener {
                    inner: inner,
                })
            }
        }
    }

    /// Accepts a new incoming connection to this listener.
    pub fn accept(&self) -> io::Result<UnixStream> {
        unsafe {
            let ret = libc::accept(self.inner.0, 0 as *mut _, 0 as *mut _);
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(UnixStream {
                    inner: Inner(ret)
                })
            }
        }
    }

    /// Returns an iterator over incoming connections.
    ///
    /// The iterator will never return `None`.
    pub fn incoming<'a>(&'a self) -> Incoming<'a> {
        Incoming {
            listener: self
        }
    }
}

impl AsRawFd for UnixListener {
    fn as_raw_fd(&self) -> Fd {
        self.inner.0
    }
}

impl<'a> IntoIterator for &'a UnixListener {
    type Item = io::Result<UnixStream>;
    type IntoIter = Incoming<'a>;

    fn into_iter(self) -> Incoming<'a> {
        self.incoming()
    }
}

/// An iterator over incoming connections to a `UnixListener`.
///
/// It will never return `None`.
pub struct Incoming<'a> {
    listener: &'a UnixListener,
}

impl<'a> Iterator for Incoming<'a> {
    type Item = io::Result<UnixStream>;

    fn next(&mut self) -> Option<io::Result<UnixStream>> {
        Some(self.listener.accept())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (Int::max_value(), None)
    }
}

#[cfg(test)]
mod test {
    extern crate temporary;

    use std::thread;
    use std::io;
    use std::io::prelude::*;

    use {UnixListener, UnixStream};

    macro_rules! or_panic {
        ($e:expr) => {
            match $e {
                Ok(e) => e,
                Err(e) => panic!("{}", e),
            }
        }
    }

    #[test]
    fn basic() {
        let dir = or_panic!(temporary::Directory::new("unix_socket"));
        let socket_path = dir.path().join("sock");
        let msg1 = b"hello";
        let msg2 = b"world!";

        let listener = or_panic!(UnixListener::bind(&socket_path));
        let thread = thread::scoped(|| {
            let mut stream = or_panic!(listener.accept());
            let mut buf = [0; 5];
            or_panic!(stream.read(&mut buf));
            assert_eq!(msg1, buf);
            or_panic!(stream.write_all(msg2));
        });

        let mut stream = or_panic!(UnixStream::connect(&socket_path));
        or_panic!(stream.write_all(msg1));
        let mut buf = vec![];
        or_panic!(stream.read_to_end(&mut buf));
        assert_eq!(msg2, buf);
        drop(stream);

        thread.join();
    }

    #[test]
    fn iter() {
        let dir = or_panic!(temporary::Directory::new("unix_socket"));
        let socket_path = dir.path().join("sock");

        let listener = or_panic!(UnixListener::bind(&socket_path));
        let thread = thread::scoped(|| {
            for stream in listener.incoming().take(2) {
                let mut stream = or_panic!(stream);
                let mut buf = [0];
                or_panic!(stream.read(&mut buf));
            }
        });

        for _ in 0..2 {
            let mut stream = or_panic!(UnixStream::connect(&socket_path));
            or_panic!(stream.write_all(&[0]));
        }

        thread.join();
    }

    #[test]
    fn long_path() {
        let socket_path = "asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd\
                           asdfasdfasdfadfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd";
        match UnixStream::connect(socket_path) {
            Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {}
            Err(e) => panic!("unexpected error {}", e),
            Ok(_) => panic!("unexpected success"),
        }

        match UnixListener::bind(socket_path) {
            Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {}
            Err(e) => panic!("unexpected error {}", e),
            Ok(_) => panic!("unexpected success"),
        }
    }
}
<commit_msg>Fix doc root<commit_after>//! Support for Unix domain socket clients and servers.
#![feature(io, std_misc, path, core)]
#![warn(missing_docs)]
#![doc(html_root_url="https://sfackler.github.io/rust-unix-socket/doc")]

extern crate libc;

use std::cmp;
use std::ffi::AsOsStr;
use std::io;
use std::iter::IntoIterator;
use std::mem;
use std::num::Int;
use std::os::unix::{Fd, OsStrExt, AsRawFd};
use std::path::AsPath;

struct Inner(Fd);

impl Drop for Inner {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.0);
        }
    }
}

impl Inner {
    unsafe fn new() -> io::Result<Inner> {
        let fd = libc::socket(libc::AF_UNIX, libc::SOCK_STREAM, 0);
        if fd < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(Inner(fd))
        }
    }

}

unsafe fn sockaddr_un<P: AsPath + ?Sized>(path: &P) -> io::Result<libc::sockaddr_un> {
    let mut addr: libc::sockaddr_un = mem::zeroed();
    addr.sun_family = libc::AF_UNIX as libc::sa_family_t;

    let bytes = path.as_path().as_os_str().as_bytes();
    if bytes.len() >= addr.sun_path.len() {
        return Err(io::Error::new(io::ErrorKind::InvalidInput,
                                  "path must be smaller than SUN_LEN",
                                  None));
    }
    for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
        *dst = *src as libc::c_char;
    }
    // null byte's already there because we zeroed the struct

    Ok(addr)
}

/// A stream which communicates over a Unix domain socket.
pub struct UnixStream {
    inner: Inner,
}

impl UnixStream {
    /// Connect to the socket named by `path`.
    pub fn connect<P: AsPath + ?Sized>(path: &P) -> io::Result<UnixStream> {
        unsafe {
            let inner = try!(Inner::new());
            let addr = try!(sockaddr_un(path));

            let ret = libc::connect(inner.0,
                                    &addr as *const _ as *const _,
                                    mem::size_of::<libc::sockaddr_un>() as libc::socklen_t);
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(UnixStream {
                    inner: inner,
                })
            }
        }
    }
}

fn calc_len(buf: &[u8]) -> libc::size_t {
    cmp::min(<libc::size_t as Int>::max_value() as usize, buf.len()) as libc::size_t
}

impl io::Read for UnixStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let ret = unsafe {
            libc::recv(self.inner.0, buf.as_mut_ptr() as *mut _, calc_len(buf), 0)
        };

        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(ret as usize)
        }
    }
}

impl io::Write for UnixStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let ret = unsafe {
            libc::send(self.inner.0, buf.as_ptr() as *const _, calc_len(buf), 0)
        };

        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(ret as usize)
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl AsRawFd for UnixStream {
    fn as_raw_fd(&self) -> Fd {
        self.inner.0
    }
}

/// A structure representing a Unix domain socket server.
pub struct UnixListener {
    inner: Inner,
}

impl UnixListener {
    /// Creates a new `UnixListener` which will be bound to the specified socket.
    pub fn bind<P: AsPath + ?Sized>(path: &P) -> io::Result<UnixListener> {
        unsafe {
            let inner = try!(Inner::new());
            let addr = try!(sockaddr_un(path));

            let ret = libc::bind(inner.0,
                                 &addr as *const _ as *const _,
                                 mem::size_of::<libc::sockaddr_un>() as libc::socklen_t);
            if ret < 0 {
                return Err(io::Error::last_os_error());
            }

            let ret = libc::listen(inner.0, 128);
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(UnixListener {
                    inner: inner,
                })
            }
        }
    }

    /// Accepts a new incoming connection to this listener.
    pub fn accept(&self) -> io::Result<UnixStream> {
        unsafe {
            let ret = libc::accept(self.inner.0, 0 as *mut _, 0 as *mut _);
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(UnixStream {
                    inner: Inner(ret)
                })
            }
        }
    }

    /// Returns an iterator over incoming connections.
    ///
    /// The iterator will never return `None`.
    pub fn incoming<'a>(&'a self) -> Incoming<'a> {
        Incoming {
            listener: self
        }
    }
}

impl AsRawFd for UnixListener {
    fn as_raw_fd(&self) -> Fd {
        self.inner.0
    }
}

impl<'a> IntoIterator for &'a UnixListener {
    type Item = io::Result<UnixStream>;
    type IntoIter = Incoming<'a>;

    fn into_iter(self) -> Incoming<'a> {
        self.incoming()
    }
}

/// An iterator over incoming connections to a `UnixListener`.
///
/// It will never return `None`.
pub struct Incoming<'a> {
    listener: &'a UnixListener,
}

impl<'a> Iterator for Incoming<'a> {
    type Item = io::Result<UnixStream>;

    fn next(&mut self) -> Option<io::Result<UnixStream>> {
        Some(self.listener.accept())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (Int::max_value(), None)
    }
}

#[cfg(test)]
mod test {
    extern crate temporary;

    use std::thread;
    use std::io;
    use std::io::prelude::*;

    use {UnixListener, UnixStream};

    macro_rules! or_panic {
        ($e:expr) => {
            match $e {
                Ok(e) => e,
                Err(e) => panic!("{}", e),
            }
        }
    }

    #[test]
    fn basic() {
        let dir = or_panic!(temporary::Directory::new("unix_socket"));
        let socket_path = dir.path().join("sock");
        let msg1 = b"hello";
        let msg2 = b"world!";

        let listener = or_panic!(UnixListener::bind(&socket_path));
        let thread = thread::scoped(|| {
            let mut stream = or_panic!(listener.accept());
            let mut buf = [0; 5];
            or_panic!(stream.read(&mut buf));
            assert_eq!(msg1, buf);
            or_panic!(stream.write_all(msg2));
        });

        let mut stream = or_panic!(UnixStream::connect(&socket_path));
        or_panic!(stream.write_all(msg1));
        let mut buf = vec![];
        or_panic!(stream.read_to_end(&mut buf));
        assert_eq!(msg2, buf);
        drop(stream);

        thread.join();
    }

    #[test]
    fn iter() {
        let dir = or_panic!(temporary::Directory::new("unix_socket"));
        let socket_path = dir.path().join("sock");

        let listener = or_panic!(UnixListener::bind(&socket_path));
        let thread = thread::scoped(|| {
            for stream in listener.incoming().take(2) {
                let mut stream = or_panic!(stream);
                let mut buf = [0];
                or_panic!(stream.read(&mut buf));
            }
        });

        for _ in 0..2 {
            let mut stream = or_panic!(UnixStream::connect(&socket_path));
            or_panic!(stream.write_all(&[0]));
        }

        thread.join();
    }

    #[test]
    fn long_path() {
        let socket_path = "asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd\
                           asdfasdfasdfadfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd";
        match UnixStream::connect(socket_path) {
            Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {}
            Err(e) => panic!("unexpected error {}", e),
            Ok(_) => panic!("unexpected success"),
        }

        match UnixListener::bind(socket_path) {
            Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {}
            Err(e) => panic!("unexpected error {}", e),
            Ok(_) => panic!("unexpected success"),
        }
    }
}
<|endoftext|>


<commit_before>// XXX: Use a ref-counted gene Pool.
// A population is then only a collection of pool item ids.
// This prevents from duplicating potential large genes.
//
// Use typing to make sure that individuals are evaluated when required.
// fn evaluate(self, evaluator) -> EvaluatedPopulation
// fn add(self, ind) -> Population

#![feature(num_bits_bytes)]
extern crate bit_vec;
extern crate rand;
use rand::{Rng, Rand};
use std::cmp::PartialOrd;

pub mod bit_string;

/// A probability is a value in the range [0.0, 1.0].
/// A probability of 1.0 means `always`, that of 0.0
/// means `never`.
#[derive(Copy, Clone, Debug)]
pub struct Probability(f32);

impl Probability {
    #[inline]
    pub fn new(pb: f32) -> Probability {
        assert!(pb >= 0.0 && pb <= 1.0);
        Probability(pb)
    }
}

impl std::ops::Add<Probability> for Probability {
    type Output = Probability;
    #[inline]
    fn add(self, rhs: Probability) -> Probability {
        Probability::new(self.0 + rhs.0)
    }
}

/// A probability value is a random value in the
/// range [0.0, 1.0).
#[derive(Copy, Clone, Debug)]
pub struct ProbabilityValue(f32);

impl Rand for ProbabilityValue {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> ProbabilityValue {
        let val = rng.gen::<f32>();
        assert!(val >= 0.0 && val < 1.0);
        ProbabilityValue(val)
    }
}

impl ProbabilityValue {
    pub fn is_probable_with(self, pb: Probability) -> bool {
        self.0 < pb.0
    }
}

/// Represents a fitness value.
pub trait Fitness: Clone {
    fn fitter_than(&self, other: &Self) -> bool;
}

/// Maximizes the fitness value as objective.
#[derive(Copy, Clone, Debug)]
pub struct MaxFitness<T:PartialOrd+Clone>(pub T);
impl<T:PartialOrd+Clone> Fitness for MaxFitness<T> {
    fn fitter_than(&self, other: &MaxFitness<T>) -> bool {
        self.0 > other.0
    }
}

/// Minimizes the fitness value as objective.
#[derive(Copy, Clone, Debug)]
pub struct MinFitness<T:PartialOrd+Clone>(pub T);
impl<T:PartialOrd+Clone> Fitness for MinFitness<T> {
    fn fitter_than(&self, other: &MinFitness<T>) -> bool {
        self.0 < other.0
    }
}

/// Represents an individual in a Population.
pub trait Individual: Clone {
}

/// Evaluates the fitness of an Individual.
pub trait Evaluator<I:Individual, F:Fitness> {
    fn fitness(&self, individual: &I) -> F;
}

/// Caches the `fitness` value for an individual.
#[derive(Clone, Debug)]
pub struct EvaluatedIndividual<I:Individual, F:Fitness> {
    individual: I,
    fitness: Option<F>,
}

impl<I:Individual, F:Fitness>  EvaluatedIndividual<I,F> {
    pub fn new(ind: I) -> EvaluatedIndividual<I,F> {
        EvaluatedIndividual{individual: ind, fitness: None}
    }
    pub fn fitness(&self) -> Option<F> {
        self.fitness.clone()
    }
    pub fn individual<'a>(&'a self) -> &'a I {
        &self.individual
    }
}

/// Manages a population of individuals.
#[derive(Clone, Debug)]
pub struct Population<I:Individual, F:Fitness> {
    population: Vec<EvaluatedIndividual<I,F>>
}

impl<I:Individual, F:Fitness> Population<I,F> {
    pub fn new() -> Population<I,F> {
        Population{population: Vec::new()}
    }

    pub fn with_capacity(capa: usize) -> Population<I,F> {
        Population{population: Vec::with_capacity(capa)}
    }

    pub fn len(&self) -> usize {
        self.population.len()
    }

    /// Return individual with best fitness.
    pub fn fittest(&self) -> Option<(usize, F)> {
        let mut fittest: Option<(usize, F)> = None;

        for (i, ref ind) in self.population.iter().enumerate() {
            if let Some(ref f) = ind.fitness {
                let mut is_better = true;
                if let Some((_, ref best_f)) = fittest {
                    if !f.fitter_than(best_f) {
                        is_better = false;
                    }
                }
                if is_better {
                    fittest = Some((i, f.clone()));
                }
            }
        }
        return fittest;
    }

    pub fn get_ref<'a>(&'a self, idx: usize) -> &'a EvaluatedIndividual<I, F> {
        &self.population[idx]
    }

    pub fn add_individual(&mut self, ind: I) {
        self.population.push(EvaluatedIndividual::new(ind));
    }

    pub fn add(&mut self, ind: EvaluatedIndividual<I,F>) {
        self.population.push(ind);
    }

    /// Evaluates the whole population, i.e. determines the fitness of
    /// each `individual` (unless already calculated).
    /// Returns the number of evaluations performed.
    pub fn evaluate<E>(&mut self, evaluator: &E) -> usize where E:Evaluator<I,F> {
        let mut nevals = 0;
        for i in self.population.iter_mut() {
            if i.fitness.is_some() { continue; }
            i.fitness = Some(evaluator.fitness(&i.individual));
            nevals += 1;
        }
        return nevals;
    }

    fn add_population(&mut self, p: &Population<I,F>) {
        for ind in p.population.iter() {
            self.add(ind.clone());
        }
    }
}

/// Select the best individual out of `k` randomly choosen.
/// This gives individuals with better fitness a higher chance to reproduce.
/// `n` is the total number of individuals.
///
/// NOTE: We are not using `sample(rng, 0..n, k)` as it is *very* expensive.
/// Instead we call `rng.gen_range()` k-times. The drawn items could be the same,
/// but the probability is very low if `n` high compared to `k`.
pub fn tournament_selection<R:Rng, F, E>(rng: &mut R, evaluate: E, n: usize, k: usize) -> Option<(usize, F)>
  where F:Fitness,
        E:Fn(usize) -> F {
    assert!(n >= k);

    let mut best: Option<(usize, F)> = None;

    for _ in 0..k {
        let i = rng.gen_range(0, n);
        let fitness = evaluate(i);
        let better = match best {
            Some((_, ref current_best_fitness)) => {
                fitness.fitter_than(current_best_fitness)
            }
            None => { true }
       };
       if better {
           best = Some((i, fitness));
       }
    }
    return best;
}

pub enum VariationMethod {
    Crossover,
    Mutation,
    Reproduction,
}

/// Mates two individual, producing two children.
pub trait OpCrossover<I: Individual> {
    fn crossover(&mut self, parent1: &I, parent2: &I) -> (I, I);
}

/// Mutates an individual.
pub trait OpMutate<I: Individual> {
    fn mutate(&mut self, ind: &I) -> I;
}

/// Selects a variation method to use.
pub trait OpVariation {
    fn variation(&mut self) -> VariationMethod;
}

/// Selects a random individual from the population.
pub trait OpSelectRandomIndividual<I: Individual, F: Fitness> {
    fn select_random_individual<'a>(&mut self, population: &'a Population<I, F>) -> &'a EvaluatedIndividual<I, F>;
}

/// Produce new generation through selection of \mu individuals from population.
pub trait OpSelect<I: Individual, F: Fitness> {
    fn select(&mut self, population: &Population<I,F>, mu: usize) -> Population<I,F>;
}

pub fn variation_or<I, F, T>(toolbox: &mut T, population: &Population<I,F>, lambda: usize) -> Population<I,F>
where I: Individual,
      F: Fitness,
      T: OpCrossover<I> + OpMutate<I> + OpVariation + OpSelectRandomIndividual<I,F>
{
    let mut offspring = Population::with_capacity(lambda);
    // Each step produces exactly one child.
    for _ in 0..lambda {
        let method = toolbox.variation();
        let child = match method {
            VariationMethod::Crossover => {
                // select two individuals and mate them.
                // only the first offspring is used, the second is thrown away.
                let parent1 = toolbox.select_random_individual(population);
                let parent2 = toolbox.select_random_individual(population);
                let (child1, _child2) = toolbox.crossover(&parent1.individual, &parent2.individual);
                EvaluatedIndividual::new(child1)
            }
            VariationMethod::Mutation => {
                // select a single individual and mutate it.
                let ind = toolbox.select_random_individual(population);
                let child = toolbox.mutate(&ind.individual);
                EvaluatedIndividual::new(child)
            }
            VariationMethod::Reproduction => {
                let ind = toolbox.select_random_individual(population);
                ind.clone()
            }
        };
        offspring.add(child);
    }
    return offspring;
}

// The (\mu + \lambda) algorithm.
// From `population`, \lambda offspring is produced, through either
// mutation, crossover or random reproduction.
// For the next generation, \mu individuals are selected from the \mu + \lambda (parents and offspring).
pub fn ea_mu_plus_lambda<I,F,T,E,S>(toolbox: &mut T, evaluator: &E, population: &Population<I,F>, mu: usize, lambda: usize, num_generations: usize, stat: S)
    -> Population<I,F>
where I: Individual,
      F: Fitness,
      T: OpCrossover<I> + OpMutate<I> + OpVariation + OpSelectRandomIndividual<I,F> + OpSelect<I,F>,
      E: Evaluator<I,F>,
      S: Fn(usize, &Population<I,F>)
{
    let mut p = population.clone();
    p.evaluate(evaluator);
    stat(0, &p);

    for gen in 0..num_generations {
        // evaluate population. make sure that every individual has been rated.
        let mut offspring = variation_or(toolbox, &p, lambda);
        offspring.add_population(&p);
        offspring.evaluate(evaluator);
        // select from offspring the `best` individuals
        p = toolbox.select(&offspring, mu);
        stat(gen+1, &p);
    }

    return p;
}
<commit_msg>Count number of evaluations<commit_after>// XXX: Use a ref-counted gene Pool.
// A population is then only a collection of pool item ids.
// This prevents from duplicating potential large genes.
//
// Use typing to make sure that individuals are evaluated when required.
// fn evaluate(self, evaluator) -> EvaluatedPopulation
// fn add(self, ind) -> Population

#![feature(num_bits_bytes)]
extern crate bit_vec;
extern crate rand;
use rand::{Rng, Rand};
use std::cmp::PartialOrd;

pub mod bit_string;

/// A probability is a value in the range [0.0, 1.0].
/// A probability of 1.0 means `always`, that of 0.0
/// means `never`.
#[derive(Copy, Clone, Debug)]
pub struct Probability(f32);

impl Probability {
    #[inline]
    pub fn new(pb: f32) -> Probability {
        assert!(pb >= 0.0 && pb <= 1.0);
        Probability(pb)
    }
}

impl std::ops::Add<Probability> for Probability {
    type Output = Probability;
    #[inline]
    fn add(self, rhs: Probability) -> Probability {
        Probability::new(self.0 + rhs.0)
    }
}

/// A probability value is a random value in the
/// range [0.0, 1.0).
#[derive(Copy, Clone, Debug)]
pub struct ProbabilityValue(f32);

impl Rand for ProbabilityValue {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> ProbabilityValue {
        let val = rng.gen::<f32>();
        assert!(val >= 0.0 && val < 1.0);
        ProbabilityValue(val)
    }
}

impl ProbabilityValue {
    pub fn is_probable_with(self, pb: Probability) -> bool {
        self.0 < pb.0
    }
}

/// Represents a fitness value.
pub trait Fitness: Clone {
    fn fitter_than(&self, other: &Self) -> bool;
}

/// Maximizes the fitness value as objective.
#[derive(Copy, Clone, Debug)]
pub struct MaxFitness<T:PartialOrd+Clone>(pub T);
impl<T:PartialOrd+Clone> Fitness for MaxFitness<T> {
    fn fitter_than(&self, other: &MaxFitness<T>) -> bool {
        self.0 > other.0
    }
}

/// Minimizes the fitness value as objective.
#[derive(Copy, Clone, Debug)]
pub struct MinFitness<T:PartialOrd+Clone>(pub T);
impl<T:PartialOrd+Clone> Fitness for MinFitness<T> {
    fn fitter_than(&self, other: &MinFitness<T>) -> bool {
        self.0 < other.0
    }
}

/// Represents an individual in a Population.
pub trait Individual: Clone {
}

/// Evaluates the fitness of an Individual.
pub trait Evaluator<I:Individual, F:Fitness> {
    fn fitness(&self, individual: &I) -> F;
}

/// Caches the `fitness` value for an individual.
#[derive(Clone, Debug)]
pub struct EvaluatedIndividual<I:Individual, F:Fitness> {
    individual: I,
    fitness: Option<F>,
}

impl<I:Individual, F:Fitness>  EvaluatedIndividual<I,F> {
    pub fn new(ind: I) -> EvaluatedIndividual<I,F> {
        EvaluatedIndividual{individual: ind, fitness: None}
    }
    pub fn fitness(&self) -> Option<F> {
        self.fitness.clone()
    }
    pub fn individual<'a>(&'a self) -> &'a I {
        &self.individual
    }
}

/// Manages a population of individuals.
#[derive(Clone, Debug)]
pub struct Population<I:Individual, F:Fitness> {
    population: Vec<EvaluatedIndividual<I,F>>
}

impl<I:Individual, F:Fitness> Population<I,F> {
    pub fn new() -> Population<I,F> {
        Population{population: Vec::new()}
    }

    pub fn with_capacity(capa: usize) -> Population<I,F> {
        Population{population: Vec::with_capacity(capa)}
    }

    pub fn len(&self) -> usize {
        self.population.len()
    }

    /// Return individual with best fitness.
    pub fn fittest(&self) -> Option<(usize, F)> {
        let mut fittest: Option<(usize, F)> = None;

        for (i, ref ind) in self.population.iter().enumerate() {
            if let Some(ref f) = ind.fitness {
                let mut is_better = true;
                if let Some((_, ref best_f)) = fittest {
                    if !f.fitter_than(best_f) {
                        is_better = false;
                    }
                }
                if is_better {
                    fittest = Some((i, f.clone()));
                }
            }
        }
        return fittest;
    }

    pub fn get_ref<'a>(&'a self, idx: usize) -> &'a EvaluatedIndividual<I, F> {
        &self.population[idx]
    }

    pub fn add_individual(&mut self, ind: I) {
        self.population.push(EvaluatedIndividual::new(ind));
    }

    pub fn add(&mut self, ind: EvaluatedIndividual<I,F>) {
        self.population.push(ind);
    }

    /// Evaluates the whole population, i.e. determines the fitness of
    /// each `individual` (unless already calculated).
    /// Returns the number of evaluations performed.
    pub fn evaluate<E>(&mut self, evaluator: &E) -> usize where E:Evaluator<I,F> {
        let mut nevals = 0;
        for i in self.population.iter_mut() {
            if i.fitness.is_some() { continue; }
            i.fitness = Some(evaluator.fitness(&i.individual));
            nevals += 1;
        }
        return nevals;
    }

    fn add_population(&mut self, p: &Population<I,F>) {
        for ind in p.population.iter() {
            self.add(ind.clone());
        }
    }
}

/// Select the best individual out of `k` randomly choosen.
/// This gives individuals with better fitness a higher chance to reproduce.
/// `n` is the total number of individuals.
///
/// NOTE: We are not using `sample(rng, 0..n, k)` as it is *very* expensive.
/// Instead we call `rng.gen_range()` k-times. The drawn items could be the same,
/// but the probability is very low if `n` high compared to `k`.
pub fn tournament_selection<R:Rng, F, E>(rng: &mut R, evaluate: E, n: usize, k: usize) -> Option<(usize, F)>
  where F:Fitness,
        E:Fn(usize) -> F {
    assert!(n >= k);

    let mut best: Option<(usize, F)> = None;

    for _ in 0..k {
        let i = rng.gen_range(0, n);
        let fitness = evaluate(i);
        let better = match best {
            Some((_, ref current_best_fitness)) => {
                fitness.fitter_than(current_best_fitness)
            }
            None => { true }
       };
       if better {
           best = Some((i, fitness));
       }
    }
    return best;
}

pub enum VariationMethod {
    Crossover,
    Mutation,
    Reproduction,
}

/// Mates two individual, producing two children.
pub trait OpCrossover<I: Individual> {
    fn crossover(&mut self, parent1: &I, parent2: &I) -> (I, I);
}

/// Mutates an individual.
pub trait OpMutate<I: Individual> {
    fn mutate(&mut self, ind: &I) -> I;
}

/// Selects a variation method to use.
pub trait OpVariation {
    fn variation(&mut self) -> VariationMethod;
}

/// Selects a random individual from the population.
pub trait OpSelectRandomIndividual<I: Individual, F: Fitness> {
    fn select_random_individual<'a>(&mut self, population: &'a Population<I, F>) -> &'a EvaluatedIndividual<I, F>;
}

/// Produce new generation through selection of \mu individuals from population.
pub trait OpSelect<I: Individual, F: Fitness> {
    fn select(&mut self, population: &Population<I,F>, mu: usize) -> Population<I,F>;
}

pub fn variation_or<I, F, T>(toolbox: &mut T, population: &Population<I,F>, lambda: usize) -> Population<I,F>
where I: Individual,
      F: Fitness,
      T: OpCrossover<I> + OpMutate<I> + OpVariation + OpSelectRandomIndividual<I,F>
{
    let mut offspring = Population::with_capacity(lambda);
    // Each step produces exactly one child.
    for _ in 0..lambda {
        let method = toolbox.variation();
        let child = match method {
            VariationMethod::Crossover => {
                // select two individuals and mate them.
                // only the first offspring is used, the second is thrown away.
                let parent1 = toolbox.select_random_individual(population);
                let parent2 = toolbox.select_random_individual(population);
                let (child1, _child2) = toolbox.crossover(&parent1.individual, &parent2.individual);
                EvaluatedIndividual::new(child1)
            }
            VariationMethod::Mutation => {
                // select a single individual and mutate it.
                let ind = toolbox.select_random_individual(population);
                let child = toolbox.mutate(&ind.individual);
                EvaluatedIndividual::new(child)
            }
            VariationMethod::Reproduction => {
                let ind = toolbox.select_random_individual(population);
                ind.clone()
            }
        };
        offspring.add(child);
    }
    return offspring;
}

// The (\mu + \lambda) algorithm.
// From `population`, \lambda offspring is produced, through either
// mutation, crossover or random reproduction.
// For the next generation, \mu individuals are selected from the \mu + \lambda (parents and offspring).
pub fn ea_mu_plus_lambda<I,F,T,E,S>(toolbox: &mut T, evaluator: &E, population: &Population<I,F>, mu: usize, lambda: usize, num_generations: usize, stat: S)
    -> Population<I,F>
where I: Individual,
      F: Fitness,
      T: OpCrossover<I> + OpMutate<I> + OpVariation + OpSelectRandomIndividual<I,F> + OpSelect<I,F>,
      E: Evaluator<I,F>,
      S: Fn(usize, &Population<I,F>)
{
    let mut nevals = 0;
    let mut p = population.clone();
    nevals += p.evaluate(evaluator);
    stat(0, &p);

    for gen in 0..num_generations {
        // evaluate population. make sure that every individual has been rated.
        let mut offspring = variation_or(toolbox, &p, lambda);
        offspring.add_population(&p);
        nevals += offspring.evaluate(evaluator);
        // select from offspring the `best` individuals
        p = toolbox.select(&offspring, mu);
        stat(gen+1, &p);
    }

    return p;
}
<|endoftext|>


<commit_before>//! This crate is a reimplementation
//! of GNU gettext translation framework in Rust.
//! It allows your Rust programs to parse out GNU MO files
//! containing translations and use them in your user interface.
//!
//! It contains several differences from the official C implementation.
//! Notably, this crate does not in any way depend on a global locale
//! ([2.2](https://www.gnu.org/software/gettext/manual/gettext.html#Setting-the-GUI-Locale))
//! and does not enforce a directory structure
//! for storing your translation catalogs
//! ([11.2.3](https://www.gnu.org/software/gettext/manual/gettext.html#Locating-Catalogs)).
//! Instead, the choice of translation catalog to use is explicitly made by the user.
//!
//! This crate is still in-progress
//! and may not be on par with the original implementation feature-wise.
//!
//! For the exact feature parity see the roadmap in the
//! [README](https://github.com/justinas/gettext#readme).
//!
//! # Example
//!
//! ```ignore
//! extern crate gettext;
//!
//! use std::fs::File;
//! use gettext::Catalog;
//!
//! fn main() {
//!     let f = File::open("french.mo").expect("could not open the catalog");
//!     let catalog = Catalog::parse(f).expect("could not parse the catalog");
//!
//!     // Will print out the French translation
//!     // if it is found in the parsed file
//!     // or "Name" otherwise.
//!     println!("{}", catalog.gettext("Name"));
//! }
//! ```

// https://pascalhertleif.de/artikel/good-practices-for-writing-rust-libraries/
#![deny(missing_docs, missing_debug_implementations,
        trivial_casts, trivial_numeric_casts, unused_import_braces)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

mod metadata;
mod parser;

use std::collections::HashMap;
use std::io::Read;
use std::ops::Deref;

pub use parser::{Error, ParseOptions};

/// Returns the number of the appropriate plural form
/// for the given count `n` of objects for germanic languages.
fn plural_form(n: usize) -> usize {
    if n != 1 {
        1
    } else {
        0
    }
}

fn key_with_context(context: &str, key: &str) -> String {
    let mut result = context.to_owned();
    result.push('\x04');
    result.push_str(key);
    result
}

/// Catalog represents a set of translation strings
/// parsed out of one MO file.
#[derive(Debug)]
pub struct Catalog {
    strings: HashMap<String, Message>,
}

impl Catalog {
    /// Creates a new, empty gettext catalog.
    fn new() -> Self {
        Catalog { strings: HashMap::new() }
    }

    /// Parses a gettext catalog from the given binary MO file.
    /// Returns the `Err` variant upon encountering an invalid file format
    /// or invalid byte sequence in strings.
    ///
    /// Calling this method is equivalent to calling
    /// `ParseOptions::new().parse(reader)`.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use gettext::Catalog;
    /// use std::fs::File;
    ///
    /// let file = File::open("french.mo").unwrap();
    /// let catalog = Catalog::parse(file).unwrap();
    /// ```

    pub fn parse<R: Read>(reader: R) -> Result<Self, parser::Error> {
        ParseOptions::new().parse(reader)
    }

    fn insert(&mut self, msg: Message) {
        let key = match msg.context {
            Some(ref ctxt) => key_with_context(ctxt, &msg.id),
            None => msg.id.clone(),
        };
        self.strings.insert(key, msg);
    }

    /// Returns the singular translation of `msg_id` from the given catalog
    /// or `msg_id` itself if a translation does not exist.
    pub fn gettext<'a>(&'a self, msg_id: &'a str) -> &'a str {
        self.strings.get(msg_id).and_then(|msg| msg.get_translated(0)).unwrap_or(msg_id)
    }

    /// Returns the plural translation of `msg_id` from the given catalog
    /// with the correct plural form for the number `n` of objects.
    /// Returns msg_id if a translation does not exist and `n == 1`,
    /// msg_id_plural otherwise.
    ///
    /// Currently, the only supported plural formula is `n != 1`.
    pub fn ngettext<'a>(&'a self, msg_id: &'a str, msg_id_plural: &'a str, n: usize) -> &'a str {
        let form_no = plural_form(n);

        match self.strings.get(msg_id) {
            Some(msg) => {
                msg.get_translated(form_no).unwrap_or_else(|| [msg_id, msg_id_plural][form_no])
            }
            None if form_no == 0 => msg_id,
            None if form_no == 1 => msg_id_plural,
            _ => unreachable!(),
        }
    }

    /// Returns the singular translation of `msg_id`
    /// in the context `msg_context`
    /// or `msg_id` itself if a translation does not exist.
    // TODO: DRY gettext/pgettext
    pub fn pgettext<'a>(&'a self, msg_context: &'a str, msg_id: &'a str) -> &'a str {
        let key = key_with_context(msg_context, &msg_id);
        self.strings.get(&key).and_then(|msg| msg.get_translated(0)).unwrap_or(msg_id)
    }

    /// Returns the plural translation of `msg_id`
    /// in the context `msg_context`
    /// with the correct plural form for the number `n` of objects.
    /// Returns msg_id if a translation does not exist and `n == 1`,
    /// msg_id_plural otherwise.
    ///
    /// Currently, the only supported plural formula is `n != 1`.
    // TODO: DRY ngettext/npgettext
    pub fn npgettext<'a>(&'a self,
                         msg_context: &'a str,
                         msg_id: &'a str,
                         msg_id_plural: &'a str,
                         n: usize)
                         -> &'a str {
        let key = key_with_context(msg_context, &msg_id);
        let form_no = plural_form(n);
        match self.strings.get(&key) {
            Some(msg) => {
                msg.get_translated(form_no).unwrap_or_else(|| [msg_id, msg_id_plural][form_no])
            }
            None if form_no == 0 => msg_id,
            None if form_no == 1 => msg_id_plural,
            _ => unreachable!(),
        }
    }
}

#[derive(Debug, Eq, PartialEq)]
struct Message {
    id: String,
    context: Option<String>,
    translated: Vec<String>,
}

impl Message {
    fn new<T: Into<String>>(id: T, context: Option<T>, translated: Vec<T>) -> Self {
        Message {
            id: id.into(),
            context: context.map(Into::into),
            translated: translated.into_iter().map(Into::into).collect(),
        }
    }

    fn get_translated(&self, form_no: usize) -> Option<&str> {
        self.translated.get(form_no).map(|s| s.deref())
    }
}

#[test]
fn catalog_insert() {
    let mut cat = Catalog::new();
    cat.insert(Message::new("thisisid", None, vec![]));
    cat.insert(Message::new("anotherid", Some("context"), vec![]));
    let mut keys = cat.strings.keys().collect::<Vec<_>>();
    keys.sort();
    assert_eq!(keys, &["context\x04anotherid", "thisisid"])
}

#[test]
fn catalog_gettext() {
    let mut cat = Catalog::new();
    cat.insert(Message::new("Text", None, vec!["Tekstas"]));
    cat.insert(Message::new("Image", Some("context"), vec!["Paveikslelis"]));
    assert_eq!(cat.gettext("Text"), "Tekstas");
    assert_eq!(cat.gettext("Image"), "Image");
}

#[test]
fn catalog_ngettext() {
    let mut cat = Catalog::new();
    {
        // n == 1, no translation
        assert_eq!(cat.ngettext("Text", "Texts", 1), "Text");
        // n != 1, no translation
        assert_eq!(cat.ngettext("Text", "Texts", 0), "Texts");
        assert_eq!(cat.ngettext("Text", "Texts", 2), "Texts");
    }
    {
        cat.insert(Message::new("Text", None, vec!["Tekstas", "Tekstai"]));
        // n == 1, translation available
        assert_eq!(cat.ngettext("Text", "Texts", 1), "Tekstas");
        // n != 1, translation available
        assert_eq!(cat.ngettext("Text", "Texts", 0), "Tekstai");
        assert_eq!(cat.ngettext("Text", "Texts", 2), "Tekstai");
    }
}

#[test]
fn catalog_pgettext() {
    let mut cat = Catalog::new();
    cat.insert(Message::new("Text", Some("unit test"), vec!["Tekstas"]));
    assert_eq!(cat.pgettext("unit test", "Text"), "Tekstas");
    assert_eq!(cat.pgettext("integration test", "Text"), "Text");
}

#[test]
fn catalog_npgettext() {
    let mut cat = Catalog::new();
    cat.insert(Message::new("Text", Some("unit test"), vec!["Tekstas", "Tekstai"]));

    assert_eq!(cat.npgettext("unit test", "Text", "Texts", 1), "Tekstas");
    assert_eq!(cat.npgettext("unit test", "Text", "Texts", 0), "Tekstai");
    assert_eq!(cat.npgettext("unit test", "Text", "Texts", 2), "Tekstai");

    assert_eq!(cat.npgettext("integration test", "Text", "Texts", 1),
               "Text");
    assert_eq!(cat.npgettext("integration test", "Text", "Texts", 0),
               "Texts");
    assert_eq!(cat.npgettext("integration test", "Text", "Texts", 2),
               "Texts");
}
<commit_msg>Plural resolver: function<commit_after>//! This crate is a reimplementation
//! of GNU gettext translation framework in Rust.
//! It allows your Rust programs to parse out GNU MO files
//! containing translations and use them in your user interface.
//!
//! It contains several differences from the official C implementation.
//! Notably, this crate does not in any way depend on a global locale
//! ([2.2](https://www.gnu.org/software/gettext/manual/gettext.html#Setting-the-GUI-Locale))
//! and does not enforce a directory structure
//! for storing your translation catalogs
//! ([11.2.3](https://www.gnu.org/software/gettext/manual/gettext.html#Locating-Catalogs)).
//! Instead, the choice of translation catalog to use is explicitly made by the user.
//!
//! This crate is still in-progress
//! and may not be on par with the original implementation feature-wise.
//!
//! For the exact feature parity see the roadmap in the
//! [README](https://github.com/justinas/gettext#readme).
//!
//! # Example
//!
//! ```ignore
//! extern crate gettext;
//!
//! use std::fs::File;
//! use gettext::Catalog;
//!
//! fn main() {
//!     let f = File::open("french.mo").expect("could not open the catalog");
//!     let catalog = Catalog::parse(f).expect("could not parse the catalog");
//!
//!     // Will print out the French translation
//!     // if it is found in the parsed file
//!     // or "Name" otherwise.
//!     println!("{}", catalog.gettext("Name"));
//! }
//! ```

// https://pascalhertleif.de/artikel/good-practices-for-writing-rust-libraries/
#![deny(missing_docs, missing_debug_implementations,
        trivial_casts, trivial_numeric_casts, unused_import_braces)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

mod metadata;
mod parser;
mod plurals;

use std::collections::HashMap;
use std::io::Read;
use std::ops::Deref;

pub use parser::{Error, ParseOptions};
use plurals::Resolver::{self, Function};

/// Returns the number of the appropriate plural form
/// for the given count `n` of objects for germanic languages.
fn plural_form(n: usize) -> usize {
    if n != 1 {
        1
    } else {
        0
    }
}

fn key_with_context(context: &str, key: &str) -> String {
    let mut result = context.to_owned();
    result.push('\x04');
    result.push_str(key);
    result
}

/// Catalog represents a set of translation strings
/// parsed out of one MO file.
#[derive(Debug)]
pub struct Catalog {
    strings: HashMap<String, Message>,
    resolver: Resolver,
}

impl Catalog {
    /// Creates a new, empty gettext catalog.
    fn new() -> Self {
        Catalog {
            strings: HashMap::new(),
            resolver: Function(Box::new(|n| {
                if n != 1 {
                    1
                } else {
                    0
                }
            })),
        }
    }

    /// Parses a gettext catalog from the given binary MO file.
    /// Returns the `Err` variant upon encountering an invalid file format
    /// or invalid byte sequence in strings.
    ///
    /// Calling this method is equivalent to calling
    /// `ParseOptions::new().parse(reader)`.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use gettext::Catalog;
    /// use std::fs::File;
    ///
    /// let file = File::open("french.mo").unwrap();
    /// let catalog = Catalog::parse(file).unwrap();
    /// ```

    pub fn parse<R: Read>(reader: R) -> Result<Self, parser::Error> {
        ParseOptions::new().parse(reader)
    }

    fn insert(&mut self, msg: Message) {
        let key = match msg.context {
            Some(ref ctxt) => key_with_context(ctxt, &msg.id),
            None => msg.id.clone(),
        };
        self.strings.insert(key, msg);
    }

    /// Returns the singular translation of `msg_id` from the given catalog
    /// or `msg_id` itself if a translation does not exist.
    pub fn gettext<'a>(&'a self, msg_id: &'a str) -> &'a str {
        self.strings.get(msg_id).and_then(|msg| msg.get_translated(0)).unwrap_or(msg_id)
    }

    /// Returns the plural translation of `msg_id` from the given catalog
    /// with the correct plural form for the number `n` of objects.
    /// Returns msg_id if a translation does not exist and `n == 1`,
    /// msg_id_plural otherwise.
    ///
    /// Currently, the only supported plural formula is `n != 1`.
    pub fn ngettext<'a>(&'a self, msg_id: &'a str, msg_id_plural: &'a str, n: u64) -> &'a str {
        let form_no = self.resolver.resolve(n);

        match self.strings.get(msg_id) {
            Some(msg) => {
                msg.get_translated(form_no).unwrap_or_else(|| [msg_id, msg_id_plural][form_no])
            }
            None if n == 1 => msg_id,
            None if n != 1 => msg_id_plural,
            _ => unreachable!(),
        }
    }

    /// Returns the singular translation of `msg_id`
    /// in the context `msg_context`
    /// or `msg_id` itself if a translation does not exist.
    // TODO: DRY gettext/pgettext
    pub fn pgettext<'a>(&'a self, msg_context: &'a str, msg_id: &'a str) -> &'a str {
        let key = key_with_context(msg_context, &msg_id);
        self.strings.get(&key).and_then(|msg| msg.get_translated(0)).unwrap_or(msg_id)
    }

    /// Returns the plural translation of `msg_id`
    /// in the context `msg_context`
    /// with the correct plural form for the number `n` of objects.
    /// Returns msg_id if a translation does not exist and `n == 1`,
    /// msg_id_plural otherwise.
    ///
    /// Currently, the only supported plural formula is `n != 1`.
    // TODO: DRY ngettext/npgettext
    pub fn npgettext<'a>(&'a self,
                         msg_context: &'a str,
                         msg_id: &'a str,
                         msg_id_plural: &'a str,
                         n: u64)
                         -> &'a str {
        let key = key_with_context(msg_context, &msg_id);
        let form_no = self.resolver.resolve(n);
        match self.strings.get(&key) {
            Some(msg) => {
                msg.get_translated(form_no).unwrap_or_else(|| [msg_id, msg_id_plural][form_no])
            }
            None if n == 1 => msg_id,
            None if n != 1 => msg_id_plural,
            _ => unreachable!(),
        }
    }
}

#[derive(Debug, Eq, PartialEq)]
struct Message {
    id: String,
    context: Option<String>,
    translated: Vec<String>,
}

impl Message {
    fn new<T: Into<String>>(id: T, context: Option<T>, translated: Vec<T>) -> Self {
        Message {
            id: id.into(),
            context: context.map(Into::into),
            translated: translated.into_iter().map(Into::into).collect(),
        }
    }

    fn get_translated(&self, form_no: usize) -> Option<&str> {
        self.translated.get(form_no).map(|s| s.deref())
    }
}

#[test]
fn catalog_insert() {
    let mut cat = Catalog::new();
    cat.insert(Message::new("thisisid", None, vec![]));
    cat.insert(Message::new("anotherid", Some("context"), vec![]));
    let mut keys = cat.strings.keys().collect::<Vec<_>>();
    keys.sort();
    assert_eq!(keys, &["context\x04anotherid", "thisisid"])
}

#[test]
fn catalog_gettext() {
    let mut cat = Catalog::new();
    cat.insert(Message::new("Text", None, vec!["Tekstas"]));
    cat.insert(Message::new("Image", Some("context"), vec!["Paveikslelis"]));
    assert_eq!(cat.gettext("Text"), "Tekstas");
    assert_eq!(cat.gettext("Image"), "Image");
}

#[test]
fn catalog_ngettext() {
    let mut cat = Catalog::new();
    {
        // n == 1, no translation
        assert_eq!(cat.ngettext("Text", "Texts", 1), "Text");
        // n != 1, no translation
        assert_eq!(cat.ngettext("Text", "Texts", 0), "Texts");
        assert_eq!(cat.ngettext("Text", "Texts", 2), "Texts");
    }
    {
        cat.insert(Message::new("Text", None, vec!["Tekstas", "Tekstai"]));
        // n == 1, translation available
        assert_eq!(cat.ngettext("Text", "Texts", 1), "Tekstas");
        // n != 1, translation available
        assert_eq!(cat.ngettext("Text", "Texts", 0), "Tekstai");
        assert_eq!(cat.ngettext("Text", "Texts", 2), "Tekstai");
    }
}

#[test]
fn catalog_pgettext() {
    let mut cat = Catalog::new();
    cat.insert(Message::new("Text", Some("unit test"), vec!["Tekstas"]));
    assert_eq!(cat.pgettext("unit test", "Text"), "Tekstas");
    assert_eq!(cat.pgettext("integration test", "Text"), "Text");
}

#[test]
fn catalog_npgettext() {
    let mut cat = Catalog::new();
    cat.insert(Message::new("Text", Some("unit test"), vec!["Tekstas", "Tekstai"]));

    assert_eq!(cat.npgettext("unit test", "Text", "Texts", 1), "Tekstas");
    assert_eq!(cat.npgettext("unit test", "Text", "Texts", 0), "Tekstai");
    assert_eq!(cat.npgettext("unit test", "Text", "Texts", 2), "Tekstai");

    assert_eq!(cat.npgettext("integration test", "Text", "Texts", 1),
               "Text");
    assert_eq!(cat.npgettext("integration test", "Text", "Texts", 0),
               "Texts");
    assert_eq!(cat.npgettext("integration test", "Text", "Texts", 2),
               "Texts");
}

#[cfg(test)]
fn lithuanian_plural(n: u64) -> usize {
    if (n % 10) == 1 && (n % 100) != 11 {
        0
    } else if ((n % 10) >= 2) && ((n % 100) < 10 || (n % 100) >= 20) {
        1
    } else {
        2
    }
}

#[test]
fn catalog_ngettext_resolver() {
    let mut cat = Catalog::new();
    cat.insert(Message::new("Garlic", None, vec!["Česnakas", "Česnakai", "Česnakų"]));
    // https://localization-guide.readthedocs.org/en/latest/l10n/pluralforms.html
    cat.resolver = Resolver::Function(Box::new(lithuanian_plural));

    assert_eq!(cat.ngettext("Garlic", "Garlics", 0), "Česnakų");
    assert_eq!(cat.ngettext("Garlic", "Garlics", 1), "Česnakas");
    for i in 2..9 {
        assert_eq!(cat.ngettext("Garlic", "Garlics", i), "Česnakai");
    }
    for i in 10..20 {
        assert_eq!(cat.ngettext("Garlic", "Garlics", i), "Česnakų");
    }
    assert_eq!(cat.ngettext("Garlic", "Garlics", 21), "Česnakas");
}
<|endoftext|>


<commit_before>// Code style
#![forbid(private_in_public)]
#![forbid(tyvar_behind_raw_pointer)]
#![deny(unused_assignments)]
// Safety
#![deny(overflowing_literals)]
#![deny(safe_packed_borrows)]
#![deny(unused_must_use)]
// Code style (development time)
#![allow(unused_macros)]
#![allow(dead_code)]
// Code style (temp)
#![allow(unused_variables)]
#![allow(unused_imports)]
#![allow(unused_parens)]
#![allow(unused_mut)]
#![allow(unused_unsafe)]
#![allow(unreachable_code)]
// Disable some clippy lints
#![allow(clippy::cast_ptr_alignment)]
#![allow(clippy::empty_loop)]
#![allow(clippy::identity_op)]
#![allow(clippy::inconsistent_digit_grouping)]
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::needless_range_loop)]
#![allow(clippy::unreadable_literal)]
// No-std
#![no_std]
// Unstable features
#![feature(abi_x86_interrupt)]
#![feature(alloc_error_handler)]
#![feature(alloc_prelude)]
#![feature(allocator_api)]
#![feature(asm)]
#![feature(box_into_raw_non_null)]
#![feature(box_syntax, box_patterns)]
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![feature(integer_atomics)]
#![feature(lang_items)]
#![feature(maybe_uninit_extra)]
#![feature(naked_functions)]
#![feature(no_more_cas)]
#![feature(panic_info_message)]
#![feature(ptr_internals)]
#![feature(stmt_expr_attributes)]
#![feature(trait_alias)]
#![feature(try_trait)]

use core::alloc::Layout;
use core::panic::PanicInfo;

#[macro_use]
extern crate bitflags;

#[macro_use]
extern crate alloc;

// Utilities and macros:
#[macro_use]
mod util;

// Hardware drivers
#[macro_use]
mod driver;

// Everything else
mod cpuid;
mod filesystem;
mod interrupt;
mod kernel_shell;
mod memory;
mod multitasking;
mod syscall;
mod time;

/// The kernel main function
#[cfg(not(test))]
#[no_mangle]
pub extern "C" fn rust_main() -> ! {
    rreset!();
    rprintln!("Loading the system...\n");

    // Finish system setup

    // Interrupt controller
    driver::pic::init();
    // apic::init();

    // Interrupt system
    interrupt::init();

    // Memory allocation and paging
    memory::init();

    // More interrupts controls
    interrupt::init_after_memory();

    // PIT
    driver::pit::init();

    // CPU data
    cpuid::init();

    // Filesystem
    filesystem::init();

    // Keyboard
    driver::keyboard::init();

    // PCI
    driver::pci::init();

    // Disk IO (ATA, IDE, VirtIO)
    interrupt::enable_external_interrupts();
    driver::disk_io::init();
    interrupt::disable_external_interrupts();

    // StaticFS retuires disk drivers for now
    filesystem::staticfs::init();

    // Memory init late phase
    memory::init_late();

    rreset!();
    rprintln!("Kernel initialized.\n");

    {
        use crate::filesystem::FILESYSTEM;
        let readme_bytes = FILESYSTEM
            .lock()
            .read_file("/mnt/staticfs/README.md")
            .unwrap();
        let mut lines = 3;
        for b in readme_bytes {
            if b == 0x0a {
                lines -= 1;
                if lines == 0 {
                    break;
                }
            }
            if (0x20 <= b && b <= 0x7f) || b == 0x0a {
                rprint!("{}", b as char);
            }
        }
    }

    crate::memory::configure(|mut mem_ctrl| {
        use crate::filesystem::FILESYSTEM;
        use crate::multitasking::SCHEDULER;

        let mut fs = FILESYSTEM.lock();
        let mut sched = SCHEDULER.lock();

        fs.kernel_exec(&mut mem_ctrl, &mut sched, "/mnt/staticfs/mod_test")
            .expect("Could not spawn");
    });

    // Wait until the next clock tick interrupt,
    // after that the process scheduler takes over
    unsafe {
        interrupt::enable_external_interrupts();
        loop {
            asm!("hlt")
        }
    }
}

#[global_allocator]
static HEAP_ALLOCATOR: d7alloc::GlobAlloc = d7alloc::GlobAlloc::new(d7alloc::BumpAllocator::new(
    d7alloc::HEAP_START,
    d7alloc::HEAP_START + d7alloc::HEAP_SIZE,
));

#[alloc_error_handler]
fn out_of_memory(_: Layout) -> ! {
    unsafe {
        asm!("cli"::::"intel","volatile");
        panic_indicator!(0x4f4D4f21); // !M as in "No memory"
        asm!("jmp panic"::::"intel","volatile");
    }
    loop {}
}

#[panic_handler]
#[allow(unused_variables)]
#[no_mangle]
extern "C" fn panic(info: &PanicInfo) -> ! {
    unsafe {
        // asm!("jmp panic"::::"intel","volatile");

        asm!("cli"::::"intel","volatile");
        panic_indicator!(0x4f214f21); // !!

        rforce_unlock!();

        if let Some(location) = info.location() {
            rprintln!(
                "\nKernel Panic: file: '{}', line: {}",
                location.file(),
                location.line()
            );
        } else {
            rprintln!("\nKernel Panic: Location unavailable");
        }
        if let Some(msg) = info.message() {
            rprintln!("  {:?}", msg);
        } else {
            rprintln!("  Info unavailable");
        }
        asm!("jmp panic"::::"intel","volatile");
    }
    loop {}
}

// Static assert assumptions
static_assertions::assert_eq_size!(u64, usize);
<commit_msg>Print newline after test text<commit_after>// Code style
#![forbid(private_in_public)]
#![forbid(tyvar_behind_raw_pointer)]
#![deny(unused_assignments)]
// Safety
#![deny(overflowing_literals)]
#![deny(safe_packed_borrows)]
#![deny(unused_must_use)]
// Code style (development time)
#![allow(unused_macros)]
#![allow(dead_code)]
// Code style (temp)
#![allow(unused_variables)]
#![allow(unused_imports)]
#![allow(unused_parens)]
#![allow(unused_mut)]
#![allow(unused_unsafe)]
#![allow(unreachable_code)]
// Disable some clippy lints
#![allow(clippy::cast_ptr_alignment)]
#![allow(clippy::empty_loop)]
#![allow(clippy::identity_op)]
#![allow(clippy::inconsistent_digit_grouping)]
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::needless_range_loop)]
#![allow(clippy::unreadable_literal)]
// No-std
#![no_std]
// Unstable features
#![feature(abi_x86_interrupt)]
#![feature(alloc_error_handler)]
#![feature(alloc_prelude)]
#![feature(allocator_api)]
#![feature(asm)]
#![feature(box_into_raw_non_null)]
#![feature(box_syntax, box_patterns)]
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![feature(integer_atomics)]
#![feature(lang_items)]
#![feature(maybe_uninit_extra)]
#![feature(naked_functions)]
#![feature(no_more_cas)]
#![feature(panic_info_message)]
#![feature(ptr_internals)]
#![feature(stmt_expr_attributes)]
#![feature(trait_alias)]
#![feature(try_trait)]

use core::alloc::Layout;
use core::panic::PanicInfo;

#[macro_use]
extern crate bitflags;

#[macro_use]
extern crate alloc;

// Utilities and macros:
#[macro_use]
mod util;

// Hardware drivers
#[macro_use]
mod driver;

// Everything else
mod cpuid;
mod filesystem;
mod interrupt;
mod kernel_shell;
mod memory;
mod multitasking;
mod syscall;
mod time;

/// The kernel main function
#[cfg(not(test))]
#[no_mangle]
pub extern "C" fn rust_main() -> ! {
    rreset!();
    rprintln!("Loading the system...\n");

    // Finish system setup

    // Interrupt controller
    driver::pic::init();
    // apic::init();

    // Interrupt system
    interrupt::init();

    // Memory allocation and paging
    memory::init();

    // More interrupts controls
    interrupt::init_after_memory();

    // PIT
    driver::pit::init();

    // CPU data
    cpuid::init();

    // Filesystem
    filesystem::init();

    // Keyboard
    driver::keyboard::init();

    // PCI
    driver::pci::init();

    // Disk IO (ATA, IDE, VirtIO)
    interrupt::enable_external_interrupts();
    driver::disk_io::init();
    interrupt::disable_external_interrupts();

    // StaticFS retuires disk drivers for now
    filesystem::staticfs::init();

    // Memory init late phase
    memory::init_late();

    rreset!();
    rprintln!("Kernel initialized.\n");

    {
        use crate::filesystem::FILESYSTEM;
        let readme_bytes = FILESYSTEM
            .lock()
            .read_file("/mnt/staticfs/README.md")
            .unwrap();
        let mut lines = 3;
        for b in readme_bytes {
            if b == 0x0a {
                lines -= 1;
                if lines == 0 {
                    break;
                }
            }
            if (0x20 <= b && b <= 0x7f) || b == 0x0a {
                rprint!("{}", b as char);
            }
        }
    }
    rprintln!("");

    crate::memory::configure(|mut mem_ctrl| {
        use crate::filesystem::FILESYSTEM;
        use crate::multitasking::SCHEDULER;

        let mut fs = FILESYSTEM.lock();
        let mut sched = SCHEDULER.lock();

        fs.kernel_exec(&mut mem_ctrl, &mut sched, "/mnt/staticfs/mod_test")
            .expect("Could not spawn");
    });

    // Wait until the next clock tick interrupt,
    // after that the process scheduler takes over
    unsafe {
        interrupt::enable_external_interrupts();
        loop {
            asm!("hlt")
        }
    }
}

#[global_allocator]
static HEAP_ALLOCATOR: d7alloc::GlobAlloc = d7alloc::GlobAlloc::new(d7alloc::BumpAllocator::new(
    d7alloc::HEAP_START,
    d7alloc::HEAP_START + d7alloc::HEAP_SIZE,
));

#[alloc_error_handler]
fn out_of_memory(_: Layout) -> ! {
    unsafe {
        asm!("cli"::::"intel","volatile");
        panic_indicator!(0x4f4D4f21); // !M as in "No memory"
        asm!("jmp panic"::::"intel","volatile");
    }
    loop {}
}

#[panic_handler]
#[allow(unused_variables)]
#[no_mangle]
extern "C" fn panic(info: &PanicInfo) -> ! {
    unsafe {
        // asm!("jmp panic"::::"intel","volatile");

        asm!("cli"::::"intel","volatile");
        panic_indicator!(0x4f214f21); // !!

        rforce_unlock!();

        if let Some(location) = info.location() {
            rprintln!(
                "\nKernel Panic: file: '{}', line: {}",
                location.file(),
                location.line()
            );
        } else {
            rprintln!("\nKernel Panic: Location unavailable");
        }
        if let Some(msg) = info.message() {
            rprintln!("  {:?}", msg);
        } else {
            rprintln!("  Info unavailable");
        }
        asm!("jmp panic"::::"intel","volatile");
    }
    loop {}
}

// Static assert assumptions
static_assertions::assert_eq_size!(u64, usize);
<|endoftext|>