<commit_before>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::num::{Int, UnsignedInt, NumCast, cast, Float};
use std::collections;
use std::slice;
use std;

use alphabets::{Alphabet, RankTransform};

struct QGrams<'a, Q: UnsignedInt + NumCast> {
    text: slice::Iter<'a, u8>,
    qgram: Q,
    bits: usize,
    mask: Q,
    ranks: RankTransform,
}

impl<'a, Q: UnsignedInt + NumCast> QGrams<'a, Q> {
    pub fn new(q: usize, text: &'a [u8], alphabet: &Alphabet) -> Self {
        let ranks = RankTransform::new(alphabet);
        let mut qgrams = QGrams {
            text: text.iter(),
            qgram: cast(0).unwrap(),
            ranks: ranks,
            bits: (alphabet.len() as f32).log2().ceil() as usize,
            mask: cast((1 << q) - 1).unwrap(),
        };
        for _ in 0..q-1 {
            qgrams.next();
        }

        qgrams
    }

    fn qgram_push(&mut self, a: u8) {
        self.qgram = self.qgram << self.bits;
        self.qgram = (self.qgram | cast(a).unwrap()) & self.mask;
    }
}

impl<'a, Q: UnsignedInt + NumCast> Iterator for QGrams<'a, Q> {
    type Item = Q;

    fn next(&mut self) -> Option<Q> {
        match self.text.next() {
            Some(a) => {
                let b = self.ranks.get(*a);
                self.qgram_push(b);
                Some(self.qgram)
            },
            None    => None
        }
    }
}

pub struct QGramIndex<'a> {
    q: usize,
    alphabet: &'a Alphabet,
    address: Vec<usize>,
    pos: Vec<usize>,
}

impl<'a> QGramIndex<'a> {
    pub fn new(q: usize, text: &[u8], alphabet: &'a Alphabet) -> Self {
        QGramIndex::with_max_count(q, text, alphabet, std::usize::MAX)
    }

    pub fn with_max_count(q: usize, text: &[u8], alphabet: &'a Alphabet, max_count: usize) -> Self {
        let qgram_count = alphabet.len().pow(q as u32);
        let mut address = vec![0; qgram_count + 1];
        let mut pos = vec![0; text.len()];

        for qgram in QGrams::<u32>::new(q, text, alphabet) {
            address[qgram as usize] += 1;
        }

        for g in 1..address.len() {
            if address[g] > max_count {
                // mask qgram
                address[g] = 0;
            }
        }

        for i in 1..address.len() {
            address[i] += address[i - 1];
        }

        {
            let mut offset = vec![0; qgram_count];
            for (i, qgram) in QGrams::<u32>::new(q, text, alphabet).enumerate() {
                let a = address[qgram as usize];
                if address[qgram as usize + 1] - a != 0 {
                    // if not masked, insert positions
                    pos[a + offset[qgram as usize]] = i;
                    offset[qgram as usize] += 1;
                }
            }
        }

        QGramIndex { q: q, alphabet: alphabet, address: address, pos: pos }
    }

    pub fn matches(&self, qgram: u32) -> &[usize] {
        &self.pos[self.address[qgram as usize]..self.address[qgram as usize + 1]]
    }

    pub fn diagonals(&self, pattern: &[u8]) -> Vec<Diagonal> {
        let mut diagonals = collections::HashMap::new();
        for (i, qgram) in QGrams::<u32>::new(self.q, pattern, self.alphabet).enumerate() {
            for p in self.matches(qgram) {
                let diagonal = p - i;
                if diagonals.contains_key(&diagonal) {
                    diagonals.insert(diagonal, 1);
                }
                else {
                    *diagonals.get_mut(&diagonal).unwrap() += 1;
                }
            }
        }
        diagonals.into_iter().map(|(diagonal, count)| Diagonal { pos: diagonal, count: count }).collect()
    }

    pub fn exact_matches(&self, pattern: &[u8]) -> Vec<ExactMatch> {
        let mut diagonals: collections::HashMap<usize, ExactMatch> = collections::HashMap::new();
        let mut intervals = Vec::new();
        for (i, qgram) in QGrams::<u32>::new(self.q, pattern, self.alphabet).enumerate() {
            for &p in self.matches(qgram) {
                let diagonal = p - i;
                if !diagonals.contains_key(&diagonal) {
                    // nothing yet, start new match
                    diagonals.insert(diagonal, ExactMatch {
                            pattern_start: i,
                            pattern_stop: i + self.q,
                            text_start: p,
                            text_stop: p + self.q
                    });
                }
                else {
                    let interval = diagonals.get_mut(&diagonal).unwrap();
                    if interval.pattern_stop == i {
                        // extend exact match
                        interval.pattern_stop = i + self.q;
                        interval.text_stop = p + self.q;
                    }
                    else {
                        // report previous match
                        intervals.push(interval.clone());
                        // mismatch or indel, start new match
                        interval.pattern_start = i;
                        interval.pattern_stop = i + self.q;
                        interval.text_start = p;
                        interval.text_stop = p + self.q;
                    }

                }
            }
        }
        // report remaining intervals
        for (_, interval) in diagonals.into_iter() {
            intervals.push(interval);
        }
        intervals
    }
}

pub struct Diagonal {
    pub pos: usize,
    pub count: usize,
}

#[derive(Clone)]
pub struct ExactMatch {
    pub pattern_start: usize,
    pub pattern_stop: usize,
    pub text_start: usize,
    pub text_stop: usize,
}
<commit_msg>Fixes. TODO make qgrams always u64.<commit_after>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::num::{Int, UnsignedInt, NumCast, cast, Float};
use std::collections;
use std::slice;
use std;

use alphabets::{Alphabet, RankTransform};
use utils;

/// Iterator over the q-grams of a given text. Q-grams are encoded as integers.
/// The number of bits for encoding a single symbol is chosen as log2(A) with A being the alphabet
/// size.
///
/// The type Q has to be chosen such that the q-gram fits into it.
pub struct QGrams<'a, Q: UnsignedInt + NumCast> {
    text: &'a [u8],
    bits: usize,
    mask: Q,
    ranks: RankTransform,
}

impl<'a, Q: UnsignedInt + NumCast> QGrams<'a, Q> {
    /// Create new instance.
    ///
    /// # Arguments
    ///
    /// * `q` - the length of the q-gram
    /// * `text` - the text
    /// * `alphabet` - the alphabet to use
    pub fn new(q: usize, text: &'a [u8], alphabet: &Alphabet) -> Self {
        let ranks = RankTransform::new(alphabet);
        let bits = (alphabet.len() as f32).log2().ceil() as usize;
        assert!(bits * q <= Q::
        QGrams {
            text: text,
            ranks: ranks,
            bits: bits,
            mask: cast((1 << q * bits) - 1).unwrap(),
        }
    }

    pub fn iter(&self) -> QGramIter {
        let mut iter = QGramIter { qgrams: self, text: text.iter(), qgram: cast(0).unwrap() };
        for _ in 0..q-1 {
            iter.next();
        }

        iter
    }
}

pub struct QGramIter<'a, Q: UnsignedInt + NumCast> {
    qgrams: &'a QGrams,
    text: slice::Iter<'a, u8>,
    qgram: Q,
}

impl<'a, Q: UnsignedInt + NumCast> QGramIter<'a, Q> {
    fn qgram_push(&mut self, a: u8) {
        self.qgram = self.qgram << self.qgrams.bits;
        self.qgram = (self.qgram | cast(a).unwrap()) & self.qgrams.mask;
    }
}

impl<'a, Q: UnsignedInt + NumCast> Iterator for QGramIter<'a, Q> {
    type Item = Q;

    fn next(&mut self) -> Option<Q> {
        match self.text.next() {
            Some(a) => {
                let b = self.qgrams.ranks.get(*a);
                self.qgram_push(b);
                Some(self.qgram)
            },
            None    => None
        }
    }
}

pub struct QGramIndex<'a> {
    q: usize,
    alphabet: &'a Alphabet,
    address: Vec<usize>,
    pos: Vec<usize>,
}

impl<'a> QGramIndex<'a> {
    pub fn new(q: usize, text: &[u8], alphabet: &'a Alphabet) -> Self {
        QGramIndex::with_max_count(q, text, alphabet, std::usize::MAX)
    }

    pub fn with_max_count(q: usize, text: &[u8], alphabet: &'a Alphabet, max_count: usize) -> Self {
        let qgram_count = alphabet.len().pow(q as u32);
        let mut address = vec![0; qgram_count + 1];
        let mut pos = vec![0; text.len()];

        for qgram in QGrams::<u32>::new(q, text, alphabet) {
            address[qgram as usize] += 1;
        }

        for g in 1..address.len() {
            if address[g] > max_count {
                // mask qgram
                address[g] = 0;
            }
        }

        utils::prescan(&mut address, 0, |a, b| a + b);

        {
            let mut offset = vec![0; qgram_count];
            for (i, qgram) in QGrams::<u32>::new(q, text, alphabet).enumerate() {
                let a = address[qgram as usize];
                if address[qgram as usize + 1] - a != 0 {
                    // if not masked, insert positions
                    pos[a + offset[qgram as usize]] = i;
                    offset[qgram as usize] += 1;
                }
            }
        }

        QGramIndex { q: q, alphabet: alphabet, address: address, pos: pos }
    }

    pub fn matches(&self, qgram: u32) -> &[usize] {
        &self.pos[self.address[qgram as usize]..self.address[qgram as usize + 1]]
    }

    pub fn diagonals(&self, pattern: &[u8]) -> Vec<Diagonal> {
        let mut diagonals = collections::HashMap::new();
        for (i, qgram) in QGrams::<u32>::new(self.q, pattern, self.alphabet).enumerate() {
            for p in self.matches(qgram) {
                let diagonal = p - i;
                if !diagonals.contains_key(&diagonal) {
                    diagonals.insert(diagonal, 1);
                }
                else {
                    *diagonals.get_mut(&diagonal).unwrap() += 1;
                }
            }
        }
        diagonals.into_iter().map(|(diagonal, count)| Diagonal { pos: diagonal, count: count }).collect()
    }

