<commit_before>use regex_syntax::{Expr, Repeater, CharClass, ClassRange};
use utf8_ranges::{Utf8Sequences, Utf8Sequence};

use regex::{Error, Inst};
use Result;

pub struct Compiler {
    size_limit: usize,
    insts: Vec<Inst>,
}

impl Compiler {
    pub fn new(size_limit: usize) -> Compiler {
        Compiler {
            size_limit: size_limit,
            insts: vec![],
        }
    }

    pub fn compile(mut self, ast: &Expr) -> Result<Vec<Inst>> {
        try!(self.c(ast));
        self.insts.push(Inst::Match);
        Ok(self.insts)
    }

    fn c(&mut self, ast: &Expr) -> Result<()> {
        use regex::Inst::*;
        match *ast {
            Expr::StartLine
            | Expr::EndLine
            | Expr::StartText
            | Expr::EndText => return Err(From::from(Error::NoEmpty)),
            Expr::WordBoundary
            | Expr::NotWordBoundary => {
                return Err(From::from(Error::NoWordBoundary));
            }
            Expr::Empty => {},
            Expr::Literal { ref chars, casei } => {
                for &c in chars {
                    if casei {
                        try!(self.c(&Expr::Class(CharClass::new(vec![
                            ClassRange { start: c, end: c },
                        ]).case_fold())));
                    } else {
                        // One scalar value, so we're guaranteed to get a
                        // single byte sequence.
                        for seq in Utf8Sequences::new(c, c) {
                            self.compile_utf8_ranges(&seq);
                        }
                    }
                }
            }
            Expr::AnyChar => try!(self.c(&Expr::Class(CharClass::new(vec![
                ClassRange { start: '\u{0}', end: '\u{10FFFF}' },
            ])))),
            Expr::AnyCharNoNL => try!(self.c(&Expr::Class(CharClass::new(vec![
                ClassRange { start: '\u{0}', end: '\u{09}' },
                ClassRange { start: '\u{0B}', end: '\u{10FFFF}' },
            ])))),
            Expr::Class(ref cls) => {
                try!(self.compile_class(cls));
            }
            Expr::Group { ref e, .. } => try!(self.c(e)),
            Expr::Concat(ref es) => {
                for e in es {
                    try!(self.c(e));
                }
            }
            Expr::Alternate(ref es) => {
                if es.len() == 0 {
                    return Ok(());
                }
                let mut jmps_to_end = vec![];
                for e in &es[0..es.len()-1] {
                    let split = self.empty_split();
                    let j1 = self.insts.len();
                    try!(self.c(e));
                    jmps_to_end.push(self.empty_jump());
                    let j2 = self.insts.len();
                    self.set_split(split, j1, j2);
                }
                try!(self.c(&es[es.len()-1]));
                let end = self.insts.len();
                for jmp_to_end in jmps_to_end {
                    self.set_jump(jmp_to_end, end);
                }
            }
            Expr::Repeat { greedy: false, .. } => {
                return Err(Error::NoLazy.into());
            }
            Expr::Repeat { ref e, r: Repeater::ZeroOrOne, .. } => {
                let split = self.empty_split();
                let j1 = self.insts.len();
                try!(self.c(e));
                let j2 = self.insts.len();
                self.set_split(split, j1, j2);
            }
            Expr::Repeat { ref e, r: Repeater::ZeroOrMore, .. } => {
                let j1 = self.insts.len();
                let split = self.empty_split();
                let j2 = self.insts.len();
                try!(self.c(e));
                let jmp = self.empty_jump();
                let j3 = self.insts.len();

                self.set_jump(jmp, j1);
                self.set_split(split, j2, j3);
            }
            Expr::Repeat { ref e, r: Repeater::OneOrMore, .. } => {
                let j1 = self.insts.len();
                try!(self.c(e));
                let split = self.empty_split();
                let j2 = self.insts.len();
                self.set_split(split, j1, j2);
            }
            Expr::Repeat {
                ref e,
                r: Repeater::Range { min, max: None },
                ..
            } => {
                for _ in 0..min {
                    try!(self.c(e));
                }
                try!(self.c(&Expr::Repeat {
                    e: e.clone(),
                    r: Repeater::ZeroOrMore,
                    greedy: true,
                }));
            }
            Expr::Repeat {
                ref e,
                r: Repeater::Range { min, max: Some(max) },
                ..
            } => {
                for _ in 0..min {
                    try!(self.c(e));
                }
                let (mut splits, mut starts) = (vec![], vec![]);
                for _ in min..max {
                    splits.push(self.empty_split());
                    starts.push(self.insts.len());
                    try!(self.c(e));
                }
                let end = self.insts.len();
                for (split, start) in splits.into_iter().zip(starts) {
                    self.set_split(split, start, end);
                }
            }
        }
        self.check_size()
    }

    fn compile_class(&mut self, class: &CharClass) -> Result<()> {
        if class.is_empty() {
            return Ok(());
        }
        let mut jmps = vec![];
        for r in &class[0..class.len()-1] {
            let split = self.empty_split();
            let j1 = self.insts.len();
            try!(self.compile_class_range(r));
            jmps.push(self.empty_jump());
            let j2 = self.insts.len();
            self.set_split(split, j1, j2);
        }
        try!(self.compile_class_range(&class[class.len()-1]));
        let end = self.insts.len();
        for jmp in jmps {
            self.set_jump(jmp, end);
        }
        Ok(())
    }

    fn compile_class_range(&mut self, char_range: &ClassRange) -> Result<()> {
        let mut it = Utf8Sequences::new(char_range.start, char_range.end)
                                   .peekable();
        let mut jmps = vec![];
        let mut utf8_ranges = it.next().expect("non-empty char class");
        while it.peek().is_some() {
            let split = self.empty_split();
            let j1 = self.insts.len();
            self.compile_utf8_ranges(&utf8_ranges);
            jmps.push(self.empty_jump());
            let j2 = self.insts.len();
            self.set_split(split, j1, j2);
            utf8_ranges = it.next().unwrap(); // because peek says so
        }
        self.compile_utf8_ranges(&utf8_ranges);
        let end = self.insts.len();
        for jmp in jmps {
            self.set_jump(jmp, end);
        }
        Ok(())
    }

    fn compile_utf8_ranges(&mut self, utf8_ranges: &Utf8Sequence) {
        for r in utf8_ranges {
            self.push(Inst::Range(r.start, r.end));
        }
    }

    fn check_size(&self) -> Result<()> {
        use std::mem::size_of;

        if self.insts.len() * size_of::<Inst>() > self.size_limit {
            Err(Error::CompiledTooBig(self.size_limit).into())
        } else {
            Ok(())
        }
    }

    /// Appends the given instruction to the program.
    #[inline]
    fn push(&mut self, x: Inst) {
        self.insts.push(x)
    }

    /// Appends an *empty* `Split` instruction to the program and returns
    /// the index of that instruction. (The index can then be used to "patch"
    /// the actual locations of the split in later.)
    #[inline]
    fn empty_split(&mut self) -> usize {
        self.insts.push(Inst::Split(0, 0));
        self.insts.len() - 1
    }

    /// Sets the left and right locations of a `Split` instruction at index
    /// `i` to `pc1` and `pc2`, respectively.
    /// If the instruction at index `i` isn't a `Split` instruction, then
    /// `panic!` is called.
    #[inline]
    fn set_split(&mut self, i: usize, pc1: usize, pc2: usize) {
        let split = &mut self.insts[i];
        match *split {
            Inst::Split(_, _) => *split = Inst::Split(pc1, pc2),
            _ => panic!("BUG: Invalid split index."),
        }
    }

    /// Appends an *empty* `Jump` instruction to the program and returns the
    /// index of that instruction.
    #[inline]
    fn empty_jump(&mut self) -> usize {
        self.insts.push(Inst::Jump(0));
        self.insts.len() - 1
    }

    /// Sets the location of a `Jump` instruction at index `i` to `pc`.
    /// If the instruction at index `i` isn't a `Jump` instruction, then
    /// `panic!` is called.
    #[inline]
    fn set_jump(&mut self, i: usize, pc: usize) {
        let jmp = &mut self.insts[i];
        match *jmp {
            Inst::Jump(_) => *jmp = Inst::Jump(pc),
            _ => panic!("BUG: Invalid jump index."),
        }
    }
}
<commit_msg>remove unused import<commit_after>use regex_syntax::{Expr, Repeater, CharClass, ClassRange};
use utf8_ranges::{Utf8Sequences, Utf8Sequence};

use regex::{Error, Inst};
use Result;

pub struct Compiler {
    size_limit: usize,
    insts: Vec<Inst>,
}

impl Compiler {
    pub fn new(size_limit: usize) -> Compiler {
        Compiler {
            size_limit: size_limit,
            insts: vec![],
        }
    }

    pub fn compile(mut self, ast: &Expr) -> Result<Vec<Inst>> {
        try!(self.c(ast));
        self.insts.push(Inst::Match);
        Ok(self.insts)
    }

    fn c(&mut self, ast: &Expr) -> Result<()> {
        match *ast {
            Expr::StartLine
            | Expr::EndLine
            | Expr::StartText
            | Expr::EndText => return Err(From::from(Error::NoEmpty)),
            Expr::WordBoundary
            | Expr::NotWordBoundary => {
                return Err(From::from(Error::NoWordBoundary));
            }
            Expr::Empty => {},
            Expr::Literal { ref chars, casei } => {
                for &c in chars {
                    if casei {
                        try!(self.c(&Expr::Class(CharClass::new(vec![
                            ClassRange { start: c, end: c },
                        ]).case_fold())));
                    } else {
                        // One scalar value, so we're guaranteed to get a
                        // single byte sequence.
                        for seq in Utf8Sequences::new(c, c) {
                            self.compile_utf8_ranges(&seq);
                        }
                    }
                }
            }
            Expr::AnyChar => try!(self.c(&Expr::Class(CharClass::new(vec![
                ClassRange { start: '\u{0}', end: '\u{10FFFF}' },
            ])))),
            Expr::AnyCharNoNL => try!(self.c(&Expr::Class(CharClass::new(vec![
                ClassRange { start: '\u{0}', end: '\u{09}' },
                ClassRange { start: '\u{0B}', end: '\u{10FFFF}' },
            ])))),
            Expr::Class(ref cls) => {
                try!(self.compile_class(cls));
            }
            Expr::Group { ref e, .. } => try!(self.c(e)),
            Expr::Concat(ref es) => {
                for e in es {
                    try!(self.c(e));
                }
            }
            Expr::Alternate(ref es) => {
                if es.len() == 0 {
                    return Ok(());
                }
                let mut jmps_to_end = vec![];
                for e in &es[0..es.len()-1] {
                    let split = self.empty_split();
                    let j1 = self.insts.len();
                    try!(self.c(e));
                    jmps_to_end.push(self.empty_jump());
                    let j2 = self.insts.len();
                    self.set_split(split, j1, j2);
                }
                try!(self.c(&es[es.len()-1]));
                let end = self.insts.len();
                for jmp_to_end in jmps_to_end {
                    self.set_jump(jmp_to_end, end);
                }
            }
            Expr::Repeat { greedy: false, .. } => {
                return Err(Error::NoLazy.into());
            }
            Expr::Repeat { ref e, r: Repeater::ZeroOrOne, .. } => {
                let split = self.empty_split();
                let j1 = self.insts.len();
                try!(self.c(e));
                let j2 = self.insts.len();
                self.set_split(split, j1, j2);
            }
            Expr::Repeat { ref e, r: Repeater::ZeroOrMore, .. } => {
                let j1 = self.insts.len();
                let split = self.empty_split();
                let j2 = self.insts.len();
                try!(self.c(e));
                let jmp = self.empty_jump();
                let j3 = self.insts.len();

                self.set_jump(jmp, j1);
                self.set_split(split, j2, j3);
            }
            Expr::Repeat { ref e, r: Repeater::OneOrMore, .. } => {
                let j1 = self.insts.len();
                try!(self.c(e));
                let split = self.empty_split();
                let j2 = self.insts.len();
                self.set_split(split, j1, j2);
            }
            Expr::Repeat {
                ref e,
                r: Repeater::Range { min, max: None },
                ..
            } => {
                for _ in 0..min {
                    try!(self.c(e));
                }
                try!(self.c(&Expr::Repeat {
                    e: e.clone(),
                    r: Repeater::ZeroOrMore,
                    greedy: true,
                }));
            }
            Expr::Repeat {
                ref e,
                r: Repeater::Range { min, max: Some(max) },
                ..
            } => {
                for _ in 0..min {
                    try!(self.c(e));
                }
                let (mut splits, mut starts) = (vec![], vec![]);
                for _ in min..max {
                    splits.push(self.empty_split());
                    starts.push(self.insts.len());
                    try!(self.c(e));
                }
                let end = self.insts.len();
                for (split, start) in splits.into_iter().zip(starts) {
                    self.set_split(split, start, end);
                }
            }
        }
        self.check_size()
    }

