<commit_before>use cipher::block::{BlockFn, BlockCipher};
use cipher::block::feistel::Feistel;
use secret::Secret;
use truncate::Truncate;

use typenum::consts::U16;

struct SubKey {
    // The top 16 bits are 0
    key: Secret<u64>
}

struct DesRound {
    key: SubKey
}

impl BlockFn for DesRound {
    type Block = Secret<u32>;
    fn encrypt(&self, block: Secret<u32>) -> Secret<u32> {
        permute(substitute(expand(block) ^ self.key.key))
    }
}

pub struct Des {
    inner: Feistel<DesRound, U16>
}

impl BlockFn for Des {
    type Block = Secret<u64>;
    fn encrypt(&self, block: Secret<u64>) -> Secret<u64> {
        final_permute(self.inner.encrypt(initial_permute(block)))
    }
}

impl BlockCipher for Des {
    fn decrypt(&self, block: Secret<u64>) -> Secret<u64> {
        final_permute(self.inner.decrypt(initial_permute(block)))
    }
}

fn run_permutation(perm: &[u8], val: Secret<u64>) -> Secret<u64> {
    let mut out = Secret::new(0);
    for (i, src) in perm.iter().enumerate() {
        out |= ((val >> *src as usize) & 1) << i;
    }
    out
}

// See FIPS Publication 46-3, Appendix 1
const INITIAL_PERMUTATION: [u8; 64] = [
    58, 50, 42, 34, 26, 18, 10, 2,
    60, 52, 44, 36, 28, 20, 12, 4,
    62, 54, 46, 38, 30, 22, 14, 6,
    64, 56, 48, 40, 32, 24, 16, 8,
    57, 49, 41, 33, 25, 17, 9,  1,
    59, 51, 43, 35, 27, 19, 11, 3,
    61, 53, 45, 37, 29, 21, 13, 5,
    63, 55, 47, 39, 31, 23, 15, 7
];

// Inverse of final_permute
fn initial_permute(block: Secret<u64>) -> (Secret<u32>, Secret<u32>) {
    let ret = run_permutation(&INITIAL_PERMUTATION, block);
    (ret.truncate(), (ret >> 32).truncate())
}

// See FIPS Publication 46-3, Appendix 1
const FINAL_PERMUTATION: [u8; 64] = [
    40, 8, 48, 16, 56, 24, 64, 32,
    39, 7, 47, 15, 55, 23, 63, 31,
    38, 6, 46, 14, 54, 22, 62, 30,
	37, 5, 45, 13, 53, 21, 61, 29,
	36, 4, 44, 12, 52, 20, 60, 28,
	35, 3, 43, 11, 51, 19, 59, 27,
	34, 2, 42, 10, 50, 18, 58, 26,
	33, 1, 41, 9,  49, 17, 57, 25
];

// Inverse of initial_permute
fn final_permute(block: (Secret<u32>, Secret<u32>)) -> Secret<u64> {
    let joined = Secret::<u64>::from(block.0) | (Secret::<u64>::from(block.1) << 32);
    run_permutation(&FINAL_PERMUTATION, joined)
}

// See FIPS Publication 46-3, Appendix 1
const EXPANSION_PERMUTATION: [u8; 48] = [
	32, 1,  2,  3,  4,  5,
	4,  5,  6,  7,  8,  9,
	8,  9,  10, 11, 12, 13,
	12, 13, 14, 15, 16, 17,
	16, 17, 18, 19, 20, 21,
	20, 21, 22, 23, 24, 25,
	24, 25, 26, 27, 28, 29,
	28, 29, 30, 31, 32, 1
];

// Returns 48 bits
fn expand(half_block: Secret<u32>) -> Secret<u64> {
    run_permutation(&EXPANSION_PERMUTATION, Secret::<u64>::from(half_block))
}

// Takes 48 bits
fn substitute(block: Secret<u64>) -> Secret<u32> {
    unimplemented!()
}

// See FIPS Publication 46-3, Appendix 1
const ROUND_PERMUTATION: [u8; 32] = [
	16, 7,  20, 21, 29, 12, 28, 17,
	1,  15, 23, 26, 5,  18, 31, 10,
	2,  8,  24, 14, 32, 27, 3,  9,
	19, 13, 30, 6,  22, 11, 4,  25
];

fn permute(block: Secret<u32>) -> Secret<u32> {
    run_permutation(&ROUND_PERMUTATION, Secret::<u64>::from(block)).truncate()
}
<commit_msg>Add tests for inital and final permutations<commit_after>use cipher::block::{BlockFn, BlockCipher};
use cipher::block::feistel::Feistel;
use secret::Secret;
use truncate::Truncate;

use typenum::consts::U16;

struct SubKey {
    // The top 16 bits are 0
    key: Secret<u64>
}

struct DesRound {
    key: SubKey
}

impl BlockFn for DesRound {
    type Block = Secret<u32>;
    fn encrypt(&self, block: Secret<u32>) -> Secret<u32> {
        permute(substitute(expand(block) ^ self.key.key))
    }
}

pub struct Des {
    inner: Feistel<DesRound, U16>
}

impl BlockFn for Des {
    type Block = Secret<u64>;
    fn encrypt(&self, block: Secret<u64>) -> Secret<u64> {
        final_permute(join_block(self.inner.encrypt(split_block(initial_permute(block)))))
    }
}

impl BlockCipher for Des {
    fn decrypt(&self, block: Secret<u64>) -> Secret<u64> {
        final_permute(join_block(self.inner.decrypt(split_block(initial_permute(block)))))
    }
}

fn split_block(block: Secret<u64>) -> (Secret<u32>, Secret<u32>) {
    (block.truncate(), (block >> 32).truncate())
}

fn join_block(parts: (Secret<u32>, Secret<u32>)) -> Secret<u64> {
    Secret::<u64>::from(parts.0) | (Secret::<u64>::from(parts.1) << 32)
}

fn run_permutation(perm: &[u8], val: Secret<u64>) -> Secret<u64> {
    let mut out = Secret::new(0);
    for (i, src) in perm.iter().enumerate() {
        out |= ((val >> (*src as usize - 1)) & 1) << i;
    }
    out
}

// See FIPS Publication 46-3, Appendix 1
const INITIAL_PERMUTATION: [u8; 64] = [
    58, 50, 42, 34, 26, 18, 10, 2,
    60, 52, 44, 36, 28, 20, 12, 4,
    62, 54, 46, 38, 30, 22, 14, 6,
    64, 56, 48, 40, 32, 24, 16, 8,
    57, 49, 41, 33, 25, 17, 9,  1,
    59, 51, 43, 35, 27, 19, 11, 3,
    61, 53, 45, 37, 29, 21, 13, 5,
    63, 55, 47, 39, 31, 23, 15, 7
];

// Inverse of final_permute
fn initial_permute(block: Secret<u64>) -> Secret<u64> {
    run_permutation(&INITIAL_PERMUTATION, block)
}

// See FIPS Publication 46-3, Appendix 1
const FINAL_PERMUTATION: [u8; 64] = [
    40, 8, 48, 16, 56, 24, 64, 32,
    39, 7, 47, 15, 55, 23, 63, 31,
    38, 6, 46, 14, 54, 22, 62, 30,
	37, 5, 45, 13, 53, 21, 61, 29,
	36, 4, 44, 12, 52, 20, 60, 28,
	35, 3, 43, 11, 51, 19, 59, 27,
	34, 2, 42, 10, 50, 18, 58, 26,
	33, 1, 41, 9,  49, 17, 57, 25
];

// Inverse of initial_permute
fn final_permute(block: Secret<u64>) -> Secret<u64> {
    run_permutation(&FINAL_PERMUTATION, block)
}

// See FIPS Publication 46-3, Appendix 1
const EXPANSION_PERMUTATION: [u8; 48] = [
	32, 1,  2,  3,  4,  5,
	4,  5,  6,  7,  8,  9,
	8,  9,  10, 11, 12, 13,
	12, 13, 14, 15, 16, 17,
	16, 17, 18, 19, 20, 21,
	20, 21, 22, 23, 24, 25,
	24, 25, 26, 27, 28, 29,
	28, 29, 30, 31, 32, 1
];

// Returns 48 bits
fn expand(half_block: Secret<u32>) -> Secret<u64> {
    run_permutation(&EXPANSION_PERMUTATION, Secret::<u64>::from(half_block))
}

// Takes 48 bits
fn substitute(block: Secret<u64>) -> Secret<u32> {
    unimplemented!()
}

// See FIPS Publication 46-3, Appendix 1
const ROUND_PERMUTATION: [u8; 32] = [
	16, 7,  20, 21, 29, 12, 28, 17,
	1,  15, 23, 26, 5,  18, 31, 10,
	2,  8,  24, 14, 32, 27, 3,  9,
	19, 13, 30, 6,  22, 11, 4,  25
];

fn permute(block: Secret<u32>) -> Secret<u32> {
    run_permutation(&ROUND_PERMUTATION, Secret::<u64>::from(block)).truncate()
}

#[cfg(test)]
mod tests {
    use super::{initial_permute, final_permute};

    use secret::Secret;

    #[test]
    fn initial_final_inverses() {
        for i in 0..64 {
            let val = 1 << i;
            assert_eq!(final_permute(initial_permute(Secret::new(val))).expose(), val);
            assert_eq!(initial_permute(final_permute(Secret::new(val))).expose(), val);
        }
    }
}
<|endoftext|>


<commit_before>
#[macro_use]
extern crate itertools;

use itertools::Itertools;

use std::u32;

#[derive(Debug, Clone)]
struct Character {
    hp: u32,
    damage: u32,
    armor: u32,
}

impl Character {
    fn new(inv: &Inventory) -> Character {
        Character {
            hp: 100,
            damage: inv.weapon.damage +
                    inv.armor.damage +
                    inv.left_ring.damage +
                    inv.right_ring.damage,
            armor: inv.weapon.armor +
                   inv.armor.armor +
                   inv.left_ring.armor +
                   inv.right_ring.armor,
        }
    }

    fn attack(&self, enemy: &mut Character) -> bool {
        let damage = if self.damage > enemy.armor {
            self.damage - enemy.armor
        } else {
            1
        };

        if damage >= enemy.hp {
            enemy.hp = 0;
            true
        } else {
            enemy.hp -= damage;
            false
        }
    }

    fn fight_it_out(&mut self, enemy: &mut Character) -> (bool, u32) {
        let mut round = 1;

        loop {
            if self.attack(enemy) {
                return (true, round);
            }

            if enemy.attack(self) {
                return (false, round);
            }

            round += 1;
        }
    }
}

#[derive(Debug)]
struct Item {
    name: String,
    cost: u32,
    damage: u32,
    armor: u32,
}

#[derive(Debug)]
struct Inventory<'a> {
    weapon: &'a Item,
    armor: &'a Item,
    left_ring: &'a Item,
    right_ring: &'a Item,
}

impl<'a> Inventory<'a> {
    fn get_cost(&self) -> u32 {
        self.weapon.cost + self.armor.cost + self.left_ring.cost + self.right_ring.cost
    }
}