    pub fn exact_matches(&self, pattern: &[u8]) -> Vec<ExactMatch> {
        let mut diagonals: collections::HashMap<usize, ExactMatch> = collections::HashMap::new();
        let mut intervals = Vec::new();
        for (i, qgram) in QGrams::<u32>::new(self.q, pattern, self.alphabet).enumerate() {
            for &p in self.matches(qgram) {
                let diagonal = p - i;
                if !diagonals.contains_key(&diagonal) {
                    // nothing yet, start new match
                    diagonals.insert(diagonal, ExactMatch {
                            pattern: Interval{ start: i, stop: i + self.q},
                            text: Interval { start: p, stop: p + self.q },
                    });
                }
                else {
                    let interval = diagonals.get_mut(&diagonal).unwrap();
                    if interval.pattern.stop - self.q + 1 == i {
                        // extend exact match
                        interval.pattern.stop = i + self.q;
                        interval.text.stop = p + self.q;
                    }
                    else {
                        // report previous match
                        intervals.push(interval.clone());
                        // mismatch or indel, start new match
                        interval.pattern.start = i;
                        interval.pattern.stop = i + self.q;
                        interval.text.start = p;
                        interval.text.stop = p + self.q;
                    }

                }
            }
        }
        // report remaining intervals
        for (_, interval) in diagonals.into_iter() {
            intervals.push(interval);
        }
        intervals
    }
}

#[derive(PartialEq)]
#[derive(Debug)]
pub struct Diagonal {
    pub pos: usize,
    pub count: usize,
}

/// An interval, consisting of start and stop position (the latter exclusive).
#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Debug)]
pub struct Interval {
    pub start: usize,
    pub stop: usize
}

impl Interval {
    pub fn get<'a>(&self, text: &'a [u8]) -> &'a [u8] {
        &text[self.start..self.stop]
    }
}

#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Debug)]
pub struct ExactMatch {
    pub pattern: Interval,
    pub text: Interval,
}

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

    fn setup() -> (&'static [u8], alphabets::Alphabet) {
        let text = b"ACGGCTGAGATGAT";
        let alphabet = alphabets::dna::alphabet();

        (text, alphabet)
    }

    #[test]
    fn test_matches() {
        let (text, alphabet) = setup();
        let q = 3;
        let qgram_index = QGramIndex::new(q, text, &alphabet);

        let qgram = QGrams::new(q, b"TGA", &alphabet).next().unwrap();

        let matches = qgram_index.matches(qgram);
        assert_eq!(matches, [5, 10]);
    }

    #[test]
    fn test_diagonals() {
        let (text, alphabet) = setup();
        let q = 3;
        let qgram_index = QGramIndex::new(q, text, &alphabet);

        let pattern = b"GCTG";
        let diagonals = qgram_index.diagonals(pattern);
        assert_eq!(diagonals, [Diagonal { pos: 3, count: 2 }]);
    }

    #[test]
    fn test_exact_matches() {
        let (text, alphabet) = setup();
        let q = 3;
        let qgram_index = QGramIndex::new(q, text, &alphabet);

        let pattern = b"GCTGA";
        let exact_matches = qgram_index.exact_matches(pattern);
        assert!(exact_matches.len() == 2);
        for m in exact_matches {
            assert_eq!(m.pattern.get(pattern), m.text.get(text));
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Enable setting triplet via environment variable<commit_after><|endoftext|>


<commit_before>#![allow(dead_code)]

use std::fmt;
use std::iter;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Sym {
    Add,
    Sub,
    Mul,
    Div,
}

impl fmt::Display for Sym {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Sym::*;
        write!(f, "{}",
            match *self {
                Add => "+",
                Sub => "-",
                Mul => "*",
                Div => "/",
            }
        )
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Atom<T> {
    Num(T),
    Sym(Sym),
}

impl<T> From<Sym> for Atom<T> {
    fn from(s: Sym) -> Self {
        Atom::Sym(s)
    }
}

impl<T> fmt::Display for Atom<T> where T: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Atom::*;
        match *self {
            Num(ref t) => write!(f, "{}", t),
            Sym(ref t) => write!(f, "{}", t),
        }
    }
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Expr<T> {
    Atom(Atom<T>),
    List(Vec<Expr<T>>),
}

impl<T> Expr<T> {
    fn is_atom(&self) -> bool {
        use self::Expr::*;
        match *self {
            Atom(_) => true,
            List(_) => false,
        }
    }

    fn is_list(&self) -> bool {
        use self::Expr::*;
        match *self {
            Atom(_) => false,
            List(_) => true,
        }
    }
}

impl<T> From<T> for Expr<T> {
    fn from(t: T) -> Self {
        Expr::Atom(Atom::Num(t))
    }
}

impl<T> From<Vec<T>> for Expr<T> {
    fn from(v: Vec<T>) -> Self {
        Expr::List(v.into_iter().map(Atom::Num).map(Expr::Atom).collect())
    }
}

impl<T> fmt::Display for Expr<T> where T: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Expr::Atom(ref a) => write!(f, "{}", a),
            &Expr::List(ref l) => write!(f, "( {} )",
                l.iter().map(ToString::to_string).collect::<Vec<_>>().join(" "))
               // l.iter().fold("".to_string(), |a, ref e| format!("{} {}", a, e)))
        }
    }
}

impl<T> iter::FromIterator<Expr<T>> for Expr<T> {
    fn from_iter<U>(iterator: U) -> Self
        where U: IntoIterator<Item = Expr<T>>
    {
        Expr::List::<T>(iterator.into_iter().collect())
    }
}

impl<T> iter::FromIterator<Atom<T>> for Expr<T> {
        fn from_iter<U>(iterator: U) -> Self
        where U: IntoIterator<Item = Atom<T>>
    {
        Expr::List::<T>(iterator.into_iter().map(Expr::Atom).collect())
    }
}

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

    #[test]
    fn test_display()
    {
        assert_eq!("1", Expr::from(1).to_string());
        assert_eq!("( 1 2 )", Expr::<i32>::from(vec![1, 2]).to_string());
    }
}<commit_msg>Apply rustfmt to atom.rs<commit_after>#![allow(dead_code)]

use std::fmt;
use std::iter;
use std::borrow::Borrow;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Sym {
    Add,
    Sub,
    Mul,
    Div,
}

impl fmt::Display for Sym {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Sym::*;
        write!(f,
               "{}",
               match *self {
                   Add => "+",
                   Sub => "-",
                   Mul => "*",
                   Div => "/",
               })
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Atom<T> {
    Num(T),
    Sym(Sym),
}

impl<T> From<Sym> for Atom<T> {
    fn from(s: Sym) -> Self {
        Atom::Sym(s)
    }
}

impl<T> fmt::Display for Atom<T>
    where T: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Atom::*;
        match *self {
            Num(ref t) => write!(f, "{}", t),
            Sym(ref t) => write!(f, "{}", t),
        }
    }
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Expr<T> {
    Atom(Atom<T>),
    List(Vec<Expr<T>>),
}

impl<T> Expr<T> {
    fn is_atom(&self) -> bool {
        if let Expr::Atom(_) = *self {
            true
        } else {
            false
        }
    }

    fn is_list(&self) -> bool {
        if let Expr::List(_) = *self {
            true
        } else {
            false
        }
    }
}

impl<T> From<T> for Expr<T> {
    fn from(t: T) -> Self {
        Expr::Atom(Atom::Num(t))
    }
}

impl<T> From<Vec<T>> for Expr<T> {
    fn from(v: Vec<T>) -> Self {
        Expr::List(v.into_iter().map(Expr::from).collect())
    }
}

impl<T> Borrow<[Expr<T>]> for Expr<T>
{
    fn borrow(&self) -> &[Expr<T>] {
        use self::Expr::*;
        match *self {
            Atom(ref a) => { let v = Vec::new(); v.push(Expr::from(*a.clone())); v.as_slice() },
            List(ref l) => l.as_slice(),
        }
    }
}

impl<T> fmt::Display for Expr<T>
    where T: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Expr::*;
        match *self {
            Atom(ref a) => write!(f, "{}", a),
            List(ref l) => write!(f, "( {} )", l.join(" ")),
        }
    }
}

impl<T> iter::FromIterator<Expr<T>> for Expr<T> {
    fn from_iter<U>(iterator: U) -> Self
        where U: IntoIterator<Item = Expr<T>>
    {
        Expr::List::<T>(iterator.into_iter().collect())
    }
}

impl<T> iter::FromIterator<Atom<T>> for Expr<T> {
    fn from_iter<U>(iterator: U) -> Self
        where U: IntoIterator<Item = Atom<T>>
    {
        Expr::List::<T>(iterator.into_iter().map(Expr::Atom).collect())
    }
}

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

    #[test]
    fn test_display() {
        assert_eq!("1", Expr::from(1).to_string());
        assert_eq!("( 1 2 )", Expr::<i32>::from(vec![1, 2]).to_string());
    }
}
<|endoftext|>


<commit_before>

#[derive(Debug, PartialEq)]
pub struct Card {
    suit: Suit,
    rank: Rank
}

impl Card {

}

#[derive(Debug, PartialEq)]
pub enum Suit {
	Heart,
	Diamond,
	Spade,
	Club
}

impl Suit {
	pub fn from_number(num: &u32) -> Option<Suit> {
		match *num {
			1 => Some(Suit::Heart),
			2 => Some(Suit::Diamond),
			3 => Some(Suit::Spade),
			4 => Some(Suit::Club),
			_ => None
		}
	}
}

impl Into<u32> for Suit {
	fn into(self) -> u32 {
		match self {
			Suit::Heart => 1,
			Suit::Diamond => 2,
			Suit::Spade => 3,
			Suit::Club => 4
		}
	}
}

#[derive(Debug, PartialEq)]
pub enum Rank {
	Ace,
	Two,
	Three,
	Four,
	Five,
	Six,
	Seven,
	Eight,
	Nine,
	Ten,
	Jack,
	Queen,
	King
}

impl Rank {
	pub fn from_number(num: &u32) -> Option<Rank> {
		match *num {
			1 => Some(Rank::Ace),
			2 => Some(Rank::Two),
			3 => Some(Rank::Three),
			4 => Some(Rank::Four),
			5 => Some(Rank::Five),
			6 => Some(Rank::Six),
			7 => Some(Rank::Seven),
			8 => Some(Rank::Eight),
			9 => Some(Rank::Nine),
			10 => Some(Rank::Ten),
			11 => Some(Rank::Jack),
			12 => Some(Rank::Queen),
			13 => Some(Rank::King),
			_ => None
		}
	}
}