    fn compile_class(&mut self, class: &CharClass) -> Result<()> {
        if class.is_empty() {
            return Ok(());
        }
        let mut jmps = vec![];
        for r in &class[0..class.len()-1] {
            let split = self.empty_split();
            let j1 = self.insts.len();
            try!(self.compile_class_range(r));
            jmps.push(self.empty_jump());
            let j2 = self.insts.len();
            self.set_split(split, j1, j2);
        }
        try!(self.compile_class_range(&class[class.len()-1]));
        let end = self.insts.len();
        for jmp in jmps {
            self.set_jump(jmp, end);
        }
        Ok(())
    }

    fn compile_class_range(&mut self, char_range: &ClassRange) -> Result<()> {
        let mut it = Utf8Sequences::new(char_range.start, char_range.end)
                                   .peekable();
        let mut jmps = vec![];
        let mut utf8_ranges = it.next().expect("non-empty char class");
        while it.peek().is_some() {
            let split = self.empty_split();
            let j1 = self.insts.len();
            self.compile_utf8_ranges(&utf8_ranges);
            jmps.push(self.empty_jump());
            let j2 = self.insts.len();
            self.set_split(split, j1, j2);
            utf8_ranges = it.next().unwrap(); // because peek says so
        }
        self.compile_utf8_ranges(&utf8_ranges);
        let end = self.insts.len();
        for jmp in jmps {
            self.set_jump(jmp, end);
        }
        Ok(())
    }

    fn compile_utf8_ranges(&mut self, utf8_ranges: &Utf8Sequence) {
        for r in utf8_ranges {
            self.push(Inst::Range(r.start, r.end));
        }
    }

    fn check_size(&self) -> Result<()> {
        use std::mem::size_of;

        if self.insts.len() * size_of::<Inst>() > self.size_limit {
            Err(Error::CompiledTooBig(self.size_limit).into())
        } else {
            Ok(())
        }
    }

    /// Appends the given instruction to the program.
    #[inline]
    fn push(&mut self, x: Inst) {
        self.insts.push(x)
    }

    /// Appends an *empty* `Split` instruction to the program and returns
    /// the index of that instruction. (The index can then be used to "patch"
    /// the actual locations of the split in later.)
    #[inline]
    fn empty_split(&mut self) -> usize {
        self.insts.push(Inst::Split(0, 0));
        self.insts.len() - 1
    }

    /// Sets the left and right locations of a `Split` instruction at index
    /// `i` to `pc1` and `pc2`, respectively.
    /// If the instruction at index `i` isn't a `Split` instruction, then
    /// `panic!` is called.
    #[inline]
    fn set_split(&mut self, i: usize, pc1: usize, pc2: usize) {
        let split = &mut self.insts[i];
        match *split {
            Inst::Split(_, _) => *split = Inst::Split(pc1, pc2),
            _ => panic!("BUG: Invalid split index."),
        }
    }

    /// Appends an *empty* `Jump` instruction to the program and returns the
    /// index of that instruction.
    #[inline]
    fn empty_jump(&mut self) -> usize {
        self.insts.push(Inst::Jump(0));
        self.insts.len() - 1
    }

    /// Sets the location of a `Jump` instruction at index `i` to `pc`.
    /// If the instruction at index `i` isn't a `Jump` instruction, then
    /// `panic!` is called.
    #[inline]
    fn set_jump(&mut self, i: usize, pc: usize) {
        let jmp = &mut self.insts[i];
        match *jmp {
            Inst::Jump(_) => *jmp = Inst::Jump(pc),
            _ => panic!("BUG: Invalid jump index."),
        }
    }
}
<|endoftext|>


<commit_before>pub mod human;
pub mod ki;

use arena;
use db::pokemon_token::PokemonToken;
use db::pokedex::*;
use std::collections::HashMap;
use db::{moves, enums};

/// The Player type represents if the Player is a Human or a specific Ai to call different funcions
/// for e.g. choosing Pokemon
#[derive(Clone, Debug)]
pub enum PlayerType {
    Human,
    SimpleAi,
}

/// An enum which represents the AttackSlot to match with it
#[derive(Debug, Clone, Copy)]
pub enum AttackSlot {
    One,
    Two,
    Three,
    Four,
}
/// An enum representing the PokemonSlot
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PokemonSlot {
    One,
    Two,
    Three,
    Four,
    Five,
    Six,
}
impl PokemonSlot {
    pub fn get_int(&self) -> usize {
        match *self {
            PokemonSlot::One => 1,
            PokemonSlot::Two => 2,
            PokemonSlot::Three => 3,
            PokemonSlot::Four => 4,
            PokemonSlot::Five => 5,
            PokemonSlot::Six => 6,
        }
    }
}
#[derive(Clone, Debug, PartialEq)]
pub enum Next {
    Switch(PokemonSlot),
    Move(moves::Technique),
    Flinch,
    None,
}

/// The Player struct represents a Player and holds his Type (Human, Ai...), a list of his pokemon,
/// the amount of pokemon, his currently fighting pokemon and the next_move he wants to make
#[derive(Clone, Debug)]
pub struct Player {
    player: PlayerType,
    pokemon_list: Vec<PokemonToken>,
    pokemon_count: usize,
    current: usize,
    next_move: Option<Next>,
    flags: HashMap<enums::PlayerFlag, u8>,
    last_move: Option<moves::Technique>,
    last_action: (Next, u8),
    switched: bool,
}

impl Player {
    // Constructor
    //
    /// Takes an array with pokemon id´s and the PlayerType and returns a player
    pub fn new_by_id(input: &[usize], player_type: PlayerType) -> Self {
        let mut pokemon = Vec::new();
        let len = input.len();
        let dex = Pokedex::new();
        for i in 0..input.len() {
            pokemon.push(PokemonToken::from_model(dex.pokemon_by_id(input[i]).unwrap()));
        }
        Player {
            player: player_type,
            pokemon_list: pokemon,
            pokemon_count: len,
            current: 0,
            next_move: None,
            flags: HashMap::new(),
            last_move: None,
            last_action: (Next::None, 0),
            switched: false,
        }
    }

    // Getter methods
    //
    /// Returns the list of pokemon choosen by the player
    pub fn get_pokemon_list(&mut self) -> &mut Vec<PokemonToken> {
        &mut self.pokemon_list
    }
    /// Returns the currently fighting pokemon
    pub fn get_current(&self) -> usize {
        self.current
    }
    /// Gets the amount of pokemon choosen by the player
    pub fn get_pokemon_count(&self) -> usize {
        self.pokemon_count
    }
    /// Returns the amount of pokemon with atleast one hp
    pub fn get_alive_count(&mut self) -> usize {
        let mut alive = 0;
        for i in 0..self.pokemon_list.len() {
            if self.pokemon_list[i].get_current().get_stat(&enums::Stats::Hp) == 0 {
                alive += 1;
            }
        }
        alive
    }
    /// Returns a Vec with the id´s in the player model from the pokemon which are alive
    pub fn get_alive_list(&mut self) -> Vec<usize> {
        let mut vec = Vec::new();
        for i in 0..self.pokemon_list.len() {
            if self.get_pokemon_list()[i].get_current().get_stat(&enums::Stats::Hp) != 0 {
                vec.push(i);
            }
        }
        vec
    }
    /// Gets a attack saved in an attackslot
    pub fn get_attack(&mut self, slot: &AttackSlot) -> moves::Technique {
        match slot {
            &AttackSlot::One => self.pokemon_list[self.current].clone().get_move_one().unwrap(),
            &AttackSlot::Two => self.pokemon_list[self.current].clone().get_move_two().unwrap(),
            &AttackSlot::Three => self.pokemon_list[self.current].clone().get_move_three().unwrap(),
            &AttackSlot::Four => self.pokemon_list[self.current].clone().get_move_four().unwrap(),
        }
    }
    /// Checks if an attack is in the Attackslots and returns the Slot
    pub fn get_attack_slot(&mut self, attack: moves::Technique) -> Option<AttackSlot> {
        if self.get_attack(&AttackSlot::One) == attack {
            return Some(AttackSlot::One);
        } else if self.get_attack(&AttackSlot::Two) == attack {
            return Some(AttackSlot::Two);
        } else if self.get_attack(&AttackSlot::Three) == attack {
            return Some(AttackSlot::Three);
        } else if self.get_attack(&AttackSlot::Four) == attack {
            return Some(AttackSlot::Four);
        }
        None
    }
    /// Gets the next attack from the Player. Returns none if no Technique is selected
    pub fn get_next_move(&self) -> Option<Next> {
        self.next_move.clone()
    }
    /// Gets the last move with the Slot. Returns None if the last move wasn´t an attack
    pub fn get_last_move(&self) -> Option<moves::Technique> {
        self.last_move.clone()
    }

    pub fn get_last_action(&self) -> &(Next, u8) {
        &self.last_action
    }

    pub fn get_flags(&mut self) -> &mut HashMap<enums::PlayerFlag, u8> {
        &mut self.flags
    }

    pub fn get_switched(&mut self) -> bool {
        self.switched
    }

    // Setter methods
    //
    /// Sets the current value (e.g. after a pokemon swap)
    /// Given values should be between 1 and the maximum amount of pokemon you have
    pub fn set_current(&mut self, new: usize) {
        self.current = new;
    }
    /// Sets a next move to the Player
    pub fn set_next_move(&mut self, next: Option<Next>) {
        self.next_move = next;
    }
    pub fn add_flag(&mut self, flag: enums::PlayerFlag) {
        if !self.flags.contains_key(&flag) {
            self.flags.insert(flag, 0);
        } else {
            println!("It has no effect");
        }
    }
    /// Sets the last move the attacking pokemon made with the Slot in which it is saved
    pub fn set_last_move(&mut self, last: Option<moves::Technique>) {
        self.last_move = last;
    }