fn main() {
    let boss_template = Character {
        hp: 100,
        damage: 8,
        armor: 2,
    };

    let weapons = vec![
        Item { name: "Dagger".to_string(), cost: 8, damage: 4, armor: 0 },
        Item { name: "Shortsword".to_string(), cost: 10, damage: 5, armor: 0 },
        Item { name: "Warhammer".to_string(), cost: 25, damage: 6, armor: 0 },
        Item { name: "Longsword".to_string(), cost: 40, damage: 7, armor: 0 },
        Item { name: "Greataxe".to_string(), cost: 74, damage: 8, armor: 0 },
    ];

    let armors = vec![
        Item { name: "Unequipped".to_string(), cost: 0, damage: 0, armor: 0 },
        Item { name: "Leather".to_string(), cost: 13, damage: 0, armor: 1 },
        Item { name: "Chainmail".to_string(), cost: 31, damage: 0, armor: 2 },
        Item { name: "Splintmail".to_string(), cost: 53, damage: 0, armor: 3 },
        Item { name: "Bandedmail".to_string(), cost: 75, damage: 0, armor: 4 },
        Item { name: "Platemail".to_string(), cost: 102, damage: 0, armor: 5 },
    ];

    let rings = vec![
        Item { name: "Unequipped".to_string(), cost: 0, damage: 0, armor: 0 },
        Item { name: "Damage+1".to_string(), cost: 25, damage: 1, armor: 0 },
        Item { name: "Damage+2".to_string(), cost: 50, damage: 2, armor: 0 },
        Item { name: "Damage+3".to_string(), cost: 100, damage: 3, armor: 0 },
        Item { name: "Defense+1".to_string(), cost: 20, damage: 0, armor: 1 },
        Item { name: "Defense+2".to_string(), cost: 40, damage: 0, armor: 2 },
        Item { name: "Defense+3".to_string(), cost: 80, damage: 0, armor: 3 },
    ];

    let mut equipment_combinations = iproduct!(weapons.iter(),
                                               armors.iter(),
                                               rings.iter(),
                                               rings.iter())
                                         .filter(|&(w, a, lr, rr)| {
                                             lr.name != rr.name ||
                                             (lr.name == "Unequiped" && rr.name == "Unequiped")
                                         });

    let mut min_cost = u32::MAX;
    let mut max_cost = u32::MIN;

    for combination in equipment_combinations {

        let i = Inventory {
            weapon: combination.0,
            armor: combination.1,
            left_ring: combination.2,
            right_ring: combination.3,
        };

        let mut player = Character::new(&i);
        let mut boss = boss_template.clone();

        let (won, num_rounds) = player.fight_it_out(&mut boss);
        if won {
            if min_cost > i.get_cost() {
                min_cost = i.get_cost();

                println!("--- Found a new possible minimum configuration.");
                println!("--- Cost: {}", min_cost);
                println!("--- {:?}", i);
            }
        }

        if !won {
            if max_cost < i.get_cost() {
                max_cost = i.get_cost();

                println!("### Found a new possible maximum configuration.");
                println!("### Cost: {}", max_cost);
                println!("### {:?}", i);
            }
        }
    }
}

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

    #[test]
    fn fight_test() {
        let mut player = Character {
            hp: 8,
            damage: 5,
            armor: 5,
        };

        let mut boss = Character {
            hp: 12,
            damage: 7,
            armor: 2,
        };

        assert!(!player.attack(&mut boss));
        assert_eq!(boss.hp, 9);
        assert!(!boss.attack(&mut player));
        assert_eq!(player.hp, 6);

        assert!(!player.attack(&mut boss));
        assert_eq!(boss.hp, 6);
        assert!(!boss.attack(&mut player));
        assert_eq!(player.hp, 4);

        assert!(!player.attack(&mut boss));
        assert_eq!(boss.hp, 3);
        assert!(!boss.attack(&mut player));
        assert_eq!(player.hp, 2);

        assert!(player.attack(&mut boss));
        assert_eq!(boss.hp, 0);

        player.hp = 8;
        boss.hp = 12;

        assert_eq!(player.fight_it_out(&mut boss), (true, 4));
    }
}
<commit_msg>Minor fixes to silence compiler warnings.<commit_after>
#[macro_use]
extern crate itertools;

use std::u32;

#[derive(Debug, Clone)]
struct Character {
    hp: u32,
    damage: u32,
    armor: u32,
}

impl Character {
    fn new(inv: &Inventory) -> Character {
        Character {
            hp: 100,
            damage: inv.weapon.damage +
                    inv.armor.damage +
                    inv.left_ring.damage +
                    inv.right_ring.damage,
            armor: inv.weapon.armor +
                   inv.armor.armor +
                   inv.left_ring.armor +
                   inv.right_ring.armor,
        }
    }

    fn attack(&self, enemy: &mut Character) -> bool {
        let damage = if self.damage > enemy.armor {
            self.damage - enemy.armor
        } else {
            1
        };

        if damage >= enemy.hp {
            enemy.hp = 0;
            true
        } else {
            enemy.hp -= damage;
            false
        }
    }

    fn fight_it_out(&mut self, enemy: &mut Character) -> (bool, u32) {
        let mut round = 1;

        loop {
            if self.attack(enemy) {
                return (true, round);
            }

            if enemy.attack(self) {
                return (false, round);
            }

            round += 1;
        }
    }
}

#[derive(Debug)]
struct Item {
    name: String,
    cost: u32,
    damage: u32,
    armor: u32,
}

#[derive(Debug)]
struct Inventory<'a> {
    weapon: &'a Item,
    armor: &'a Item,
    left_ring: &'a Item,
    right_ring: &'a Item,
}

impl<'a> Inventory<'a> {
    fn get_cost(&self) -> u32 {
        self.weapon.cost + self.armor.cost + self.left_ring.cost + self.right_ring.cost
    }
}

fn main() {
    let boss_template = Character {
        hp: 100,
        damage: 8,
        armor: 2,
    };

    let weapons = vec![
        Item { name: "Dagger".to_string(), cost: 8, damage: 4, armor: 0 },
        Item { name: "Shortsword".to_string(), cost: 10, damage: 5, armor: 0 },
        Item { name: "Warhammer".to_string(), cost: 25, damage: 6, armor: 0 },
        Item { name: "Longsword".to_string(), cost: 40, damage: 7, armor: 0 },
        Item { name: "Greataxe".to_string(), cost: 74, damage: 8, armor: 0 },
    ];

    let armors = vec![
        Item { name: "Unequipped".to_string(), cost: 0, damage: 0, armor: 0 },
        Item { name: "Leather".to_string(), cost: 13, damage: 0, armor: 1 },
        Item { name: "Chainmail".to_string(), cost: 31, damage: 0, armor: 2 },
        Item { name: "Splintmail".to_string(), cost: 53, damage: 0, armor: 3 },
        Item { name: "Bandedmail".to_string(), cost: 75, damage: 0, armor: 4 },
        Item { name: "Platemail".to_string(), cost: 102, damage: 0, armor: 5 },
    ];

    let rings = vec![
        Item { name: "Unequipped".to_string(), cost: 0, damage: 0, armor: 0 },
        Item { name: "Damage+1".to_string(), cost: 25, damage: 1, armor: 0 },
        Item { name: "Damage+2".to_string(), cost: 50, damage: 2, armor: 0 },
        Item { name: "Damage+3".to_string(), cost: 100, damage: 3, armor: 0 },
        Item { name: "Defense+1".to_string(), cost: 20, damage: 0, armor: 1 },
        Item { name: "Defense+2".to_string(), cost: 40, damage: 0, armor: 2 },
        Item { name: "Defense+3".to_string(), cost: 80, damage: 0, armor: 3 },
    ];

    let equipment_combinations = iproduct!(weapons.iter(),
                                               armors.iter(),
                                               rings.iter(),
                                               rings.iter())
                                         .filter(|&(_, _, lr, rr)| {
                                             lr.name != rr.name ||
                                             (lr.name == "Unequiped" && rr.name == "Unequiped")
                                         });

    let mut min_cost = u32::MAX;
    let mut max_cost = u32::MIN;

    for combination in equipment_combinations {

        let i = Inventory {
            weapon: combination.0,
            armor: combination.1,
            left_ring: combination.2,
            right_ring: combination.3,
        };

        let mut player = Character::new(&i);
        let mut boss = boss_template.clone();

        let (won, _) = player.fight_it_out(&mut boss);
        if won {
            if min_cost > i.get_cost() {
                min_cost = i.get_cost();

                println!("--- Found a new possible minimum configuration.");
                println!("--- Cost: {}", min_cost);
                println!("--- {:?}", i);
            }
        }

        if !won {
            if max_cost < i.get_cost() {
                max_cost = i.get_cost();

                println!("### Found a new possible maximum configuration.");
                println!("### Cost: {}", max_cost);
                println!("### {:?}", i);
            }
        }
    }
}

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

    #[test]
    fn fight_test() {
        let mut player = Character {
            hp: 8,
            damage: 5,
            armor: 5,
        };

        let mut boss = Character {
            hp: 12,
            damage: 7,
            armor: 2,
        };

        assert!(!player.attack(&mut boss));
        assert_eq!(boss.hp, 9);
        assert!(!boss.attack(&mut player));
        assert_eq!(player.hp, 6);

        assert!(!player.attack(&mut boss));
        assert_eq!(boss.hp, 6);
        assert!(!boss.attack(&mut player));
        assert_eq!(player.hp, 4);

        assert!(!player.attack(&mut boss));
        assert_eq!(boss.hp, 3);
        assert!(!boss.attack(&mut player));
        assert_eq!(player.hp, 2);

        assert!(player.attack(&mut boss));
        assert_eq!(boss.hp, 0);

        player.hp = 8;
        boss.hp = 12;

        assert_eq!(player.fight_it_out(&mut boss), (true, 4));
    }
}
<|endoftext|>


<commit_before>//! Defines types for operating with floating point and 8 bit RGB colors

use std::num::Float;
use std::ops::{Add, Sub, Mul, Div, Neg, Index, IndexMut};
use linalg;

/// Colorf is a floating point RGBA color type
/// `a` is typically used to store the weight of a color eg. in the
/// render target for multisampling we need to track the weight to
/// normalize in the end and is always initialized to 0
#[derive(Show, Copy, Clone, PartialEq)]
pub struct Colorf {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32,
}

impl Colorf {
    /// Create an RGB color
    pub fn new(r: f32, g: f32, b: f32) -> Colorf {
        Colorf { r: r, g: g, b: b, a: 1.0 }
    }
    /// Create an RGB color using the same value for all channels
    pub fn broadcast(r: f32) -> Colorf {
        Colorf { r: r, g: r, b: r, a: r }
    }
    /// Clamp the color values between [0, 1]
    pub fn clamp(&self) -> Colorf {
        Colorf { r: linalg::clamp(self.r, 0.0, 1.0),
                 g: linalg::clamp(self.g, 0.0, 1.0),
                 b: linalg::clamp(self.b, 0.0, 1.0),
                 a: linalg::clamp(self.a, 0.0, 1.0) }
    }
    /// Compute the luminance of the color
    pub fn luminance(&self) -> f32 {
        0.2126 * self.r + 0.7152 * self.g + 0.0722 * self.b
    }
    /// Check if the color is black
    pub fn is_black(&self) -> bool {
        self.r == 0f32 && self.g == 0f32 && self.b == 0f32
    }
    /// Convert the linear RGB color to sRGB
    pub fn to_srgb(&self) -> Colorf {
        let a = 0.055f32;
        let b = 1f32 / 2.4;
        let mut srgb = Colorf::broadcast(0.0);
        for i in 0..3us {
            if self[i] <= 0.0031308 {
                srgb[i] = 12.92 * self[i];
            } else {
                srgb[i] = (1.0 + a) * Float::powf(self[i], b) - a;
            }
        }
        srgb
    }
    /// Return the color with values { e^r, e^g, e^b }
    pub fn exp(&self) -> Colorf {
        Colorf { r: Float::exp(self.r), g: Float::exp(self.g),
                 b: Float::exp(self.b), a: Float::exp(self.a) }
    }
}

impl Add for Colorf {
    type Output = Colorf;
    /// Add two colors together
    fn add(self, rhs: Colorf) -> Colorf {
        Colorf { r: self.r + rhs.r, g: self.g + rhs.g, b: self.b + rhs.b, a: self.a + rhs.a }
    }
}

impl Sub for Colorf {
    type Output = Colorf;
    /// Subtract the two colors
    fn sub(self, rhs: Colorf) -> Colorf {
        Colorf { r: self.r - rhs.r, g: self.g - rhs.g, b: self.b - rhs.b, a: self.a - rhs.a }
    }
}

impl Mul for Colorf {
    type Output = Colorf;
    /// Multiply the two colors
    fn mul(self, rhs: Colorf) -> Colorf {
        Colorf { r: self.r * rhs.r, g: self.g * rhs.g, b: self.b * rhs.b, a: self.a * rhs.a }
    }
}

impl Mul<f32> for Colorf {
    type Output = Colorf;
    /// Scale the color by the float
    fn mul(self, rhs: f32) -> Colorf {
        Colorf { r: self.r * rhs, g: self.g * rhs, b: self.b * rhs, a: self.a * rhs }
    }
}

impl Div for Colorf {
    type Output = Colorf;
    /// Divide the channels of one color by another
    fn div(self, rhs: Colorf) -> Colorf {
        Colorf { r: self.r / rhs.r, g: self.g / rhs.g, b: self.b / rhs.b, a: self.a / rhs.a }
    }
}