impl Into<u32> for Rank {
	fn into(self) -> u32 {
		match self {
			Rank::Ace => 1,
			Rank::Two => 2,
			Rank::Three => 3,
			Rank::Four => 4,
			Rank::Five => 5,
			Rank::Six => 6,
			Rank::Seven => 7,
			Rank::Eight => 8,
			Rank::Nine => 9,
			Rank::Ten => 10,
			Rank::Jack => 11,
			Rank::Queen => 12,
			Rank::King => 13
		}
	}
}

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

    #[test]
    fn reversible_suit() {
    	assert_eq!(Some(Suit::Heart), Suit::from_number(&Suit::Heart.into()));
    }

    #[test]
    fn reversible_rank() {
    	assert_eq!(Some(Rank::Ace), Rank::from_number(&Rank::Ace.into()));
    }
}
<commit_msg>Update card.rs<commit_after>

#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Card {
    pub suit: Suit,
    pub rank: Rank
}

impl Card {

}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Suit {
	Club,
	Diamond,
	Heart,
	Spade
}

impl Suit {
	pub fn from_number(num: &u32) -> Option<Suit> {
		match *num {
			1 => Some(Suit::Heart),
			2 => Some(Suit::Diamond),
			3 => Some(Suit::Spade),
			4 => Some(Suit::Club),
			_ => None
		}
	}
}

impl Into<u32> for Suit {
	fn into(self) -> u32 {
		match self {
			Suit::Heart => 1,
			Suit::Diamond => 2,
			Suit::Spade => 3,
			Suit::Club => 4
		}
	}
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Rank {
	Ace,
	Two,
	Three,
	Four,
	Five,
	Six,
	Seven,
	Eight,
	Nine,
	Ten,
	Jack,
	Queen,
	King
}

impl Rank {
	pub fn from_number(num: &u32) -> Option<Rank> {
		match *num {
			1 => Some(Rank::Ace),
			2 => Some(Rank::Two),
			3 => Some(Rank::Three),
			4 => Some(Rank::Four),
			5 => Some(Rank::Five),
			6 => Some(Rank::Six),
			7 => Some(Rank::Seven),
			8 => Some(Rank::Eight),
			9 => Some(Rank::Nine),
			10 => Some(Rank::Ten),
			11 => Some(Rank::Jack),
			12 => Some(Rank::Queen),
			13 => Some(Rank::King),
			_ => None
		}
	}
}

impl Into<u32> for Rank {
	fn into(self) -> u32 {
		match self {
			Rank::Ace => 1,
			Rank::Two => 2,
			Rank::Three => 3,
			Rank::Four => 4,
			Rank::Five => 5,
			Rank::Six => 6,
			Rank::Seven => 7,
			Rank::Eight => 8,
			Rank::Nine => 9,
			Rank::Ten => 10,
			Rank::Jack => 11,
			Rank::Queen => 12,
			Rank::King => 13
		}
	}
}

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

    #[test]
    fn reversible_suit() {
    	assert_eq!(Some(Suit::Heart), Suit::from_number(&Suit::Heart.into()));
    }

    #[test]
    fn reversible_rank() {
    	assert_eq!(Some(Rank::Ace), Rank::from_number(&Rank::Ace.into()));
    }
}
<|endoftext|>


<commit_before>use activation_function::ActivationFunction;
use acyclic_network::{NodeType, Network};
pub use acyclic_network::NodeIndex as CppnNodeIndex;
use fixedbitset::FixedBitSet;
use std::fmt::Debug;

pub trait CppnNodeType: NodeType + ActivationFunction {
    fn is_input_node(&self) -> bool;
    fn is_output_node(&self) -> bool;
}

#[derive(Clone, Copy, Debug)]
pub enum CppnNodeKind {
    Bias,
    Input,
    Output,
    Hidden,
}

/// A concrete implementation of a CppnNodeType.

#[derive(Clone, Debug)]
pub struct CppnNode<A: ActivationFunction> {
    kind: CppnNodeKind,
    activation_function: A,
}

impl<A> CppnNode<A> where A: ActivationFunction {
    pub fn new(kind: CppnNodeKind, activation_function: A) -> Self {
        CppnNode {
            kind: kind,
            activation_function: activation_function
        }
    }

    pub fn input(activation_function: A) -> Self {
        Self::new(CppnNodeKind::Input, activation_function)
    }

    pub fn output(activation_function: A) -> Self {
        Self::new(CppnNodeKind::Output, activation_function)
    }

    pub fn hidden(activation_function: A) -> Self {
        Self::new(CppnNodeKind::Hidden, activation_function)
    }

    pub fn bias(activation_function: A) -> Self {
        Self::new(CppnNodeKind::Bias, activation_function)
    }

}

impl<A: ActivationFunction> ActivationFunction for CppnNode<A> {
    fn formula_gnuplot(&self, x: String) -> String {
        match self.kind {
            CppnNodeKind::Input | CppnNodeKind::Output | CppnNodeKind::Hidden | CppnNodeKind::Bias => {
                self.activation_function.formula_gnuplot(x)
            }
        }
    }

    fn calculate(&self, input: f64) -> f64 {
        self.activation_function.calculate(input)
    }
}

impl<A: ActivationFunction> NodeType for CppnNode<A> {
    fn accept_incoming_links(&self) -> bool {
        match self.kind {
            CppnNodeKind::Hidden | CppnNodeKind::Output => true,
            CppnNodeKind::Input | CppnNodeKind::Bias => false,
        }
    }

    fn accept_outgoing_links(&self) -> bool {
        match self.kind {
            CppnNodeKind::Hidden | CppnNodeKind::Input | CppnNodeKind::Bias => true,
            CppnNodeKind::Output => false,
        }
    }
}

impl<A: ActivationFunction> CppnNodeType for CppnNode<A> {
    fn is_input_node(&self) -> bool {
        match self.kind {
            CppnNodeKind::Input => true,
            _ => false,
        }
    }
    fn is_output_node(&self) -> bool {
        match self.kind {
            CppnNodeKind::Output => true,
            _ => false,
        }
    }
}

pub type CppnGraph<N, L, EXTID>
    where N: CppnNodeType,
          L: Copy + Debug + Send + Sized + Into<f64>,
          EXTID: Copy + Debug + Send + Sized + Ord = Network<N, L, EXTID>;

/// Represents a Compositional Pattern Producing Network (CPPN)
pub struct Cppn<'a, N, L, EXTID>
    where N: CppnNodeType + 'a,
          L: Copy + Debug + Send + Sized + Into<f64> + 'a,
          EXTID: Copy + Debug + Send + Sized + Ord + 'a
{
    graph: &'a CppnGraph<N, L, EXTID>,
    inputs: Vec<CppnNodeIndex>,
    outputs: Vec<CppnNodeIndex>,

    // For each node in `graph` there exists a corresponding field in `incoming_signals` describing
    // the sum of all input signals for that node.  We could store it inline in the `CppnNode`, but
    // this would require to make the whole CppnGraph mutable.
    incoming_signals: Vec<f64>,
}