    /// Sets the last action
    pub fn set_last_action(&mut self, last: (Next, u8)) {
        self.last_action = last;
    }
    /// Sets the switched flag with a bool
    pub fn set_switched(&mut self, stat: bool) {
        self.switched = stat;
    }
    // Other
    //
    pub fn attack_or_swap(&self) -> arena::to_ui::Move {
        match self.player {
            PlayerType::Human => arena::to_ui::ui_move(),
            PlayerType::SimpleAi => arena::to_ui::ui_move(),
        }
    }
}
<commit_msg>edited get_alive_list in for player struct<commit_after>pub mod human;
pub mod ki;

use arena;
use db::pokemon_token::PokemonToken;
use db::pokedex::*;
use std::collections::HashMap;
use db::{moves, enums};

/// The Player type represents if the Player is a Human or a specific Ai to call different funcions
/// for e.g. choosing Pokemon
#[derive(Clone, Debug)]
pub enum PlayerType {
    Human,
    SimpleAi,
}

/// An enum which represents the AttackSlot to match with it
#[derive(Debug, Clone, Copy)]
pub enum AttackSlot {
    One,
    Two,
    Three,
    Four,
}
/// An enum representing the PokemonSlot
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PokemonSlot {
    One,
    Two,
    Three,
    Four,
    Five,
    Six,
}
impl PokemonSlot {
    pub fn get_int(&self) -> usize {
        match *self {
            PokemonSlot::One => 1,
            PokemonSlot::Two => 2,
            PokemonSlot::Three => 3,
            PokemonSlot::Four => 4,
            PokemonSlot::Five => 5,
            PokemonSlot::Six => 6,
        }
    }
}
#[derive(Clone, Debug, PartialEq)]
pub enum Next {
    Switch(PokemonSlot),
    Move(moves::Technique),
    Flinch,
    None,
}

/// The Player struct represents a Player and holds his Type (Human, Ai...), a list of his pokemon,
/// the amount of pokemon, his currently fighting pokemon and the next_move he wants to make
#[derive(Clone, Debug)]
pub struct Player {
    player: PlayerType,
    pokemon_list: Vec<PokemonToken>,
    pokemon_count: usize,
    current: usize,
    next_move: Option<Next>,
    flags: HashMap<enums::PlayerFlag, u8>,
    last_move: Option<moves::Technique>,
    last_action: (Next, u8),
    switched: bool,
}

impl Player {
    // Constructor
    //
    /// Takes an array with pokemon id´s and the PlayerType and returns a player
    pub fn new_by_id(input: &[usize], player_type: PlayerType) -> Self {
        let mut pokemon = Vec::new();
        let len = input.len();
        let dex = Pokedex::new();
        for i in 0..input.len() {
            pokemon.push(PokemonToken::from_model(dex.pokemon_by_id(input[i]).unwrap()));
        }
        Player {
            player: player_type,
            pokemon_list: pokemon,
            pokemon_count: len,
            current: 0,
            next_move: None,
            flags: HashMap::new(),
            last_move: None,
            last_action: (Next::None, 0),
            switched: false,
        }
    }

    // Getter methods
    //
    /// Returns the list of pokemon choosen by the player
    pub fn get_pokemon_list(&mut self) -> &mut Vec<PokemonToken> {
        &mut self.pokemon_list
    }
    /// Returns the currently fighting pokemon
    pub fn get_current(&self) -> usize {
        self.current
    }
    /// Gets the amount of pokemon choosen by the player
    pub fn get_pokemon_count(&self) -> usize {
        self.pokemon_count
    }
    /// Returns the amount of pokemon with atleast one hp
    pub fn get_alive_count(&mut self) -> usize {
        let mut alive = 0;
        for i in 0..self.pokemon_list.len() {
            if self.pokemon_list[i].get_current().get_stat(&enums::Stats::Hp) == 0 {
                alive += 1;
            }
        }
        alive
    }
    /// Returns a Vec with the id´s in the player model from the pokemon which are alive
    pub fn get_alive_list(&mut self) -> Vec<usize> {
        let mut vec = Vec::new();
        for i in 0..self.pokemon_list.len() {
            if self.pokemon_list[i].is_alive() {
                vec.push(i);
            }
        }
        vec
    }
    /// Gets a attack saved in an attackslot
    pub fn get_attack(&mut self, slot: &AttackSlot) -> moves::Technique {
        match slot {
            &AttackSlot::One => self.pokemon_list[self.current].clone().get_move_one().unwrap(),
            &AttackSlot::Two => self.pokemon_list[self.current].clone().get_move_two().unwrap(),
            &AttackSlot::Three => self.pokemon_list[self.current].clone().get_move_three().unwrap(),
            &AttackSlot::Four => self.pokemon_list[self.current].clone().get_move_four().unwrap(),
        }
    }
    /// Checks if an attack is in the Attackslots and returns the Slot
    pub fn get_attack_slot(&mut self, attack: moves::Technique) -> Option<AttackSlot> {
        if self.get_attack(&AttackSlot::One) == attack {
            return Some(AttackSlot::One);
        } else if self.get_attack(&AttackSlot::Two) == attack {
            return Some(AttackSlot::Two);
        } else if self.get_attack(&AttackSlot::Three) == attack {
            return Some(AttackSlot::Three);
        } else if self.get_attack(&AttackSlot::Four) == attack {
            return Some(AttackSlot::Four);
        }
        None
    }
    /// Gets the next attack from the Player. Returns none if no Technique is selected
    pub fn get_next_move(&self) -> Option<Next> {
        self.next_move.clone()
    }
    /// Gets the last move with the Slot. Returns None if the last move wasn´t an attack
    pub fn get_last_move(&self) -> Option<moves::Technique> {
        self.last_move.clone()
    }

    pub fn get_last_action(&self) -> &(Next, u8) {
        &self.last_action
    }

    pub fn get_flags(&mut self) -> &mut HashMap<enums::PlayerFlag, u8> {
        &mut self.flags
    }

    pub fn get_switched(&mut self) -> bool {
        self.switched
    }

    // Setter methods
    //
    /// Sets the current value (e.g. after a pokemon swap)
    /// Given values should be between 1 and the maximum amount of pokemon you have
    pub fn set_current(&mut self, new: usize) {
        self.current = new;
    }
    /// Sets a next move to the Player
    pub fn set_next_move(&mut self, next: Option<Next>) {
        self.next_move = next;
    }
    pub fn add_flag(&mut self, flag: enums::PlayerFlag) {
        if !self.flags.contains_key(&flag) {
            self.flags.insert(flag, 0);
        } else {
            println!("It has no effect");
        }
    }
    /// Sets the last move the attacking pokemon made with the Slot in which it is saved
    pub fn set_last_move(&mut self, last: Option<moves::Technique>) {
        self.last_move = last;
    }

    /// Sets the last action
    pub fn set_last_action(&mut self, last: (Next, u8)) {
        self.last_action = last;
    }
    /// Sets the switched flag with a bool
    pub fn set_switched(&mut self, stat: bool) {
        self.switched = stat;
    }
    // Other
    //
    pub fn attack_or_swap(&self) -> arena::to_ui::Move {
        match self.player {
            PlayerType::Human => arena::to_ui::ui_move(),
            PlayerType::SimpleAi => arena::to_ui::ui_move(),
        }
    }
}
<|endoftext|>


<commit_before>use super::SI;
use super::Kat;
use super::Medium;
use super::State;
use super::Season;

#[derive(Debug, Clone, Deserialize)]
pub struct EntryList {
	pub id: SI,
	pub name: String,
	pub genre: String,
	pub medium: Medium,
	pub count: i64,
	pub state: State,
	pub rate_sum: i64,
	pub rate_count: SI,
	pub language: String,
	pub year: SI,
	pub season: Season,
	#[serde(rename = "type")]
	pub type_: Option<String>,
}
<commit_msg>fix response types<commit_after>use super::SI;
use super::Kat;
use super::Medium;
use super::State;
use super::Season;

#[derive(Debug, Clone, Deserialize)]
pub struct EntryList {
	pub id: SI,
	pub name: String,
	pub genre: String,
	pub medium: Medium,
	pub count: SI,
	pub state: State,
	pub rate_sum: SI,
	pub rate_count: SI,
	pub language: String,
	pub year: SI,
	pub season: Season,
	#[serde(rename = "type")]
	pub type_: Option<String>,
}
<|endoftext|>


<commit_before>#[link(name = "rust-fuse",
uuid = "d37c5c30-fdcd-459d-bfca-ebb8da04b2a0",
url = "https://github.com/MicahChalmer/rust-fuse")];

#[comment = "FUSE bindings"];
#[license = "MIT"];
#[crate_type = "lib"];

use std::libc::{
    c_char,
    c_int,
    c_uint,
    c_ulong,
    c_void,
    mode_t,
    off_t,
    pid_t,
    size_t,
    stat,
    uid_t,
    gid_t
};

use std::ptr;
use std::str;
use std::vec;
use std::sys::size_of;

// A cfuncptr is used here to stand in for a C function pointer.
// For this struct, see fuse.h
type cfuncptr = *u8;
struct c_fuse_operations {
    getattr: cfuncptr,
    readlink: cfuncptr,
    getdir: cfuncptr,
    mknod: cfuncptr,
    mkdir: cfuncptr,
    unlink: cfuncptr,
    rmdir: cfuncptr,
    symlink: cfuncptr,
    rename: cfuncptr,
    link: cfuncptr,
    chmod: cfuncptr,
    chown: cfuncptr,
    truncate: cfuncptr,
    utime: cfuncptr,
    open: cfuncptr,
    read: cfuncptr,
    write: cfuncptr,
    statfs: cfuncptr,
    flush: cfuncptr,
    release: cfuncptr,
    fsync: cfuncptr,
    setxattr: cfuncptr,
    getxattr: cfuncptr,
    listxattr: cfuncptr,
    removexattr: cfuncptr,
    opendir: cfuncptr,
    readdir: cfuncptr,
    releasedir: cfuncptr,
    fsyncdir: cfuncptr,
    init: cfuncptr,
    destroy: cfuncptr,
    access: cfuncptr,
    create: cfuncptr,
    ftruncate: cfuncptr,
    fgetattr: cfuncptr,
    lock: cfuncptr,
    utimens: cfuncptr,
    bmap: cfuncptr,

    flag_nullpath_ok: uint,
    flag_nopath: uint,
    flag_utime_omit_ok: uint,
    flag_reserved: uint,

    ioctl: cfuncptr,
    poll: cfuncptr,
    write_buf: cfuncptr,
    read_buf: cfuncptr,
    flock: cfuncptr
}

// TODO: this should not be public
pub struct fuse_file_info {
    flags: c_int,
    fh_old: c_ulong, // Old file handle, don't use
    writepage: c_int,
    direct_io: c_uint,
    keep_cache: c_uint,
    flush: c_uint,
    nonseekable: c_uint,
    flock_release: c_uint,
    padding: c_uint, // Padding.  Do not use
    fh: u64,
    lock_owner: u64
}