impl Div<f32> for Colorf {
    type Output = Colorf;
    /// Divide the channels of the color by the float
    fn div(self, rhs: f32) -> Colorf {
        Colorf { r: self.r / rhs, g: self.g / rhs, b: self.b / rhs, a: self.a / rhs }
    }
}

impl Neg for Colorf {
    type Output = Colorf;
    /// Negate the color channels
    fn neg(self) -> Colorf {
        Colorf { r: -self.r, g: -self.g, b: -self.b, a: -self.a }
    }
}

impl Index<usize> for Colorf {
    type Output = f32;
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    /// - 3 = a
    fn index(&self, i: &usize) -> &f32 {
        match *i {
            0 => &self.r,
            1 => &self.g,
            2 => &self.b,
            3 => &self.a,
            _ => panic!("Invalid index into color"),
        }
    }
}

impl IndexMut<usize> for Colorf {
    type Output = f32;
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    /// - 3 = a
    fn index_mut(&mut self, i: &usize) -> &mut f32 {
        match *i {
            0 => &mut self.r,
            1 => &mut self.g,
            2 => &mut self.b,
            3 => &mut self.a,
            _ => panic!("Invalid index into color"),
        }
    }
}

<commit_msg>Add a has_nans function to Colorf for debugging nans in colors<commit_after>//! Defines types for operating with floating point and 8 bit RGB colors

use std::num::Float;
use std::ops::{Add, Sub, Mul, Div, Neg, Index, IndexMut};

use linalg;

/// Colorf is a floating point RGBA color type
/// `a` is typically used to store the weight of a color eg. in the
/// render target for multisampling we need to track the weight to
/// normalize in the end and is always initialized to 0
#[derive(Show, Copy, Clone, PartialEq)]
pub struct Colorf {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32,
}

impl Colorf {
    /// Create an RGB color
    pub fn new(r: f32, g: f32, b: f32) -> Colorf {
        Colorf { r: r, g: g, b: b, a: 1.0 }
    }
    /// Create an RGB color using the same value for all channels
    pub fn broadcast(r: f32) -> Colorf {
        Colorf { r: r, g: r, b: r, a: r }
    }
    /// Clamp the color values between [0, 1]
    pub fn clamp(&self) -> Colorf {
        Colorf { r: linalg::clamp(self.r, 0.0, 1.0),
                 g: linalg::clamp(self.g, 0.0, 1.0),
                 b: linalg::clamp(self.b, 0.0, 1.0),
                 a: linalg::clamp(self.a, 0.0, 1.0) }
    }
    /// Compute the luminance of the color
    pub fn luminance(&self) -> f32 {
        0.2126 * self.r + 0.7152 * self.g + 0.0722 * self.b
    }
    /// Check if the color is black
    pub fn is_black(&self) -> bool {
        self.r == 0f32 && self.g == 0f32 && self.b == 0f32
    }
    /// Check if any of the color channels are NaN
    pub fn has_nans(&self) -> bool {
        Float::is_nan(self.r) || Float::is_nan(self.g) || Float::is_nan(self.b) || Float::is_nan(self.a)
    }
    /// Convert the linear RGB color to sRGB
    pub fn to_srgb(&self) -> Colorf {
        let a = 0.055f32;
        let b = 1f32 / 2.4;
        let mut srgb = Colorf::broadcast(0.0);
        for i in 0..3us {
            if self[i] <= 0.0031308 {
                srgb[i] = 12.92 * self[i];
            } else {
                srgb[i] = (1.0 + a) * Float::powf(self[i], b) - a;
            }
        }
        srgb
    }
    /// Return the color with values { e^r, e^g, e^b }
    pub fn exp(&self) -> Colorf {
        Colorf { r: Float::exp(self.r), g: Float::exp(self.g),
                 b: Float::exp(self.b), a: Float::exp(self.a) }
    }
}

impl Add for Colorf {
    type Output = Colorf;
    /// Add two colors together
    fn add(self, rhs: Colorf) -> Colorf {
        Colorf { r: self.r + rhs.r, g: self.g + rhs.g, b: self.b + rhs.b, a: self.a + rhs.a }
    }
}

impl Sub for Colorf {
    type Output = Colorf;
    /// Subtract the two colors
    fn sub(self, rhs: Colorf) -> Colorf {
        Colorf { r: self.r - rhs.r, g: self.g - rhs.g, b: self.b - rhs.b, a: self.a - rhs.a }
    }
}

impl Mul for Colorf {
    type Output = Colorf;
    /// Multiply the two colors
    fn mul(self, rhs: Colorf) -> Colorf {
        Colorf { r: self.r * rhs.r, g: self.g * rhs.g, b: self.b * rhs.b, a: self.a * rhs.a }
    }
}

impl Mul<f32> for Colorf {
    type Output = Colorf;
    /// Scale the color by the float
    fn mul(self, rhs: f32) -> Colorf {
        Colorf { r: self.r * rhs, g: self.g * rhs, b: self.b * rhs, a: self.a * rhs }
    }
}

impl Div for Colorf {
    type Output = Colorf;
    /// Divide the channels of one color by another
    fn div(self, rhs: Colorf) -> Colorf {
        Colorf { r: self.r / rhs.r, g: self.g / rhs.g, b: self.b / rhs.b, a: self.a / rhs.a }
    }
}

impl Div<f32> for Colorf {
    type Output = Colorf;
    /// Divide the channels of the color by the float
    fn div(self, rhs: f32) -> Colorf {
        Colorf { r: self.r / rhs, g: self.g / rhs, b: self.b / rhs, a: self.a / rhs }
    }
}

impl Neg for Colorf {
    type Output = Colorf;
    /// Negate the color channels
    fn neg(self) -> Colorf {
        Colorf { r: -self.r, g: -self.g, b: -self.b, a: -self.a }
    }
}

impl Index<usize> for Colorf {
    type Output = f32;
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    /// - 3 = a
    fn index(&self, i: &usize) -> &f32 {
        match *i {
            0 => &self.r,
            1 => &self.g,
            2 => &self.b,
            3 => &self.a,
            _ => panic!("Invalid index into color"),
        }
    }
}

impl IndexMut<usize> for Colorf {
    type Output = f32;
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    /// - 3 = a
    fn index_mut(&mut self, i: &usize) -> &mut f32 {
        match *i {
            0 => &mut self.r,
            1 => &mut self.g,
            2 => &mut self.b,
            3 => &mut self.a,
            _ => panic!("Invalid index into color"),
        }
    }
}

<|endoftext|>


<commit_before>mod page;
pub use self::page::Page;

use std::env;
use std::io::Read;
use std::ascii::AsciiExt;
use std::default::Default;
use std::collections::BTreeMap;

use url::Url;
use reqwest::Client as HttpClient;
use reqwest::header::UserAgent;
use reqwest::StatusCode;
use reqwest::Response as HttpResponse;
use robotparser::RobotFileParser;
use html5ever::tokenizer::Tokenizer;
use html5ever::tokenizer::buffer_queue::BufferQueue;
use sidekiq::Client as SidekiqClient;
use sidekiq::ClientOpts as SidekiqClientOpts;
use sidekiq::RedisPool;
use encoding::{Encoding, DecoderTrap};
use encoding::all::UTF_8;
use url_serde::Serde;

const MAMAN_ENV: &'static str = "MAMAN_ENV";
const MAMAN_ENV_DEFAULT: &'static str = "development";

pub struct Spider<'a> {
    pub base_url: Url,
    pub visited_urls: Vec<Serde<Url>>,
    pub unvisited_urls: Vec<Serde<Url>>,
    pub env: String,
    pub limit: isize,
    sidekiq: SidekiqClient,
    robot_parser: RobotFileParser<'a>,
}

impl<'a> Spider<'a> {
    pub fn new(redis_pool: RedisPool, base_url: Url, limit: isize) -> Spider<'a> {
        let maman_env = env::var(&MAMAN_ENV.to_owned()).unwrap_or_else(|_| MAMAN_ENV_DEFAULT.to_owned());
        let robots_txt = base_url.join("/robots.txt").unwrap();
        let robot_file_parser = RobotFileParser::new(robots_txt);
        let client_opts = SidekiqClientOpts {
            namespace: Some(maman_env.to_string()),
            ..Default::default()
        };
        let sidekiq = SidekiqClient::new(redis_pool, client_opts);
        Spider {
            base_url: base_url,
            visited_urls: Vec::new(),
            unvisited_urls: Vec::new(),
            sidekiq: sidekiq,
            env: maman_env,
            robot_parser: robot_file_parser,
            limit: limit,
        }
    }

    pub fn visit_page(&mut self, page: Page) {
        self.visited_urls.push(page.url.clone());
        for u in &page.urls {
            self.unvisited_urls.push(u.clone());
        }
        match self.sidekiq.push(page.to_job()) {
            Err(err) => {
                error!("SidekiqClient push failed: {}", err);
            }
            Ok(_) => {}
        }
    }

    pub fn crawl(&mut self) {
        self.robot_parser.read();
        let base_url = self.base_url.clone();
        if let Some(response) = Spider::load_url(self.base_url.as_ref()) {
            self.visit(&base_url, response);
            while let Some(url) = self.unvisited_urls.pop() {
                if self.continue_to_crawl() {
                    if !self.visited_urls.contains(&url) {
                        if let Some(response) = Spider::load_url(url.as_ref()) {
                            self.visit(&url, response);
                        }
                    }
                } else {
                    break;
                }
            }
        }
    }

    pub fn read_page(page: Page, document: &str) -> Tokenizer<Page> {
        let mut tok = Tokenizer::new(page, Default::default());
        let mut input = BufferQueue::new();
        input.push_back(String::from(document).into());
        let _ = tok.feed(&mut input);
        tok.end();
        tok
    }

    fn visit(&mut self, page_url: &Url, response: HttpResponse) {
        if self.can_visit(page_url) {
            info!("{}", page_url);
            if let Some(page) = Spider::read_response(page_url, response) {
                self.visit_page(page);
            }
        }
    }

    fn continue_to_crawl(&self) -> bool {
        self.limit == 0 || (self.visited_urls.len() as isize) < self.limit
    }

    fn can_visit(&self, page_url: &Url) -> bool {
        self.robot_parser
            .can_fetch(maman_name!(), page_url.path())
    }

    fn read_response(page_url: &Url, mut response: HttpResponse) -> Option<Page> {
        let mut headers = BTreeMap::new();
        {
            for h in response.headers().iter() {
                headers.insert(h.name().to_ascii_lowercase(), h.value_string());
            }
        }
        let mut document = vec![];
        let _ = response.read_to_end(&mut document);
        match UTF_8.decode(&document, DecoderTrap::Ignore) {
            Ok(doc) => {
                let page = Page::new(page_url.clone(), doc.to_string(), headers.clone());
                let read = Spider::read_page(page, &doc).unwrap();
                Some(read)
            }
            Err(_) => None,
        }
    }

    fn load_url(url: &str) -> Option<HttpResponse> {
        let client = HttpClient::new().expect("HttpClient failed to construct");
        let request = client
            .get(url)
            .header(UserAgent(maman_user_agent!().to_owned()));
        match request.send() {
            Ok(response) => {
                match response.status() {
                    &StatusCode::Ok |
                    &StatusCode::NotModified => Some(response),
                    _ => None,
                }
            }
            Err(_) => None,
        }
    }
}
<commit_msg>Use `if let` for destructuring a single pattern<commit_after>mod page;
pub use self::page::Page;

use std::env;
use std::io::Read;
use std::ascii::AsciiExt;
use std::default::Default;
use std::collections::BTreeMap;

use url::Url;
use reqwest::Client as HttpClient;
use reqwest::header::UserAgent;
use reqwest::StatusCode;
use reqwest::Response as HttpResponse;
use robotparser::RobotFileParser;
use html5ever::tokenizer::Tokenizer;
use html5ever::tokenizer::buffer_queue::BufferQueue;
use sidekiq::Client as SidekiqClient;
use sidekiq::ClientOpts as SidekiqClientOpts;
use sidekiq::RedisPool;
use encoding::{Encoding, DecoderTrap};
use encoding::all::UTF_8;
use url_serde::Serde;

const MAMAN_ENV: &'static str = "MAMAN_ENV";
const MAMAN_ENV_DEFAULT: &'static str = "development";