impl<'a, N, L, EXTID> Cppn<'a, N, L, EXTID>
    where N: CppnNodeType + 'a,
          L: Copy + Debug + Send + Sized + Into<f64> + 'a,
          EXTID: Copy + Debug + Send + Sized + Ord + 'a
{
    pub fn new(graph: &'a CppnGraph<N, L, EXTID>) -> Cppn<'a, N, L, EXTID> {
        let mut inputs = Vec::new();
        let mut outputs = Vec::new();

        graph.each_node_with_index(|node, index| {
            if node.node_type().is_input_node() {
                inputs.push(index);
            }
            if node.node_type().is_output_node() {
                outputs.push(index);
            }
        });

        Cppn {
            graph: graph,
            inputs: inputs,
            outputs: outputs,
            incoming_signals: graph.nodes().iter().map(|_| 0.0).collect(),
        }
    }

    fn set_signal(&mut self, node_idx: CppnNodeIndex, value: f64) {
        self.incoming_signals[node_idx.index()] = value;
    }

    fn reset_signals(&mut self) {
        for value in self.incoming_signals.iter_mut() {
            *value = 0.0;
        }
    }

    /// Forward-propagate the signals starting from `from_nodes`. We use
    /// breadth-first-search (BFS).
    fn propagate_signals(&mut self, mut nodes: Vec<CppnNodeIndex>, mut seen: FixedBitSet) {
        while let Some(node_idx) = nodes.pop() {
            let input = self.incoming_signals[node_idx.index()];
            let output = self.graph.node(node_idx).node_type().calculate(input);

            // propagate output signal to outgoing links.
            self.graph.each_active_forward_link_of_node(node_idx, |out_node_idx, weight| {
                let out_node = out_node_idx.index();
                let weight: f64 = weight.into();
                self.incoming_signals[out_node] += weight * output;
                if !seen.contains(out_node) {
                    seen.insert(out_node);
                    nodes.push(out_node_idx);
                }
            });
        }
    }

    /// Calculate all outputs
    pub fn calculate(&mut self, inputs: &[&[f64]]) -> Vec<f64> {
        assert!(self.incoming_signals.len() == self.graph.nodes().len());
        self.reset_signals();

        // assign all inputs
        let mut i = 0;
        for input_list in inputs.iter() {
            for &input in input_list.iter() {
                let input_idx = self.inputs[i];
                self.set_signal(input_idx, input);
                i += 1;
            }
        }
        assert!(i == self.inputs.len());

        let mut nodes = Vec::new(); // XXX: worst case capacity
        let mut seen = FixedBitSet::with_capacity(self.incoming_signals.len());

        // start from all nodes which have zero in_degree()
        self.graph.each_node_with_index(|node, index| {
            if node.in_degree() == 0 {
                nodes.push(index);
                seen.insert(index.index());
            }
        });

        // propagate the signals starting from the nodes with zero in degree.
        self.propagate_signals(nodes, seen);

        self.outputs
            .iter()
            .map(|&node_idx| self.incoming_signals[node_idx.index()])
            .collect()
    }
}

#[cfg(test)]
mod tests {
    use activation_function::GeometricActivationFunction as AF;
    use super::{Cppn, CppnGraph, CppnNode};
    use acyclic_network::ExternalId;
    use rand;

    #[test]
    fn test_cycle() {
        let mut g = CppnGraph::new();
        let i1 = g.add_node(CppnNode::input(AF::Linear), ExternalId(1));
        let h1 = g.add_node(CppnNode::hidden(AF::Linear), ExternalId(2));
        let h2 = g.add_node(CppnNode::hidden(AF::Linear), ExternalId(3));
        assert_eq!(true, g.valid_link(i1, i1).is_err());
        assert_eq!(true, g.valid_link(h1, h1).is_err());

        assert_eq!(true, g.valid_link(h1, i1).is_err());
        assert_eq!(Ok(()), g.valid_link(i1, h1));
        assert_eq!(Ok(()), g.valid_link(i1, h2));
        assert_eq!(Ok(()), g.valid_link(h1, h2));

        g.add_link(i1, h1, 0.0, ExternalId(1));
        assert_eq!(true, g.link_would_cycle(h1, i1));
        assert_eq!(false, g.link_would_cycle(i1, h1));
        assert_eq!(false, g.link_would_cycle(i1, h2));
        assert_eq!(true, g.link_would_cycle(i1, i1));
        assert_eq!(false, g.link_would_cycle(h1, h2));
        assert_eq!(false, g.link_would_cycle(h2, h1));
        assert_eq!(false, g.link_would_cycle(h2, i1));

        g.add_link(h1, h2, 0.0, ExternalId(2));
        assert_eq!(true, g.link_would_cycle(h2, i1));
        assert_eq!(true, g.link_would_cycle(h1, i1));
        assert_eq!(true, g.link_would_cycle(h2, h1));
        assert_eq!(false, g.link_would_cycle(i1, h2));
    }

    #[test]
    fn test_simple_cppn() {
        let mut g = CppnGraph::new();
        let i1 = g.add_node(CppnNode::input(AF::Linear), ExternalId(1));
        let h1 = g.add_node(CppnNode::hidden(AF::Linear), ExternalId(2));
        let o1 = g.add_node(CppnNode::output(AF::Linear), ExternalId(3));
        g.add_link(i1, h1, 0.5, ExternalId(1));
        g.add_link(h1, o1, 1.0, ExternalId(2));

        let mut cppn = Cppn::new(&g);

        let f = |x| 0.5 * x * 1.0;
        assert_eq!(vec![f(0.5)], cppn.calculate(&[&[0.5]]));
        assert_eq!(vec![f(4.0)], cppn.calculate(&[&[4.0]]));
        assert_eq!(vec![f(-4.0)], cppn.calculate(&[&[-4.0]]));
    }

    #[test]
    fn test_find_random_unconnected_link_no_cycle() {
        let mut g: CppnGraph<CppnNode<AF>, _, _> = CppnGraph::new();
        let i1 = g.add_node(CppnNode::input(AF::Linear), ExternalId(1));
        let o1 = g.add_node(CppnNode::output(AF::Linear), ExternalId(2));
        let o2 = g.add_node(CppnNode::output(AF::Linear), ExternalId(3));

        let mut rng = rand::thread_rng();

        let link = g.find_random_unconnected_link_no_cycle(&mut rng);
        assert_eq!(true, link.is_some());
        let l = link.unwrap();
        assert!((i1, o1) == l || (i1, o2) == l);

        g.add_link(i1, o2, 0.0, ExternalId(1));
        let link = g.find_random_unconnected_link_no_cycle(&mut rng);
        assert_eq!(true, link.is_some());
        assert_eq!((i1, o1), link.unwrap());

        g.add_link(i1, o1, 0.0, ExternalId(2));
        let link = g.find_random_unconnected_link_no_cycle(&mut rng);
        assert_eq!(false, link.is_some());
    }

}
<commit_msg>Apply the activation function to output when read<commit_after>use activation_function::ActivationFunction;
use acyclic_network::{NodeType, Network};
pub use acyclic_network::NodeIndex as CppnNodeIndex;
use fixedbitset::FixedBitSet;
use std::fmt::Debug;

pub trait CppnNodeType: NodeType + ActivationFunction {
    fn is_input_node(&self) -> bool;
    fn is_output_node(&self) -> bool;
}

#[derive(Clone, Copy, Debug)]
pub enum CppnNodeKind {
    Bias,
    Input,
    Output,
    Hidden,
}

/// A concrete implementation of a CppnNodeType.
#[derive(Clone, Debug)]
pub struct CppnNode<A: ActivationFunction> {
    kind: CppnNodeKind,
    activation_function: A,
}

impl<A> CppnNode<A>
    where A: ActivationFunction
{
    pub fn new(kind: CppnNodeKind, activation_function: A) -> Self {
        CppnNode {
            kind: kind,
            activation_function: activation_function,
        }
    }

    pub fn input(activation_function: A) -> Self {
        Self::new(CppnNodeKind::Input, activation_function)
    }

    pub fn output(activation_function: A) -> Self {
        Self::new(CppnNodeKind::Output, activation_function)
    }

    pub fn hidden(activation_function: A) -> Self {
        Self::new(CppnNodeKind::Hidden, activation_function)
    }

    pub fn bias(activation_function: A) -> Self {
        Self::new(CppnNodeKind::Bias, activation_function)
    }
}

impl<A: ActivationFunction> ActivationFunction for CppnNode<A> {
    fn formula_gnuplot(&self, x: String) -> String {
        match self.kind {
            CppnNodeKind::Input |
            CppnNodeKind::Output |
            CppnNodeKind::Hidden |
            CppnNodeKind::Bias => self.activation_function.formula_gnuplot(x),
        }
    }

    fn calculate(&self, input: f64) -> f64 {
        self.activation_function.calculate(input)
    }
}

impl<A: ActivationFunction> NodeType for CppnNode<A> {
    fn accept_incoming_links(&self) -> bool {
        match self.kind {
            CppnNodeKind::Hidden | CppnNodeKind::Output => true,
            CppnNodeKind::Input | CppnNodeKind::Bias => false,
        }
    }

    fn accept_outgoing_links(&self) -> bool {
        match self.kind {
            CppnNodeKind::Hidden | CppnNodeKind::Input | CppnNodeKind::Bias => true,
            CppnNodeKind::Output => false,
        }
    }
}

impl<A: ActivationFunction> CppnNodeType for CppnNode<A> {
    fn is_input_node(&self) -> bool {
        match self.kind {
            CppnNodeKind::Input => true,
            _ => false,
        }
    }
    fn is_output_node(&self) -> bool {
        match self.kind {
            CppnNodeKind::Output => true,
            _ => false,
        }
    }
}

pub type CppnGraph<N, L, EXTID>
    where N: CppnNodeType,
          L: Copy + Debug + Send + Sized + Into<f64>,
          EXTID: Copy + Debug + Send + Sized + Ord = Network<N, L, EXTID>;

/// Represents a Compositional Pattern Producing Network (CPPN)
pub struct Cppn<'a, N, L, EXTID>
    where N: CppnNodeType + 'a,
          L: Copy + Debug + Send + Sized + Into<f64> + 'a,
          EXTID: Copy + Debug + Send + Sized + Ord + 'a
{
    graph: &'a CppnGraph<N, L, EXTID>,
    inputs: Vec<CppnNodeIndex>,
    outputs: Vec<CppnNodeIndex>,

    // For each node in `graph` there exists a corresponding field in `incoming_signals` describing
    // the sum of all input signals for that node.  We could store it inline in the `CppnNode`, but
    // this would require to make the whole CppnGraph mutable.
    incoming_signals: Vec<f64>,
}

impl<'a, N, L, EXTID> Cppn<'a, N, L, EXTID>
    where N: CppnNodeType + 'a,
          L: Copy + Debug + Send + Sized + Into<f64> + 'a,
          EXTID: Copy + Debug + Send + Sized + Ord + 'a
{
    pub fn new(graph: &'a CppnGraph<N, L, EXTID>) -> Cppn<'a, N, L, EXTID> {
        let mut inputs = Vec::new();
        let mut outputs = Vec::new();

        graph.each_node_with_index(|node, index| {
            if node.node_type().is_input_node() {
                inputs.push(index);
            }
            if node.node_type().is_output_node() {
                outputs.push(index);
            }
        });

        Cppn {
            graph: graph,
            inputs: inputs,
            outputs: outputs,
            incoming_signals: graph.nodes().iter().map(|_| 0.0).collect(),
        }
    }

    fn set_signal(&mut self, node_idx: CppnNodeIndex, value: f64) {
        self.incoming_signals[node_idx.index()] = value;
    }

    fn reset_signals(&mut self) {
        for value in self.incoming_signals.iter_mut() {
            *value = 0.0;
        }
    }

    /// Forward-propagate the signals starting from `from_nodes`. We use
    /// breadth-first-search (BFS).
    fn propagate_signals(&mut self, mut nodes: Vec<CppnNodeIndex>, mut seen: FixedBitSet) {
        while let Some(node_idx) = nodes.pop() {
            let input = self.incoming_signals[node_idx.index()];
            let output = self.graph.node(node_idx).node_type().calculate(input);

            // propagate output signal to outgoing links.
            self.graph.each_active_forward_link_of_node(node_idx, |out_node_idx, weight| {
                let out_node = out_node_idx.index();
                let weight: f64 = weight.into();
                self.incoming_signals[out_node] += weight * output;
                if !seen.contains(out_node) {
                    seen.insert(out_node);
                    nodes.push(out_node_idx);
                }
            });
        }
    }

    /// Calculate all outputs
    pub fn calculate(&mut self, inputs: &[&[f64]]) -> Vec<f64> {
        assert!(self.incoming_signals.len() == self.graph.nodes().len());
        self.reset_signals();

        // assign all inputs
        let mut i = 0;
        for input_list in inputs.iter() {
            for &input in input_list.iter() {
                let input_idx = self.inputs[i];
                self.set_signal(input_idx, input);
                i += 1;
            }
        }
        assert!(i == self.inputs.len());

        let mut nodes = Vec::new(); // XXX: worst case capacity
        let mut seen = FixedBitSet::with_capacity(self.incoming_signals.len());

        // start from all nodes which have zero in_degree()
        self.graph.each_node_with_index(|node, index| {
            if node.in_degree() == 0 {
                nodes.push(index);
                seen.insert(index.index());
            }
        });

        // propagate the signals starting from the nodes with zero in degree.
        self.propagate_signals(nodes, seen);

        self.outputs
            .iter()
            .map(|&node_idx| {
                let input = self.incoming_signals[node_idx.index()];
                let output = self.graph.node(node_idx).node_type().calculate(input);
                output
            })
            .collect()
    }
}

#[cfg(test)]
mod tests {
    use activation_function::GeometricActivationFunction as AF;
    use super::{Cppn, CppnGraph, CppnNode};
    use acyclic_network::ExternalId;
    use rand;

    #[test]
    fn test_cycle() {
        let mut g = CppnGraph::new();
        let i1 = g.add_node(CppnNode::input(AF::Linear), ExternalId(1));
        let h1 = g.add_node(CppnNode::hidden(AF::Linear), ExternalId(2));
        let h2 = g.add_node(CppnNode::hidden(AF::Linear), ExternalId(3));
        assert_eq!(true, g.valid_link(i1, i1).is_err());
        assert_eq!(true, g.valid_link(h1, h1).is_err());

        assert_eq!(true, g.valid_link(h1, i1).is_err());
        assert_eq!(Ok(()), g.valid_link(i1, h1));
        assert_eq!(Ok(()), g.valid_link(i1, h2));
        assert_eq!(Ok(()), g.valid_link(h1, h2));

        g.add_link(i1, h1, 0.0, ExternalId(1));
        assert_eq!(true, g.link_would_cycle(h1, i1));
        assert_eq!(false, g.link_would_cycle(i1, h1));
        assert_eq!(false, g.link_would_cycle(i1, h2));
        assert_eq!(true, g.link_would_cycle(i1, i1));
        assert_eq!(false, g.link_would_cycle(h1, h2));
        assert_eq!(false, g.link_would_cycle(h2, h1));
        assert_eq!(false, g.link_would_cycle(h2, i1));

        g.add_link(h1, h2, 0.0, ExternalId(2));
        assert_eq!(true, g.link_would_cycle(h2, i1));
        assert_eq!(true, g.link_would_cycle(h1, i1));
        assert_eq!(true, g.link_would_cycle(h2, h1));
        assert_eq!(false, g.link_would_cycle(i1, h2));
    }

    #[test]
    fn test_simple_cppn() {
        let mut g = CppnGraph::new();
        let i1 = g.add_node(CppnNode::input(AF::Linear), ExternalId(1));
        let h1 = g.add_node(CppnNode::hidden(AF::Linear), ExternalId(2));
        let o1 = g.add_node(CppnNode::output(AF::Linear), ExternalId(3));
        g.add_link(i1, h1, 0.5, ExternalId(1));
        g.add_link(h1, o1, 1.0, ExternalId(2));

        let mut cppn = Cppn::new(&g);

        let f = |x| 0.5 * x * 1.0;
        assert_eq!(vec![f(0.5)], cppn.calculate(&[&[0.5]]));
        assert_eq!(vec![f(4.0)], cppn.calculate(&[&[4.0]]));
        assert_eq!(vec![f(-4.0)], cppn.calculate(&[&[-4.0]]));
    }

    #[test]
    fn test_cppn_with_output_activation_function() {
        let mut g = CppnGraph::new();
        let i1 = g.add_node(CppnNode::input(AF::Linear), ExternalId(1));
        let h1 = g.add_node(CppnNode::hidden(AF::Linear), ExternalId(2));
        let o1 = g.add_node(CppnNode::output(AF::Constant1), ExternalId(3));
        g.add_link(i1, h1, 0.5, ExternalId(1));
        g.add_link(h1, o1, 1.0, ExternalId(2));

        let mut cppn = Cppn::new(&g);

        assert_eq!(vec![1.0], cppn.calculate(&[&[0.5]]));
        assert_eq!(vec![1.0], cppn.calculate(&[&[4.0]]));
        assert_eq!(vec![1.0], cppn.calculate(&[&[-4.0]]));
    }

    #[test]
    fn test_find_random_unconnected_link_no_cycle() {
        let mut g: CppnGraph<CppnNode<AF>, _, _> = CppnGraph::new();
        let i1 = g.add_node(CppnNode::input(AF::Linear), ExternalId(1));
        let o1 = g.add_node(CppnNode::output(AF::Linear), ExternalId(2));
        let o2 = g.add_node(CppnNode::output(AF::Linear), ExternalId(3));

        let mut rng = rand::thread_rng();

        let link = g.find_random_unconnected_link_no_cycle(&mut rng);
        assert_eq!(true, link.is_some());
        let l = link.unwrap();
        assert!((i1, o1) == l || (i1, o2) == l);

        g.add_link(i1, o2, 0.0, ExternalId(1));
        let link = g.find_random_unconnected_link_no_cycle(&mut rng);
        assert_eq!(true, link.is_some());
        assert_eq!((i1, o1), link.unwrap());

        g.add_link(i1, o1, 0.0, ExternalId(2));
        let link = g.find_random_unconnected_link_no_cycle(&mut rng);
        assert_eq!(false, link.is_some());
    }

}
<|endoftext|>


<commit_before>use std::fmt::{Display, Formatter, Error};

#[derive(Debug, PartialEq)]
pub struct PerElem {
    pub name: String,
    pub coef: u32,
    pub pos: usize,
    pub len: usize,
}

pub type Molecule = Vec<PerElem>;

/// Sorts the PerElems and groups those with the same name field.
///
/// Grouping of two (or more) PerElems means adding the coef field of the
/// duplicate to the one already found, and then throwing away the duplicate.
/// E.g. CH3CH3 would turn into C2H6.
pub fn group_elems(mut molecule: Molecule) -> Molecule {
    let mut out = Vec::<PerElem>::new();
    molecule.as_mut_slice().sort_by(|a, b| a.name.cmp(&b.name));
    // since the elements are now sorted, if the current elem does not match the
    // last element in out (i.e. what we previously pushed), then it won't match
    // anything in out
    for elem in molecule.into_iter() {
        if out.last().and_then(|e| Some(e.name == elem.name)).unwrap_or(false) {
            out.last_mut().unwrap().coef += elem.coef;
        } else {
            out.push(elem);
        }
    }
    out
}

impl Display for Molecule {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        for elem in self.iter() {
            fmt.write_str(elem.name.as_slice());
            // TODO: Use a proper conversion function -- if it exists
            if elem.coef > 1 {
                fmt.write_str(format!("{}", elem.coef).as_slice());
            }
        }
        Ok(())
    }
}

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

    macro_rules! dummy_elem(
        ($name:expr) => (
            PerElem { name: $name.to_string(), coef: 1, pos: 0, len: 1 }
        );
        ($name:expr, $coef:expr) => (
            PerElem { name: $name.to_string(), coef: $coef, pos: 0, len: 1 }
        );
    );

    #[test]
    fn group() {
        let result = group_elems(vec!(dummy_elem!("C"), dummy_elem!("H"), dummy_elem!("C")));
        let expected = vec!(dummy_elem!("C", 2), dummy_elem!("H", 1));
        assert_eq!(result, expected);
    }

    #[test]
    fn molecule_display() {
        let molecule = vec!(dummy_elem!("C", 2), dummy_elem!("H", 3));
        let result = format!("{}", molecule);
        let expected = "C2H3";
        assert_eq!(result, expected);
    }
}<commit_msg>Add 1 more test to Molecule's prettyprinter<commit_after>use std::fmt::{Display, Formatter, Error};