struct c_fuse_context {
    fuse: *c_void,
    uid: uid_t,
    gid: gid_t,
    pid: pid_t,
    private_data: *rust_fuse_data,  // we use this to know what object to call
    umask: mode_t
}

struct rust_fuse_data {
    ops: ~FuseOperations
}

extern {
    fn fuse_main_real(argc:c_int, argv:**c_char,
                      op:*c_fuse_operations, op_size: size_t,
                      user_data: *c_void) -> c_int;

    fn fuse_get_context() -> *c_fuse_context;

    // Workaround for the fact that we can't call into c via a function ptr right
    // from rust
    fn call_filler_function(filler: cfuncptr, buf: *c_void, name: *c_char, stbuf: *stat,
                           off: off_t) -> c_int;
}

// Used for return values from FS operations
pub type errno = c_int;

pub type fuse_fill_dir_func<'self> = &'self fn (&str, Option<stat>, off_t) -> c_int;

pub type filehandle = u64;

pub struct dir_entry {
    name: ~str,
    stat: Option<stat>,
    off: off_t
}

#[deriving(Clone, Eq, ToStr)]
pub enum ErrorOrResult<E, T> {
    Error(E),
    Result(T)
}

pub trait FuseOperations {
    fn getattr(&self, path:&str) -> ErrorOrResult<errno, stat>;
    fn readdir(&self, path:&str, filler: fuse_fill_dir_func,
               offset: off_t, info: &fuse_file_info) -> ErrorOrResult<errno, ()>;
    fn open(&self, path:&str, info: &fuse_file_info) -> ErrorOrResult<errno, filehandle>;
    fn read(&self, path:&str, buf:&mut [u8], size: size_t, offset: off_t,
            info: &fuse_file_info) -> ErrorOrResult<errno, c_int>;
}

unsafe fn get_context_ops() -> &~FuseOperations {
    &((*(*fuse_get_context()).private_data).ops)
}

extern fn c_getattr(path: *c_char, stbuf: *mut stat) -> errno {
    unsafe {
        let ops = get_context_ops();
        ptr::zero_memory(stbuf, 1);
        match ops.getattr(str::raw::from_c_str(path)) {
            Error(e) => -e,
            Result(st) => { ptr::copy_memory(stbuf, &st, 1); 0 }
        }
    }
}

unsafe fn option_to_ptr<T>(opt: Option<T>) -> *T {
    match opt {
        Some(ref t) => ptr::to_unsafe_ptr(t),
        None => ptr::null()
    }
}

extern fn c_readdir(path: *c_char, buf: *c_void, filler: cfuncptr,
                    offset: off_t, fi: *fuse_file_info) -> c_int {
    unsafe {
        let ops = get_context_ops();
        let fill_func: fuse_fill_dir_func = |name, st, ofs| -> c_int {
            do name.as_c_str |c_name| {
                call_filler_function(filler, buf, c_name, option_to_ptr(st), ofs)
            }
        };
        match ops.readdir(str::raw::from_c_str(path), fill_func, offset, &*fi) {
            Error(e) => -e,
            Result(_) => 0
        }
    }
}

extern fn c_open(path: *c_char, info: *mut fuse_file_info) -> c_int {
    unsafe {
        let ops = get_context_ops();
        match ops.open(str::raw::from_c_str(path), &*info) {
            Error(e) => -e,
            Result(fh) => { (*info).fh = fh; 0 }
        }
    }
}

extern fn c_read(path: *c_char, buf: *mut u8, size: size_t, offset: off_t,
                 fi: *fuse_file_info) -> c_int {
    unsafe {
        let ops = get_context_ops();
        do vec::raw::mut_buf_as_slice(buf, size as uint) |slice| {
            match ops.read(str::raw::from_c_str(path), slice, size, offset, &*fi) {
                Error(e) => -e,
                Result(sz) => sz
            }
        }
    }
}

pub fn fuse_main<T: FuseOperations>(args: ~[~str], ops: ~T) -> c_int {
    let cfo = c_fuse_operations {
        getattr: c_getattr,
        readdir: c_readdir,
        open: c_open,
        read: c_read,

        readlink: ptr::null(),
        getdir: ptr::null(),
        mknod: ptr::null(),
        mkdir: ptr::null(),
        unlink: ptr::null(),
        rmdir: ptr::null(),
        symlink: ptr::null(),
        rename: ptr::null(),
        link: ptr::null(),
        chmod: ptr::null(),
        chown: ptr::null(),
        truncate: ptr::null(),
        utime: ptr::null(),
        write: ptr::null(),
        statfs: ptr::null(),
        flush: ptr::null(),
        release: ptr::null(),
        fsync: ptr::null(),
        setxattr: ptr::null(),
        getxattr: ptr::null(),
        listxattr: ptr::null(),
        removexattr: ptr::null(),
        opendir: ptr::null(),
        releasedir: ptr::null(),
        fsyncdir: ptr::null(),
        init: ptr::null(),
        destroy: ptr::null(),
        access: ptr::null(),
        create: ptr::null(),
        ftruncate: ptr::null(),
        fgetattr: ptr::null(),
        lock: ptr::null(),
        utimens: ptr::null(),
        bmap: ptr::null(),

        flag_nullpath_ok: 0,
        flag_nopath: 0,
        flag_utime_omit_ok: 0,
        flag_reserved: 29,

        ioctl: ptr::null(),
        poll: ptr::null(),
        write_buf: ptr::null(),
        read_buf: ptr::null(),
        flock: ptr::null()
    };
    unsafe {
        let arg_c_strs = vec::raw::to_ptr(args.map(|s| vec::raw::to_ptr(s.as_bytes_with_null())));
        fuse_main_real(args.len() as c_int, std::cast::transmute(arg_c_strs),
                       &cfo, size_of::<c_fuse_operations>() as size_t,
                       std::cast::transmute(&ops))
    }
}
<commit_msg>Change module name again<commit_after>#[link(name = "rust_fuse",
uuid = "d37c5c30-fdcd-459d-bfca-ebb8da04b2a0",
url = "https://github.com/MicahChalmer/rust-fuse")];

#[comment = "FUSE bindings"];
#[license = "MIT"];
#[crate_type = "lib"];

use std::libc::{
    c_char,
    c_int,
    c_uint,
    c_ulong,
    c_void,
    mode_t,
    off_t,
    pid_t,
    size_t,
    stat,
    uid_t,
    gid_t
};

use std::ptr;
use std::str;
use std::vec;
use std::sys::size_of;

// A cfuncptr is used here to stand in for a C function pointer.
// For this struct, see fuse.h
type cfuncptr = *u8;
struct c_fuse_operations {
    getattr: cfuncptr,
    readlink: cfuncptr,
    getdir: cfuncptr,
    mknod: cfuncptr,
    mkdir: cfuncptr,
    unlink: cfuncptr,
    rmdir: cfuncptr,
    symlink: cfuncptr,
    rename: cfuncptr,
    link: cfuncptr,
    chmod: cfuncptr,
    chown: cfuncptr,
    truncate: cfuncptr,
    utime: cfuncptr,
    open: cfuncptr,
    read: cfuncptr,
    write: cfuncptr,
    statfs: cfuncptr,
    flush: cfuncptr,
    release: cfuncptr,
    fsync: cfuncptr,
    setxattr: cfuncptr,
    getxattr: cfuncptr,
    listxattr: cfuncptr,
    removexattr: cfuncptr,
    opendir: cfuncptr,
    readdir: cfuncptr,
    releasedir: cfuncptr,
    fsyncdir: cfuncptr,
    init: cfuncptr,
    destroy: cfuncptr,
    access: cfuncptr,
    create: cfuncptr,
    ftruncate: cfuncptr,
    fgetattr: cfuncptr,
    lock: cfuncptr,
    utimens: cfuncptr,
    bmap: cfuncptr,

    flag_nullpath_ok: uint,
    flag_nopath: uint,
    flag_utime_omit_ok: uint,
    flag_reserved: uint,

    ioctl: cfuncptr,
    poll: cfuncptr,
    write_buf: cfuncptr,
    read_buf: cfuncptr,
    flock: cfuncptr
}

// TODO: this should not be public
pub struct fuse_file_info {
    flags: c_int,
    fh_old: c_ulong, // Old file handle, don't use
    writepage: c_int,
    direct_io: c_uint,
    keep_cache: c_uint,
    flush: c_uint,
    nonseekable: c_uint,
    flock_release: c_uint,
    padding: c_uint, // Padding.  Do not use
    fh: u64,
    lock_owner: u64
}

struct c_fuse_context {
    fuse: *c_void,
    uid: uid_t,
    gid: gid_t,
    pid: pid_t,
    private_data: *rust_fuse_data,  // we use this to know what object to call
    umask: mode_t
}

struct rust_fuse_data {
    ops: ~FuseOperations
}

extern {
    fn fuse_main_real(argc:c_int, argv:**c_char,
                      op:*c_fuse_operations, op_size: size_t,
                      user_data: *c_void) -> c_int;

    fn fuse_get_context() -> *c_fuse_context;

    // Workaround for the fact that we can't call into c via a function ptr right
    // from rust
    fn call_filler_function(filler: cfuncptr, buf: *c_void, name: *c_char, stbuf: *stat,
                           off: off_t) -> c_int;
}

// Used for return values from FS operations
pub type errno = c_int;

pub type fuse_fill_dir_func<'self> = &'self fn (&str, Option<stat>, off_t) -> c_int;

pub type filehandle = u64;

pub struct dir_entry {
    name: ~str,
    stat: Option<stat>,
    off: off_t
}

#[deriving(Clone, Eq, ToStr)]
pub enum ErrorOrResult<E, T> {
    Error(E),
    Result(T)
}

pub trait FuseOperations {
    fn getattr(&self, path:&str) -> ErrorOrResult<errno, stat>;
    fn readdir(&self, path:&str, filler: fuse_fill_dir_func,
               offset: off_t, info: &fuse_file_info) -> ErrorOrResult<errno, ()>;
    fn open(&self, path:&str, info: &fuse_file_info) -> ErrorOrResult<errno, filehandle>;
    fn read(&self, path:&str, buf:&mut [u8], size: size_t, offset: off_t,
            info: &fuse_file_info) -> ErrorOrResult<errno, c_int>;
}

unsafe fn get_context_ops() -> &~FuseOperations {
    &((*(*fuse_get_context()).private_data).ops)
}

extern fn c_getattr(path: *c_char, stbuf: *mut stat) -> errno {
    unsafe {
        let ops = get_context_ops();
        ptr::zero_memory(stbuf, 1);
        match ops.getattr(str::raw::from_c_str(path)) {
            Error(e) => -e,
            Result(st) => { ptr::copy_memory(stbuf, &st, 1); 0 }
        }
    }
}

unsafe fn option_to_ptr<T>(opt: Option<T>) -> *T {
    match opt {
        Some(ref t) => ptr::to_unsafe_ptr(t),
        None => ptr::null()
    }
}

extern fn c_readdir(path: *c_char, buf: *c_void, filler: cfuncptr,
                    offset: off_t, fi: *fuse_file_info) -> c_int {
    unsafe {
        let ops = get_context_ops();
        let fill_func: fuse_fill_dir_func = |name, st, ofs| -> c_int {
            do name.as_c_str |c_name| {
                call_filler_function(filler, buf, c_name, option_to_ptr(st), ofs)
            }
        };
        match ops.readdir(str::raw::from_c_str(path), fill_func, offset, &*fi) {
            Error(e) => -e,
            Result(_) => 0
        }
    }
}