pub struct Spider<'a> {
    pub base_url: Url,
    pub visited_urls: Vec<Serde<Url>>,
    pub unvisited_urls: Vec<Serde<Url>>,
    pub env: String,
    pub limit: isize,
    sidekiq: SidekiqClient,
    robot_parser: RobotFileParser<'a>,
}

impl<'a> Spider<'a> {
    pub fn new(redis_pool: RedisPool, base_url: Url, limit: isize) -> Spider<'a> {
        let maman_env = env::var(&MAMAN_ENV.to_owned()).unwrap_or_else(|_| MAMAN_ENV_DEFAULT.to_owned());
        let robots_txt = base_url.join("/robots.txt").unwrap();
        let robot_file_parser = RobotFileParser::new(robots_txt);
        let client_opts = SidekiqClientOpts {
            namespace: Some(maman_env.to_string()),
            ..Default::default()
        };
        let sidekiq = SidekiqClient::new(redis_pool, client_opts);
        Spider {
            base_url: base_url,
            visited_urls: Vec::new(),
            unvisited_urls: Vec::new(),
            sidekiq: sidekiq,
            env: maman_env,
            robot_parser: robot_file_parser,
            limit: limit,
        }
    }

    pub fn visit_page(&mut self, page: Page) {
        self.visited_urls.push(page.url.clone());
        for u in &page.urls {
            self.unvisited_urls.push(u.clone());
        }
        if let Err(err) = self.sidekiq.push(page.to_job()) {
            error!("SidekiqClient push failed: {}", err);
        }
    }

    pub fn crawl(&mut self) {
        self.robot_parser.read();
        let base_url = self.base_url.clone();
        if let Some(response) = Spider::load_url(self.base_url.as_ref()) {
            self.visit(&base_url, response);
            while let Some(url) = self.unvisited_urls.pop() {
                if self.continue_to_crawl() {
                    if !self.visited_urls.contains(&url) {
                        if let Some(response) = Spider::load_url(url.as_ref()) {
                            self.visit(&url, response);
                        }
                    }
                } else {
                    break;
                }
            }
        }
    }

    pub fn read_page(page: Page, document: &str) -> Tokenizer<Page> {
        let mut tok = Tokenizer::new(page, Default::default());
        let mut input = BufferQueue::new();
        input.push_back(String::from(document).into());
        let _ = tok.feed(&mut input);
        tok.end();
        tok
    }

    fn visit(&mut self, page_url: &Url, response: HttpResponse) {
        if self.can_visit(page_url) {
            info!("{}", page_url);
            if let Some(page) = Spider::read_response(page_url, response) {
                self.visit_page(page);
            }
        }
    }

    fn continue_to_crawl(&self) -> bool {
        self.limit == 0 || (self.visited_urls.len() as isize) < self.limit
    }

    fn can_visit(&self, page_url: &Url) -> bool {
        self.robot_parser
            .can_fetch(maman_name!(), page_url.path())
    }

    fn read_response(page_url: &Url, mut response: HttpResponse) -> Option<Page> {
        let mut headers = BTreeMap::new();
        {
            for h in response.headers().iter() {
                headers.insert(h.name().to_ascii_lowercase(), h.value_string());
            }
        }
        let mut document = vec![];
        let _ = response.read_to_end(&mut document);
        match UTF_8.decode(&document, DecoderTrap::Ignore) {
            Ok(doc) => {
                let page = Page::new(page_url.clone(), doc.to_string(), headers.clone());
                let read = Spider::read_page(page, &doc).unwrap();
                Some(read)
            }
            Err(_) => None,
        }
    }

    fn load_url(url: &str) -> Option<HttpResponse> {
        let client = HttpClient::new().expect("HttpClient failed to construct");
        let request = client
            .get(url)
            .header(UserAgent(maman_user_agent!().to_owned()));
        match request.send() {
            Ok(response) => {
                match response.status() {
                    &StatusCode::Ok |
                    &StatusCode::NotModified => Some(response),
                    _ => None,
                }
            }
            Err(_) => None,
        }
    }
}
<|endoftext|>


<commit_before>//! A control flow graph represented as mappings of extended basic blocks to their predecessors
//! and successors.
//!
//! Successors are represented as extended basic blocks while predecessors are represented by basic
//! blocks. Basic blocks are denoted by tuples of EBB and branch/jump instructions. Each
//! predecessor tuple corresponds to the end of a basic block.
//!
//! ```c
//!     Ebb0:
//!         ...          ; beginning of basic block
//!
//!         ...
//!
//!         brz vx, Ebb1 ; end of basic block
//!
//!         ...          ; beginning of basic block
//!
//!         ...
//!
//!         jmp Ebb2     ; end of basic block
//! ```
//!
//! Here `Ebb1` and `Ebb2` would each have a single predecessor denoted as `(Ebb0, brz)`
//! and `(Ebb0, jmp Ebb2)` respectively.

use ir::{Function, Inst, Ebb};
use ir::instructions::BranchInfo;
use entity_map::{EntityMap, Keys};
use std::collections::HashSet;

/// A basic block denoted by its enclosing Ebb and last instruction.
pub type BasicBlock = (Ebb, Inst);

/// A container for the successors and predecessors of some Ebb.
#[derive(Debug, Clone, Default)]
pub struct CFGNode {
    /// EBBs that are the targets of branches and jumps in this EBB.
    pub successors: Vec<Ebb>,
    /// Basic blocks that can branch or jump to this EBB.
    pub predecessors: Vec<BasicBlock>,
}

/// The Control Flow Graph maintains a mapping of ebbs to their predecessors
/// and successors where predecessors are basic blocks and successors are
/// extended basic blocks.
#[derive(Debug)]
pub struct ControlFlowGraph {
    entry_block: Option<Ebb>,
    data: EntityMap<Ebb, CFGNode>,
}

impl ControlFlowGraph {
    /// During initialization mappings will be generated for any existing
    /// blocks within the CFG's associated function.
    pub fn new(func: &Function) -> ControlFlowGraph {

        let mut cfg = ControlFlowGraph {
            data: EntityMap::with_capacity(func.dfg.num_ebbs()),
            entry_block: func.layout.entry_block(),
        };

        for ebb in &func.layout {
            for inst in func.layout.ebb_insts(ebb) {
                match func.dfg[inst].analyze_branch() {
                    BranchInfo::SingleDest(dest, _) => {
                        cfg.add_edge((ebb, inst), dest);
                    }
                    BranchInfo::Table(jt) => {
                        for (_, dest) in func.jump_tables[jt].entries() {
                            cfg.add_edge((ebb, inst), dest);
                        }
                    }
                    BranchInfo::NotABranch => {}
                }
            }
        }
        cfg
    }

    fn add_edge(&mut self, from: BasicBlock, to: Ebb) {
        self.data[from.0].successors.push(to);
        self.data[to].predecessors.push(from);
    }

    /// Get the CFG predecessor basic blocks to `ebb`.
    pub fn get_predecessors(&self, ebb: Ebb) -> &Vec<BasicBlock> {
        &self.data[ebb].predecessors
    }

    /// Get the CFG successors to `ebb`.
    pub fn get_successors(&self, ebb: Ebb) -> &Vec<Ebb> {
        &self.data[ebb].successors
    }

    /// Return [reachable] ebbs in post-order.
    pub fn postorder_ebbs(&self) -> Vec<Ebb> {
        let entry_block = match self.entry_block {
            None => {
                return Vec::new();
            }
            Some(eb) => eb,
        };

        let mut grey = HashSet::new();
        let mut black = HashSet::new();
        let mut stack = vec![entry_block.clone()];
        let mut postorder = Vec::new();

        while !stack.is_empty() {
            let node = stack.pop().unwrap();
            if !grey.contains(&node) {
                // This is a white node. Mark it as gray.
                grey.insert(node);
                stack.push(node);
                // Get any children we've never seen before.
                for child in self.get_successors(node) {
                    if !grey.contains(child) {
                        stack.push(child.clone());
                    }
                }
            } else if !black.contains(&node) {
                postorder.push(node.clone());
                black.insert(node.clone());
            }
        }
        postorder
    }

    /// An iterator across all of the ebbs stored in the CFG.
    pub fn ebbs(&self) -> Keys<Ebb> {
        self.data.keys()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ir::{Function, InstBuilder, Cursor, VariableArgs, types};

    #[test]
    fn empty() {
        let func = Function::new();
        let cfg = ControlFlowGraph::new(&func);
        assert_eq!(None, cfg.ebbs().next());
    }

    #[test]
    fn no_predecessors() {
        let mut func = Function::new();
        let ebb0 = func.dfg.make_ebb();
        let ebb1 = func.dfg.make_ebb();
        let ebb2 = func.dfg.make_ebb();
        func.layout.append_ebb(ebb0);
        func.layout.append_ebb(ebb1);
        func.layout.append_ebb(ebb2);

        let cfg = ControlFlowGraph::new(&func);
        let nodes = cfg.ebbs().collect::<Vec<_>>();
        assert_eq!(nodes.len(), 3);

        let mut fun_ebbs = func.layout.ebbs();
        for ebb in nodes {
            assert_eq!(ebb, fun_ebbs.next().unwrap());
            assert_eq!(cfg.get_predecessors(ebb).len(), 0);
            assert_eq!(cfg.get_successors(ebb).len(), 0);
        }
    }

    #[test]
    fn branches_and_jumps() {
        let mut func = Function::new();
        let ebb0 = func.dfg.make_ebb();
        let cond = func.dfg.append_ebb_arg(ebb0, types::I32);
        let ebb1 = func.dfg.make_ebb();
        let ebb2 = func.dfg.make_ebb();

        let br_ebb0_ebb2;
        let br_ebb1_ebb1;
        let jmp_ebb0_ebb1;
        let jmp_ebb1_ebb2;

        {
            let dfg = &mut func.dfg;
            let cur = &mut Cursor::new(&mut func.layout);

            cur.insert_ebb(ebb0);
            br_ebb0_ebb2 = dfg.ins(cur).brnz(cond, ebb2, VariableArgs::new());
            jmp_ebb0_ebb1 = dfg.ins(cur).jump(ebb1, VariableArgs::new());

            cur.insert_ebb(ebb1);
            br_ebb1_ebb1 = dfg.ins(cur).brnz(cond, ebb1, VariableArgs::new());
            jmp_ebb1_ebb2 = dfg.ins(cur).jump(ebb2, VariableArgs::new());

            cur.insert_ebb(ebb2);
        }

        let cfg = ControlFlowGraph::new(&func);

        let ebb0_predecessors = cfg.get_predecessors(ebb0);
        let ebb1_predecessors = cfg.get_predecessors(ebb1);
        let ebb2_predecessors = cfg.get_predecessors(ebb2);

        let ebb0_successors = cfg.get_successors(ebb0);
        let ebb1_successors = cfg.get_successors(ebb1);
        let ebb2_successors = cfg.get_successors(ebb2);

        assert_eq!(ebb0_predecessors.len(), 0);
        assert_eq!(ebb1_predecessors.len(), 2);
        assert_eq!(ebb2_predecessors.len(), 2);

        assert_eq!(ebb1_predecessors.contains(&(ebb0, jmp_ebb0_ebb1)), true);
        assert_eq!(ebb1_predecessors.contains(&(ebb1, br_ebb1_ebb1)), true);
        assert_eq!(ebb2_predecessors.contains(&(ebb0, br_ebb0_ebb2)), true);
        assert_eq!(ebb2_predecessors.contains(&(ebb1, jmp_ebb1_ebb2)), true);

        assert_eq!(ebb0_successors.len(), 2);
        assert_eq!(ebb1_successors.len(), 2);
        assert_eq!(ebb2_successors.len(), 0);

        assert_eq!(ebb0_successors.contains(&ebb1), true);
        assert_eq!(ebb0_successors.contains(&ebb2), true);
        assert_eq!(ebb1_successors.contains(&ebb1), true);
        assert_eq!(ebb1_successors.contains(&ebb2), true);
    }
}
<commit_msg>Return slices instead of &Vec references.<commit_after>//! A control flow graph represented as mappings of extended basic blocks to their predecessors
//! and successors.
//!
//! Successors are represented as extended basic blocks while predecessors are represented by basic
//! blocks. Basic blocks are denoted by tuples of EBB and branch/jump instructions. Each
//! predecessor tuple corresponds to the end of a basic block.
//!
//! ```c
//!     Ebb0:
//!         ...          ; beginning of basic block
//!
//!         ...
//!
//!         brz vx, Ebb1 ; end of basic block
//!
//!         ...          ; beginning of basic block
//!
//!         ...
//!
//!         jmp Ebb2     ; end of basic block
//! ```
//!
//! Here `Ebb1` and `Ebb2` would each have a single predecessor denoted as `(Ebb0, brz)`
//! and `(Ebb0, jmp Ebb2)` respectively.

use ir::{Function, Inst, Ebb};
use ir::instructions::BranchInfo;
use entity_map::{EntityMap, Keys};
use std::collections::HashSet;

/// A basic block denoted by its enclosing Ebb and last instruction.
pub type BasicBlock = (Ebb, Inst);

/// A container for the successors and predecessors of some Ebb.
#[derive(Debug, Clone, Default)]
pub struct CFGNode {
    /// EBBs that are the targets of branches and jumps in this EBB.
    pub successors: Vec<Ebb>,
    /// Basic blocks that can branch or jump to this EBB.
    pub predecessors: Vec<BasicBlock>,
}

/// The Control Flow Graph maintains a mapping of ebbs to their predecessors
/// and successors where predecessors are basic blocks and successors are
/// extended basic blocks.
#[derive(Debug)]
pub struct ControlFlowGraph {
    entry_block: Option<Ebb>,
    data: EntityMap<Ebb, CFGNode>,
}

impl ControlFlowGraph {
    /// During initialization mappings will be generated for any existing
    /// blocks within the CFG's associated function.
    pub fn new(func: &Function) -> ControlFlowGraph {

        let mut cfg = ControlFlowGraph {
            data: EntityMap::with_capacity(func.dfg.num_ebbs()),
            entry_block: func.layout.entry_block(),
        };

        for ebb in &func.layout {
            for inst in func.layout.ebb_insts(ebb) {
                match func.dfg[inst].analyze_branch() {
                    BranchInfo::SingleDest(dest, _) => {
                        cfg.add_edge((ebb, inst), dest);
                    }
                    BranchInfo::Table(jt) => {
                        for (_, dest) in func.jump_tables[jt].entries() {
                            cfg.add_edge((ebb, inst), dest);
                        }
                    }
                    BranchInfo::NotABranch => {}
                }
            }
        }
        cfg
    }