#[derive(Debug, PartialEq)]
pub struct PerElem {
    pub name: String,
    pub coef: u32,
    pub pos: usize,
    pub len: usize,
}

pub type Molecule = Vec<PerElem>;

/// Sorts the PerElems and groups those with the same name field.
///
/// Grouping of two (or more) PerElems means adding the coef field of the
/// duplicate to the one already found, and then throwing away the duplicate.
/// E.g. CH3CH3 would turn into C2H6.
pub fn group_elems(mut molecule: Molecule) -> Molecule {
    let mut out = Vec::<PerElem>::new();
    molecule.as_mut_slice().sort_by(|a, b| a.name.cmp(&b.name));
    // since the elements are now sorted, if the current elem does not match the
    // last element in out (i.e. what we previously pushed), then it won't match
    // anything in out
    for elem in molecule.into_iter() {
        if out.last().and_then(|e| Some(e.name == elem.name)).unwrap_or(false) {
            out.last_mut().unwrap().coef += elem.coef;
        } else {
            out.push(elem);
        }
    }
    out
}

impl Display for Molecule {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        for elem in self.iter() {
            fmt.write_str(elem.name.as_slice());
            // TODO: Use a proper conversion function -- if it exists
            if elem.coef > 1 {
                fmt.write_str(format!("{}", elem.coef).as_slice());
            }
        }
        Ok(())
    }
}

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

    macro_rules! dummy_elem(
        ($name:expr) => (
            PerElem { name: $name.to_string(), coef: 1, pos: 0, len: 1 }
        );
        ($name:expr, $coef:expr) => (
            PerElem { name: $name.to_string(), coef: $coef, pos: 0, len: 1 }
        );
    );

    #[test]
    fn group() {
        let result = group_elems(vec!(dummy_elem!("C"), dummy_elem!("H"), dummy_elem!("C")));
        let expected = vec!(dummy_elem!("C", 2), dummy_elem!("H", 1));
        assert_eq!(result, expected);
    }

    #[test]
    fn molecule_display() {
        let molecule = vec!(dummy_elem!("C", 2), dummy_elem!("H", 3));
        let result = format!("{}", molecule);
        let expected = "C2H3";
        assert_eq!(result, expected);
    }

    #[test]
    fn molecule_display_coefs() {
       let molecule = vec!(dummy_elem!("C", 1), dummy_elem!("H", 3));
        let result = format!("{}", molecule);
        let expected = "CH3";
        assert_eq!(result, expected);
    }
}<|endoftext|>


<commit_before>use std::slice;
use std::fmt;
use std::ops::Index;