extern fn c_open(path: *c_char, info: *mut fuse_file_info) -> c_int {
    unsafe {
        let ops = get_context_ops();
        match ops.open(str::raw::from_c_str(path), &*info) {
            Error(e) => -e,
            Result(fh) => { (*info).fh = fh; 0 }
        }
    }
}

extern fn c_read(path: *c_char, buf: *mut u8, size: size_t, offset: off_t,
                 fi: *fuse_file_info) -> c_int {
    unsafe {
        let ops = get_context_ops();
        do vec::raw::mut_buf_as_slice(buf, size as uint) |slice| {
            match ops.read(str::raw::from_c_str(path), slice, size, offset, &*fi) {
                Error(e) => -e,
                Result(sz) => sz
            }
        }
    }
}

pub fn fuse_main<T: FuseOperations>(args: ~[~str], ops: ~T) -> c_int {
    let cfo = c_fuse_operations {
        getattr: c_getattr,
        readdir: c_readdir,
        open: c_open,
        read: c_read,

        readlink: ptr::null(),
        getdir: ptr::null(),
        mknod: ptr::null(),
        mkdir: ptr::null(),
        unlink: ptr::null(),
        rmdir: ptr::null(),
        symlink: ptr::null(),
        rename: ptr::null(),
        link: ptr::null(),
        chmod: ptr::null(),
        chown: ptr::null(),
        truncate: ptr::null(),
        utime: ptr::null(),
        write: ptr::null(),
        statfs: ptr::null(),
        flush: ptr::null(),
        release: ptr::null(),
        fsync: ptr::null(),
        setxattr: ptr::null(),
        getxattr: ptr::null(),
        listxattr: ptr::null(),
        removexattr: ptr::null(),
        opendir: ptr::null(),
        releasedir: ptr::null(),
        fsyncdir: ptr::null(),
        init: ptr::null(),
        destroy: ptr::null(),
        access: ptr::null(),
        create: ptr::null(),
        ftruncate: ptr::null(),
        fgetattr: ptr::null(),
        lock: ptr::null(),
        utimens: ptr::null(),
        bmap: ptr::null(),

        flag_nullpath_ok: 0,
        flag_nopath: 0,
        flag_utime_omit_ok: 0,
        flag_reserved: 29,

        ioctl: ptr::null(),
        poll: ptr::null(),
        write_buf: ptr::null(),
        read_buf: ptr::null(),
        flock: ptr::null()
    };
    unsafe {
        let arg_c_strs = vec::raw::to_ptr(args.map(|s| vec::raw::to_ptr(s.as_bytes_with_null())));
        fuse_main_real(args.len() as c_int, std::cast::transmute(arg_c_strs),
                       &cfo, size_of::<c_fuse_operations>() as size_t,
                       std::cast::transmute(&ops))
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 Jeffery Olson
//
// Licensed under the 3-Clause BSD License, see LICENSE.txt
// at the top-level of this repository.
// This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="http://olsonjeffery.github.io#schemers:0.0.1"]
#![desc = "Simple Scheme Interpreter"]
#![license = "3-Clause BSD"]

use std::from_str::FromStr;

// this is starting out as a straight port of Peter Norvig's
// lis.py (the first iteration) to Rust

#[cfg(not(test))]
fn main() {
    use std::os::args;
    let args: Vec<~str> = args().move_iter().skip(1).collect();
    if args.len() == 0 {
        fail!("no program provided");
    }
    let program: ~str = args.move_iter()
        .fold(~"", |memo, arg| memo + arg + " ").trim().to_owned();
    let parsed_items = parse_str(program);
    println!("{}", parsed_items.print());
}

// parser impl
fn parse_str(input: ~str) -> Expr {
    parse(&mut tokenize(input))
}

fn pad_input(input: ~str) -> ~str {
    input.replace("(", " ( ").replace(")", " ) ")
}

fn tokenize(input: ~str) -> Vec<~str> {
    pad_input(input).split_str(" ")
        .filter(|i| *i != "").map(|i| i.to_owned()).collect()
}

#[deriving(Eq, Show, Clone)]
pub enum Expr {
    Atom(AtomType),
    List(Vec<~Expr>)
}
impl Expr {
    pub fn new_atom(input: ~str) -> Expr {
        let first_char = input.char_at(0);
        match first_char {
            '0' | '1' | '2' | '3' | '4' | '5' |
            '6' | '7' | '8' | '9' => {
                match input.contains(".") {
                    true => {
                        match FromStr::from_str(input) {
                            Some(val) => Atom(Float(val)),
                            None => fail!("Cannot parse number-like input of: {}", input)
                        }
                    },
                    false => {
                        match FromStr::from_str(input) {
                            Some(val) => Atom(Integer(val)),
                            None => fail!("Cannot parse number-like input of: {}", input)
                        }
                    }
                }
            },
            _ => Atom(Symbol(input))
        }
    }

    pub fn is_atom(&self) -> bool {
        match *self {
            Atom(_) => true,
            _ => false
        }
    }

    pub fn print(&self) -> ~str {
        match self {
            &List(ref items) => {
                let out = items.iter().map(|i| i.print())
                    .fold(~"(", |m, v| m + v + " ");
                out.trim() + ")"
            },
            &Atom(ref v) => v.print()
        }
    }
    pub fn un_cons(self) -> (Expr, Option<Expr>) {
        match self {
            Atom(v) => (Atom(v), None),
            List(mut items) => {
                if items.len() == 0 {
                    fail!("cannot build car/cdr of empty list");
                }
                let car = items.shift()
                    .expect("at least one item in the least; shouldn't happen");
                (*car, Some(List(items)))
            }
        }
    }
}

#[deriving(Eq, Show, Clone)]
pub enum AtomType {
    Symbol(~str),
    Integer(i64),
    Float(f64)
}

impl AtomType {
    pub fn print(&self) -> ~str {
        match self {
            &Symbol(ref v) => v.to_owned(),
            &Integer(ref v) => v.to_str(),
            &Float(ref v) => v.to_str()
        }
    }
}

fn parse(tokens: &mut Vec<~str>) -> Expr {
    let current_token =
        tokens.shift().expect("calling parse() w/ empty token list; shouldn't happen");
    match current_token {
        ref x if *x == ~"(" => {
            let mut list = Vec::new();
            while *tokens.get(0) != ~")" {
                list.push(box parse(tokens));
            }
            tokens.shift();
            List(list)
        },
        ref x if *x == ~")" => fail!("hit ) token; shouldn't happen"),
        x => Expr::new_atom(x)
    }
}

#[cfg(test)]
mod parser_test {
    use super::{pad_input, tokenize, parse, Atom, List, Symbol, Integer, Float};

    #[test]
    fn pad_input_should_insert_spaces_before_and_after_parens() {
        assert_eq!(pad_input(~"(x 1 2 3)"), ~" ( x 1 2 3 ) ");
    }

    #[test]
    fn tokenize_string_into_tokens() {
        let tokens = tokenize(~"(foo 12 3)");
        assert_eq!(tokens.len(), 5);
        assert_eq!(tokens.get(0).to_owned(), ~"(");
        assert_eq!(tokens.get(1).to_owned(), ~"foo");
        assert_eq!(tokens.get(2).to_owned(), ~"12");
        assert_eq!(tokens.get(3).to_owned(), ~"3");
        assert_eq!(tokens.get(4).to_owned(), ~")");
    }

    #[test]
    fn should_parse_tokens_consisting_of_a_str_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"bar");
        let parsed_item = parse(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Symbol(val)) => {
                assert_eq!(val, ~"bar")
            },
            _ => assert!(false)
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_an_int_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"42");
        let parsed_item = parse(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Integer(val)) => {
                assert_eq!(val, 42)
            },
            _ => assert!(false)
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_a_float_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"1.1");
        let parsed_item = parse(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Float(val)) => {
                assert_eq!(val, 1.1)
            },
            _ => assert!(false)
        }
    }

    #[test]
    fn should_parse_tokens_consisting_of_a_list_of_atoms_and_parse_it() {
        let tokens = &mut tokenize(~"(bar 12 45)");
        let parsed_item = parse(tokens);
        assert_eq!(parsed_item.is_atom(), false);
        match parsed_item {
            List(items) => {
                let items_len = items.len();
                assert!(3 == items_len);
                assert_eq!(items.get(0).is_atom(), true);
                assert_eq!(*items.get(0), ~Atom(Symbol(~"bar")));
                assert_eq!(items.get(1).is_atom(), true);
                assert_eq!(*items.get(1), ~Atom(Integer(12)));
                assert_eq!(items.get(2).is_atom(), true);
                assert_eq!(*items.get(2), ~Atom(Integer(45)));
            },
            _ => fail!("got back an atom, it seems")
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_a_list_of_atoms_and_a_nested_list() {
        let tokens = &mut tokenize(~"((2 3) bar 12 (hee (hah)))");
        let parsed_item = parse(tokens);
        assert_eq!(parsed_item.is_atom(), false);
        match parsed_item {
            List(items) => {
                let items_len = items.len();
                assert!(4 == items_len);
                match *items.get(0) {
                    ~List(ref items) => {
                        assert_eq!(items.len(), 2);
                        assert_eq!(*items.get(0), ~Atom(Integer(2)));
                        assert_eq!(*items.get(1), ~Atom(Integer(3)));
                    },
                    _ => fail!("shoulda got a list")
                }
                assert_eq!(*items.get(1), ~Atom(Symbol(~"bar")));
                assert_eq!(*items.get(2), ~Atom(Integer(12)));
                match *items.get(3) {
                    ~List(ref items) => {
                        assert_eq!(items.len(), 2);
                        assert_eq!(*items.get(0), ~Atom(Symbol(~"hee")));
                        match *items.get(1) {
                            ~List(ref items) => {
                                assert_eq!(items.len(), 1);
                                assert_eq!(*items.get(0), ~Atom(Symbol(~"hah")));
                            },
                            _ => fail!("shoulda got a list")
                        }
                    },
                    _ => fail!("shoulda got a list")
                }
            },
            _ => fail!("got back an atom, it seems")
        }
    }
    #[test]
    fn parsed_tokens_of_a_list_of_atoms_and_a_nested_list_should_to_str_correctly() {
        let input = ~"((2 3) bar 12 (hee (hah)))";
        let tokens = &mut tokenize(input.to_owned());
        let parsed_item = parse(tokens);
        let output = parsed_item.print();
        assert_eq!(input, output);
    }
}

#[cfg(test)]
mod eval_test {
    mod un_cons {
        use super::super::{parse_str, Atom, List, Symbol};
        #[test]
        fn an_atom_expr_returns_the_atom_in_the_car_with_none_in_the_cdr() {
            let expr = parse_str(~"x");
            let (car, cdr) = expr.un_cons();
            assert_eq!(car, Atom(Symbol(~"x")));
            assert_eq!(cdr, None);
        }

        #[test]
        fn a_list_with_one_atom_element_returns_an_atom_car_and_an_empty_list_in_the_cdr() {
            let expr = parse_str(~"(x)");
            let (car, cdr) = expr.un_cons();
            assert_eq!(car, Atom(Symbol(~"x")));
            match cdr.expect("should be a value here") {
                List(items) => assert_eq!(items.len(), 0),
                _ => fail!("expected a list")
            }
        }

        #[test]
        fn a_list_with_multiple_elements_returns_the_first_car_and_the_rust_in_the_cdr() {
            let expr = parse_str(~"(y 2 3)");
            let (car, cdr) = expr.un_cons();
            assert_eq!(car, Atom(Symbol(~"y")));
            match cdr.expect("should be a value here") {
                List(items) => {
                    assert_eq!(items.len(), 2)
                },
                _ => fail!("expected a list")
            }
        }

        #[test]
        #[should_fail]
        fn calling_extract_on_an_empty_list_should_fail() {
            let expr = parse_str(~"()");
            expr.un_cons();
        }
    }
}
<commit_msg>rename AtomType->AtomVal and start flushing out Env<commit_after>// Copyright 2013-2014 Jeffery Olson
//
// Licensed under the 3-Clause BSD License, see LICENSE.txt
// at the top-level of this repository.
// This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="http://olsonjeffery.github.io#schemers:0.0.1"]
#![desc = "Simple Scheme Interpreter"]
#![license = "3-Clause BSD"]

extern crate collections = "collections";

use std::from_str::FromStr;
use collections::hashmap::HashMap;

// this is starting out as a straight port of Peter Norvig's
// lis.py (the first iteration) to Rust

#[cfg(not(test))]
fn main() {
    use std::os::args;
    let args: Vec<~str> = args().move_iter().skip(1).collect();
    if args.len() == 0 {
        fail!("no program provided");
    }
    let program: ~str = args.move_iter()
        .fold(~"", |memo, arg| memo + arg + " ").trim().to_owned();
    let parsed_items = parse_str(program);
    println!("{}", parsed_items.print());
}

pub struct Env {
    entries: HashMap<~str, Expr>,
    outer: Option<~Env>
}

#[deriving(Eq, Show, Clone)]
pub enum Expr {
    Atom(AtomVal),
    List(Vec<~Expr>)
}

#[deriving(Eq, Show, Clone)]
pub enum AtomVal {
    Symbol(~str),
    Integer(i64),
    Float(f64)
}

fn parse_str(input: ~str) -> Expr {
    parse(&mut tokenize(input))
}

fn pad_input(input: ~str) -> ~str {
    input.replace("(", " ( ").replace(")", " ) ")
}

fn tokenize(input: ~str) -> Vec<~str> {
    pad_input(input).split_str(" ")
        .filter(|i| *i != "").map(|i| i.to_owned()).collect()
}

fn parse(tokens: &mut Vec<~str>) -> Expr {
    let current_token =
        tokens.shift().expect("calling parse() w/ empty token list; shouldn't happen");
    match current_token {
        ref x if *x == ~"(" => {
            let mut list = Vec::new();
            while *tokens.get(0) != ~")" {
                list.push(box parse(tokens));
            }
            tokens.shift();
            List(list)
        },
        ref x if *x == ~")" => fail!("hit ) token; shouldn't happen"),
        x => Expr::new_atom(x)
    }
}

impl Env {
    pub fn new(params: Option<Vec<~str>>, args: Option<Vec<Expr>>, outer: Option<~Env>) -> Env {
        let mut entries = HashMap::new();
        if params.is_some() && args.is_some() {
            let params = params.expect("params should be a value");
            let args = args.expect("args should be a value");
            if params.len() == args.len() {
                for ctr in range(0,params.len()) {
                    entries.insert(params.get(ctr).to_owned(),
                                   args.get(ctr).clone());
                }
            } else {
                fail!("params and args length doesn't match")
            }
        }
        else if params.is_none() && args.is_none() {
            // do nothing!
        } else {
            fail!("cannot have params & args unset")
        }
        Env { entries: entries, outer: outer }
    }
}

impl Expr {
    pub fn new_atom(input: ~str) -> Expr {
        let first_char = input.char_at(0);
        match first_char {
            '0' | '1' | '2' | '3' | '4' | '5' |
            '6' | '7' | '8' | '9' => {
                match input.contains(".") {
                    true => {
                        match FromStr::from_str(input) {
                            Some(val) => Atom(Float(val)),
                            None => fail!("Cannot parse number-like input of: {}", input)
                        }
                    },
                    false => {
                        match FromStr::from_str(input) {
                            Some(val) => Atom(Integer(val)),
                            None => fail!("Cannot parse number-like input of: {}", input)
                        }
                    }
                }
            },
            _ => Atom(Symbol(input))
        }
    }

    pub fn is_atom(&self) -> bool {
        match *self {
            Atom(_) => true,
            _ => false
        }
    }

    pub fn print(&self) -> ~str {
        match self {
            &List(ref items) => {
                let out = items.iter().map(|i| i.print())
                    .fold(~"(", |m, v| m + v + " ");
                out.trim() + ")"
            },
            &Atom(ref v) => v.print()
        }
    }
    pub fn un_cons(self) -> (Expr, Option<Expr>) {
        match self {
            Atom(v) => (Atom(v), None),
            List(mut items) => {
                if items.len() == 0 {
                    fail!("cannot build car/cdr of empty list");
                }
                let car = items.shift()
                    .expect("at least one item in the least; shouldn't happen");
                (*car, Some(List(items)))
            }
        }
    }
}

impl AtomVal {
    pub fn print(&self) -> ~str {
        match self {
            &Symbol(ref v) => v.to_owned(),
            &Integer(ref v) => v.to_str(),
            &Float(ref v) => v.to_str()
        }
    }
}

#[cfg(test)]
mod parser_test {
    use super::{pad_input, tokenize, parse, Atom, List, Symbol, Integer, Float};

    #[test]
    fn pad_input_should_insert_spaces_before_and_after_parens() {
        assert_eq!(pad_input(~"(x 1 2 3)"), ~" ( x 1 2 3 ) ");
    }

    #[test]
    fn tokenize_string_into_tokens() {
        let tokens = tokenize(~"(foo 12 3)");
        assert_eq!(tokens.len(), 5);
        assert_eq!(tokens.get(0).to_owned(), ~"(");
        assert_eq!(tokens.get(1).to_owned(), ~"foo");
        assert_eq!(tokens.get(2).to_owned(), ~"12");
        assert_eq!(tokens.get(3).to_owned(), ~"3");
        assert_eq!(tokens.get(4).to_owned(), ~")");
    }

    #[test]
    fn should_parse_tokens_consisting_of_a_str_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"bar");
        let parsed_item = parse(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Symbol(val)) => {
                assert_eq!(val, ~"bar")
            },
            _ => assert!(false)
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_an_int_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"42");
        let parsed_item = parse(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Integer(val)) => {
                assert_eq!(val, 42)
            },
            _ => assert!(false)
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_a_float_atom_and_convert_it_to_a_parse_item() {
        let tokens = &mut tokenize(~"1.1");
        let parsed_item = parse(tokens);
        println!("{:?}", parsed_item);
        match parsed_item {
            Atom(Float(val)) => {
                assert_eq!(val, 1.1)
            },
            _ => assert!(false)
        }
    }

    #[test]
    fn should_parse_tokens_consisting_of_a_list_of_atoms_and_parse_it() {
        let tokens = &mut tokenize(~"(bar 12 45)");
        let parsed_item = parse(tokens);
        assert_eq!(parsed_item.is_atom(), false);
        match parsed_item {
            List(items) => {
                let items_len = items.len();
                assert!(3 == items_len);
                assert_eq!(items.get(0).is_atom(), true);
                assert_eq!(*items.get(0), ~Atom(Symbol(~"bar")));
                assert_eq!(items.get(1).is_atom(), true);
                assert_eq!(*items.get(1), ~Atom(Integer(12)));
                assert_eq!(items.get(2).is_atom(), true);
                assert_eq!(*items.get(2), ~Atom(Integer(45)));
            },
            _ => fail!("got back an atom, it seems")
        }
    }
    #[test]
    fn should_parse_tokens_consisting_of_a_list_of_atoms_and_a_nested_list() {
        let tokens = &mut tokenize(~"((2 3) bar 12 (hee (hah)))");
        let parsed_item = parse(tokens);
        assert_eq!(parsed_item.is_atom(), false);
        match parsed_item {
            List(items) => {
                let items_len = items.len();
                assert!(4 == items_len);
                match *items.get(0) {
                    ~List(ref items) => {
                        assert_eq!(items.len(), 2);
                        assert_eq!(*items.get(0), ~Atom(Integer(2)));
                        assert_eq!(*items.get(1), ~Atom(Integer(3)));
                    },
                    _ => fail!("shoulda got a list")
                }
                assert_eq!(*items.get(1), ~Atom(Symbol(~"bar")));
                assert_eq!(*items.get(2), ~Atom(Integer(12)));
                match *items.get(3) {
                    ~List(ref items) => {
                        assert_eq!(items.len(), 2);
                        assert_eq!(*items.get(0), ~Atom(Symbol(~"hee")));
                        match *items.get(1) {
                            ~List(ref items) => {
                                assert_eq!(items.len(), 1);
                                assert_eq!(*items.get(0), ~Atom(Symbol(~"hah")));
                            },
                            _ => fail!("shoulda got a list")
                        }
                    },
                    _ => fail!("shoulda got a list")
                }
            },
            _ => fail!("got back an atom, it seems")
        }
    }
    #[test]
    fn parsed_tokens_of_a_list_of_atoms_and_a_nested_list_should_to_str_correctly() {
        let input = ~"((2 3) bar 12 (hee (hah)))";
        let tokens = &mut tokenize(input.to_owned());
        let parsed_item = parse(tokens);
        let output = parsed_item.print();
        assert_eq!(input, output);
    }
}