    fn add_edge(&mut self, from: BasicBlock, to: Ebb) {
        self.data[from.0].successors.push(to);
        self.data[to].predecessors.push(from);
    }

    /// Get the CFG predecessor basic blocks to `ebb`.
    pub fn get_predecessors(&self, ebb: Ebb) -> &[BasicBlock] {
        &self.data[ebb].predecessors
    }

    /// Get the CFG successors to `ebb`.
    pub fn get_successors(&self, ebb: Ebb) -> &[Ebb] {
        &self.data[ebb].successors
    }

    /// Return [reachable] ebbs in post-order.
    pub fn postorder_ebbs(&self) -> Vec<Ebb> {
        let entry_block = match self.entry_block {
            None => {
                return Vec::new();
            }
            Some(eb) => eb,
        };

        let mut grey = HashSet::new();
        let mut black = HashSet::new();
        let mut stack = vec![entry_block.clone()];
        let mut postorder = Vec::new();

        while !stack.is_empty() {
            let node = stack.pop().unwrap();
            if !grey.contains(&node) {
                // This is a white node. Mark it as gray.
                grey.insert(node);
                stack.push(node);
                // Get any children we've never seen before.
                for child in self.get_successors(node) {
                    if !grey.contains(child) {
                        stack.push(child.clone());
                    }
                }
            } else if !black.contains(&node) {
                postorder.push(node.clone());
                black.insert(node.clone());
            }
        }
        postorder
    }

    /// An iterator across all of the ebbs stored in the CFG.
    pub fn ebbs(&self) -> Keys<Ebb> {
        self.data.keys()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ir::{Function, InstBuilder, Cursor, VariableArgs, types};

    #[test]
    fn empty() {
        let func = Function::new();
        let cfg = ControlFlowGraph::new(&func);
        assert_eq!(None, cfg.ebbs().next());
    }

    #[test]
    fn no_predecessors() {
        let mut func = Function::new();
        let ebb0 = func.dfg.make_ebb();
        let ebb1 = func.dfg.make_ebb();
        let ebb2 = func.dfg.make_ebb();
        func.layout.append_ebb(ebb0);
        func.layout.append_ebb(ebb1);
        func.layout.append_ebb(ebb2);

        let cfg = ControlFlowGraph::new(&func);
        let nodes = cfg.ebbs().collect::<Vec<_>>();
        assert_eq!(nodes.len(), 3);

        let mut fun_ebbs = func.layout.ebbs();
        for ebb in nodes {
            assert_eq!(ebb, fun_ebbs.next().unwrap());
            assert_eq!(cfg.get_predecessors(ebb).len(), 0);
            assert_eq!(cfg.get_successors(ebb).len(), 0);
        }
    }

    #[test]
    fn branches_and_jumps() {
        let mut func = Function::new();
        let ebb0 = func.dfg.make_ebb();
        let cond = func.dfg.append_ebb_arg(ebb0, types::I32);
        let ebb1 = func.dfg.make_ebb();
        let ebb2 = func.dfg.make_ebb();

        let br_ebb0_ebb2;
        let br_ebb1_ebb1;
        let jmp_ebb0_ebb1;
        let jmp_ebb1_ebb2;

        {
            let dfg = &mut func.dfg;
            let cur = &mut Cursor::new(&mut func.layout);

            cur.insert_ebb(ebb0);
            br_ebb0_ebb2 = dfg.ins(cur).brnz(cond, ebb2, VariableArgs::new());
            jmp_ebb0_ebb1 = dfg.ins(cur).jump(ebb1, VariableArgs::new());

            cur.insert_ebb(ebb1);
            br_ebb1_ebb1 = dfg.ins(cur).brnz(cond, ebb1, VariableArgs::new());
            jmp_ebb1_ebb2 = dfg.ins(cur).jump(ebb2, VariableArgs::new());

            cur.insert_ebb(ebb2);
        }

        let cfg = ControlFlowGraph::new(&func);

        let ebb0_predecessors = cfg.get_predecessors(ebb0);
        let ebb1_predecessors = cfg.get_predecessors(ebb1);
        let ebb2_predecessors = cfg.get_predecessors(ebb2);

        let ebb0_successors = cfg.get_successors(ebb0);
        let ebb1_successors = cfg.get_successors(ebb1);
        let ebb2_successors = cfg.get_successors(ebb2);

        assert_eq!(ebb0_predecessors.len(), 0);
        assert_eq!(ebb1_predecessors.len(), 2);
        assert_eq!(ebb2_predecessors.len(), 2);

        assert_eq!(ebb1_predecessors.contains(&(ebb0, jmp_ebb0_ebb1)), true);
        assert_eq!(ebb1_predecessors.contains(&(ebb1, br_ebb1_ebb1)), true);
        assert_eq!(ebb2_predecessors.contains(&(ebb0, br_ebb0_ebb2)), true);
        assert_eq!(ebb2_predecessors.contains(&(ebb1, jmp_ebb1_ebb2)), true);

        assert_eq!(ebb0_successors.len(), 2);
        assert_eq!(ebb1_successors.len(), 2);
        assert_eq!(ebb2_successors.len(), 0);

        assert_eq!(ebb0_successors.contains(&ebb1), true);
        assert_eq!(ebb0_successors.contains(&ebb2), true);
        assert_eq!(ebb1_successors.contains(&ebb1), true);
        assert_eq!(ebb1_successors.contains(&ebb2), true);
    }
}
<|endoftext|>


<commit_before>//! Headers container, and common header fields.
//!
//! hyper has the opinion that Headers should be strongly-typed, because that's
//! why we're using Rust in the first place. To set or get any header, an object
//! must implement the `Header` trait from this module. Several common headers
//! are already provided, such as `Host`, `ContentType`, `UserAgent`, and others.
use std::ascii::{AsciiExt, ASCII_LOWER_MAP};
use std::fmt::{mod, Show};
use std::hash;
use std::intrinsics::TypeId;
use std::mem::{transmute, transmute_copy};
use std::raw::TraitObject;
use std::str::{from_utf8, SendStr, Slice, Owned};
use std::string::raw;
use std::collections::hashmap::{HashMap, Entries, Occupied, Vacant};
use std::sync::RWLock;

use uany::UncheckedAnyDowncast;
use typeable::Typeable;

use http::read_header;
use {HttpResult};

/// Common Headers
pub mod common;

/// A trait for any object that will represent a header field and value.
pub trait Header: Typeable + Send + Sync {
    /// Returns the name of the header field this belongs to.
    ///
    /// The market `Option` is to hint to the type system which implementation
    /// to call. This can be done away with once UFCS arrives.
    fn header_name(marker: Option<Self>) -> &'static str;
    /// Parse a header from a raw stream of bytes.
    ///
    /// It's possible that a request can include a header field more than once,
    /// and in that case, the slice will have a length greater than 1. However,
    /// it's not necessarily the case that a Header is *allowed* to have more
    /// than one field value. If that's the case, you **should** return `None`
    /// if `raw.len() > 1`.
    fn parse_header(raw: &[Vec<u8>]) -> Option<Self>;
    /// Format a header to be output into a TcpStream.
    fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result;
}

#[doc(hidden)]
trait Is {
    fn is<T: 'static>(self) -> bool;
}

impl<'a> Is for &'a Header {
    fn is<T: 'static>(self) -> bool {
        self.get_type() == TypeId::of::<T>()
    }
}

impl<'a> UncheckedAnyDowncast<'a> for &'a Header {
    #[inline]
    unsafe fn downcast_ref_unchecked<T: 'static>(self) -> &'a T {
        let to: TraitObject = transmute_copy(&self);
        transmute(to.data)
    }
}

fn header_name<T: Header>() -> &'static str {
    let name = Header::header_name(None::<T>);
    name
}

/// A map of header fields on requests and responses.
pub struct Headers {
    data: HashMap<CaseInsensitive, RWLock<Item>>
}

impl Headers {

    /// Creates a new, empty headers map.
    pub fn new() -> Headers {
        Headers {
            data: HashMap::new()
        }
    }

    #[doc(hidden)]
    pub fn from_raw<R: Reader>(rdr: &mut R) -> HttpResult<Headers> {
        let mut headers = Headers::new();
        loop {
            match try!(read_header(rdr)) {
                Some((name, value)) => {
                    // read_header already checks that name is a token, which
                    // means its safe utf8
                    let name = unsafe {
                        raw::from_utf8(name)
                    };

                    let name = CaseInsensitive(Owned(name));
                    let item = match headers.data.entry(name) {
                        Vacant(entry) => entry.set(RWLock::new(Raw(vec![]))),
                        Occupied(entry) => entry.into_mut()
                    };

                    match &mut *item.write() {
                        &Raw(ref mut raw) => raw.push(value),
                        // Unreachable
                        _ => {}
                    };
                },
                None => break,
            }
        }
        Ok(headers)
    }

    /// Set a header field to the corresponding value.
    ///
    /// The field is determined by the type of the value being set.
    pub fn set<H: Header>(&mut self, value: H) {
        self.data.insert(CaseInsensitive(Slice(header_name::<H>())), RWLock::new(Typed(box value as Box<Header + Send + Sync>)));
    }

    /// Get a clone of the header field's value, if it exists.
    ///
    /// Example:
    ///
    /// ```
    /// # use hyper::header::Headers;
    /// # use hyper::header::common::ContentType;
    /// # let mut headers = Headers::new();
    /// let content_type = headers.get::<ContentType>();
    /// ```
    pub fn get<H: Header + Clone>(&self) -> Option<H> {
        self.get_ref().map(|v: &H| v.clone())
    }

    /// Access the raw value of a header, if it exists and has not
    /// been already parsed.
    ///
    /// If the header field has already been parsed into a typed header,
    /// then you *must* access it through that representation.
    ///
    /// This operation is unsafe because the raw representation can be
    /// invalidated by lasting too long or by the header being parsed
    /// while you still have a reference to the data.
    ///
    /// Example:
    /// ```
    /// # use hyper::header::Headers;
    /// # let mut headers = Headers::new();
    /// let raw_content_type = unsafe { headers.get_raw("content-type") };
    /// ```
    pub unsafe fn get_raw(&self, name: &'static str) -> Option<*const [Vec<u8>]> {
        self.data.find(&CaseInsensitive(Slice(name))).and_then(|item| {
            match *item.read() {
                Raw(ref raw) => Some(raw.as_slice() as *const [Vec<u8>]),
                _ => None
            }
        })
    }