#[derive(Debug,Clone,Copy,PartialEq)]
pub enum YUVRange {
    Limited,
    Full
}

impl fmt::Display for YUVRange {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            YUVRange::Limited => write!(f, "Limited range"),
            YUVRange::Full => write!(f, "Full range")
        }
    }
}

#[derive(Debug,Clone,Copy,PartialEq)]
pub enum YUVSystem {
    YCbCr(YUVRange),
    YCoCg,
    ICtCp
}

impl fmt::Display for YUVSystem {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::YUVSystem::*;
        match *self {
            YCbCr(range) => write!(f, "YCbCr ({})", range),
            YCoCg => write!(f, "YCbCg"),
            ICtCp => write!(f, "ICtCp"),
        }
    }
}

#[derive(Debug, Clone,Copy,PartialEq)]
pub enum TrichromaticEncodingSystem {
    RGB,
    YUV(YUVSystem),
    XYZ
}

impl fmt::Display for TrichromaticEncodingSystem {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::TrichromaticEncodingSystem::*;
        match *self {
            YUV(system) => write!(f, "{}", system),
            RGB => write!(f, "RGB"),
            XYZ => write!(f, "XYZ"),
        }
    }
}

#[derive(Debug, Clone,Copy,PartialEq)]
pub enum ColorModel {
    Trichromatic(TrichromaticEncodingSystem),
    CMYK,
    HSV,
    LAB,
}

impl fmt::Display for ColorModel {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::ColorModel::*;
        match *self {
            Trichromatic(system) => write!(f, "{}", system),
            CMYK => write!(f, "CMYK"),
            HSV => write!(f, "HSV"),
            LAB => write!(f, "LAB"),
        }
    }
}

impl ColorModel {
    pub fn get_default_components(&self) -> usize {
        match *self {
            ColorModel::CMYK => 4,
            _ => 3,
        }
    }
}

#[derive(Clone,Copy,Debug,PartialEq)]
pub struct Chromaton {
    h_ss: u8,
    v_ss: u8,
    packed: bool,
    depth: u8,
    shift: u8,
    comp_offs: u8,
    next_elem: u8,
}

fn align(v: usize, a: usize) -> usize {
    (v + a - 1) & !(a - 1)
}

impl Chromaton {
    pub fn get_subsampling(&self) -> (u8, u8) {
        (self.h_ss, self.v_ss)
    }
    pub fn is_packed(&self) -> bool {
        self.packed
    }
    pub fn get_depth(&self) -> u8 {
        self.depth
    }
    pub fn get_shift(&self) -> u8 {
        self.shift
    }
    pub fn get_offset(&self) -> u8 {
        self.comp_offs
    }
    pub fn get_step(&self) -> u8 {
        self.next_elem
    }

    pub fn get_width(&self, width: usize) -> usize {
        (width + ((1 << self.v_ss) - 1)) >> self.v_ss
    }
    pub fn get_height(&self, height: usize) -> usize {
        (height + ((1 << self.h_ss) - 1)) >> self.h_ss
    }
    pub fn get_linesize(&self, width: usize, alignment: usize) -> usize {
        let d = self.depth as usize;
        align((self.get_width(width) * d + d - 1) >> 3, alignment)
    }
    pub fn get_data_size(&self, width: usize, height: usize, align: usize) -> usize {
        let nh = (height + ((1 << self.v_ss) - 1)) >> self.v_ss;
        self.get_linesize(width, align) * nh
    }
}

impl fmt::Display for Chromaton {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let pfmt = if self.packed {
            let mask = ((1 << self.depth) - 1) << self.shift;
            format!("packed(+{},{:X}, step {})",
                    self.comp_offs,
                    mask,
                    self.next_elem)
        } else {
            format!("planar({},{})", self.comp_offs, self.next_elem)
        };
        write!(f, "({}x{}, {})", self.h_ss, self.v_ss, pfmt)
    }
}

#[derive(Clone,Copy,PartialEq,Debug)]
pub struct Formaton {
    model: ColorModel,
    components: u8,
    comp_info: [Option<Chromaton>; 5],
    elem_size: u8,
    be: bool,
    alpha: bool,
    palette: bool,
}

bitflags! {
    pub flags Flags: u8 {
        const BE       = 0x01,
        const ALPHA    = 0x02,
        const PALETTE  = 0x04,
    }
}

impl Formaton {
    pub fn new(model: ColorModel, components: &[Chromaton], flags: Flags, elem_size: u8) -> Self {
        let be = flags.contains(BE);
        let alpha = flags.contains(ALPHA);
        let palette = flags.contains(PALETTE);
        let mut c: [Option<Chromaton>; 5] = [None; 5];

        if components.len() > 5 {
            panic!("too many components");
        }

        for (i, v) in components.iter().enumerate() {
            c[i] = Some(*v);
        }

        Formaton {
            model: model,
            components: components.len() as u8,
            comp_info: c,
            elem_size: elem_size,
            be: be,
            alpha: alpha,
            palette: palette,
        }
    }

    pub fn get_model(&self) -> ColorModel {
        self.model
    }
    pub fn get_num_comp(&self) -> usize {
        self.components as usize
    }
    pub fn get_chromaton(&self, idx: usize) -> Option<Chromaton> {
        if idx < self.comp_info.len() {
            return self.comp_info[idx];
        }
        None
    }
    pub fn is_be(&self) -> bool {
        self.be
    }
    pub fn has_alpha(&self) -> bool {
        self.alpha
    }
    pub fn is_paletted(&self) -> bool {
        self.palette
    }
    pub fn get_elem_size(&self) -> u8 {
        self.elem_size
    }

    pub fn iter<'a>(&'a self) -> slice::Iter<'a, Option<Chromaton>> {
        self.comp_info.iter()
    }
}

impl<'a> Index<usize> for &'a Formaton {
    type Output = Option<Chromaton>;

    fn index(&self, index: usize) -> &Self::Output {
        self.comp_info.index(index)
    }
}

impl<'a> IntoIterator for &'a Formaton {
    type Item = &'a Option<Chromaton>;
    type IntoIter = slice::Iter<'a, Option<Chromaton>>;

    fn into_iter(self) -> Self::IntoIter {
        self.comp_info.iter()
    }
}

impl fmt::Display for Formaton {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let end = if self.be {
            "BE"
        } else {
            "LE"
        };
        let palstr = if self.palette {
            "palette "
        } else {
            ""
        };
        let astr = if self.alpha {
            "alpha "
        } else {
            ""
        };
        let mut str = format!("Formaton for {} ({}{}elem {} size {}): ",
                              self.model,
                              palstr,
                              astr,
                              end,
                              self.elem_size);
        for &i in self.into_iter() {
            if let Some(chr) = i {
                str = format!("{} {}", str, chr);
            }
        }
        write!(f, "[{}]", str)
    }
}

macro_rules! chromaton {
    ($hs: expr, $vs: expr, $pck: expr, $d: expr, $sh: expr, $co: expr, $ne: expr) => ({
        Some(Chromaton {
                h_ss: $hs,
                v_ss: $vs,
                packed: $pck,
                depth: $d,
                shift: $sh,
                comp_offs: $co,
                next_elem: $ne })
    });
    (yuv8; $hs: expr, $vs: expr, $co: expr) => ({
        chromaton!($hs, $vs, false, 8, 0, $co, 1)
    });
    (packrgb; $d: expr, $s: expr, $co: expr, $ne: expr) => ({
        chromaton!(0, 0, true, $d, $s, $co, $ne)
    });
    (pal8; $co: expr) => ({
        chromaton!(0, 0, true, 8, 0, $co, 3)
    });
}

pub mod formats {
    use pixel::*;
    use self::ColorModel::*;
    use self::TrichromaticEncodingSystem::*;
    use self::YUVSystem::*;
    use self::YUVRange::*;

    pub const YUV420: &Formaton = &Formaton {
        model: Trichromatic(YUV(YCbCr(Limited))),
        components: 3,
        comp_info: [chromaton!(0, 0, false, 8, 0, 0, 1),
                    chromaton!(yuv8; 1, 1, 1),
                    chromaton!(yuv8; 1, 1, 2),
                    None,
                    None],
        elem_size: 0,
        be: false,
        alpha: false,
        palette: false,
    };

    pub const YUV410: &Formaton = &Formaton {
        model: Trichromatic(YUV(YCbCr(Limited))),
        components: 3,
        comp_info: [chromaton!(0, 0, false, 8, 0, 0, 1),
                    chromaton!(yuv8; 2, 2, 1),
                    chromaton!(yuv8; 2, 2, 2),
                    None,
                    None],
        elem_size: 0,
        be: false,
        alpha: false,
        palette: false,
    };

    pub const PAL8: &Formaton = &Formaton {
        model: Trichromatic(RGB),
        components: 3,
        comp_info: [chromaton!(pal8; 0), chromaton!(pal8; 1), chromaton!(pal8; 2), None, None],
        elem_size: 3,
        be: false,
        alpha: false,
        palette: true,
    };

    pub const RGB565: &Formaton = &Formaton {
        model: Trichromatic(RGB),
        components: 3,
        comp_info: [chromaton!(packrgb; 5, 11, 0, 2),
                    chromaton!(packrgb; 6,  5, 0, 2),
                    chromaton!(packrgb; 5,  0, 0, 2),
                    None,
                    None],
        elem_size: 2,
        be: false,
        alpha: false,
        palette: false,
    };

    pub const RGB24: &Formaton = &Formaton {
        model: Trichromatic(RGB),
        components: 3,
        comp_info: [chromaton!(packrgb; 8, 0, 2, 3),
                    chromaton!(packrgb; 8, 0, 1, 3),
                    chromaton!(packrgb; 8, 0, 0, 3),
                    None,
                    None],
        elem_size: 3,
        be: false,
        alpha: false,
        palette: false,
    };
}

#[cfg(test)]
mod test {
    mod formats {
        use super::super::*;
        #[test]
        fn fmt() {
            println!("formaton yuv- {}", formats::YUV420);
            println!("formaton pal- {}", formats::PAL8);
            println!("formaton rgb565- {}", formats::RGB565);
        }