#[cfg(test)]
mod eval_test {
    mod un_cons {
        use super::super::{parse_str, Atom, List, Symbol};
        #[test]
        fn an_atom_expr_returns_the_atom_in_the_car_with_none_in_the_cdr() {
            let expr = parse_str(~"x");
            let (car, cdr) = expr.un_cons();
            assert_eq!(car, Atom(Symbol(~"x")));
            assert_eq!(cdr, None);
        }

        #[test]
        fn a_list_with_one_atom_element_returns_an_atom_car_and_an_empty_list_in_the_cdr() {
            let expr = parse_str(~"(x)");
            let (car, cdr) = expr.un_cons();
            assert_eq!(car, Atom(Symbol(~"x")));
            match cdr.expect("should be a value here") {
                List(items) => assert_eq!(items.len(), 0),
                _ => fail!("expected a list")
            }
        }

        #[test]
        fn a_list_with_multiple_elements_returns_the_first_car_and_the_rust_in_the_cdr() {
            let expr = parse_str(~"(y 2 3)");
            let (car, cdr) = expr.un_cons();
            assert_eq!(car, Atom(Symbol(~"y")));
            match cdr.expect("should be a value here") {
                List(items) => {
                    assert_eq!(items.len(), 2)
                },
                _ => fail!("expected a list")
            }
        }

        #[test]
        #[should_fail]
        fn calling_extract_on_an_empty_list_should_fail() {
            let expr = parse_str(~"()");
            expr.un_cons();
        }
    }