    /// Get a reference to the header field's value, if it exists.
    pub fn get_ref<H: Header>(&self) -> Option<&H> {
        self.data.find(&CaseInsensitive(Slice(header_name::<H>()))).and_then(|item| {
            let header = match *item.read() {
                // Huge borrowck hack here, should be refactored to just return here.
                Typed(ref typed) if typed.is::<H>() => None,
                // Typed, wrong type
                Typed(_) => return None,
                Raw(ref raw) => match Header::parse_header(raw.as_slice()) {
                    Some::<H>(h) => {
                        Some(h)
                    },
                    None => return None
                },
            };

            match header {
                Some(header) => {
                    *item.write() = Typed(box header as Box<Header + Send + Sync>);
                    Some(item)
                },
                None => {
                    Some(item)
                }
            }
        }).and_then(|item| {
            let read = item.read();
            debug!("downcasting {}", *read);
            let ret = match *read {
                Typed(ref val) => {
                    unsafe { Some(val.downcast_ref_unchecked()) }
                },
                _ => unreachable!()
            };
            unsafe { transmute::<Option<&H>, Option<&H>>(ret) }
        })
    }

    /// Returns a boolean of whether a certain header is in the map.
    ///
    /// Example:
    ///
    /// ```
    /// # use hyper::header::Headers;
    /// # use hyper::header::common::ContentType;
    /// # let mut headers = Headers::new();
    /// let has_type = headers.has::<ContentType>();
    /// ```
    pub fn has<H: Header>(&self) -> bool {
        self.data.contains_key(&CaseInsensitive(Slice(header_name::<H>())))
    }

    /// Removes a header from the map, if one existed.
    /// Returns true if a header has been removed.
    pub fn remove<H: Header>(&mut self) -> bool {
        self.data.remove(&CaseInsensitive(Slice(Header::header_name(None::<H>))))
    }

    /// Returns an iterator over the header fields.
    pub fn iter<'a>(&'a self) -> HeadersItems<'a> {
        HeadersItems {
            inner: self.data.iter()
        }
    }
}

impl fmt::Show for Headers {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!("Headers {\n".fmt(fmt));
        for (k, v) in self.iter() {
            try!(write!(fmt, "\t{}: {}\n", k, v));
        }
        "}".fmt(fmt)
    }
}

/// An `Iterator` over the fields in a `Headers` map.
pub struct HeadersItems<'a> {
    inner: Entries<'a, CaseInsensitive, RWLock<Item>>
}

impl<'a> Iterator<(&'a str, HeaderView<'a>)> for HeadersItems<'a> {
    fn next(&mut self) -> Option<(&'a str, HeaderView<'a>)> {
        match self.inner.next() {
            Some((k, v)) => Some((k.as_slice(), HeaderView(v))),
            None => None
        }
    }
}

/// Returned with the `HeadersItems` iterator.
pub struct HeaderView<'a>(&'a RWLock<Item>);

impl<'a> fmt::Show for HeaderView<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let HeaderView(item) = *self;
        item.read().fmt(fmt)
    }
}

impl Collection for Headers {
    fn len(&self) -> uint {
        self.data.len()
    }
}

impl Mutable for Headers {
    fn clear(&mut self) {
        self.data.clear()
    }
}

enum Item {
    Raw(Vec<Vec<u8>>),
    Typed(Box<Header + Send + Sync>)
}

impl fmt::Show for Item {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Typed(ref h) => h.fmt_header(fmt),
            Raw(ref raw) => {
                for part in raw.iter() {
                    try!(fmt.write(part.as_slice()));
                }
                Ok(())
            },
        }
    }
}

struct CaseInsensitive(SendStr);

impl Str for CaseInsensitive {
    fn as_slice(&self) -> &str {
        let CaseInsensitive(ref s) = *self;
        s.as_slice()
    }

}

impl fmt::Show for CaseInsensitive {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(fmt)
    }
}

impl PartialEq for CaseInsensitive {
    fn eq(&self, other: &CaseInsensitive) -> bool {
        self.as_slice().eq_ignore_ascii_case(other.as_slice())
    }
}

impl Eq for CaseInsensitive {}

impl<H: hash::Writer> hash::Hash<H> for CaseInsensitive {
    #[inline]
    fn hash(&self, hasher: &mut H) {
        for byte in self.as_slice().bytes() {
            hasher.write([ASCII_LOWER_MAP[byte as uint]].as_slice());
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io::MemReader;
    use std::fmt;
    use std::str::Slice;
    use std::hash::sip::hash;
    use mime::{Mime, Text, Plain};
    use super::CaseInsensitive;
    use super::{Headers, Header};
    use super::common::{ContentLength, ContentType};

    fn mem(s: &str) -> MemReader {
        MemReader::new(s.as_bytes().to_vec())
    }

    #[test]
    fn test_case_insensitive() {
        let a = CaseInsensitive(Slice("foobar"));
        let b = CaseInsensitive(Slice("FOOBAR"));

        assert_eq!(a, b);
        assert_eq!(hash(&a), hash(&b));
    }

    #[test]
    fn test_from_raw() {
        let headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        assert_eq!(headers.get_ref(), Some(&ContentLength(10)));
    }

    #[test]
    fn test_content_type() {
        let content_type = Header::parse_header(["text/plain".as_bytes().to_vec()].as_slice());
        assert_eq!(content_type, Some(ContentType(Mime(Text, Plain, vec![]))));
    }

    #[deriving(Clone)]
    struct CrazyLength(Option<bool>, uint);

    impl Header for CrazyLength {
        fn header_name(_: Option<CrazyLength>) -> &'static str {
            "content-length"
        }
        fn parse_header(raw: &[Vec<u8>]) -> Option<CrazyLength> {
            use std::str::from_utf8;
            use std::from_str::FromStr;

            if raw.len() != 1 {
                return None;
            }
            // we JUST checked that raw.len() == 1, so raw[0] WILL exist.
            match from_utf8(unsafe { raw.as_slice().unsafe_get(0).as_slice() }) {
                Some(s) => FromStr::from_str(s),
                None => None
            }.map(|u| CrazyLength(Some(false), u))
        }
        fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
            use std::fmt::Show;
            let CrazyLength(_, ref value) = *self;
            value.fmt(fmt)
        }
    }

    #[test]
    fn test_different_structs_for_same_header() {
        let headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        let ContentLength(_) = headers.get::<ContentLength>().unwrap();
        assert!(headers.get::<CrazyLength>().is_none());
    }

    #[test]
    fn test_multiple_reads() {
        let headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        let ContentLength(one) = headers.get::<ContentLength>().unwrap();
        let ContentLength(two) = headers.get::<ContentLength>().unwrap();
        assert_eq!(one, two);
    }

    #[test]
    fn test_different_reads() {
        let headers = Headers::from_raw(&mut mem("Content-Length: 10\r\nContent-Type: text/plain\r\n\r\n")).unwrap();
        let ContentLength(_) = headers.get::<ContentLength>().unwrap();
        let ContentType(_) = headers.get::<ContentType>().unwrap();
    }
}

<commit_msg>Fixed a race condition in `get_ref`<commit_after>//! Headers container, and common header fields.
//!
//! hyper has the opinion that Headers should be strongly-typed, because that's
//! why we're using Rust in the first place. To set or get any header, an object
//! must implement the `Header` trait from this module. Several common headers
//! are already provided, such as `Host`, `ContentType`, `UserAgent`, and others.
use std::ascii::{AsciiExt, ASCII_LOWER_MAP};
use std::fmt::{mod, Show};
use std::hash;
use std::intrinsics::TypeId;
use std::mem::{transmute, transmute_copy};
use std::raw::TraitObject;
use std::str::{from_utf8, SendStr, Slice, Owned};
use std::string::raw;
use std::collections::hashmap::{HashMap, Entries, Occupied, Vacant};
use std::sync::RWLock;

use uany::UncheckedAnyDowncast;
use typeable::Typeable;

use http::read_header;
use {HttpResult};

/// Common Headers
pub mod common;

/// A trait for any object that will represent a header field and value.
pub trait Header: Typeable + Send + Sync {
    /// Returns the name of the header field this belongs to.
    ///
    /// The market `Option` is to hint to the type system which implementation
    /// to call. This can be done away with once UFCS arrives.
    fn header_name(marker: Option<Self>) -> &'static str;
    /// Parse a header from a raw stream of bytes.
    ///
    /// It's possible that a request can include a header field more than once,
    /// and in that case, the slice will have a length greater than 1. However,
    /// it's not necessarily the case that a Header is *allowed* to have more
    /// than one field value. If that's the case, you **should** return `None`
    /// if `raw.len() > 1`.
    fn parse_header(raw: &[Vec<u8>]) -> Option<Self>;
    /// Format a header to be output into a TcpStream.
    fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result;
}

#[doc(hidden)]
trait Is {
    fn is<T: 'static>(self) -> bool;
}

impl<'a> Is for &'a Header {
    fn is<T: 'static>(self) -> bool {
        self.get_type() == TypeId::of::<T>()
    }
}

impl<'a> UncheckedAnyDowncast<'a> for &'a Header {
    #[inline]
    unsafe fn downcast_ref_unchecked<T: 'static>(self) -> &'a T {
        let to: TraitObject = transmute_copy(&self);
        transmute(to.data)
    }
}

fn header_name<T: Header>() -> &'static str {
    let name = Header::header_name(None::<T>);
    name
}

/// A map of header fields on requests and responses.
pub struct Headers {
    data: HashMap<CaseInsensitive, RWLock<Item>>
}

impl Headers {

    /// Creates a new, empty headers map.
    pub fn new() -> Headers {
        Headers {
            data: HashMap::new()
        }
    }

    #[doc(hidden)]
    pub fn from_raw<R: Reader>(rdr: &mut R) -> HttpResult<Headers> {
        let mut headers = Headers::new();
        loop {
            match try!(read_header(rdr)) {
                Some((name, value)) => {
                    // read_header already checks that name is a token, which
                    // means its safe utf8
                    let name = unsafe {
                        raw::from_utf8(name)
                    };

                    let name = CaseInsensitive(Owned(name));
                    let item = match headers.data.entry(name) {
                        Vacant(entry) => entry.set(RWLock::new(Raw(vec![]))),
                        Occupied(entry) => entry.into_mut()
                    };

                    match &mut *item.write() {
                        &Raw(ref mut raw) => raw.push(value),
                        // Unreachable
                        _ => {}
                    };
                },
                None => break,
            }
        }
        Ok(headers)
    }

    /// Set a header field to the corresponding value.
    ///
    /// The field is determined by the type of the value being set.
    pub fn set<H: Header>(&mut self, value: H) {
        self.data.insert(CaseInsensitive(Slice(header_name::<H>())), RWLock::new(Typed(box value as Box<Header + Send + Sync>)));
    }

    /// Get a clone of the header field's value, if it exists.
    ///
    /// Example:
    ///
    /// ```
    /// # use hyper::header::Headers;
    /// # use hyper::header::common::ContentType;
    /// # let mut headers = Headers::new();
    /// let content_type = headers.get::<ContentType>();
    /// ```
    pub fn get<H: Header + Clone>(&self) -> Option<H> {
        self.get_ref().map(|v: &H| v.clone())
    }

    /// Access the raw value of a header, if it exists and has not
    /// been already parsed.
    ///
    /// If the header field has already been parsed into a typed header,
    /// then you *must* access it through that representation.
    ///
    /// This operation is unsafe because the raw representation can be
    /// invalidated by lasting too long or by the header being parsed
    /// while you still have a reference to the data.
    ///
    /// Example:
    /// ```
    /// # use hyper::header::Headers;
    /// # let mut headers = Headers::new();
    /// let raw_content_type = unsafe { headers.get_raw("content-type") };
    /// ```
    pub unsafe fn get_raw(&self, name: &'static str) -> Option<*const [Vec<u8>]> {
        self.data.find(&CaseInsensitive(Slice(name))).and_then(|item| {
            match *item.read() {
                Raw(ref raw) => Some(raw.as_slice() as *const [Vec<u8>]),
                _ => None
            }
        })
    }