        #[test]
        fn comparison() {
            use std::sync::Arc;
            let rcf = Arc::new(*formats::YUV420);
            let ref cf = formats::YUV420.clone();

            if cf != formats::YUV420 {
                panic!("cf");
            }

            if *rcf != *formats::YUV420 {
                panic!("rcf");
            }
        }
    }
}
<commit_msg>data: Add YUV411, YUV422 and YUV444 Formatons<commit_after>use std::slice;
use std::fmt;
use std::ops::Index;

#[derive(Debug,Clone,Copy,PartialEq)]
pub enum YUVRange {
    Limited,
    Full
}

impl fmt::Display for YUVRange {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            YUVRange::Limited => write!(f, "Limited range"),
            YUVRange::Full => write!(f, "Full range")
        }
    }
}

#[derive(Debug,Clone,Copy,PartialEq)]
pub enum YUVSystem {
    YCbCr(YUVRange),
    YCoCg,
    ICtCp
}

impl fmt::Display for YUVSystem {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::YUVSystem::*;
        match *self {
            YCbCr(range) => write!(f, "YCbCr ({})", range),
            YCoCg => write!(f, "YCbCg"),
            ICtCp => write!(f, "ICtCp"),
        }
    }
}

#[derive(Debug, Clone,Copy,PartialEq)]
pub enum TrichromaticEncodingSystem {
    RGB,
    YUV(YUVSystem),
    XYZ
}

impl fmt::Display for TrichromaticEncodingSystem {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::TrichromaticEncodingSystem::*;
        match *self {
            YUV(system) => write!(f, "{}", system),
            RGB => write!(f, "RGB"),
            XYZ => write!(f, "XYZ"),
        }
    }
}

#[derive(Debug, Clone,Copy,PartialEq)]
pub enum ColorModel {
    Trichromatic(TrichromaticEncodingSystem),
    CMYK,
    HSV,
    LAB,
}

impl fmt::Display for ColorModel {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::ColorModel::*;
        match *self {
            Trichromatic(system) => write!(f, "{}", system),
            CMYK => write!(f, "CMYK"),
            HSV => write!(f, "HSV"),
            LAB => write!(f, "LAB"),
        }
    }
}

impl ColorModel {
    pub fn get_default_components(&self) -> usize {
        match *self {
            ColorModel::CMYK => 4,
            _ => 3,
        }
    }
}

#[derive(Clone,Copy,Debug,PartialEq)]
pub struct Chromaton {
    h_ss: u8,
    v_ss: u8,
    packed: bool,
    depth: u8,
    shift: u8,
    comp_offs: u8,
    next_elem: u8,
}

fn align(v: usize, a: usize) -> usize {
    (v + a - 1) & !(a - 1)
}

impl Chromaton {
    pub fn get_subsampling(&self) -> (u8, u8) {
        (self.h_ss, self.v_ss)
    }
    pub fn is_packed(&self) -> bool {
        self.packed
    }
    pub fn get_depth(&self) -> u8 {
        self.depth
    }
    pub fn get_shift(&self) -> u8 {
        self.shift
    }
    pub fn get_offset(&self) -> u8 {
        self.comp_offs
    }
    pub fn get_step(&self) -> u8 {
        self.next_elem
    }

    pub fn get_width(&self, width: usize) -> usize {
        (width + ((1 << self.v_ss) - 1)) >> self.v_ss
    }
    pub fn get_height(&self, height: usize) -> usize {
        (height + ((1 << self.h_ss) - 1)) >> self.h_ss
    }
    pub fn get_linesize(&self, width: usize, alignment: usize) -> usize {
        let d = self.depth as usize;
        align((self.get_width(width) * d + d - 1) >> 3, alignment)
    }
    pub fn get_data_size(&self, width: usize, height: usize, align: usize) -> usize {
        let nh = (height + ((1 << self.v_ss) - 1)) >> self.v_ss;
        self.get_linesize(width, align) * nh
    }
}

impl fmt::Display for Chromaton {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let pfmt = if self.packed {
            let mask = ((1 << self.depth) - 1) << self.shift;
            format!("packed(+{},{:X}, step {})",
                    self.comp_offs,
                    mask,
                    self.next_elem)
        } else {
            format!("planar({},{})", self.comp_offs, self.next_elem)
        };
        write!(f, "({}x{}, {})", self.h_ss, self.v_ss, pfmt)
    }
}

#[derive(Clone,Copy,PartialEq,Debug)]
pub struct Formaton {
    model: ColorModel,
    components: u8,
    comp_info: [Option<Chromaton>; 5],
    elem_size: u8,
    be: bool,
    alpha: bool,
    palette: bool,
}

bitflags! {
    pub flags Flags: u8 {
        const BE       = 0x01,
        const ALPHA    = 0x02,
        const PALETTE  = 0x04,
    }
}

impl Formaton {
    pub fn new(model: ColorModel, components: &[Chromaton], flags: Flags, elem_size: u8) -> Self {
        let be = flags.contains(BE);
        let alpha = flags.contains(ALPHA);
        let palette = flags.contains(PALETTE);
        let mut c: [Option<Chromaton>; 5] = [None; 5];

        if components.len() > 5 {
            panic!("too many components");
        }

        for (i, v) in components.iter().enumerate() {
            c[i] = Some(*v);
        }

        Formaton {
            model: model,
            components: components.len() as u8,
            comp_info: c,
            elem_size: elem_size,
            be: be,
            alpha: alpha,
            palette: palette,
        }
    }

    pub fn get_model(&self) -> ColorModel {
        self.model
    }
    pub fn get_num_comp(&self) -> usize {
        self.components as usize
    }
    pub fn get_chromaton(&self, idx: usize) -> Option<Chromaton> {
        if idx < self.comp_info.len() {
            return self.comp_info[idx];
        }
        None
    }
    pub fn is_be(&self) -> bool {
        self.be
    }
    pub fn has_alpha(&self) -> bool {
        self.alpha
    }
    pub fn is_paletted(&self) -> bool {
        self.palette
    }
    pub fn get_elem_size(&self) -> u8 {
        self.elem_size
    }

    pub fn iter<'a>(&'a self) -> slice::Iter<'a, Option<Chromaton>> {
        self.comp_info.iter()
    }
}

impl<'a> Index<usize> for &'a Formaton {
    type Output = Option<Chromaton>;

    fn index(&self, index: usize) -> &Self::Output {
        self.comp_info.index(index)
    }
}

impl<'a> IntoIterator for &'a Formaton {
    type Item = &'a Option<Chromaton>;
    type IntoIter = slice::Iter<'a, Option<Chromaton>>;

    fn into_iter(self) -> Self::IntoIter {
        self.comp_info.iter()
    }
}

impl fmt::Display for Formaton {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let end = if self.be {
            "BE"
        } else {
            "LE"
        };
        let palstr = if self.palette {
            "palette "
        } else {
            ""
        };
        let astr = if self.alpha {
            "alpha "
        } else {
            ""
        };
        let mut str = format!("Formaton for {} ({}{}elem {} size {}): ",
                              self.model,
                              palstr,
                              astr,
                              end,
                              self.elem_size);
        for &i in self.into_iter() {
            if let Some(chr) = i {
                str = format!("{} {}", str, chr);
            }
        }
        write!(f, "[{}]", str)
    }
}

macro_rules! chromaton {
    ($hs: expr, $vs: expr, $pck: expr, $d: expr, $sh: expr, $co: expr, $ne: expr) => ({
        Some(Chromaton {
                h_ss: $hs,
                v_ss: $vs,
                packed: $pck,
                depth: $d,
                shift: $sh,
                comp_offs: $co,
                next_elem: $ne })
    });
    (yuv8; $hs: expr, $vs: expr, $co: expr) => ({
        chromaton!($hs, $vs, false, 8, 0, $co, 1)
    });
    (packrgb; $d: expr, $s: expr, $co: expr, $ne: expr) => ({
        chromaton!(0, 0, true, $d, $s, $co, $ne)
    });
    (pal8; $co: expr) => ({
        chromaton!(0, 0, true, 8, 0, $co, 3)
    });
}

pub mod formats {
    use pixel::*;
    use self::ColorModel::*;
    use self::TrichromaticEncodingSystem::*;
    use self::YUVSystem::*;
    use self::YUVRange::*;

    pub const YUV444: &Formaton = &Formaton {
        model: Trichromatic(YUV(YCbCr(Limited))),
        components: 3,
        comp_info: [chromaton!(0, 0, false, 8, 0, 0, 1),
                    chromaton!(yuv8; 0, 0, 1),
                    chromaton!(yuv8; 0, 0, 2),
                    None,
                    None],
        elem_size: 0,
        be: false,
        alpha: false,
        palette: false,
    };

    pub const YUV422: &Formaton = &Formaton {
        model: Trichromatic(YUV(YCbCr(Limited))),
        components: 3,
        comp_info: [chromaton!(0, 0, false, 8, 0, 0, 1),
                    chromaton!(yuv8; 0, 1, 1),
                    chromaton!(yuv8; 0, 1, 2),
                    None,
                    None],
        elem_size: 0,
        be: false,
        alpha: false,
        palette: false,
    };

    pub const YUV420: &Formaton = &Formaton {
        model: Trichromatic(YUV(YCbCr(Limited))),
        components: 3,
        comp_info: [chromaton!(0, 0, false, 8, 0, 0, 1),
                    chromaton!(yuv8; 1, 1, 1),
                    chromaton!(yuv8; 1, 1, 2),
                    None,
                    None],
        elem_size: 0,
        be: false,
        alpha: false,
        palette: false,
    };

    pub const YUV411: &Formaton = &Formaton {
        model: Trichromatic(YUV(YCbCr(Limited))),
        components: 3,
        comp_info: [chromaton!(0, 0, false, 8, 0, 0, 1),
                    chromaton!(yuv8; 2, 0, 1),
                    chromaton!(yuv8; 2, 0, 2),
                    None,
                    None],
        elem_size: 0,
        be: false,
        alpha: false,
        palette: false,
    };

    pub const YUV410: &Formaton = &Formaton {
        model: Trichromatic(YUV(YCbCr(Limited))),
        components: 3,
        comp_info: [chromaton!(0, 0, false, 8, 0, 0, 1),
                    chromaton!(yuv8; 2, 1, 1),
                    chromaton!(yuv8; 2, 1, 2),
                    None,
                    None],
        elem_size: 0,
        be: false,
        alpha: false,
        palette: false,
    };