    mod env_tests {
        use super::super::{Env};

        #[test]
        fn a_new_env_with_no_parent_params_or_vars_should_be_set_up_empty() {
            let _env = Env::new(None, None, None);
        }
    }
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

pub type StateId = u32;

///
/// Trait implemented by objects that represent a state machine, whose transitions depend on a particular symbol type
///
/// These state machines can be nondeterministic - which is to say, have more than one transition per state. They always
/// start in state 0.
///
pub trait StateMachine<InputSymbol, OutputSymbol> {
    ///
    /// Returns the number of states in this state machine
    ///
    fn count_states(&self) -> StateId;

    ///
    /// Returns the transitions for a particular symbol
    ///
    fn get_transitions_for_state(&self, state: StateId) -> [(InputSymbol, StateId)];

    ///
    /// If a state is an accepting state, then this returns the output symbol that should be produced if this is the longest match
    ///
    fn output_symbol_for_state(&self, state: StateId) -> Option<OutputSymbol>;
}

///
/// Trait used to indicate that a particular state machine is deterministic (has at most one
/// transition per symbol from the original)
///
pub trait DeterministicStateMachine<InputSymbol, OutputSymbol> : StateMachine<InputSymbol, OutputSymbol> { }
<commit_msg>Add convenience methods so we can treat Rc<StateMachine> as a StateMachine<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

use std::rc::*;

///
/// Identifies a state in a state machine
///
pub type StateId = u32;

///
/// Trait implemented by objects that represent a state machine, whose transitions depend on a particular symbol type
///
/// These state machines can be nondeterministic - which is to say, have more than one transition per state. They always
/// start in state 0.
///
pub trait StateMachine<InputSymbol, OutputSymbol> {
    ///
    /// Returns the number of states in this state machine
    ///
    fn count_states(&self) -> StateId;

    ///
    /// Returns the transitions for a particular symbol
    ///
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)>;

    ///
    /// If a state is an accepting state, then this returns the output symbol that should be produced if this is the longest match
    ///
    fn output_symbol_for_state(&self, state: StateId) -> Option<OutputSymbol>;
}

///
/// Trait used to indicate that a particular state machine is deterministic (has at most one
/// transition per symbol from the original)
///
pub trait DeterministicStateMachine<InputSymbol, OutputSymbol> : StateMachine<InputSymbol, OutputSymbol> { }

///
/// Any reference to a state machine is also a state machine
///
impl<InputSymbol, OutputSymbol> StateMachine<InputSymbol, OutputSymbol> for Rc<StateMachine<InputSymbol, OutputSymbol>> {
    #[inline]
    fn count_states(&self) -> StateId {
        (**self).count_states()
    }

    #[inline]
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)> {
        (**self).get_transitions_for_state(state)
    }

    #[inline]
    fn output_symbol_for_state(&self, state: StateId) -> Option<OutputSymbol> {
        (**self).output_symbol_for_state(state)
    }
}

impl<InputSymbol, OutputSymbol> StateMachine<InputSymbol, OutputSymbol> for Rc<DeterministicStateMachine<InputSymbol, OutputSymbol>> {
    #[inline]
    fn count_states(&self) -> StateId {
        (**self).count_states()
    }

    #[inline]
    fn get_transitions_for_state(&self, state: StateId) -> Vec<(InputSymbol, StateId)> {
        (**self).get_transitions_for_state(state)
    }

    #[inline]
    fn output_symbol_for_state(&self, state: StateId) -> Option<OutputSymbol> {
        (**self).output_symbol_for_state(state)
    }
}

impl<InputSymbol, OutputSymbol> DeterministicStateMachine<InputSymbol, OutputSymbol> for Rc<DeterministicStateMachine<InputSymbol, OutputSymbol>> {
}
<|endoftext|>


<commit_before>mod seconds;
mod minutes;
mod hours;
mod days_of_month;
mod months;
mod days_of_week;
mod years;

pub use self::seconds::Seconds;
pub use self::minutes::Minutes;
pub use self::hours::Hours;
pub use self::days_of_month::DaysOfMonth;
pub use self::months::Months;
pub use self::days_of_week::DaysOfWeek;
pub use self::years::Years;

use std::collections::btree_set;
//use std::collections::range::{RangeArgument};
use std::ops::RangeBounds;
use schedule::{Specifier, Ordinal, OrdinalSet};
use error::*;
use std::borrow::Cow;
use std::iter;

pub struct OrdinalIter<'a> {
    set_iter: btree_set::Iter<'a, Ordinal>
}

impl <'a> Iterator for OrdinalIter<'a> {
    type Item = Ordinal;
    fn next(&mut self) -> Option<Ordinal> {
      self.set_iter.next().map(|ordinal| ordinal.clone()) // No real expense; Ordinal is u32: Copy
    }
}

pub struct OrdinalRangeIter<'a> {
  range_iter: btree_set::Range<'a, Ordinal>
}

impl <'a> Iterator for OrdinalRangeIter<'a> {
  type Item = Ordinal;
  fn next(&mut self) -> Option<Ordinal> {
    self.range_iter.next().map(|ordinal| ordinal.clone()) // No real expense; Ordinal is u32: Copy
  }
}

/// Methods exposing a schedule's configured ordinals for each individual unit of time.
/// # Example
/// ```
/// use cron::{Schedule,TimeUnitSpec};
/// use std::collections::Bound::{Included,Excluded};
/// use std::str::FromStr;
///
/// let expression = "* * * * * * 2015-2044";
/// let schedule = Schedule::from_str(expression).expect("Failed to parse expression.");
///
/// // Membership
/// assert_eq!(true, schedule.years().includes(2031));
/// assert_eq!(false, schedule.years().includes(1969));
///
/// // Number of years specified
/// assert_eq!(30, schedule.years().count());
///
/// // Iterator
/// let mut years_iter = schedule.years().iter();
/// assert_eq!(Some(2015), years_iter.next());
/// assert_eq!(Some(2016), years_iter.next());
/// // ...
///
/// // Range Iterator
/// let mut five_year_plan = schedule.years().range((Included(2017), Excluded(2017 + 5)));
/// assert_eq!(Some(2017), five_year_plan.next());
/// assert_eq!(Some(2018), five_year_plan.next());
/// assert_eq!(Some(2019), five_year_plan.next());
/// assert_eq!(Some(2020), five_year_plan.next());
/// assert_eq!(Some(2021), five_year_plan.next());
/// assert_eq!(None, five_year_plan.next());
/// ```
pub trait TimeUnitSpec {
  /// Returns true if the provided ordinal was included in the schedule spec for the unit of time
  /// being described.
  /// # Example
  /// ```
  /// use cron::{Schedule,TimeUnitSpec};
  /// use std::str::FromStr;
  ///
  /// let expression = "* * * * * * 2015-2044";
  /// let schedule = Schedule::from_str(expression).expect("Failed to parse expression.");
  ///
  /// // Membership
  /// assert_eq!(true, schedule.years().includes(2031));
  /// assert_eq!(false, schedule.years().includes(2004));
  /// ```
  fn includes(&self, ordinal: Ordinal) -> bool;

  /// Provides an iterator which will return each included ordinal for this schedule in order from
  /// lowest to highest.
  /// # Example
  /// ```
  /// use cron::{Schedule,TimeUnitSpec};
  /// use std::str::FromStr;
  ///
  /// let expression = "* * * * 5-8 * *";
  /// let schedule = Schedule::from_str(expression).expect("Failed to parse expression.");
  ///
  /// // Iterator
  /// let mut summer = schedule.months().iter();
  /// assert_eq!(Some(5), summer.next());
  /// assert_eq!(Some(6), summer.next());
  /// assert_eq!(Some(7), summer.next());
  /// assert_eq!(Some(8), summer.next());
  /// assert_eq!(None, summer.next());
  /// ```
  fn iter<'a>(&'a self) -> OrdinalIter<'a>;

  /// Provides an iterator which will return each included ordinal within the specified range.
  /// # Example
  /// ```
  /// use cron::{Schedule,TimeUnitSpec};
  /// use std::collections::Bound::{Included,Excluded};
  /// use std::str::FromStr;
  ///
  /// let expression = "* * * 1,15 * * *";
  /// let schedule = Schedule::from_str(expression).expect("Failed to parse expression.");
  ///
  /// // Range Iterator
  /// let mut mid_month_paydays = schedule.days_of_month().range((Included(10), Included(20)));
  /// assert_eq!(Some(15), mid_month_paydays.next());
  /// assert_eq!(None, mid_month_paydays.next());
  /// ```
  fn range<'a, R>(&'a self, range: R) -> OrdinalRangeIter<'a> where R: RangeBounds<Ordinal>;

  /// Returns the number of ordinals included in the associated schedule
  /// # Example
  /// ```
  /// use cron::{Schedule,TimeUnitSpec};
  /// use std::str::FromStr;
  ///
  /// let expression = "* * * 1,15 * * *";
  /// let schedule = Schedule::from_str(expression).expect("Failed to parse expression.");
  ///
  /// assert_eq!(2, schedule.days_of_month().count());
  /// ```
  fn count(&self) -> u32;
}

impl <T> TimeUnitSpec for T where T: TimeUnitField {
  fn includes(&self, ordinal: Ordinal) -> bool {
    self.ordinals().contains(&ordinal)
  }
  fn iter<'a>(&'a self) -> OrdinalIter<'a> {
    OrdinalIter {
      set_iter: TimeUnitField::ordinals(self).iter()
    }
  }
  fn range<'a, R>(&'a self, range: R) -> OrdinalRangeIter<'a> where R: RangeBounds<Ordinal> {
    OrdinalRangeIter {
      range_iter: TimeUnitField::ordinals(self).range(range)
    }
  }
  fn count(&self) -> u32 {
    self.ordinals().len() as u32
  }
}