    /// Get a reference to the header field's value, if it exists.
    pub fn get_ref<H: Header>(&self) -> Option<&H> {
        self.data.find(&CaseInsensitive(Slice(header_name::<H>()))).and_then(|item| {
            let done = match *item.read() {
                // Huge borrowck hack here, should be refactored to just return here.
                Typed(ref typed) if typed.is::<H>() => true,

                // Typed, wrong type.
                Typed(_) => return None,

                // Raw, work to do.
                Raw(_) => false,
            };

            // borrowck hack continued
            if done { return Some(item); }

            // Take out a write lock to do the parsing and mutation.
            let mut write = item.write();

            let header = match *write {
                // Since this lock can queue, it's possible another thread just
                // did the work for us.
                //
                // Check they inserted the correct type and move on.
                Typed(ref typed) if typed.is::<H>() => return Some(item),

                // Wrong type, another thread got here before us and parsed
                // as a different representation.
                Typed(_) => return None,

                // We are first in the queue or the only ones, so do the actual
                // work of parsing and mutation.
                Raw(ref raw) => match Header::parse_header(raw.as_slice()) {
                    Some::<H>(h) => h,
                    None => return None
                }
            };

            // Mutate in the raw case.
            *write = Typed(box header as Box<Header + Send + Sync>);
            Some(item)
        }).map(|item| {
            let read = item.read();
            debug!("downcasting {}", *read);
            let ret = match *read {
                Typed(ref val) => unsafe { val.downcast_ref_unchecked() },
                _ => unreachable!()
            };
            unsafe { transmute::<&H, &H>(ret) }
        })
    }

    /// Returns a boolean of whether a certain header is in the map.
    ///
    /// Example:
    ///
    /// ```
    /// # use hyper::header::Headers;
    /// # use hyper::header::common::ContentType;
    /// # let mut headers = Headers::new();
    /// let has_type = headers.has::<ContentType>();
    /// ```
    pub fn has<H: Header>(&self) -> bool {
        self.data.contains_key(&CaseInsensitive(Slice(header_name::<H>())))
    }

    /// Removes a header from the map, if one existed.
    /// Returns true if a header has been removed.
    pub fn remove<H: Header>(&mut self) -> bool {
        self.data.remove(&CaseInsensitive(Slice(Header::header_name(None::<H>))))
    }

    /// Returns an iterator over the header fields.
    pub fn iter<'a>(&'a self) -> HeadersItems<'a> {
        HeadersItems {
            inner: self.data.iter()
        }
    }
}

impl fmt::Show for Headers {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!("Headers {\n".fmt(fmt));
        for (k, v) in self.iter() {
            try!(write!(fmt, "\t{}: {}\n", k, v));
        }
        "}".fmt(fmt)
    }
}

/// An `Iterator` over the fields in a `Headers` map.
pub struct HeadersItems<'a> {
    inner: Entries<'a, CaseInsensitive, RWLock<Item>>
}

impl<'a> Iterator<(&'a str, HeaderView<'a>)> for HeadersItems<'a> {
    fn next(&mut self) -> Option<(&'a str, HeaderView<'a>)> {
        match self.inner.next() {
            Some((k, v)) => Some((k.as_slice(), HeaderView(v))),
            None => None
        }
    }
}

/// Returned with the `HeadersItems` iterator.
pub struct HeaderView<'a>(&'a RWLock<Item>);

impl<'a> fmt::Show for HeaderView<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let HeaderView(item) = *self;
        item.read().fmt(fmt)
    }
}

impl Collection for Headers {
    fn len(&self) -> uint {
        self.data.len()
    }
}

impl Mutable for Headers {
    fn clear(&mut self) {
        self.data.clear()
    }
}

enum Item {
    Raw(Vec<Vec<u8>>),
    Typed(Box<Header + Send + Sync>)
}

impl fmt::Show for Item {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Typed(ref h) => h.fmt_header(fmt),
            Raw(ref raw) => {
                for part in raw.iter() {
                    try!(fmt.write(part.as_slice()));
                }
                Ok(())
            },
        }
    }
}

struct CaseInsensitive(SendStr);

impl Str for CaseInsensitive {
    fn as_slice(&self) -> &str {
        let CaseInsensitive(ref s) = *self;
        s.as_slice()
    }

}

impl fmt::Show for CaseInsensitive {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(fmt)
    }
}

impl PartialEq for CaseInsensitive {
    fn eq(&self, other: &CaseInsensitive) -> bool {
        self.as_slice().eq_ignore_ascii_case(other.as_slice())
    }
}

impl Eq for CaseInsensitive {}

impl<H: hash::Writer> hash::Hash<H> for CaseInsensitive {
    #[inline]
    fn hash(&self, hasher: &mut H) {
        for byte in self.as_slice().bytes() {
            hasher.write([ASCII_LOWER_MAP[byte as uint]].as_slice());
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io::MemReader;
    use std::fmt;
    use std::str::Slice;
    use std::hash::sip::hash;
    use mime::{Mime, Text, Plain};
    use super::CaseInsensitive;
    use super::{Headers, Header};
    use super::common::{ContentLength, ContentType};

    fn mem(s: &str) -> MemReader {
        MemReader::new(s.as_bytes().to_vec())
    }

    #[test]
    fn test_case_insensitive() {
        let a = CaseInsensitive(Slice("foobar"));
        let b = CaseInsensitive(Slice("FOOBAR"));

        assert_eq!(a, b);
        assert_eq!(hash(&a), hash(&b));
    }

    #[test]
    fn test_from_raw() {
        let headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        assert_eq!(headers.get_ref(), Some(&ContentLength(10)));
    }

    #[test]
    fn test_content_type() {
        let content_type = Header::parse_header(["text/plain".as_bytes().to_vec()].as_slice());
        assert_eq!(content_type, Some(ContentType(Mime(Text, Plain, vec![]))));
    }

    #[deriving(Clone)]
    struct CrazyLength(Option<bool>, uint);

    impl Header for CrazyLength {
        fn header_name(_: Option<CrazyLength>) -> &'static str {
            "content-length"
        }
        fn parse_header(raw: &[Vec<u8>]) -> Option<CrazyLength> {
            use std::str::from_utf8;
            use std::from_str::FromStr;

            if raw.len() != 1 {
                return None;
            }
            // we JUST checked that raw.len() == 1, so raw[0] WILL exist.
            match from_utf8(unsafe { raw.as_slice().unsafe_get(0).as_slice() }) {
                Some(s) => FromStr::from_str(s),
                None => None
            }.map(|u| CrazyLength(Some(false), u))
        }
        fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
            use std::fmt::Show;
            let CrazyLength(_, ref value) = *self;
            value.fmt(fmt)
        }
    }

    #[test]
    fn test_different_structs_for_same_header() {
        let headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        let ContentLength(_) = headers.get::<ContentLength>().unwrap();
        assert!(headers.get::<CrazyLength>().is_none());
    }

    #[test]
    fn test_multiple_reads() {
        let headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        let ContentLength(one) = headers.get::<ContentLength>().unwrap();
        let ContentLength(two) = headers.get::<ContentLength>().unwrap();
        assert_eq!(one, two);
    }

    #[test]
    fn test_different_reads() {
        let headers = Headers::from_raw(&mut mem("Content-Length: 10\r\nContent-Type: text/plain\r\n\r\n")).unwrap();
        let ContentLength(_) = headers.get::<ContentLength>().unwrap();
        let ContentType(_) = headers.get::<ContentType>().unwrap();
    }
}

<|endoftext|>


<commit_before>use crate::{Cell, Edge, Face, Point};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Hash, Eq, PartialEq, Debug)]
pub struct KeyPoint {
    pub x: u64,
    pub y: u64,
    pub z: u64,
}

#[derive(Hash, Eq, PartialEq, Debug)]
pub struct KeyEdge {
    pub a: usize,
    pub b: usize,
}

#[derive(Hash, Eq, PartialEq, Debug)]
pub struct KeyFace {
    pub a: usize,
    pub b: usize,
    pub c: usize,
}

pub struct MeshMaps {
    pub ndim: usize,
    pub points: HashMap<KeyPoint, Point>,
    pub edges: HashMap<KeyEdge, Edge>,
    pub faces: HashMap<KeyFace, Face>,
    pub cells: Vec<Cell>,
}

#[derive(Deserialize, Serialize)]
pub struct Mesh {
    pub ndim: usize,
    pub points: Vec<Point>,
    pub edges: Vec<Edge>,
    pub faces: Vec<Face>,
    pub cells: Vec<Cell>,
}

impl MeshMaps {
    pub fn new(ndim: usize) -> Self {
        MeshMaps {
            ndim,
            points: HashMap::<KeyPoint, Point>::new(),
            edges: HashMap::<KeyEdge, Edge>::new(),
            faces: HashMap::<KeyFace, Face>::new(),
            cells: Vec::<Cell>::new(),
        }
    }

    pub fn to_mesh(&self) {
        let npoint = self.points.len();
        let nedge = self.edges.len();
        let nface = self.faces.len();
        // let mut points:Vec<Point>;
        for point in self.points.values() {
            println!("{:?}", point);
        }
    }

    pub fn print(&self) {
        for point in self.points.values() {
            println!("{:?}", point);
        }
        println!();
        for edge in self.edges.values() {
            println!("{:?}", edge);
        }
        println!();
        for face in self.faces.values() {
            println!("{:?}", face);
        }
        println!();
        for cell in &self.cells {
            println!("{:?}", cell);
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

    #[test]
    fn serialize_works() {
        // todo
    }
}
<commit_msg>Rem warning<commit_after>use crate::{Cell, Edge, Face, Point};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Hash, Eq, PartialEq, Debug)]
pub struct KeyPoint {
    pub x: u64,
    pub y: u64,
    pub z: u64,
}

#[derive(Hash, Eq, PartialEq, Debug)]
pub struct KeyEdge {
    pub a: usize,
    pub b: usize,
}

#[derive(Hash, Eq, PartialEq, Debug)]
pub struct KeyFace {
    pub a: usize,
    pub b: usize,
    pub c: usize,
}

pub struct MeshMaps {
    pub ndim: usize,
    pub points: HashMap<KeyPoint, Point>,
    pub edges: HashMap<KeyEdge, Edge>,
    pub faces: HashMap<KeyFace, Face>,
    pub cells: Vec<Cell>,
}

#[derive(Deserialize, Serialize)]
pub struct Mesh {
    pub ndim: usize,
    pub points: Vec<Point>,
    pub edges: Vec<Edge>,
    pub faces: Vec<Face>,
    pub cells: Vec<Cell>,
}

impl MeshMaps {
    pub fn new(ndim: usize) -> Self {
        MeshMaps {
            ndim,
            points: HashMap::<KeyPoint, Point>::new(),
            edges: HashMap::<KeyEdge, Edge>::new(),
            faces: HashMap::<KeyFace, Face>::new(),
            cells: Vec::<Cell>::new(),
        }
    }

    pub fn to_mesh(&self) {
        // let npoint = self.points.len();
        // let nedge = self.edges.len();
        // let nface = self.faces.len();
        // let mut points:Vec<Point>;
        for point in self.points.values() {
            println!("{:?}", point);
        }
    }

    pub fn print(&self) {
        for point in self.points.values() {
            println!("{:?}", point);
        }
        println!();
        for edge in self.edges.values() {
            println!("{:?}", edge);
        }
        println!();
        for face in self.faces.values() {
            println!("{:?}", face);
        }
        println!();
        for cell in &self.cells {
            println!("{:?}", cell);
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

    #[test]
    fn serialize_works() {
        // todo
    }
}
<|endoftext|>


<commit_before>//! Hyphenating iterators.

use std::borrow::Cow;

use unicode_segmentation::UnicodeSegmentation;

use language::{Corpus};
use utilia::{Interspersable, Intersperse};

pub trait Hyphenation<Hyphenator> where Hyphenator : Iterator {
    /// Returns the indices of valid hyphenation points within the given word.
    fn opportunities(self, corp: &Corpus) -> Vec<usize>;

    /// Returns an iterator over orthographic syllables of the given word,
    /// separated by valid hyphenation points.
    ///
    /// Note that, in some orthographies, the syllables of a hyphenated
    /// word are not necessarily substrings of the original word.
    fn hyphenate(self, corp: &Corpus) -> Hyphenator;
}

pub trait FullTextHyphenation<Hyphenator> : Hyphenation<Hyphenator>
    where Hyphenator : Iterator {
    /// Returns the indices of valid hyphenation points within the given text.
    fn fulltext_opportunities(self, corp: &Corpus) -> Vec<usize>;

    /// Returns an iterator over segments of the given text, separated by
    /// valid hyphenation points.
    fn fulltext_hyphenate(self, corp: &Corpus) -> Hyphenator;
}

/// The `Standard` hyphenator iterates over a string, returning slices
/// delimited by string boundaries and valid hyphenation points.
///
/// For individual words, such slices coincide with orthographic syllables.
#[derive(Clone, Debug)]
pub struct Standard<'a> {
    text: &'a str,
    opportunities: Vec<usize>,
    prior: usize,
    current: usize
}

impl<'a> Standard<'a> {
    /// Inserts a soft hyphen at hyphenation points.
    pub fn punctuate(self) -> Intersperse<Self> {
        self.intersperse("\u{ad}")
    }