    pub const PAL8: &Formaton = &Formaton {
        model: Trichromatic(RGB),
        components: 3,
        comp_info: [chromaton!(pal8; 0), chromaton!(pal8; 1), chromaton!(pal8; 2), None, None],
        elem_size: 3,
        be: false,
        alpha: false,
        palette: true,
    };

    pub const RGB565: &Formaton = &Formaton {
        model: Trichromatic(RGB),
        components: 3,
        comp_info: [chromaton!(packrgb; 5, 11, 0, 2),
                    chromaton!(packrgb; 6,  5, 0, 2),
                    chromaton!(packrgb; 5,  0, 0, 2),
                    None,
                    None],
        elem_size: 2,
        be: false,
        alpha: false,
        palette: false,
    };

    pub const RGB24: &Formaton = &Formaton {
        model: Trichromatic(RGB),
        components: 3,
        comp_info: [chromaton!(packrgb; 8, 0, 2, 3),
                    chromaton!(packrgb; 8, 0, 1, 3),
                    chromaton!(packrgb; 8, 0, 0, 3),
                    None,
                    None],
        elem_size: 3,
        be: false,
        alpha: false,
        palette: false,
    };
}

#[cfg(test)]
mod test {
    mod formats {
        use super::super::*;
        #[test]
        fn fmt() {
            println!("formaton yuv- {}", formats::YUV420);
            println!("formaton pal- {}", formats::PAL8);
            println!("formaton rgb565- {}", formats::RGB565);
        }

        #[test]
        fn comparison() {
            use std::sync::Arc;
            let rcf = Arc::new(*formats::YUV420);
            let ref cf = formats::YUV420.clone();

            if cf != formats::YUV420 {
                panic!("cf");
            }

            if *rcf != *formats::YUV420 {
                panic!("rcf");
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Read, Write};
use ::BufferRedirect;

/// Hold output until dropped. On drop, the held output is sent to the stdout/stderr.
///
/// Note: This will ignore IO errors when printing held output.
pub struct Hold {
    buf_redir: Option<BufferRedirect>,
    is_stdout: bool,
}

impl Hold {
    /// Hold stderr output.
    pub fn stderr() -> io::Result<Hold> {
        Ok(Hold {
            buf_redir: Some(try!(BufferRedirect::stderr())),
            is_stdout: false,
        })
    }

    /// Hold stdout output.
    pub fn stdout() -> io::Result<Hold> {
        Ok(Hold {
            buf_redir: Some(try!(BufferRedirect::stdout())),
            is_stdout: true,
        })
    }
}

impl Drop for Hold {
    fn drop(&mut self) {
        fn read_into<R: Read, W: Write>(mut from: R, mut to: W) -> io::Result<()> {
            // TODO: use sendfile?
            let mut buf = [0u8; 4096];
            loop {
                match from.read(&mut buf) {
                    Ok(0) => return Ok(()),
                    Ok(size) => try!(to.write_all(&buf[..size])),
                    Err(e) => return Err(e),
                }
            }
        }

        let from = self.buf_redir.take().unwrap().into_inner();
        // Ignore errors.
        if self.is_stdout {
            let stdout = io::stdout();
            let _ = read_into(from, stdout.lock());
        } else {
            let stderr = io::stderr();
            let _ = read_into(from, stderr.lock());
        }
    }
}
<commit_msg>flush on drop in hold<commit_after>use std::io::{self, Read, Write};
use ::BufferRedirect;

/// Hold output until dropped. On drop, the held output is sent to the stdout/stderr.
///
/// Note: This will ignore IO errors when printing held output.
pub struct Hold {
    buf_redir: Option<BufferRedirect>,
    is_stdout: bool,
}

impl Hold {
    /// Hold stderr output.
    pub fn stderr() -> io::Result<Hold> {
        Ok(Hold {
            buf_redir: Some(try!(BufferRedirect::stderr())),
            is_stdout: false,
        })
    }

    /// Hold stdout output.
    pub fn stdout() -> io::Result<Hold> {
        Ok(Hold {
            buf_redir: Some(try!(BufferRedirect::stdout())),
            is_stdout: true,
        })
    }
}

impl Drop for Hold {
    fn drop(&mut self) {
        fn read_into<R: Read, W: Write>(mut from: R, mut to: W) {
            // TODO: use sendfile?
            let mut buf = [0u8; 4096];
            loop {
                // Ignore errors
                match from.read(&mut buf) {
                    Ok(0) => break,
                    Ok(size) => if let Err(_) = to.write_all(&buf[..size]) { break },
                    Err(_) => break,
                }
            }
            // Just in case...
            let _ = to.flush();
        }

        let from = self.buf_redir.take().unwrap().into_inner();
        // Ignore errors.
        if self.is_stdout {
            let stdout = io::stdout();
            read_into(from, stdout.lock());
        } else {
            let stderr = io::stderr();
            read_into(from, stderr.lock());
        }
    }
}
<|endoftext|>


<commit_before>extern crate irc;

use std::default::Default;
use std::thread::spawn;
use irc::client::prelude::*;

fn main() {
    let config = Config {
        nickname: Some(format!("pickles")),
        server: Some(format!("irc.fyrechat.net")),
        channels: Some(vec![format!("#vana")]),
        .. Default::default()
    };
    let server = IrcServer::from_config(config).unwrap();
    // FIXME: if set_keepalive is stabilized, this can be readded.
    // server.conn().set_keepalive(Some(5)).unwrap();
    let server = server.clone();
    let _ = spawn(move || {
        server.identify().unwrap();
        loop {
            let mut quit = false;
            for msg in server.iter() {
                match msg {
                    Ok(msg) => {
                        print!("{}", msg.into_string());
                        match (&msg).into() {
                            Ok(Command::PRIVMSG(_, msg)) => if msg.contains("bye") {
                                server.send_quit("").unwrap()
                            },
                            Ok(Command::ERROR(ref msg)) if msg.contains("Quit") => quit = true,
                            _ => (),
                        }
                    },
                    Err(_)  => break,
                }
            }
            if quit { break }
            server.reconnect().unwrap();
            server.identify().unwrap();
        }
    }).join();
}
<commit_msg>Removed autoreconnect example because it now happens automatically.<commit_after><|endoftext|>


<commit_before>
extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

use gitlab::GitLab;
// use gitlab::Pagination;

fn main() {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    // // Projects
    // // List projects
    // let projects = gl.projects().list()
    // let projects = gl.projects().archived(...).visibility(...).order_by(...).sort(...).search(...).simple(...).list()
    // // List all projects (admin)
    // let projects = gl.projects().all().list()
    // let projects = gl.projects().all().archived(...).visibility(...).order_by(...).sort(...).search(...).list()
    // // Single project
    // let project = gl.projects().id(142).list()
    // // Search
    // let projects = gl.projects().search(...).list()
    // // Owned
    // let projects = gl.projects().owned().archived(...).visibility(...).order_by(...).sort(...).search(...).list()

    let gl = GitLab::new(&hostname, &token);

    // let projects = gl.projects().list();
    let projects = gl.projects().archived(false).list();
    println!("projects: {:?}", projects);

    let projects = gl.projects().owned().archived(false).list();
    println!("projects: {:?}", projects);

    // // for i in 1..82 {
    // //     gl.set_pagination(Pagination{page: i, per_page: 1});
    // //     println!("projects: {:?}", gl.projects_list().unwrap());
    // // }
    // // gl.set_pagination(Pagination {
    // //     page: 1,
    // //     per_page: 100,
    // // });
    // let projects = gl.projects_list(projects::Listing::new()).unwrap();
    // println!("projects: {:?}", projects);
    // // FIXME: Project's members are private
    // // for project in projects {
    // //     println!("{:?}", project.path_with_namespace);
    // // }
    //
    // let projects = gl.projects_all(projects::all::Listing::new()).unwrap();
    // println!("projects: {:?}", projects);
    //
    // let listing = projects::id::Listing::new(projects::id::ListingId::Id(10));
    // let projects = gl.project_id(listing).unwrap();
    // println!("projects: {:?}", projects);
}
<commit_msg>Add example for `projects::all`<commit_after>
extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

use gitlab::GitLab;
// use gitlab::Pagination;

fn main() {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    // // Projects
    // // List projects
    // let projects = gl.projects().list()
    // let projects = gl.projects().archived(...).visibility(...).order_by(...).sort(...).search(...).simple(...).list()
    // // List all projects (admin)
    // let projects = gl.projects().all().list()
    // let projects = gl.projects().all().archived(...).visibility(...).order_by(...).sort(...).search(...).list()
    // // Single project
    // let project = gl.projects().id(142).list()
    // // Search
    // let projects = gl.projects().search(...).list()
    // // Owned
    // let projects = gl.projects().owned().archived(...).visibility(...).order_by(...).sort(...).search(...).list()

    let gl = GitLab::new(&hostname, &token);

    // let projects = gl.projects().list();
    let projects = gl.projects().archived(false).list();
    println!("projects: {:?}", projects);

    let projects = gl.projects().owned().archived(false).list();
    println!("projects: {:?}", projects);

    let projects = gl.projects().all().order_by(gitlab::projects::ListingOrderBy::Name).list();
    println!("projects: {:?}", projects);

    // // for i in 1..82 {
    // //     gl.set_pagination(Pagination{page: i, per_page: 1});
    // //     println!("projects: {:?}", gl.projects_list().unwrap());
    // // }
    // // gl.set_pagination(Pagination {
    // //     page: 1,
    // //     per_page: 100,
    // // });
    // let projects = gl.projects_list(projects::Listing::new()).unwrap();
    // println!("projects: {:?}", projects);
    // // FIXME: Project's members are private
    // // for project in projects {
    // //     println!("{:?}", project.path_with_namespace);
    // // }
    //
    // let projects = gl.projects_all(projects::all::Listing::new()).unwrap();
    // println!("projects: {:?}", projects);
    //
    // let listing = projects::id::Listing::new(projects::id::ListingId::Id(10));
    // let projects = gl.project_id(listing).unwrap();
    // println!("projects: {:?}", projects);
}
<|endoftext|>