pub trait TimeUnitField
    where Self: Sized
{
    fn from_ordinal_set(ordinal_set: OrdinalSet) -> Self;
    fn name() -> Cow<'static, str>;
    fn inclusive_min() -> Ordinal;
    fn inclusive_max() -> Ordinal;
    fn ordinals(&self) -> &OrdinalSet;
    fn from_ordinal(ordinal: Ordinal) -> Self {
        Self::from_ordinal_set(iter::once(ordinal).collect())
    }
    fn supported_ordinals() -> OrdinalSet {
        (Self::inclusive_min()..Self::inclusive_max() + 1).collect()
    }
    fn all() -> Self {
        Self::from_ordinal_set(Self::supported_ordinals())
    }
    fn ordinal_from_name(name: &str) -> Result<Ordinal> {
        bail!(ErrorKind::Expression(format!("The '{}' field does not support using names. '{}' \
                                     specified.",
                                            Self::name(),
                                            name)))
    }
    fn validate_ordinal(ordinal: Ordinal) -> Result<Ordinal> {
        //println!("validate_ordinal for {} => {}", Self::name(), ordinal);
        match ordinal {
            i if i < Self::inclusive_min() => {
                bail!(ErrorKind::Expression(format!("{} must be greater than or equal to {}. ('{}' \
                                             specified.)",
                                                    Self::name(),
                                                    Self::inclusive_min(),
                                                    i)))
            }
            i if i > Self::inclusive_max() => {
                bail!(ErrorKind::Expression(format!("{} must be less than {}. ('{}' specified.)",
                                                    Self::name(),
                                                    Self::inclusive_max(),
                                                    i)))
            }
            i => Ok(i),
        }
    }

    fn ordinals_from_specifier(specifier: &Specifier) -> Result<OrdinalSet> {
        use self::Specifier::*;
        //println!("ordinals_from_specifier for {} => {:?}", Self::name(), specifier);
        match *specifier {
            All => Ok(Self::supported_ordinals()),
            Point(ordinal) => Ok((&[ordinal]).iter().cloned().collect()),
            NamedPoint(ref name) => {
                Ok((&[Self::ordinal_from_name(name)?])
                       .iter()
                       .cloned()
                       .collect())
            }
            Period(start, step) => {
                let start = Self::validate_ordinal(start)?;
                Ok((start..Self::inclusive_max() + 1)
                       .step_by(step as usize)
                       .collect())
            }
            Range(start, end) => {
                match (Self::validate_ordinal(start), Self::validate_ordinal(end)) {
                    (Ok(start), Ok(end)) if start <= end => Ok((start..end + 1).collect()),
                    _ => {
                        bail!(ErrorKind::Expression(format!("Invalid range for {}: {}-{}",
                                                            Self::name(),
                                                            start,
                                                            end)))
                    }
                }
            }
            NamedRange(ref start_name, ref end_name) => {
                let start = Self::ordinal_from_name(start_name)?;
                let end = Self::ordinal_from_name(end_name)?;
                match (Self::validate_ordinal(start), Self::validate_ordinal(end)) {
                    (Ok(start), Ok(end)) if start <= end => Ok((start..end + 1).collect()),
                    _ => {
                        bail!(ErrorKind::Expression(format!("Invalid named range for {}: {}-{}",
                                                            Self::name(),
                                                            start_name,
                                                            end_name)))
                    }
                }
            }
        }
    }
}
<commit_msg>Delete commented out line<commit_after>mod seconds;
mod minutes;
mod hours;
mod days_of_month;
mod months;
mod days_of_week;
mod years;

pub use self::seconds::Seconds;
pub use self::minutes::Minutes;
pub use self::hours::Hours;
pub use self::days_of_month::DaysOfMonth;
pub use self::months::Months;
pub use self::days_of_week::DaysOfWeek;
pub use self::years::Years;

use std::collections::btree_set;
use std::ops::RangeBounds;
use schedule::{Specifier, Ordinal, OrdinalSet};
use error::*;
use std::borrow::Cow;
use std::iter;

pub struct OrdinalIter<'a> {
    set_iter: btree_set::Iter<'a, Ordinal>
}

impl <'a> Iterator for OrdinalIter<'a> {
    type Item = Ordinal;
    fn next(&mut self) -> Option<Ordinal> {
      self.set_iter.next().map(|ordinal| ordinal.clone()) // No real expense; Ordinal is u32: Copy
    }
}

pub struct OrdinalRangeIter<'a> {
  range_iter: btree_set::Range<'a, Ordinal>
}

impl <'a> Iterator for OrdinalRangeIter<'a> {
  type Item = Ordinal;
  fn next(&mut self) -> Option<Ordinal> {
    self.range_iter.next().map(|ordinal| ordinal.clone()) // No real expense; Ordinal is u32: Copy
  }
}

/// Methods exposing a schedule's configured ordinals for each individual unit of time.
/// # Example
/// ```
/// use cron::{Schedule,TimeUnitSpec};
/// use std::collections::Bound::{Included,Excluded};
/// use std::str::FromStr;
///
/// let expression = "* * * * * * 2015-2044";
/// let schedule = Schedule::from_str(expression).expect("Failed to parse expression.");
///
/// // Membership
/// assert_eq!(true, schedule.years().includes(2031));
/// assert_eq!(false, schedule.years().includes(1969));
///
/// // Number of years specified
/// assert_eq!(30, schedule.years().count());
///
/// // Iterator
/// let mut years_iter = schedule.years().iter();
/// assert_eq!(Some(2015), years_iter.next());
/// assert_eq!(Some(2016), years_iter.next());
/// // ...
///
/// // Range Iterator
/// let mut five_year_plan = schedule.years().range((Included(2017), Excluded(2017 + 5)));
/// assert_eq!(Some(2017), five_year_plan.next());
/// assert_eq!(Some(2018), five_year_plan.next());
/// assert_eq!(Some(2019), five_year_plan.next());
/// assert_eq!(Some(2020), five_year_plan.next());
/// assert_eq!(Some(2021), five_year_plan.next());
/// assert_eq!(None, five_year_plan.next());
/// ```
pub trait TimeUnitSpec {
  /// Returns true if the provided ordinal was included in the schedule spec for the unit of time
  /// being described.
  /// # Example
  /// ```
  /// use cron::{Schedule,TimeUnitSpec};
  /// use std::str::FromStr;
  ///
  /// let expression = "* * * * * * 2015-2044";
  /// let schedule = Schedule::from_str(expression).expect("Failed to parse expression.");
  ///
  /// // Membership
  /// assert_eq!(true, schedule.years().includes(2031));
  /// assert_eq!(false, schedule.years().includes(2004));
  /// ```
  fn includes(&self, ordinal: Ordinal) -> bool;

  /// Provides an iterator which will return each included ordinal for this schedule in order from
  /// lowest to highest.
  /// # Example
  /// ```
  /// use cron::{Schedule,TimeUnitSpec};
  /// use std::str::FromStr;
  ///
  /// let expression = "* * * * 5-8 * *";
  /// let schedule = Schedule::from_str(expression).expect("Failed to parse expression.");
  ///
  /// // Iterator
  /// let mut summer = schedule.months().iter();
  /// assert_eq!(Some(5), summer.next());
  /// assert_eq!(Some(6), summer.next());
  /// assert_eq!(Some(7), summer.next());
  /// assert_eq!(Some(8), summer.next());
  /// assert_eq!(None, summer.next());
  /// ```
  fn iter<'a>(&'a self) -> OrdinalIter<'a>;

  /// Provides an iterator which will return each included ordinal within the specified range.
  /// # Example
  /// ```
  /// use cron::{Schedule,TimeUnitSpec};
  /// use std::collections::Bound::{Included,Excluded};
  /// use std::str::FromStr;
  ///
  /// let expression = "* * * 1,15 * * *";
  /// let schedule = Schedule::from_str(expression).expect("Failed to parse expression.");
  ///
  /// // Range Iterator
  /// let mut mid_month_paydays = schedule.days_of_month().range((Included(10), Included(20)));
  /// assert_eq!(Some(15), mid_month_paydays.next());
  /// assert_eq!(None, mid_month_paydays.next());
  /// ```
  fn range<'a, R>(&'a self, range: R) -> OrdinalRangeIter<'a> where R: RangeBounds<Ordinal>;

  /// Returns the number of ordinals included in the associated schedule
  /// # Example
  /// ```
  /// use cron::{Schedule,TimeUnitSpec};
  /// use std::str::FromStr;
  ///
  /// let expression = "* * * 1,15 * * *";
  /// let schedule = Schedule::from_str(expression).expect("Failed to parse expression.");
  ///
  /// assert_eq!(2, schedule.days_of_month().count());
  /// ```
  fn count(&self) -> u32;
}

impl <T> TimeUnitSpec for T where T: TimeUnitField {
  fn includes(&self, ordinal: Ordinal) -> bool {
    self.ordinals().contains(&ordinal)
  }
  fn iter<'a>(&'a self) -> OrdinalIter<'a> {
    OrdinalIter {
      set_iter: TimeUnitField::ordinals(self).iter()
    }
  }
  fn range<'a, R>(&'a self, range: R) -> OrdinalRangeIter<'a> where R: RangeBounds<Ordinal> {
    OrdinalRangeIter {
      range_iter: TimeUnitField::ordinals(self).range(range)
    }
  }
  fn count(&self) -> u32 {
    self.ordinals().len() as u32
  }
}

pub trait TimeUnitField
    where Self: Sized
{
    fn from_ordinal_set(ordinal_set: OrdinalSet) -> Self;
    fn name() -> Cow<'static, str>;
    fn inclusive_min() -> Ordinal;
    fn inclusive_max() -> Ordinal;
    fn ordinals(&self) -> &OrdinalSet;
    fn from_ordinal(ordinal: Ordinal) -> Self {
        Self::from_ordinal_set(iter::once(ordinal).collect())
    }
    fn supported_ordinals() -> OrdinalSet {
        (Self::inclusive_min()..Self::inclusive_max() + 1).collect()
    }
    fn all() -> Self {
        Self::from_ordinal_set(Self::supported_ordinals())
    }
    fn ordinal_from_name(name: &str) -> Result<Ordinal> {
        bail!(ErrorKind::Expression(format!("The '{}' field does not support using names. '{}' \
                                     specified.",
                                            Self::name(),
                                            name)))
    }
    fn validate_ordinal(ordinal: Ordinal) -> Result<Ordinal> {
        //println!("validate_ordinal for {} => {}", Self::name(), ordinal);
        match ordinal {
            i if i < Self::inclusive_min() => {
                bail!(ErrorKind::Expression(format!("{} must be greater than or equal to {}. ('{}' \
                                             specified.)",
                                                    Self::name(),
                                                    Self::inclusive_min(),
                                                    i)))
            }
            i if i > Self::inclusive_max() => {
                bail!(ErrorKind::Expression(format!("{} must be less than {}. ('{}' specified.)",
                                                    Self::name(),
                                                    Self::inclusive_max(),
                                                    i)))
            }
            i => Ok(i),
        }
    }

    fn ordinals_from_specifier(specifier: &Specifier) -> Result<OrdinalSet> {
        use self::Specifier::*;
        //println!("ordinals_from_specifier for {} => {:?}", Self::name(), specifier);
        match *specifier {
            All => Ok(Self::supported_ordinals()),
            Point(ordinal) => Ok((&[ordinal]).iter().cloned().collect()),
            NamedPoint(ref name) => {
                Ok((&[Self::ordinal_from_name(name)?])
                       .iter()
                       .cloned()
                       .collect())
            }
            Period(start, step) => {
                let start = Self::validate_ordinal(start)?;
                Ok((start..Self::inclusive_max() + 1)
                       .step_by(step as usize)
                       .collect())
            }
            Range(start, end) => {
                match (Self::validate_ordinal(start), Self::validate_ordinal(end)) {
                    (Ok(start), Ok(end)) if start <= end => Ok((start..end + 1).collect()),
                    _ => {
                        bail!(ErrorKind::Expression(format!("Invalid range for {}: {}-{}",
                                                            Self::name(),
                                                            start,
                                                            end)))
                    }
                }
            }
            NamedRange(ref start_name, ref end_name) => {
                let start = Self::ordinal_from_name(start_name)?;
                let end = Self::ordinal_from_name(end_name)?;
                match (Self::validate_ordinal(start), Self::validate_ordinal(end)) {
                    (Ok(start), Ok(end)) if start <= end => Ok((start..end + 1).collect()),
                    _ => {
                        bail!(ErrorKind::Expression(format!("Invalid named range for {}: {}-{}",
                                                            Self::name(),
                                                            start_name,
                                                            end_name)))
                    }
                }
            }
        }
    }
}
<|endoftext|>