    /// Inserts a given string at hyphenation points.
    pub fn punctuate_with(self, mark: &'a str) -> Intersperse<Self> {
        self.intersperse(mark)
    }
}

impl<'a> Iterator for Standard<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        let start = self.prior;
        let current = self.current;

        match self.opportunities.get(current) {
            Some(&end) => {
                self.prior = end;
                self.current = current + 1;
                Some(&self.text[start .. end])
            },
            None => {
                if current <= self.opportunities.len() {
                    self.current = current + 1;
                    Some(&self.text[start ..])
                } else {
                    None
                }
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let remaining = self.opportunities.len() + 1 - self.current;
        (remaining, Some(remaining))
    }
}

impl<'a> Hyphenation<Standard<'a>> for &'a str {
    /// Returns the byte indices of valid hyphenation points within the string.
    fn opportunities(self, corp: &Corpus) -> Vec<usize> {
        let (l_min, r_min) = (corp.left_min, corp.right_min);
        let length_min = l_min + r_min;

        if self.chars().count() < length_min {
            return vec![];
        }

        let pts = match corp.exceptions.iter()
                            .filter_map(|exs| exs.score(self))
                            .next() {
                                Some(vec) => Cow::Borrowed(vec),
                                None => Cow::Owned(corp.patterns.score(self))
        };

        self.char_indices().skip(l_min)
            .zip(&pts[l_min - 1 .. pts.len() - r_min + 1])
            .filter(|&(_, p)| p % 2 != 0)
            .map(|((i, _), _)| i)
            .collect()
    }

    /// Returns an iterator over string slices separated by valid hyphenation
    /// points.
    fn hyphenate(self, corp: &Corpus) -> Standard<'a> {
        Standard {
            text: self,
            opportunities: self.opportunities(corp),
            prior: 0,
            current: 0
        }
    }
}

impl<'a> FullTextHyphenation<Standard<'a>> for &'a str {
    fn fulltext_opportunities(self, corp: &Corpus) -> Vec<usize> {
        let (l_min, r_min) = (corp.left_min, corp.right_min);
        let length_min = l_min + r_min;

        if self.chars().count() < length_min {
            return vec![];
        }

        let by_word = self.split_word_bound_indices();
        by_word.flat_map(|(i, word)| {
            let pts = match corp.exceptions.iter()
                                .filter_map(|exs| exs.score(word))
                                .next() {
                                    Some(vec) => Cow::Borrowed(vec),
                                    None => Cow::Owned(corp.patterns.score(word))
            }.into_owned();

            let hyph_length = pts.len();
            let remaining = if hyph_length >= length_min - 1 {
                hyph_length + 2 - length_min
            } else { 0 };

            word.char_indices().skip(l_min)
                .zip(pts.into_iter().skip(l_min - 1).take(remaining))
                .filter(|&(_, p)| p % 2 != 0)
                .map(move |((i1, _), _)| i + i1)
        }).collect()
    }

    fn fulltext_hyphenate(self, corp: &Corpus) -> Standard<'a> {
        Standard {
            text: self,
            opportunities: self.fulltext_opportunities(corp),
            prior: 0,
            current: 0
        }

    }
}
<commit_msg>Implement ExactSizeIterator for Standard<commit_after>//! Hyphenating iterators.

use std::borrow::Cow;

use unicode_segmentation::UnicodeSegmentation;

use language::{Corpus};
use utilia::{Interspersable, Intersperse};

pub trait Hyphenation<Hyphenator> where Hyphenator : Iterator {
    /// Returns the indices of valid hyphenation points within the given word.
    fn opportunities(self, corp: &Corpus) -> Vec<usize>;

    /// Returns an iterator over orthographic syllables of the given word,
    /// separated by valid hyphenation points.
    ///
    /// Note that, in some orthographies, the syllables of a hyphenated
    /// word are not necessarily substrings of the original word.
    fn hyphenate(self, corp: &Corpus) -> Hyphenator;
}

pub trait FullTextHyphenation<Hyphenator> : Hyphenation<Hyphenator>
    where Hyphenator : Iterator {
    /// Returns the indices of valid hyphenation points within the given text.
    fn fulltext_opportunities(self, corp: &Corpus) -> Vec<usize>;

    /// Returns an iterator over segments of the given text, separated by
    /// valid hyphenation points.
    fn fulltext_hyphenate(self, corp: &Corpus) -> Hyphenator;
}

/// The `Standard` hyphenator iterates over a string, returning slices
/// delimited by string boundaries and valid hyphenation points.
///
/// For individual words, such slices coincide with orthographic syllables.
#[derive(Clone, Debug)]
pub struct Standard<'a> {
    text: &'a str,
    opportunities: Vec<usize>,
    prior: usize,
    current: usize
}

impl<'a> Standard<'a> {
    /// Inserts a soft hyphen at hyphenation points.
    pub fn punctuate(self) -> Intersperse<Self> {
        self.intersperse("\u{ad}")
    }

    /// Inserts a given string at hyphenation points.
    pub fn punctuate_with(self, mark: &'a str) -> Intersperse<Self> {
        self.intersperse(mark)
    }
}

impl<'a> Iterator for Standard<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        let start = self.prior;
        let current = self.current;

        match self.opportunities.get(current) {
            Some(&end) => {
                self.prior = end;
                self.current = current + 1;
                Some(&self.text[start .. end])
            },
            None => {
                if current <= self.opportunities.len() {
                    self.current = current + 1;
                    Some(&self.text[start ..])
                } else {
                    None
                }
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let remaining = self.opportunities.len() + 1 - self.current;
        (remaining, Some(remaining))
    }
}

impl<'a> ExactSizeIterator for Standard<'a> {}

impl<'a> Hyphenation<Standard<'a>> for &'a str {
    /// Returns the byte indices of valid hyphenation points within the string.
    fn opportunities(self, corp: &Corpus) -> Vec<usize> {
        let (l_min, r_min) = (corp.left_min, corp.right_min);
        let length_min = l_min + r_min;

        if self.chars().count() < length_min {
            return vec![];
        }

        let pts = match corp.exceptions.iter()
                            .filter_map(|exs| exs.score(self))
                            .next() {
                                Some(vec) => Cow::Borrowed(vec),
                                None => Cow::Owned(corp.patterns.score(self))
        };

        self.char_indices().skip(l_min)
            .zip(&pts[l_min - 1 .. pts.len() - r_min + 1])
            .filter(|&(_, p)| p % 2 != 0)
            .map(|((i, _), _)| i)
            .collect()
    }

    /// Returns an iterator over string slices separated by valid hyphenation
    /// points.
    fn hyphenate(self, corp: &Corpus) -> Standard<'a> {
        Standard {
            text: self,
            opportunities: self.opportunities(corp),
            prior: 0,
            current: 0
        }
    }
}

impl<'a> FullTextHyphenation<Standard<'a>> for &'a str {
    fn fulltext_opportunities(self, corp: &Corpus) -> Vec<usize> {
        let (l_min, r_min) = (corp.left_min, corp.right_min);
        let length_min = l_min + r_min;

        if self.chars().count() < length_min {
            return vec![];
        }

        let by_word = self.split_word_bound_indices();
        by_word.flat_map(|(i, word)| {
            let pts = match corp.exceptions.iter()
                                .filter_map(|exs| exs.score(word))
                                .next() {
                                    Some(vec) => Cow::Borrowed(vec),
                                    None => Cow::Owned(corp.patterns.score(word))
            }.into_owned();

            let hyph_length = pts.len();
            let remaining = if hyph_length >= length_min - 1 {
                hyph_length + 2 - length_min
            } else { 0 };

            word.char_indices().skip(l_min)
                .zip(pts.into_iter().skip(l_min - 1).take(remaining))
                .filter(|&(_, p)| p % 2 != 0)
                .map(move |((i1, _), _)| i + i1)
        }).collect()
    }

    fn fulltext_hyphenate(self, corp: &Corpus) -> Standard<'a> {
        Standard {
            text: self,
            opportunities: self.fulltext_opportunities(corp),
            prior: 0,
            current: 0
        }

    }
}
<|endoftext|>


<commit_before>/*!
 varlink-rust-generator is a CLI, that generates rust code from a varlink
 interface definition file

 # Usage
 $ varlink-rust-generator `[<varlink_file>]`

 If <varlink_file> is omitted, input is expected to come from stdin.

 Output is sent to stdout.
!*/
extern crate varlink_generator;

use std::env;
use std::fs::File;
use std::io;
use std::io::{Read, Write};
use std::path::Path;

use chainerror::*;
use varlink_generator::{generate, Error, Result};

fn print_usage(program: &str, opts: &getopts::Options) {
    let brief = format!("Usage: {} [VARLINK FILE]", program);
    print!("{}", opts.usage(&brief));
}

fn main() -> Result<()> {
    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();

    let mut opts = getopts::Options::new();
    opts.optflag("h", "help", "print this help menu");
    opts.optflag("", "nosource", "don't print doc header and allow");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("{}", f.to_string());
            print_usage(&program, &opts);
            return Err(strerr!(Error, "Invalid Arguments"));
        }
    };

    if matches.opt_present("h") {
        print_usage(&program, &opts);
        return Ok(());
    }

    let tosource = !matches.opt_present("nosource");

    let mut reader: Box<Read> = match matches.free.len() {
        0 => Box::new(io::stdin()),
        _ => {
            if matches.free[0] == "-" {
                Box::new(io::stdin())
            } else {
                Box::new(
                    File::open(Path::new(&matches.free[0])).map_err(mstrerr!(
                        Error,
                        "Failed to open '{}'",
                        &matches.free[0]
                    ))?,
                )
            }
        }
    };
    let writer: &mut Write = &mut io::stdout();
    generate(&mut reader, writer, tosource)
}
<commit_msg>workaround rust nightly compiler error<commit_after>/*!
 varlink-rust-generator is a CLI, that generates rust code from a varlink
 interface definition file

 # Usage
 $ varlink-rust-generator `[<varlink_file>]`

 If <varlink_file> is omitted, input is expected to come from stdin.

 Output is sent to stdout.
!*/
extern crate varlink_generator;

use std::env;
use std::fs::File;
use std::io;
use std::io::{Read, Write};
use std::path::Path;

use chainerror::*;
use varlink_generator::generate;

fn print_usage(program: &str, opts: &getopts::Options) {
    let brief = format!("Usage: {} [VARLINK FILE]", program);
    print!("{}", opts.usage(&brief));
}

fn main() -> std::result::Result<(), Box<std::error::Error>> {
    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();

    let mut opts = getopts::Options::new();
    opts.optflag("h", "help", "print this help menu");
    opts.optflag("", "nosource", "don't print doc header and allow");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("{}", f.to_string());
            print_usage(&program, &opts);
            return Err(strerr!("Invalid Arguments").into());
        }
    };

    if matches.opt_present("h") {
        print_usage(&program, &opts);
        return Ok(());
    }

    let tosource = !matches.opt_present("nosource");

    let mut reader: Box<Read> = match matches.free.len() {
        0 => Box::new(io::stdin()),
        _ => {
            if matches.free[0] == "-" {
                Box::new(io::stdin())
            } else {
                Box::new(File::open(Path::new(&matches.free[0])).map_err(mstrerr!(
                    "Failed to open '{}'",
                    &matches.free[0]
                ))?)
            }
        }
    };
    let writer: &mut Write = &mut io::stdout();
    generate(&mut reader, writer, tosource).map_err(|e| e.into())
}
<|endoftext|>