<commit_before>use std::mem;
use std::vec::Vec;

const NMEM : usize = 4096;
const NREG : usize = 16;
const NPIXELS : usize = 64 * 32;

/*
 * From http://www.multigesture.net/articles/how-to-write-an-emulator-chip-8-interpreter/
 * MEMORY MAP:
 * 0x000-0x1FF: Chip 8 interpreter
 * 0x050-0x0A0: 4x5 pixel font set (0-F)
 * 0x200-0xFFF: Program ROM and RAM
 */
static FONTSET : [u8;80] = [
  0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
  0x20, 0x60, 0x20, 0x20, 0x70, // 1
  0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
  0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
  0x90, 0x90, 0xF0, 0x10, 0x10, // 4
  0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
  0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
  0xF0, 0x10, 0x20, 0x40, 0x40, // 7
  0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
  0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
  0xF0, 0x90, 0xF0, 0x90, 0x90, // A
  0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
  0xF0, 0x80, 0x80, 0x80, 0xF0, // C
  0xE0, 0x90, 0x90, 0x90, 0xE0, // D
  0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
  0xF0, 0x80, 0xF0, 0x80, 0x80  // F
];

pub struct Chip8 {
    drawFlag: bool,
    opcode: u16,
    memory: [u8; NMEM],
    reg: [u8; NREG],
    index: u16,
    pc: u16,
    graphics: [u8; NPIXELS],
    timer_delay: u8,
    timer_sound: u8,
    stack: [u16; 16],
    sp: u16,
    key: [u8; 16],
}

impl Chip8 {
    pub fn new() -> Self {
        let mut chip = Chip8 {
            drawFlag: false,
            opcode: 0,
            memory: [0; NMEM],
            reg: [0; NREG],
            index: 0,
            pc: 0x200,
            graphics: [0; NPIXELS],
            timer_delay: 0,
            timer_sound: 0,
            stack: [0; 16],
            sp: 0,
            key: [0; 16],
        };

        // Initialize the font set
        for i in 0..80 {
            chip.memory[i] = FONTSET[i];
        }

        chip
    }

    pub fn loadHex(&mut self, game: &Vec<u8>) {
        for c in 0..game.len() {
            self.memory[c + 512] = game[c];
        }
    }

    pub fn loadGame(&mut self, game: String) {
        // TODO Fill in memory starting at 0x200
        unimplemented!();
    }

    pub fn emulateCycle(&mut self) {
        // Fetch opcode
        self.fetchOpcode();

        // Decode and Execute opcode
        self.executeOpcode();

        // Update timers
        self.updateTimers();
    }

    pub fn fetchOpcode(&mut self) {
        self.opcode = (self.memory[self.pc as usize] as u16) << 8 | self.memory[(self.pc + 1) as usize] as u16;
    }

    pub fn executeOpcode(&mut self) {
        // TODO Fill in table
        println!("Opcode: {:#X}", self.opcode);
        match self.opcode & 0xF000 {
            0x1000 => {
                // 0x1NNN: Jump to address NNN
                self.pc = self.opcode & 0x0FFF;
            }
            0x2000 => {
                // 0x2NNN: Call subroutine at NNN
                self.stack[self.sp as usize] = self.pc;
                self.sp += 1;
                self.pc = self.opcode & 0x0FFF;
            },
            0x3000 => {
                // 0x3XNN: Skip next instruction if regX equals NN
                let x = (self.opcode & 0x0F00) >> 8;
                let nn = (self.opcode & 0x00FF) as u8;
                if self.reg[x as usize] == nn {
                    self.pc += 2;
                }
                self.pc += 2;
            },
            0x8000 => {
                match self.opcode & 0x000F {
                    0x0004 => {
                        // 0x8XY4: Add regY to regX, set carry if needed
                        if self.reg[((self.opcode & 0x00F0) >> 4) as usize] >
                            (0xFF - self.reg[((self.opcode & 0x0F00) >> 8) as usize]) {
                            self.reg[0xF] = 1;
                        } else {
                            self.reg[0xF] = 0;
                        }
                        self.reg[((self.opcode & 0x0F00) >> 8) as usize] +=
                            self.reg[((self.opcode & 0x00F0) >> 4) as usize];
                        self.pc += 2;
                    }
                    _ => panic!("Opcode {:#X} is bad", self.opcode),
                }
            },
            0xA000 => {
                // 0xANNN: Sets I to the address NNN
                self.index = self.opcode & 0x0FFF;
                self.pc += 2;
            },
            0xB000 => {
                // 0xBNNN: Jump to address NNN + reg0
                let address = self.opcode & 0x0FFF;
                self.pc = address + self.reg[0] as u16;
            }
            _ => panic!("Opcode {:#X} is bad", self.opcode),
        }
    }

    pub fn updateTimers(&mut self) {
        if(self.timer_delay > 0) {
            self.timer_delay -= 1;
        }

        if(self.timer_sound > 0) {
            if(self.timer_sound == 1) {
                // TODO beep
                unimplemented!();
            }
            self.timer_sound -= 1;
        }
    }
}

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

    #[test]
    fn op1nnn() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x16, 0x66]);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.pc, 0x666);
    }

    #[test]
    fn op2nnn() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x26, 0x66]);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.pc, 0x666);
        assert_eq!(chip.stack[0], 512);
        assert_eq!(chip.sp, 1);
    }

    #[test]
    fn op3nnn() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x31, 0x66, 0x31, 0x67]);
        chip.reg[1] = 0x67;
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.pc, 514);
        chip.emulateCycle();
        assert_eq!(chip.pc, 518);
    }

    #[test]
    fn opAnnn() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0xA6, 0x66]);
        assert_eq!(chip.index, 0);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.index, 0x666);
        assert_eq!(chip.pc, 514);
    }

    #[test]
    fn opBnnn() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0xB6, 0x66]);
        chip.reg[0] = 0x5;
        assert_eq!(chip.index, 0);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.index, 0);
        assert_eq!(chip.pc, 0x666 + 0x5);
    }
}
<commit_msg>Added more opcodes<commit_after>use std::mem;
use std::num::Wrapping;
use std::vec::Vec;

const NMEM : usize = 4096;
const NREG : usize = 16;
const NPIXELS : usize = 64 * 32;

/*
 * From http://www.multigesture.net/articles/how-to-write-an-emulator-chip-8-interpreter/
 * MEMORY MAP:
 * 0x000-0x1FF: Chip 8 interpreter
 * 0x050-0x0A0: 4x5 pixel font set (0-F)
 * 0x200-0xFFF: Program ROM and RAM
 */
static FONTSET : [u8;80] = [
  0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
  0x20, 0x60, 0x20, 0x20, 0x70, // 1
  0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
  0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
  0x90, 0x90, 0xF0, 0x10, 0x10, // 4
  0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
  0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
  0xF0, 0x10, 0x20, 0x40, 0x40, // 7
  0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
  0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
  0xF0, 0x90, 0xF0, 0x90, 0x90, // A
  0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
  0xF0, 0x80, 0x80, 0x80, 0xF0, // C
  0xE0, 0x90, 0x90, 0x90, 0xE0, // D
  0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
  0xF0, 0x80, 0xF0, 0x80, 0x80  // F
];

pub struct Chip8 {
    drawFlag: bool,
    opcode: u16,
    memory: [u8; NMEM],
    reg: [u8; NREG],
    index: u16,
    pc: u16,
    graphics: [u8; NPIXELS],
    timer_delay: u8,
    timer_sound: u8,
    stack: [u16; 16],
    sp: u16,
    key: [u8; 16],
}

impl Chip8 {
    pub fn new() -> Self {
        let mut chip = Chip8 {
            drawFlag: false,
            opcode: 0,
            memory: [0; NMEM],
            reg: [0; NREG],
            index: 0,
            pc: 0x200,
            graphics: [0; NPIXELS],
            timer_delay: 0,
            timer_sound: 0,
            stack: [0; 16],
            sp: 0,
            key: [0; 16],
        };

        // Initialize the font set
        for i in 0..80 {
            chip.memory[i] = FONTSET[i];
        }

        chip
    }

    pub fn loadHex(&mut self, game: &Vec<u8>) {
        for c in 0..game.len() {
            self.memory[c + 512] = game[c];
        }
    }

    pub fn loadGame(&mut self, game: String) {
        // TODO Fill in memory starting at 0x200
        unimplemented!();
    }

    pub fn emulateCycle(&mut self) {
        // Fetch opcode
        self.fetchOpcode();

        // Decode and Execute opcode
        self.executeOpcode();

        // Update timers
        self.updateTimers();
    }

    pub fn fetchOpcode(&mut self) {
        self.opcode = (self.memory[self.pc as usize] as u16) << 8 | self.memory[(self.pc + 1) as usize] as u16;
    }

    pub fn executeOpcode(&mut self) {
        // TODO Fill in table
        println!("Opcode: {:#X}", self.opcode);
        match self.opcode & 0xF000 {
            0x1000 => {
                // 0x1NNN: Jump to address NNN
                self.pc = self.opcode & 0x0FFF;
            }
            0x2000 => {
                // 0x2NNN: Call subroutine at NNN
                self.stack[self.sp as usize] = self.pc;
                self.sp += 1;
                self.pc = self.opcode & 0x0FFF;
            },
            0x3000 => {
                // 0x3XNN: Skip next instruction if regX equals NN
                let x = (self.opcode & 0x0F00) >> 8;
                let nn = (self.opcode & 0x00FF) as u8;
                if self.reg[x as usize] == nn {
                    self.pc += 2;
                }
                self.pc += 2;
            },
            0x4000 => {
                // 0x4XNN: Skip next instruction if regX does not equal NN
                let x = (self.opcode & 0x0F00) >> 8;
                let nn = (self.opcode & 0x00FF) as u8;
                if self.reg[x as usize] != nn {
                    self.pc += 2;
                }
                self.pc += 2;
            },
            0x5000 => {
                // 0x5XY0: Skip next instruction if regX equals regY
                let x = (self.opcode & 0x0F00) >> 8;
                let y = (self.opcode & 0x00F0) >> 4;
                if self.reg[x as usize] == self.reg[y as usize] {
                    self.pc += 2;
                }
                self.pc += 2;
            },
            0x6000 => {
                // 0x6XNN: Set regX to NN
                let x = (self.opcode & 0x0F00) >> 8;
                let nn = (self.opcode & 0x00FF) as u8;
                self.reg[x as usize] = nn;
                self.pc += 2;
            },
            0x7000 => {
                // 0x7XNN: Add NN to regX
                let x = (self.opcode & 0x0F00) >> 8;
                let nn = (self.opcode & 0x00FF) as u8;
                self.reg[x as usize] += nn;
                self.pc += 2;
            },
            0x8000 => {
                match self.opcode & 0x000F {
                    0x0000 => {
                        // 0x8XY0: Set regX to regY
                        let x = (self.opcode & 0x0F00) >> 8;
                        let y = (self.opcode & 0x00F0) >> 4;
                        self.reg[x as usize] = self.reg[y as usize];
                        self.pc += 2;
                    }
                    0x0001 => {
                        // 0x8XY1: Set regX to regX | regY
                        let x = (self.opcode & 0x0F00) >> 8;
                        let y = (self.opcode & 0x00F0) >> 4;
                        self.reg[x as usize] = self.reg[x as usize] | self.reg[y as usize];
                        self.pc += 2;
                    }
                    0x0002 => {
                        // 0x8XY2: Set regX to regX & regY
                        let x = (self.opcode & 0x0F00) >> 8;
                        let y = (self.opcode & 0x00F0) >> 4;
                        self.reg[x as usize] = self.reg[x as usize] & self.reg[y as usize];
                        self.pc += 2;
                    }
                    0x0003 => {
                        // 0x8XY3: Set regX to regX ^ regY
                        let x = (self.opcode & 0x0F00) >> 8;
                        let y = (self.opcode & 0x00F0) >> 4;
                        self.reg[x as usize] = self.reg[x as usize] ^ self.reg[y as usize];
                        self.pc += 2;
                    }
                    0x0004 => {
                        // 0x8XY4: Add regY to regX, set carry if needed
                        if self.reg[((self.opcode & 0x00F0) >> 4) as usize] >
                            (0xFF - self.reg[((self.opcode & 0x0F00) >> 8) as usize]) {
                            self.reg[0xF] = 1;
                        } else {
                            self.reg[0xF] = 0;
                        }
                        let x = Wrapping(self.reg[((self.opcode & 0x0F00) >> 8) as usize]);
                        let y = Wrapping(self.reg[((self.opcode & 0x00F0) >> 4) as usize]);
                        self.reg[((self.opcode & 0x0F00) >> 8) as usize] = (x + y).0;
                        self.pc += 2;
                    }
                    _ => panic!("Opcode {:#X} is bad", self.opcode),
                }
            },
            0xA000 => {
                // 0xANNN: Sets I to the address NNN
                self.index = self.opcode & 0x0FFF;
                self.pc += 2;
            },
            0xB000 => {
                // 0xBNNN: Jump to address NNN + reg0
                let address = self.opcode & 0x0FFF;
                self.pc = address + self.reg[0] as u16;
            }
            _ => panic!("Opcode {:#X} is bad", self.opcode),
        }
    }

    pub fn updateTimers(&mut self) {
        if(self.timer_delay > 0) {
            self.timer_delay -= 1;
        }

        if(self.timer_sound > 0) {
            if(self.timer_sound == 1) {
                // TODO beep
                unimplemented!();
            }
            self.timer_sound -= 1;
        }
    }
}

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

    #[test]
    fn op1nnn() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x16, 0x66]);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.pc, 0x666);
    }

    #[test]
    fn op2nnn() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x26, 0x66]);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.pc, 0x666);
        assert_eq!(chip.stack[0], 512);
        assert_eq!(chip.sp, 1);
    }

    #[test]
    fn op3xnn() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x31, 0x66, 0x31, 0x67]);
        chip.reg[1] = 0x67;
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.pc, 514);
        chip.emulateCycle();
        assert_eq!(chip.pc, 518);
    }

    #[test]
    fn op4xnn() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x41, 0x66, 0x41, 0x67]);
        chip.reg[1] = 0x66;
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.pc, 514);
        chip.emulateCycle();
        assert_eq!(chip.pc, 518);
    }

    #[test]
    fn op5xy0() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x51, 0x20, 0x51, 0x30]);
        chip.reg[1] = 0x66;
        chip.reg[2] = 0x22;
        chip.reg[3] = 0x66;
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.pc, 514);
        chip.emulateCycle();
        assert_eq!(chip.pc, 518);
    }

    #[test]
    fn op6xnn() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x6A, 0x2F]);
        assert_eq!(chip.reg[0xA], 0);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.reg[0xA], 0x2F);
        assert_eq!(chip.pc, 514);
    }

    #[test]
    fn op7xnn() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x7A, 0x2F]);
        chip.reg[0xA] = 0xB;
        assert_eq!(chip.reg[0xA], 0xB);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.reg[0xA], 0x2F + 0xB);
        assert_eq!(chip.pc, 514);
    }

    #[test]
    fn op8xy0() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x8A, 0x20]);
        chip.reg[0xA] = 0xB;
        chip.reg[0x2] = 0xC;
        assert_eq!(chip.reg[0xA], 0xB);
        assert_eq!(chip.reg[0x2], 0xC);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.reg[0xA], 0xC);
        assert_eq!(chip.reg[0x2], 0xC);
        assert_eq!(chip.pc, 514);
    }

    #[test]
    fn op8xy1() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x8A, 0x21]);
        chip.reg[0xA] = 0xB;
        chip.reg[0x2] = 0xC;
        assert_eq!(chip.reg[0xA], 0xB);
        assert_eq!(chip.reg[0x2], 0xC);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.reg[0xA], 0xB | 0xC);
        assert_eq!(chip.reg[0x2], 0xC);
        assert_eq!(chip.pc, 514);
    }

    #[test]
    fn op8xy2() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x8A, 0x22]);
        chip.reg[0xA] = 0xB;
        chip.reg[0x2] = 0xC;
        assert_eq!(chip.reg[0xA], 0xB);
        assert_eq!(chip.reg[0x2], 0xC);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.reg[0xA], 0xB & 0xC);
        assert_eq!(chip.reg[0x2], 0xC);
        assert_eq!(chip.pc, 514);
    }

    #[test]
    fn op8xy3() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x8A, 0x23]);
        chip.reg[0xA] = 0xB;
        chip.reg[0x2] = 0xC;
        assert_eq!(chip.reg[0xA], 0xB);
        assert_eq!(chip.reg[0x2], 0xC);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.reg[0xA], 0xB ^ 0xC);
        assert_eq!(chip.reg[0x2], 0xC);
        assert_eq!(chip.pc, 514);
    }

    #[test]
    fn op8xy4() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0x8A, 0xB4, 0x8B, 0xC4]);
        chip.reg[0xA] = 0x00;
        chip.reg[0xB] = 0xFF;
        chip.reg[0xC] = 0x01;
        assert_eq!(chip.pc, 512);

        chip.emulateCycle();
        assert_eq!(chip.pc, 514);
        assert_eq!(chip.reg[0xA], 0xFF);
        assert_eq!(chip.reg[0xB], 0xFF);
        assert_eq!(chip.reg[0xF], 0x00);

        chip.emulateCycle();
        assert_eq!(chip.pc, 516);
        assert_eq!(chip.reg[0xB], 0x0);
        assert_eq!(chip.reg[0xC], 0x1);
        assert_eq!(chip.reg[0xF], 0x1);
    }

    #[test]
    fn opAnnn() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0xA6, 0x66]);
        assert_eq!(chip.index, 0);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.index, 0x666);
        assert_eq!(chip.pc, 514);
    }

    #[test]
    fn opBnnn() {
        let mut chip = Chip8::new();
        chip.loadHex(&vec![0xB6, 0x66]);
        chip.reg[0] = 0x5;
        assert_eq!(chip.index, 0);
        assert_eq!(chip.pc, 512);
        chip.emulateCycle();
        assert_eq!(chip.index, 0);
        assert_eq!(chip.pc, 0x666 + 0x5);
    }
}
<|endoftext|>


<commit_before>
//! Implementation of the `Synth` struct for basic polyphonic, multi-oscillator envelope synthesis.

extern crate dsp;
extern crate envelope as envelope_lib;
extern crate gaussian;
extern crate num;
extern crate panning;
extern crate pitch_calc as pitch;
extern crate time_calc as time;
extern crate rand;
extern crate rustc_serialize;
extern crate utils;

pub use dynamic::Synth as Dynamic;
pub use envelope::{Envelope, Point};
pub use note_freq::{NoteFreqGenerator, NoteFreq, Portamento, PortamentoFreq};
pub use oscillator::{AmpEnvelope, FreqEnvelope, Oscillator, Waveform};
pub use synth::Synth;
pub use voice::Voice;

pub mod dynamic;
pub mod envelope;
pub mod mode;
pub mod note_freq;
pub mod oscillator;
mod synth;
mod voice;

<commit_msg>Export EnvelopeTrait<commit_after>
//! Implementation of the `Synth` struct for basic polyphonic, multi-oscillator envelope synthesis.

extern crate dsp;
extern crate envelope as envelope_lib;
extern crate gaussian;
extern crate num;
extern crate panning;
extern crate pitch_calc as pitch;
extern crate time_calc as time;
extern crate rand;
extern crate rustc_serialize;
extern crate utils;

pub use dynamic::Synth as Dynamic;
pub use envelope::{Envelope, Point};
pub use envelope::Trait as EnvelopeTrait;
pub use note_freq::{NoteFreqGenerator, NoteFreq, Portamento, PortamentoFreq};
pub use oscillator::{AmpEnvelope, FreqEnvelope, Oscillator, Waveform};
pub use synth::Synth;
pub use voice::Voice;

pub mod dynamic;
pub mod envelope;
pub mod mode;
pub mod note_freq;
pub mod oscillator;
mod synth;
mod voice;

<|endoftext|>


<commit_before>extern crate kernel32;
extern crate libc;
extern crate winapi;

use std::path::PathBuf;

#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "linux")]
use linux as os;

#[cfg(target_os = "macos")]
mod macos;
#[cfg(target_os = "macos")]
use macos as os;

#[cfg(windows)]
mod windows;
#[cfg(windows)]
use windows as os;

pub fn get_executable_path() -> Option<PathBuf> {
    os::get_executable_path()
}
<commit_msg>Add some documentation<commit_after>//! A Rust library to get the path of the currently executing process.
//! # Example
//! ```
//! let path = get_executable_path();
//! match path {
//!     None => println!("The process path could not be determined"),
//!     Some(path) => println!("{:?}", path)
//! }
//! ```

extern crate kernel32;
extern crate libc;
extern crate winapi;

use std::path::PathBuf;

#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "linux")]
use linux as os;

#[cfg(target_os = "macos")]
mod macos;
#[cfg(target_os = "macos")]
use macos as os;

#[cfg(windows)]
mod windows;
#[cfg(windows)]
use windows as os;

/// Gets the path of the currently running process. If the path cannot be determined,
/// `None` is returned.
pub fn get_executable_path() -> Option<PathBuf> {
    os::get_executable_path()
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#![crate_type = "lib"]
#![crate_name = "memcached"]

#![feature(box_syntax, test, buf_stream)]

#[macro_use] extern crate log;
extern crate env_logger;
extern crate conhash;
extern crate test;
extern crate byteorder;
extern crate semver;
extern crate rand;
#[cfg(unix)]
extern crate unix_socket;

pub use client::Client;

pub mod proto;
pub mod client;
<commit_msg>reexport ProtoType<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#![crate_type = "lib"]
#![crate_name = "memcached"]

#![feature(box_syntax, test, buf_stream)]

#[macro_use] extern crate log;
extern crate env_logger;
extern crate conhash;
extern crate test;
extern crate byteorder;
extern crate semver;
extern crate rand;
#[cfg(unix)]
extern crate unix_socket;

pub use client::Client;
pub use proto::ProtoType;

mod proto;
pub mod client;
<|endoftext|>


<commit_before>//! A Hamelin process-hosting backend.
#![feature(collections, io, io_ext, old_io, old_path)]

extern crate mio;
extern crate nix;

use std::borrow::ToOwned;
use std::io::{Error, ErrorKind, Result};
use std::io::ErrorKind::{Other, TimedOut};
use std::old_io::{IoError, IoErrorKind, Writer};
use std::old_io::process::{Command, Process};
use std::old_path::BytesContainer;
use std::os::unix::prelude::*;
use std::str::from_utf8;
use mio::{FromFd, TryRead, TryWrite, PipeReader};
use nix::fcntl::{O_NONBLOCK, O_CLOEXEC, fcntl};
use nix::fcntl::FcntlArg::F_SETFL;
use nix::unistd::close;

/// A Hamelin daemon.
pub struct Hamelin {
    process: String,
    args: Option<Vec<String>>,
}

impl Hamelin {
    /// Constructs a Hamelin daemon from the process and optionally arguments.
    pub fn new(process: &str, args: Option<&[String]>) -> Hamelin {
        Hamelin {
            process: process.to_owned(),
            args: args.map(|s| s.to_owned()),
        }
    }

    /// Spawns a Hamelin server from the daemon.
    pub fn spawn(&self) -> Result<HamelinGuard> {
        let client_str = format!("{} ({:?})", self.process, self.args);
        let mut cmd = Command::new(&self.process);
        cmd.env_set_all(&[("H-VERSION", "hamelin.rs"),
                          ("H-TYPE", "HAMELIN.RS-GENERIC-0.1"),
                          ("H-CLIENT", &client_str)]);
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn().map_err(convert_io_error))))
    }

    /// Spawns a Hamelin server from the daemon using the specified environment variables.
    pub fn spawn_with_env<T, U>(&self, env: &[(T, U)]) -> Result<HamelinGuard>
        where T: BytesContainer, U: BytesContainer {
        let mut cmd = Command::new(&self.process);
        cmd.env_set_all(env);
        cmd.env("H-VERSION", "hamelin.rs");
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn().map_err(convert_io_error))))
    }
}

/// A Hamelin server.
pub struct HamelinGuard {
    process: Process,
    alr: AsyncLineReader,
}

impl HamelinGuard {
    /// Creates a new Hamelin server from the specified process.
    pub fn new(process: Process) -> HamelinGuard {
        let pipe = process.stdout.as_ref().map(|s| s.clone()).unwrap();
        let fd = pipe.as_raw_fd();
        fcntl(fd, F_SETFL(O_NONBLOCK | O_CLOEXEC)).unwrap();
        HamelinGuard {
            process: process,
            alr: AsyncLineReader::new(FromFd::from_fd(fd)),
        }
    }

    /// Writes a line to the server's stdin.
    pub fn write_line(&mut self, line: &str) -> Result<()> {
        self.process.stdin.as_mut().map(|mut s| s.write_line(line)).unwrap()
            .map_err(convert_io_error)
    }

    /// Reads a line asynchronously from the server's stdout.
    pub fn read_line(&mut self) -> Result<String> {
        self.alr.read_line()
    }

    /// Closes the server's stdin.
    pub fn eof(&mut self) -> Result<()> {
        self.process.stdin.as_ref().map(|s| close(s.as_raw_fd())).unwrap().map_err(|e|
            Error::new(Other, "Failed to close stdin.", Some(format!("{:?}", e)))
        )
    }

    /// Awaits the completion of the server.
    pub fn wait(&mut self) -> Result<()> {
        self.process.wait().map(|_| ()).map_err(convert_io_error)
    }

    /// Sends a kill signal to the server.
    pub fn kill(&mut self) -> Result<()> {
        try!(self.process.signal_exit().map_err(convert_io_error));
        self.process.set_timeout(Some(1000));
        if let Ok(_) = self.process.wait() {
            return Ok(())
        }
        self.process.signal_kill().map_err(convert_io_error)
    }
}

struct AsyncLineReader { read: PipeReader, buf: Vec<u8> }

impl AsyncLineReader {
    pub fn new(pr: PipeReader) -> AsyncLineReader {
        AsyncLineReader { read: pr, buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> Result<String> {
        if let Some(pos) = self.buf.position_elem(&b'\n') {
            let mut rest = self.buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.buf).unwrap().to_owned();
            self.buf = rest;
            return Ok(result);
        }
        let mut buf = [0; 100];
        match self.read.read_slice(&mut buf) {
            Ok(None) => {
                return Err(Error::new(TimedOut, "Reading would've blocked.", None))
            },
            Ok(Some(size)) => {
                self.buf.push_all(&buf[..size]);
                match self.buf.position_elem(&b'\n') {
                    Some(pos) => {
                        let mut rest = self.buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.buf).unwrap().to_owned();
                        self.buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(Error::new(TimedOut, "Reading would've blocked.", None))
                    }
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Reading would've blocked.", None))
        }
    }
}

pub struct AsyncBufStream<T: TryRead + TryWrite> {
    pub stream: T,
    read_buf: Vec<u8>
}

impl<T: TryRead + TryWrite> AsyncBufStream<T> {
    pub fn new(stream: T) -> AsyncBufStream<T> {
        AsyncBufStream { stream: stream, read_buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> Result<String> {
        if let Some(pos) = self.read_buf.position_elem(&b'\n') {
            let mut rest = self.read_buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.read_buf).unwrap().to_owned();
            self.read_buf = rest;
            return Ok(result);
        } else if let Some(_) = self.read_buf.position_elem(&4) {
            return Err(Error::new(Other, "End of File reached.", None));
        }
        let mut buf = [0; 100];
        match self.stream.read_slice(&mut buf) {
            Ok(None) => Err(Error::new(TimedOut, "Reading would've blocked.", None)),
            Ok(Some(0)) => Err(Error::new(TimedOut, "Reading would've blocked.", None)),
            Ok(Some(size)) => {
                self.read_buf.push_all(&buf[..size]);
                match self.read_buf.position_elem(&b'\n') {
                    Some(pos) => {
                        let mut rest = self.read_buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.read_buf).unwrap().to_owned();
                        self.read_buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(Error::new(TimedOut, "Reading would've blocked.", None))
                    }
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Reading would've blocked.", None))
        }
    }

    pub fn write_line(&mut self, s: &str) -> Result<()> {
        match self.stream.write_slice(&s.as_bytes()) {
            Ok(None) => Err(Error::new(TimedOut, "Writing would've blocked.", None)),
            Ok(Some(0)) => Err(Error::new(Other, "End of File reached.", None)),
            Ok(Some(_)) => {
                match self.stream.write_slice(b"\n") {
                    Ok(None) => Err(Error::new(TimedOut, "Writing would've blocked.", None)),
                    Ok(_) => Ok(()),
                    Err(_) => Err(Error::new(TimedOut, "Writing would've blocked.", None))
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Writing would've blocked.", None))
        }
    }
}

fn convert_io_error(e: IoError) -> Error {
    Error::new(match e.kind {
        IoErrorKind::FileNotFound => ErrorKind::NotFound,
        IoErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
        IoErrorKind::ConnectionRefused => ErrorKind::ConnectionRefused,
        IoErrorKind::ConnectionReset => ErrorKind::ConnectionReset,
        IoErrorKind::ConnectionAborted => ErrorKind::ConnectionAborted,
        IoErrorKind::NotConnected => ErrorKind::NotConnected,
        IoErrorKind::BrokenPipe => ErrorKind::BrokenPipe,
        IoErrorKind::PathAlreadyExists => ErrorKind::AlreadyExists,
        IoErrorKind::PathDoesntExist => ErrorKind::NotFound,
        IoErrorKind::InvalidInput => ErrorKind::InvalidInput,
        IoErrorKind::TimedOut => ErrorKind::TimedOut,
        IoErrorKind::ShortWrite(0) => ErrorKind::WriteZero,
        _ => ErrorKind::Other
    }, e.desc, e.detail)
}
<commit_msg>Updated for Rust master.<commit_after>//! A Hamelin process-hosting backend.
#![feature(collections, io, old_io, old_path)]

extern crate mio;
extern crate nix;

use std::borrow::ToOwned;
use std::io::{Error, ErrorKind, Result};
use std::io::ErrorKind::{Other, TimedOut};
use std::old_io::{IoError, IoErrorKind, Writer};
use std::old_io::process::{Command, Process};
use std::old_path::BytesContainer;
use std::os::unix::prelude::*;
use std::str::from_utf8;
use mio::{FromFd, TryRead, TryWrite, PipeReader};
use nix::fcntl::{O_NONBLOCK, O_CLOEXEC, fcntl};
use nix::fcntl::FcntlArg::F_SETFL;
use nix::unistd::close;

/// A Hamelin daemon.
pub struct Hamelin {
    process: String,
    args: Option<Vec<String>>,
}

impl Hamelin {
    /// Constructs a Hamelin daemon from the process and optionally arguments.
    pub fn new(process: &str, args: Option<&[String]>) -> Hamelin {
        Hamelin {
            process: process.to_owned(),
            args: args.map(|s| s.to_owned()),
        }
    }

    /// Spawns a Hamelin server from the daemon.
    pub fn spawn(&self) -> Result<HamelinGuard> {
        let client_str = format!("{} ({:?})", self.process, self.args);
        let mut cmd = Command::new(&self.process);
        cmd.env_set_all(&[("H-VERSION", "hamelin.rs"),
                          ("H-TYPE", "HAMELIN.RS-GENERIC-0.1"),
                          ("H-CLIENT", &client_str)]);
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn().map_err(convert_io_error))))
    }

    /// Spawns a Hamelin server from the daemon using the specified environment variables.
    pub fn spawn_with_env<T, U>(&self, env: &[(T, U)]) -> Result<HamelinGuard>
        where T: BytesContainer, U: BytesContainer {
        let mut cmd = Command::new(&self.process);
        cmd.env_set_all(env);
        cmd.env("H-VERSION", "hamelin.rs");
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn().map_err(convert_io_error))))
    }
}

/// A Hamelin server.
pub struct HamelinGuard {
    process: Process,
    alr: AsyncLineReader,
}

impl HamelinGuard {
    /// Creates a new Hamelin server from the specified process.
    pub fn new(process: Process) -> HamelinGuard {
        let pipe = process.stdout.as_ref().map(|s| s.clone()).unwrap();
        let fd = pipe.as_raw_fd();
        fcntl(fd, F_SETFL(O_NONBLOCK | O_CLOEXEC)).unwrap();
        HamelinGuard {
            process: process,
            alr: AsyncLineReader::new(FromFd::from_fd(fd)),
        }
    }

    /// Writes a line to the server's stdin.
    pub fn write_line(&mut self, line: &str) -> Result<()> {
        self.process.stdin.as_mut().map(|mut s| s.write_line(line)).unwrap()
            .map_err(convert_io_error)
    }

    /// Reads a line asynchronously from the server's stdout.
    pub fn read_line(&mut self) -> Result<String> {
        self.alr.read_line()
    }

    /// Closes the server's stdin.
    pub fn eof(&mut self) -> Result<()> {
        self.process.stdin.as_ref().map(|s| close(s.as_raw_fd())).unwrap().map_err(|_|
            Error::new(Other, "Failed to close stdin.")
        )
    }

    /// Awaits the completion of the server.
    pub fn wait(&mut self) -> Result<()> {
        self.process.wait().map(|_| ()).map_err(convert_io_error)
    }

    /// Sends a kill signal to the server.
    pub fn kill(&mut self) -> Result<()> {
        try!(self.process.signal_exit().map_err(convert_io_error));
        self.process.set_timeout(Some(1000));
        if let Ok(_) = self.process.wait() {
            return Ok(())
        }
        self.process.signal_kill().map_err(convert_io_error)
    }
}

struct AsyncLineReader { read: PipeReader, buf: Vec<u8> }

impl AsyncLineReader {
    pub fn new(pr: PipeReader) -> AsyncLineReader {
        AsyncLineReader { read: pr, buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> Result<String> {
        if let Some(pos) = self.buf.position_elem(&b'\n') {
            let mut rest = self.buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.buf).unwrap().to_owned();
            self.buf = rest;
            return Ok(result);
        }
        let mut buf = [0; 100];
        match self.read.read_slice(&mut buf) {
            Ok(None) => {
                return Err(Error::new(TimedOut, "Reading would've blocked."))
            },
            Ok(Some(size)) => {
                self.buf.push_all(&buf[..size]);
                match self.buf.position_elem(&b'\n') {
                    Some(pos) => {
                        let mut rest = self.buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.buf).unwrap().to_owned();
                        self.buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(Error::new(TimedOut, "Reading would've blocked."))
                    }
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Reading would've blocked."))
        }
    }
}

pub struct AsyncBufStream<T: TryRead + TryWrite> {
    pub stream: T,
    read_buf: Vec<u8>
}

impl<T: TryRead + TryWrite> AsyncBufStream<T> {
    pub fn new(stream: T) -> AsyncBufStream<T> {
        AsyncBufStream { stream: stream, read_buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> Result<String> {
        if let Some(pos) = self.read_buf.position_elem(&b'\n') {
            let mut rest = self.read_buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.read_buf).unwrap().to_owned();
            self.read_buf = rest;
            return Ok(result);
        } else if let Some(_) = self.read_buf.position_elem(&4) {
            return Err(Error::new(Other, "End of File reached."));
        }
        let mut buf = [0; 100];
        match self.stream.read_slice(&mut buf) {
            Ok(None) => Err(Error::new(TimedOut, "Reading would've blocked.")),
            Ok(Some(0)) => Err(Error::new(TimedOut, "Reading would've blocked.")),
            Ok(Some(size)) => {
                self.read_buf.push_all(&buf[..size]);
                match self.read_buf.position_elem(&b'\n') {
                    Some(pos) => {
                        let mut rest = self.read_buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.read_buf).unwrap().to_owned();
                        self.read_buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(Error::new(TimedOut, "Reading would've blocked."))
                    }
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Reading would've blocked."))
        }
    }

    pub fn write_line(&mut self, s: &str) -> Result<()> {
        match self.stream.write_slice(&s.as_bytes()) {
            Ok(None) => Err(Error::new(TimedOut, "Writing would've blocked.")),
            Ok(Some(0)) => Err(Error::new(Other, "End of File reached.")),
            Ok(Some(_)) => {
                match self.stream.write_slice(b"\n") {
                    Ok(None) => Err(Error::new(TimedOut, "Writing would've blocked.")),
                    Ok(_) => Ok(()),
                    Err(_) => Err(Error::new(TimedOut, "Writing would've blocked."))
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Writing would've blocked."))
        }
    }
}

fn convert_io_error(e: IoError) -> Error {
    Error::new(match e.kind {
        IoErrorKind::FileNotFound => ErrorKind::NotFound,
        IoErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
        IoErrorKind::ConnectionRefused => ErrorKind::ConnectionRefused,
        IoErrorKind::ConnectionReset => ErrorKind::ConnectionReset,
        IoErrorKind::ConnectionAborted => ErrorKind::ConnectionAborted,
        IoErrorKind::NotConnected => ErrorKind::NotConnected,
        IoErrorKind::BrokenPipe => ErrorKind::BrokenPipe,
        IoErrorKind::PathAlreadyExists => ErrorKind::AlreadyExists,
        IoErrorKind::PathDoesntExist => ErrorKind::NotFound,
        IoErrorKind::InvalidInput => ErrorKind::InvalidInput,
        IoErrorKind::TimedOut => ErrorKind::TimedOut,
        IoErrorKind::ShortWrite(0) => ErrorKind::WriteZero,
        _ => ErrorKind::Other
    }, e.desc)
}
<|endoftext|>


<commit_before>#![deny(clippy::undocumented_unsafe_blocks)]
// workarounds
#![allow(unused_doc_comments)]

pub mod data {
    pub use av_data::*;
}

pub mod format {
    pub use av_format::*;
}

pub mod bitstream {
    pub use av_bitstream::*;
}

pub use av_data::rational;

// core functionalities
mod entropy;
mod io;

// raw multimedia data manipulation
mod filter;
mod resample;
mod scale;
<commit_msg>lib: Remove a useless lint<commit_after>#![deny(clippy::undocumented_unsafe_blocks)]

pub mod data {
    pub use av_data::*;
}

pub mod format {
    pub use av_format::*;
}

pub mod bitstream {
    pub use av_bitstream::*;
}

pub use av_data::rational;

// core functionalities
mod entropy;
mod io;

// raw multimedia data manipulation
mod filter;
mod resample;
mod scale;
<|endoftext|>


<commit_before>use agent::*;

mod agent;

// Type Observer
pub trait Observer {
    fn see(&mut self, time: f64, crowd: &Crowd);
    fn request_at(&mut self, time: f64) -> bool;
}

//
// * Affichage à l'écran
//
struct ScreenPrinter {
    freq: uint,
    ticks: uint
}

pub impl ScreenPrinter {
    fn new(freq: uint) -> ScreenPrinter {
        ScreenPrinter { freq: freq, ticks: 0}
    }
}

impl Observer for ScreenPrinter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        io::println(fmt!("%f\n", time as float));
        io::println(crowd.to_str());
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }
}

//
// * Sortie sur le disque
//
struct DiskWriter {
    freq: uint,
    fname: ~str,
    curr_snap: uint,
    ticks: uint
}

pub impl DiskWriter {
    fn new(freq:uint, name: ~str) -> DiskWriter {
        DiskWriter {freq: freq, fname: copy name, curr_snap: 0, ticks: 0}
    }

    fn new_filename(&mut self) -> ~str {
        self.curr_snap+=1;
        fmt!("./%s-%u.vtk", self.fname, self.curr_snap-1)
    }
}

impl Observer for DiskWriter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        io::println(fmt!("%f : %d cells -> %s.\n",time as float, crowd.size() as int, self.fname));
        let outfile=self.new_filename();
        let writer = result::get( &io::file_writer( &Path(outfile), [io::Create, io::Truncate] ) );

        // Ecriture de l'entête
        writer.write_str("# vtk DataFile Version 3.0\n");
        writer.write_str("Rusty_Cells\n");
        writer.write_str("ASCII\n");
        writer.write_str("DATASET UNSTRUCTURED_GRID\n");
        writer.write_str(fmt!("POINTS %u float\n", crowd.size()));

        // Coordonnées des cellules
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%f %f 0\n",cell.x() as float, cell.y() as float))
        }

        // Données sur les nœuds
        writer.write_str(fmt!("POINT_DATA %u\nSCALARS %s float\nLOOKUP_TABLE default", crowd.size(), self.fname));
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%u\n", cell.id));
        }
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }

}
<commit_msg>Correction dans les sorties en vtk<commit_after>use agent::*;

mod agent;

// Type Observer
pub trait Observer {
    fn see(&mut self, time: f64, crowd: &Crowd);
    fn request_at(&mut self, time: f64) -> bool;
}

//
// * Affichage à l'écran
//
struct ScreenPrinter {
    freq: uint,
    ticks: uint
}

pub impl ScreenPrinter {
    fn new(freq: uint) -> ScreenPrinter {
        ScreenPrinter { freq: freq, ticks: 0}
    }
}

impl Observer for ScreenPrinter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        io::println(fmt!("%f\n", time as float));
        io::println(crowd.to_str());
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }
}

//
// * Sortie sur le disque
//
struct DiskWriter {
    freq: uint,
    fname: ~str,
    curr_snap: uint,
    ticks: uint
}

pub impl DiskWriter {
    fn new(freq:uint, name: ~str) -> DiskWriter {
        DiskWriter {freq: freq, fname: copy name, curr_snap: 0, ticks: 0}
    }

    fn new_filename(&mut self) -> ~str {
        self.curr_snap+=1;
        fmt!("./%s-%u.vtk", self.fname, self.curr_snap-1)
    }
}

impl Observer for DiskWriter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        io::println(fmt!("%f : %d cells -> %s.\n",time as float, crowd.size() as int, self.fname));
        let outfile=self.new_filename();
        let writer = result::get( &io::file_writer( &Path(outfile), [io::Create, io::Truncate] ) );

        // Ecriture de l'entête
        writer.write_str("# vtk DataFile Version 3.0\n");
        writer.write_str("Rusty_Cells\n");
        writer.write_str("ASCII\n");
        writer.write_str("DATASET UNSTRUCTURED_GRID\n");
        writer.write_str(fmt!("POINTS %u float\n", crowd.size()));

        // Coordonnées des cellules
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%f %f 0\n",cell.x() as float, cell.y() as float))
        }

        // Données sur les nœuds
        writer.write_str(fmt!("POINT_DATA %u\nSCALARS %s float\nLOOKUP_TABLE default\n", crowd.size(), self.fname));
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%u\n", cell.id));
        }
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }

}
<|endoftext|>


<commit_before>#![warn(missing_docs)]

extern crate hyper;
extern crate mime;
extern crate mime_guess;
extern crate mustache;
extern crate rustc_serialize;
extern crate term;
extern crate time;

use std::io;
use std::fs;
use std::fs::File;
use std::net::ToSocketAddrs;
use std::path::PathBuf;

use hyper::mime::Mime as HyperMime;
use hyper::mime::TopLevel as HyperMimeTopLevel;
use hyper::mime::Attr as HyperMimeAttr;
use hyper::mime::Value as HyperMimeValue;
use hyper::header::ContentType as HyperContentType;
use hyper::uri::RequestUri as HyperRequestUri;
use hyper::server::Server as HyperServer;

use service::log::LogProvider;

pub mod input;
pub mod output;
pub mod route;
pub mod service;

/// Starts a server with the given router.
///
/// # Parameters
///
/// - `router`: The list of routes that are handled dynamically. You are encouraged to use the
///             `router!` macro to build a router.
///
/// - `static_files`: A path to the directory containing the static files to serve.
///
/// - `services`: Configuration for the various services accessible in the dynamic routes.
///
/// # Example
///
/// ```no_run
/// # #[macro_use] extern crate rouille;
/// # fn main() {
/// # fn handler(_: rouille::input::Ignore) -> rouille::output::PlainTextOutput { panic!() }
/// use rouille::service::StaticServices;
/// use rouille::service::TemplatesCache;
///
/// let router = router! {
///     GET "/" => handler as fn(_) -> _
/// };
///
/// let services = StaticServices {
///     templates: TemplatesCache::new("./templates"),
///     .. Default::default()
/// };
///
/// rouille::start("0.0.0.0:8000", router, "static", services);
/// # }
/// ```
///
pub fn start<T, P>(addr: T, router: route::Router, static_files: P,
                   services: service::StaticServices)
                   where T: ToSocketAddrs, P: Into<PathBuf>
{
    let handler = RequestHandler {
        router: router,
        static_files: static_files.into(),
        static_services: services,
    };

    let server = HyperServer::http(addr).unwrap();
    let _ = server.handle(handler).unwrap();
}

struct RequestHandler {
    router: route::Router,
    static_files: PathBuf,
    static_services: service::StaticServices,
}

impl hyper::server::Handler for RequestHandler {
    fn handle<'a, 'k>(&'a self, request: hyper::server::request::Request<'a, 'k>,
                      response: hyper::server::response::Response<'a, hyper::net::Fresh>)
    {
        let time_before = time::precise_time_ns();
        let (method, uri) = (request.method.clone(), request.uri.clone());

        // handling static files
        if let HyperRequestUri::AbsolutePath(ref url) = request.uri {
            let possible_file = self.static_files.join(&url[1..]);      // TODO: this is a dirty hack to remove the leading `/`

            // FIXME (SECURITY): check with `relative_from` that we're still in `self.static_files`
            //                   once the function is stable

            if fs::metadata(&possible_file).map(|d| d.is_file()).ok().unwrap_or(false) {
                if let Ok(mut file) = File::open(&possible_file) {
                    let mut response = response;

                    let mut mime = mime_guess::guess_mime_type(&possible_file);

                    // adding `charset=utf8` if starting with `text/`
                    if let HyperMime(HyperMimeTopLevel::Text, _, _) = mime {
                        let HyperMime(_, _, ref mut params) = mime;
                        if params.is_empty() { *params = vec![(HyperMimeAttr::Charset, HyperMimeValue::Utf8)]; }
                    }
                    response.headers_mut().set(HyperContentType(mime));

                    if let Ok(mut response) = response.start() {
                        let _ = io::copy(&mut file, &mut response);
                    }

                    let time_after = time::precise_time_ns();
                    self.static_services.logs.log_request(&method, &uri, time_after - time_before);
                    return;
                }
            }
        }

        for route in self.router.routes.iter() {
            if !route.matches(&request) {
                continue;
            }

            match route.handler {
                route::Handler::Static(_) => unimplemented!(),
                route::Handler::Dynamic(ref handler) => {
                    handler.call(request, response, &self.static_services);
                    break;
                },
            }
        }

        let time_after = time::precise_time_ns();
        self.static_services.logs.log_request(&method, &uri, time_after - time_before);
    }
}
<commit_msg>Fix connection not being closed when serving static files<commit_after>#![warn(missing_docs)]

extern crate hyper;
extern crate mime;
extern crate mime_guess;
extern crate mustache;
extern crate rustc_serialize;
extern crate term;
extern crate time;

use std::io;
use std::fs;
use std::fs::File;
use std::net::ToSocketAddrs;
use std::path::PathBuf;

use hyper::mime::Mime as HyperMime;
use hyper::mime::TopLevel as HyperMimeTopLevel;
use hyper::mime::Attr as HyperMimeAttr;
use hyper::mime::Value as HyperMimeValue;
use hyper::header::ContentType as HyperContentType;
use hyper::uri::RequestUri as HyperRequestUri;
use hyper::server::Server as HyperServer;

use service::log::LogProvider;

pub mod input;
pub mod output;
pub mod route;
pub mod service;

/// Starts a server with the given router.
///
/// # Parameters
///
/// - `router`: The list of routes that are handled dynamically. You are encouraged to use the
///             `router!` macro to build a router.
///
/// - `static_files`: A path to the directory containing the static files to serve.
///
/// - `services`: Configuration for the various services accessible in the dynamic routes.
///
/// # Example
///
/// ```no_run
/// # #[macro_use] extern crate rouille;
/// # fn main() {
/// # fn handler(_: rouille::input::Ignore) -> rouille::output::PlainTextOutput { panic!() }
/// use rouille::service::StaticServices;
/// use rouille::service::TemplatesCache;
///
/// let router = router! {
///     GET "/" => handler as fn(_) -> _
/// };
///
/// let services = StaticServices {
///     templates: TemplatesCache::new("./templates"),
///     .. Default::default()
/// };
///
/// rouille::start("0.0.0.0:8000", router, "static", services);
/// # }
/// ```
///
pub fn start<T, P>(addr: T, router: route::Router, static_files: P,
                   services: service::StaticServices)
                   where T: ToSocketAddrs, P: Into<PathBuf>
{
    let handler = RequestHandler {
        router: router,
        static_files: static_files.into(),
        static_services: services,
    };

    let server = HyperServer::http(addr).unwrap();
    let _ = server.handle(handler).unwrap();
}

struct RequestHandler {
    router: route::Router,
    static_files: PathBuf,
    static_services: service::StaticServices,
}

impl hyper::server::Handler for RequestHandler {
    fn handle<'a, 'k>(&'a self, request: hyper::server::request::Request<'a, 'k>,
                      response: hyper::server::response::Response<'a, hyper::net::Fresh>)
    {
        let time_before = time::precise_time_ns();
        let (method, uri) = (request.method.clone(), request.uri.clone());

        // handling static files
        if let HyperRequestUri::AbsolutePath(ref url) = request.uri {
            let possible_file = self.static_files.join(&url[1..]);      // TODO: this is a dirty hack to remove the leading `/`

            // FIXME (SECURITY): check with `relative_from` that we're still in `self.static_files`
            //                   once the function is stable

            if fs::metadata(&possible_file).map(|d| d.is_file()).ok().unwrap_or(false) {
                if let Ok(mut file) = File::open(&possible_file) {
                    let mut response = response;

                    let mut mime = mime_guess::guess_mime_type(&possible_file);

                    // adding `charset=utf8` if starting with `text/`
                    if let HyperMime(HyperMimeTopLevel::Text, _, _) = mime {
                        let HyperMime(_, _, ref mut params) = mime;
                        if params.is_empty() { *params = vec![(HyperMimeAttr::Charset, HyperMimeValue::Utf8)]; }
                    }
                    response.headers_mut().set(HyperContentType(mime));

                    if let Ok(mut response) = response.start() {
                        let _ = io::copy(&mut file, &mut response);
                        let _ = response.end();
                    }

                    let time_after = time::precise_time_ns();
                    self.static_services.logs.log_request(&method, &uri, time_after - time_before);
                    return;
                }
            }
        }

        for route in self.router.routes.iter() {
            if !route.matches(&request) {
                continue;
            }

            match route.handler {
                route::Handler::Static(_) => unimplemented!(),
                route::Handler::Dynamic(ref handler) => {
                    handler.call(request, response, &self.static_services);
                    break;
                },
            }
        }

        let time_after = time::precise_time_ns();
        self.static_services.logs.log_request(&method, &uri, time_after - time_before);
    }
}
<|endoftext|>


<commit_before>//! A library implementation of so-called `static_assert` based on a macro which
//! conditionally expands into an integer overflow, breaking the compilation.
//!
//! It can take one or more constant boolean expressions as its parameters.
//! When you have multiple conditions to verify, pass them to a single
//! invocation of this macro as multiple parameters.
//!
//! **You cannot invoke this macro more than once in a given scope.**
//! This is because its implementation is based on a type synonym definition and
//! two or more invocation causes name collision.
//!
//! ## Example
//! ```
//! #[macro_use]
//! extern crate static_assert_macro;
//!
//! static_assert!(0 < 1, 1 < 2, 2 < 3);
//!
//! fn main() {
//!     const FOUR: i32 = 4;
//!     static_assert!(1 + 2 == { FOUR - 1 });
//! }
//! ```

#[macro_export]
macro_rules! static_assert {
    (let $e:expr; ) => (
        type _ArrayForStaticAssert = [i8; 0 - ((false == ($e)) as usize)];
    );

    (let $e:expr; $e1:expr $(, $ee:expr)*) => (
        static_assert!(let ($e) && ($e1); $($ee),*);
    );

    ($e:expr $(, $ee:expr)*) => (
        static_assert!(let $e; $($ee),*);
    );
}

#[cfg(test)]
mod tests {
    const _FOUR: i32 = 4;

    #[test]
    fn test_0() {
        static_assert!(1 + 2 == { _FOUR - 1 }, 2 < 3);
    }
}
<commit_msg>Elide comparison with false<commit_after>//! A library implementation of so-called `static_assert` based on a macro which
//! conditionally expands into an integer overflow, breaking the compilation.
//!
//! It can take one or more constant boolean expressions as its parameters.
//! When you have multiple conditions to verify, pass them to a single
//! invocation of this macro as multiple parameters.
//!
//! **You cannot invoke this macro more than once in a given scope.**
//! This is because its implementation is based on a type synonym definition and
//! two or more invocation causes name collision.
//!
//! ## Example
//! ```
//! #[macro_use]
//! extern crate static_assert_macro;
//!
//! static_assert!(0 < 1, 1 < 2, 2 < 3);
//!
//! fn main() {
//!     const FOUR: i32 = 4;
//!     static_assert!(1 + 2 == { FOUR - 1 });
//! }
//! ```

#[macro_export]
macro_rules! static_assert {
    (let $e:expr; ) => (
        type _ArrayForStaticAssert = [i8; ($e) as usize - 1];
    );

    (let $e:expr; $e1:expr $(, $ee:expr)*) => (
        static_assert!(let ($e) && ($e1); $($ee),*);
    );

    ($e:expr $(, $ee:expr)*) => (
        static_assert!(let true && ($e); $($ee),*);
    );
}

#[cfg(test)]
mod tests {
    const _FOUR: i32 = 4;

    #[test]
    fn test_0() {
        static_assert!(1 + 2 == { _FOUR - 1 }, 2 < 3);
    }
    #[test]
    fn test_1() {
        static_assert!(true);
    }
    #[test]
    fn test_2() {
        // static_assert!(1); // should not compile
    }
}
<|endoftext|>


<commit_before>pub mod lines;

#[macro_use]
extern crate nom;

extern crate regex;
extern crate memmap;
extern crate memchr;
extern crate ascii;

use std::path::Path;

use memmap::{Mmap, Protection};
use memchr::memchr;

// Why is it called partialEq?
#[derive(Debug, PartialEq, Default, Clone)]
pub struct Count {
    pub code: u32,
    pub comment: u32,
    pub blank: u32,
    pub lines: u32,
}

impl Count {
    pub fn merge(&mut self, o: &Count) {
        self.code += o.code;
        self.comment += o.comment;
        self.blank += o.blank;
        self.lines += o.lines;
    }
}

pub enum LineConfig<'a> {
    Multi {
        single_start: &'a str,
        multi_start: &'a str,
        multi_end: &'a str,
    },
    Single {
        single_start: &'a str,
    },
}
// Do any languages actually use utf8 chars as comment chars?

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone)]
pub enum Lang {
    C,
    CCppHeader,
    Rust,
    Haskell,
    Perl,
    BourneShell,
    Unrecognized,
}

pub fn lang_from_ext(filepath: &str) -> Lang {
    let ext = match Path::new(filepath).extension() {
        Some(os_str) => os_str.to_str().unwrap().to_lowercase(),
        None => String::from(""),
    };

    match &*ext {
        "c" => Lang::C,
        "h" => Lang::CCppHeader,
        "rs" => Lang::Rust,
        "hs" => Lang::Haskell,
        "pl" => Lang::Perl,
        // TODO(cgag): What's the correct extension? Any? Pragma?
        "sh" => Lang::BourneShell,
        // Probably dumb to just default to C.
        _ => Lang::Unrecognized,
    }
}

pub fn counter_config_for_lang<'a>(lang: &Lang) -> LineConfig<'a> {
    enum CT<'a> {
        Single(&'a str),
        Multi(&'a str, &'a str, &'a str),
    }
    // use self::ConfigTuple::*;

    let c_style = CT::Multi("//", "/*", "*/");
    let ctuple = match *lang {
        Lang::Haskell => CT::Multi("--", "{-", "-}"),
        Lang::Perl => CT::Multi("#", "=pod", "=cut"),
        Lang::BourneShell => CT::Single("#"),
        // Lang::C | Lang::CCppHeader | Lang::Rust => c_style,
        // Default to C style
        _ => c_style,
    };

    match ctuple {
        CT::Multi(single, start, end) => {
            LineConfig::Multi {
                single_start: single,
                multi_start: start,
                multi_end: end,
            }
        }
        CT::Single(single) => LineConfig::Single { single_start: single },
    }
}

struct AsciiLines<'a> {
    buf: &'a [u8],
    pos: usize,
}

struct Ascii<'a>(&'a [u8]);
impl<'a> Ascii<'a> {
    fn lines(&self) -> AsciiLines {
        AsciiLines {
            buf: self.0,
            pos: 0,
        }
    }
}

// Appears to work, now we just neeed
impl<'a> Iterator for AsciiLines<'a> {
    type Item = &'a [u8];

    fn next(&mut self) -> Option<&'a [u8]> {
        match memchr(b'\n', &self.buf[self.pos..self.buf.len()]) {
            Some(n) => {
                let start = self.pos;
                self.pos = self.pos + n + 1;
                // - 1 to drop \n char
                Some(&self.buf[start..(self.pos - 1)])
            }
            None => {
                if self.pos == self.buf.len() {
                    return None;
                }
                let start = self.pos;
                self.pos = self.buf.len();
                Some(&self.buf[start..self.pos])
            }
        }
    }
}

pub fn count(filepath: &str) -> Count {
    let lang = lang_from_ext(filepath);
    let config = counter_config_for_lang(&lang);
    match config {
        LineConfig::Single { single_start: single } => count_mmap_unsafe_single(filepath, single),
        LineConfig::Multi { single_start: single, multi_start, multi_end } => {
            count_mmap_unsafe_multi(filepath, single, multi_start, multi_end)
        }
    }
}

pub fn count_mmap_unsafe_single(filepath: &str, single_start: &str) -> Count {
    let fmmap = Mmap::open_path(filepath, Protection::Read).expect("mmap err");
    let bytes: &[u8] = unsafe { fmmap.as_slice() };

    let mut lines = 0;
    let mut code = 0;
    let mut comments = 0;
    let mut blanks = 0;

    let a = Ascii(bytes);
    for byte_line in a.lines() {
        let line = unsafe { std::str::from_utf8_unchecked(byte_line) };
        lines += 1;

        let trimmed = line.trim_left();
        if trimmed == "" {
            blanks += 1;
            continue;
        } else if trimmed.starts_with(single_start) {
            comments += 1;
            continue;
        } else {
            code += 1;
        }
    }

    Count {
        code: code,
        comment: comments,
        blank: blanks,
        lines: lines,
    }
}

pub fn count_mmap_unsafe_multi(filepath: &str,
                               single_start: &str,
                               multi_start: &str,
                               multi_end: &str)
                               -> Count {

    let single_line_start = single_start;
    let multiline_start = multi_start;
    let multiline_end = multi_end;

    let fmmap = Mmap::open_path(filepath, Protection::Read).expect("mmap err");
    let bytes: &[u8] = unsafe { fmmap.as_slice() };

    let mut lines = 0;
    let mut code = 0;
    let mut comments = 0;
    let mut blanks = 0;

    let mut in_comment = false;

    let a = Ascii(bytes);
    for byte_line in a.lines() {
        let line = unsafe { std::str::from_utf8_unchecked(byte_line) };
        lines += 1;

        let trimmed = line.trim_left();
        if trimmed == "" {
            println!("Blank: {}", line);
            blanks += 1;
            continue;
        };

        if in_comment {
            println!("Comment: {}", line);
            comments += 1;
            if trimmed.contains(multiline_end) {
                in_comment = false;
            }
        } else {
            if trimmed.starts_with(single_line_start) {
                println!("Comment: {}", line);
                comments += 1;
                continue;
            }

            // This code really sucks. Handles `/* lol */ func()` correctly as code, but
            // it's not recursive in any way.  It would count /* x */ /* x */ func() as a
            // comment.
            if trimmed.starts_with(multiline_start) {
                if trimmed.contains(multiline_end) {
                    let rest = &trimmed[multiline_start.len()..];
                    if let Some(end_pos) = rest.find(multiline_end) {
                        let after_comment = &rest[end_pos + multiline_end.len()..];
                        let after_trimmed = after_comment.trim_left();
                        if after_trimmed.is_empty() {
                            println!("Comment: {}", line);
                            comments += 1;
                        } else if after_trimmed.starts_with(multiline_start) ||
                           after_trimmed.starts_with(single_start) {
                            println!("Comment: {}", line);
                            comments += 1;
                        } else {
                            println!("Code: {}", line);
                            code += 1;
                        }
                    }
                } else {
                    println!("Comment: {}", line);
                    comments += 1;
                    in_comment = true;
                }
            } else {
                match trimmed.find(multiline_start) {
                    Some(pos) => {
                        println!("Code: {}", line);
                        code += 1;
                        // TODO(cgag): What the hell is +2.  len of of what?
                        if trimmed[pos + multiline_start.len()..].contains(multiline_end) {
                            continue;
                        }
                        in_comment = true;
                    }
                    None => {
                        println!("Code: {}", line);
                        code += 1;
                    }
                }
            }
        }
    }

    // TODO(cgag): try parsers, regex, operating on non-utf8, etc.
    // Only escelate to utf8 if needed?  When is it needed?
    Count {
        code: code,
        comment: comments,
        blank: blanks,
        lines: lines,
    }
}
<commit_msg>cleanup, add ruby<commit_after>pub mod lines;

#[macro_use]
extern crate nom;

extern crate regex;
extern crate memmap;
extern crate memchr;
extern crate ascii;

use std::path::Path;

use memmap::{Mmap, Protection};
use memchr::memchr;

// Why is it called partialEq?
#[derive(Debug, PartialEq, Default, Clone)]
pub struct Count {
    pub code: u32,
    pub comment: u32,
    pub blank: u32,
    pub lines: u32,
}

impl Count {
    pub fn merge(&mut self, o: &Count) {
        self.code += o.code;
        self.comment += o.comment;
        self.blank += o.blank;
        self.lines += o.lines;
    }
}

pub enum LineConfig<'a> {
    Multi {
        single_start: &'a str,
        multi_start: &'a str,
        multi_end: &'a str,
    },
    Single {
        single_start: &'a str,
    },
}

// Do any languages actually use utf8 chars as comment chars?
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone)]
pub enum Lang {
    C,
    CCppHeader,
    Rust,
    Ruby,
    Haskell,
    Perl,
    BourneShell,
    Unrecognized,
}

pub fn lang_from_ext(filepath: &str) -> Lang {
    let ext = match Path::new(filepath).extension() {
        Some(os_str) => os_str.to_str().unwrap().to_lowercase(),
        None => String::from(""),
    };

    match &*ext {
        "c" => Lang::C,
        "h" => Lang::CCppHeader,
        "rs" => Lang::Rust,
        "hs" => Lang::Haskell,
        "pl" => Lang::Perl,
        "rb" => Lang::Ruby,
        // TODO(cgag): What's the correct extension? Any? Pragma?
        "sh" => Lang::BourneShell,
        // Probably dumb to just default to C.
        _ => Lang::Unrecognized,
    }
}

pub fn counter_config_for_lang<'a>(lang: &Lang) -> LineConfig<'a> {
    enum CT<'a> {
        Single(&'a str),
        Multi(&'a str, &'a str, &'a str),
    }
    // use self::ConfigTuple::*;

    let c_style = CT::Multi("//", "/*", "*/");
    let sh_style = CT::Single("#");

    let ctuple = match *lang {
        Lang::Haskell => CT::Multi("--", "{-", "-}"),
        Lang::Perl => CT::Multi("#", "=pod", "=cut"),
        Lang::BourneShell | Lang::Ruby => sh_style,
        // Lang::C | Lang::CCppHeader | Lang::Rust => c_style,
        // Default to C style
        _ => c_style,
    };

    match ctuple {
        CT::Multi(single, start, end) => {
            LineConfig::Multi {
                single_start: single,
                multi_start: start,
                multi_end: end,
            }
        }
        CT::Single(single) => LineConfig::Single { single_start: single },
    }
}

struct AsciiLines<'a> {
    buf: &'a [u8],
    pos: usize,
}

struct Ascii<'a>(&'a [u8]);
impl<'a> Ascii<'a> {
    fn lines(&self) -> AsciiLines {
        AsciiLines {
            buf: self.0,
            pos: 0,
        }
    }
}

// Appears to work, now we just neeed
impl<'a> Iterator for AsciiLines<'a> {
    type Item = &'a [u8];

    fn next(&mut self) -> Option<&'a [u8]> {
        match memchr(b'\n', &self.buf[self.pos..self.buf.len()]) {
            Some(n) => {
                let start = self.pos;
                self.pos = self.pos + n + 1;
                // - 1 to drop \n char
                Some(&self.buf[start..(self.pos - 1)])
            }
            None => {
                if self.pos == self.buf.len() {
                    return None;
                }
                let start = self.pos;
                self.pos = self.buf.len();
                Some(&self.buf[start..self.pos])
            }
        }
    }
}

pub fn count(filepath: &str) -> Count {
    let lang = lang_from_ext(filepath);
    let config = counter_config_for_lang(&lang);
    match config {
        LineConfig::Single { single_start: single } => count_mmap_unsafe_single(filepath, single),
        LineConfig::Multi { single_start: single, multi_start, multi_end } => {
            count_mmap_unsafe_multi(filepath, single, multi_start, multi_end)
        }
    }
}

pub fn count_mmap_unsafe_single(filepath: &str, single_start: &str) -> Count {
    let fmmap = Mmap::open_path(filepath, Protection::Read).expect("mmap err");
    let bytes: &[u8] = unsafe { fmmap.as_slice() };

    let mut lines = 0;
    let mut code = 0;
    let mut comments = 0;
    let mut blanks = 0;

    let a = Ascii(bytes);
    for byte_line in a.lines() {
        let line = unsafe { std::str::from_utf8_unchecked(byte_line) };
        lines += 1;

        let trimmed = line.trim_left();
        if trimmed.is_empty() {
            blanks += 1;
        } else if trimmed.starts_with(single_start) {
            comments += 1;
        } else {
            code += 1;
        }
    }

    Count {
        code: code,
        comment: comments,
        blank: blanks,
        lines: lines,
    }
}

pub fn count_mmap_unsafe_multi(filepath: &str,
                               single_start: &str,
                               multi_start: &str,
                               multi_end: &str)
                               -> Count {

    let single_line_start = single_start;
    let multiline_start = multi_start;
    let multiline_end = multi_end;

    let fmmap = Mmap::open_path(filepath, Protection::Read).expect("mmap err");
    let bytes: &[u8] = unsafe { fmmap.as_slice() };

    let mut lines = 0;
    let mut code = 0;
    let mut comments = 0;
    let mut blanks = 0;

    let mut in_comment = false;

    let a = Ascii(bytes);
    for byte_line in a.lines() {
        let line = unsafe { std::str::from_utf8_unchecked(byte_line) };
        lines += 1;

        let trimmed = line.trim_left();
        if trimmed.is_empty() {
            println!("Blank: {}", line);
            blanks += 1;
            continue;
        };

        if in_comment {
            println!("Comment: {}", line);
            comments += 1;
            if trimmed.contains(multiline_end) {
                in_comment = false;
            }
        } else {
            if trimmed.starts_with(single_line_start) {
                println!("Comment: {}", line);
                comments += 1;
                continue;
            }

            // This code really sucks. Handles `/* lol */ func()` correctly as code, but
            // it's not recursive in any way.  It would count /* x */ /* x */ func() as a
            // comment.
            if trimmed.starts_with(multiline_start) {
                if trimmed.contains(multiline_end) {
                    let rest = &trimmed[multiline_start.len()..];
                    if let Some(end_pos) = rest.find(multiline_end) {
                        let after_comment = &rest[end_pos + multiline_end.len()..];
                        let after_trimmed = after_comment.trim_left();
                        if after_trimmed.is_empty() {
                            println!("Comment: {}", line);
                            comments += 1;
                        } else if after_trimmed.starts_with(multiline_start) ||
                           after_trimmed.starts_with(single_start) {
                            println!("Comment: {}", line);
                            comments += 1;
                        } else {
                            println!("Code: {}", line);
                            code += 1;
                        }
                    }
                } else {
                    println!("Comment: {}", line);
                    comments += 1;
                    in_comment = true;
                }
            } else {
                match trimmed.find(multiline_start) {
                    Some(pos) => {
                        println!("Code: {}", line);
                        code += 1;
                        // TODO(cgag): What the hell is +2.  len of of what?
                        if trimmed[pos + multiline_start.len()..].contains(multiline_end) {
                            continue;
                        }
                        in_comment = true;
                    }
                    None => {
                        println!("Code: {}", line);
                        code += 1;
                    }
                }
            }
        }
    }

    // TODO(cgag): try parsers, regex, operating on non-utf8, etc.
    // Only escelate to utf8 if needed?  When is it needed?
    Count {
        code: code,
        comment: comments,
        blank: blanks,
        lines: lines,
    }
}
<|endoftext|>


<commit_before>#[test]
fn it_works() {
}
<commit_msg>Sketch up some initial interpreter<commit_after>#![feature(box_syntax, box_patterns)]

use std::fmt;

// Nock(a)          *a
// [a b c]          [a [b c]]
//
// ?[a b]           0
// ?a               1
// +[a b]           +[a b]
// +a               1 + a
// =[a a]           0
// =[a b]           1
// =a               =a
//
// /[1 a]           a
// /[2 a b]         a
// /[3 a b]         b
// /[(a + a) b]     /[2 /[a b]]
// /[(a + a + 1) b] /[3 /[a b]]
// /a               /a
//
// *[a [b c] d]     [*[a b c] *[a d]]
//
// *[a 0 b]         /[b a]
// *[a 1 b]         b
// *[a 2 b c]       *[*[a b] *[a c]]
// *[a 3 b]         ?*[a b]
// *[a 4 b]         +*[a b]
// *[a 5 b]         =*[a b]
//
// *[a 6 b c d]     *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b]
// *[a 7 b c]       *[a 2 b 1 c]
// *[a 8 b c]       *[a 7 [[7 [0 1] b] 0 1] c]
// *[a 9 b c]       *[a 7 c 2 [0 1] 0 b]
// *[a 10 [b c] d]  *[a 8 c 7 [0 3] d]
// *[a 10 b c]      *[a c]
//
// *a               *a

#[derive(Clone, PartialEq, Eq)]
pub enum Noun {
    Atom(u64), // TODO: Need bigints?
    Cell(Box<Noun>, Box<Noun>),
}

impl fmt::Display for Noun {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Atom(ref n) => write!(f, "{}", n),
            &Cell(ref a, ref b) => {
                try!(write!(f, "[{} ", a));
                // List pretty-printer.
                let mut cur = b;
                loop {
                    match cur {
                        &box Cell(ref a, ref b) => {
                            try!(write!(f, "{} ", a));
                            cur = &b;
                        }
                        &box Atom(ref n) => {
                            return write!(f, "{}]", n);
                        }
                    }
                }
            }
        }
    }
}

impl fmt::Debug for Noun {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self) }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Op {
    Wut, // ?
    Lus, // +
    Tis, // =
    Fas, // /
    Tar, // *
}

use Op::*;
use Noun::*;

fn eval(op: Op, noun: Noun) -> Result<Noun, Noun> {
    match (op, noun) {
        (Wut, Cell(_, _)) => Ok(Atom(0)),
        (Wut, Atom(_)) => Ok(Atom(1)),
        (Lus, Atom(a)) => Ok(Atom(1 + a)),
        (Lus, a) => Err(a),
        (Tis, Cell(a, b)) => Ok(Atom(if a == b { 0 } else { 1 })),
        (Tis, a) => Err(a),

        (Fas, Cell(box Atom(1), box a)) => Ok(a),
        (Fas, Cell(box Atom(2), box Cell(box a, _))) => Ok(a),
        (Fas, Cell(box Atom(3), box Cell(_, box b))) => Ok(b),
        (Fas, Cell(box Atom(a), b)) => {
            let x = try!(eval(Fas, Cell(box Atom(a / 2), b)));
            eval(Fas, Cell(box Atom(if a % 2 == 0 { 2 } else { 3 }), box x))
        }
        (Fas, a) => Err(a),

        (Tar, Cell(a, box Cell(box Cell(b, c), d))) => {
            let x = try!(eval(Tar, Cell(a.clone(), box Cell(b, c))));
            let y = try!(eval(Tar, Cell(a, d)));
            Ok(Cell(box x, box y))
        }

        // TODO: Numbered tar ops.

        (Tar, a) => Err(a)
    }
}

pub fn nock(noun: Noun) -> Result<Noun, Noun> { eval(Wut, noun) }

#[test]
fn it_works() {
    println!("{}", Cell(box Atom(1), box Cell(box Atom(2), box Atom(3))));
    println!("{:?}", eval(Tis, Cell(box Atom(2), box Atom(2))));
    println!("{:?}", eval(Fas, Cell(box Atom(7), box Cell(box Cell(box Atom(4), box Atom(5)), box Cell(box Atom(6), box Cell(box Atom(14), box Atom(15)))))));
    assert!(false);
}
<|endoftext|>


<commit_before>#![allow(unstable)]

#[derive(Show, PartialEq)]
pub struct Error;

pub type ParseResult<O, I> = Result<(O, I), Error>;

pub trait Parser {
    type Input: Clone;
    type Output;
    fn parse(&mut self, input: <Self as Parser>::Input) -> ParseResult<<Self as Parser>::Output, <Self as Parser>::Input>;
}
impl <'a, I, O, P> Parser for &'a mut P
    where I: Clone, P: Parser<Input=I, Output=O> {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        (*self).parse(input)
    }
}

pub fn char<'a>(input: &'a str) -> ParseResult<char, &'a str> {
    match input.slice_shift_char() {
        Some(x) => Ok(x),
        None => Err(Error)
    }
}

pub struct ManyAppend<'a, O: 'a, P: Parser<Output=O> + 'a> {
    parser: P,
    vec: &'a mut Vec<O>
}
impl <'a, O, P: Parser<Output=O> + 'a> Parser for ManyAppend<'a, O, P> {
    type Input =
::Input;
    type Output = ();
    fn parse(&mut self, mut input:
::Input) -> ParseResult<(),
::Input> {
        loop {
            match self.parser.parse(input.clone()) {
                Ok((x, rest)) => {
                    self.vec.push(x);
                    input = rest;
                }
                Err(_) => break
            }
        }
        Ok(((), input))
    }
}

pub fn many_append<'a, O, P: Parser<Output=O>>(parser: P, vec: &'a mut Vec<O>) -> ManyAppend<'a, O, P> {
    ManyAppend { parser: parser, vec: vec }
}

pub struct Many
 {
    parser: P
}
impl
 Parser for Many
 {
    type Input =
::Input;
    type Output = Vec<
::Output>;
    fn parse(&mut self, input:
::Input) -> ParseResult<Vec<
::Output>,
::Input> {
        let mut result = Vec::new();
        let ((), input) = try!(many_append(&mut self.parser, &mut result).parse(input));
        Ok((result, input))
    }
}
pub fn many
(p: P) -> Many
 {
    Many { parser: p }
}

pub fn many1<'a, P: Clone + 'a>(mut p: P) -> Box<Parser<Input=
::Input, Output=Vec<
::Output>> + 'a>
    where P: Parser {
    Box::new(FnParser(move |&mut:input| {
        let (first, input) = try!(p.parse(input));
        let mut result = vec![first];
        let ((), input) = try!(many_append(&mut p, &mut result).parse(input));
        Ok((result, input))
    }))
}

pub struct SepBy
 {
    parser: P,
    separator: S
}
impl
 Parser for SepBy

    where P: Parser, S: Parser<Input=
::Input> {

    type Input =
::Input;
    type Output = Vec<
::Output>;
    fn parse(&mut self, mut input:
::Input) -> ParseResult<Vec<
::Output>,
::Input> {
        let mut result = Vec::new();
        match self.parser.parse(input.clone()) {
            Ok((x, rest)) => {
                result.push(x);
                input = rest;
            }
            Err(_) => return Ok((result, input))
        }
        let rest = FnParser(|input| {
            let mut env = Env::new(input);
            try!(env.with(&mut self.separator));
            let v = try!(env.with(&mut self.parser));
            env.result(v)
        });
        let ((), input) = try!(many_append(rest, &mut result).parse(input));
        Ok((result, input))
    }
}
pub fn sep_by
(parser: P, separator: S) -> SepBy
 {
    SepBy { parser: parser, separator: separator }
}

impl <'a, I: Clone, O> Parser for Box<FnMut(I) -> ParseResult<O, I> + 'a> {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        self(input)
    }
}
struct FnParser<'a, I: Clone, O, F: FnMut(I) -> ParseResult<O, I>>(F);

impl <'a, I, O, F> Parser for FnParser<'a, I, O, F>
    where I: Clone, F: FnMut(I) -> ParseResult<O, I> {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        (self.0)(input)
    }
}

impl <'a, I: Clone, O> Parser for fn (I) -> ParseResult<O, I> {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        self(input)
    }
}

pub struct Satisfy<Pred> { pred: Pred }

impl <'a, Pred> Parser for Satisfy<Pred>
    where Pred: FnMut(char) -> bool {

    type Input = &'a str;
    type Output = char;
    fn parse(&mut self, input: &'a str) -> ParseResult<char, &'a str> {
        match input.slice_shift_char() {
            Some((c, s)) => {
                if (self.pred)(c) { Ok((c, s)) }
                else { Err(Error) }
            }
            None => Err(Error)
        }
    }
}

pub fn satisfy<Pred>(pred: Pred) -> Satisfy<Pred>
    where Pred: FnMut(char) -> bool {
    Satisfy { pred: pred }
}

pub fn space() -> Satisfy<fn (char) -> bool> {
    satisfy(CharExt::is_whitespace as fn (char) -> bool)
}

pub struct StringP<'a> { s: &'a str }
impl <'a, 'b> Parser for StringP<'b> {
    type Input = &'a str;
    type Output = &'a str;
    fn parse(&mut self, input: &'a str) -> ParseResult<&'a str, &'a str> {
        if input.starts_with(self.s) {
            let l = self.s.len();
            Ok((&input[..l], &input[l..]))
        }
        else {
            Err(Error)
        }
    }
}

pub fn string(s: &str) -> StringP {
    StringP { s: s }
}

pub struct AndThen<P1, P2>(P1, P2);
impl  Parser for AndThen<P1, P2>
    where P1: Parser<Input=I, Output=A>, P2: Parser<Input=I, Output=B> {

    type Input = I;
    type Output = (A, B);
    fn parse(&mut self, input: I) -> ParseResult<(A, B), I> {
        let (a, rest) = try!(self.0.parse(input));
        let (b, rest) = try!(self.1.parse(rest));
        Ok(((a, b), rest))
    }
}
pub fn and_then<P1, P2>(p1: P1, p2: P2) -> AndThen<P1, P2>
    where P1: Parser, P2: Parser {
    AndThen(p1, p2)
}

pub struct Optional
(P);
impl
 Parser for Optional

    where P: Parser {
    type Input =
::Input;
    type Output = Option<
::Output>;
    fn parse(&mut self, input:
::Input) -> ParseResult<Option<
::Output>,
::Input> {
        match self.0.parse(input.clone()) {
            Ok((x, rest)) => Ok((Some(x), rest)),
            Err(_) => Ok((None, input))
        }
    }
}
pub fn optional
(parser: P) -> Optional
 {
    Optional(parser)
}

pub struct Env {
    input: I
}

impl  Env {
    pub fn new(input: I) -> Env {
        Env { input: input }
    }

    pub fn with
(&mut self, mut parser: P) -> Result<O, Error>
        where P: Parser<Input=I, Output=O> {
        let (o, rest) = try!(parser.parse(self.input.clone()));
        self.input = rest;
        Ok(o)
    }

    pub fn result<O>(self, output: O) -> ParseResult<O, I> {
        Ok((output, self.input))
    }
}

pub fn digit<'a>(input: &'a str) -> ParseResult<char, &'a str> {
    match input.slice_shift_char() {
        Some(x) if x.0.is_digit(10) => Ok(x),
        Some((c, _)) => Err(Error),
        None => Err(Error)
    }
}

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

    fn integer<'a>(input: &'a str) -> ParseResult<i64, &'a str> {
        let mut env = Env::new(input);
        let chars = try!(env.with(many(digit as fn(_) -> _)));
        let mut n = 0;
        for &c in chars.iter() {
            n = n * 10 + (c as i64 - '0' as i64);
        }
        env.result(n)
    }

    #[test]
    fn test_integer() {
        assert_eq!((integer as fn(_) -> _).parse("123"), Ok((123i64, "")));
    }
    #[test]
    fn list() {
        let mut p = sep_by(integer as fn(_) -> _, satisfy(|c| c == ','));
        assert_eq!(p.parse("123,4,56"), Ok((vec![123, 4, 56], "")));
    }
}

/*

impl Parser for  {
    type Input = ;
    type Output = ;
    fn parse(&mut self, input: ) -> Result<(, ), Error>;
}
 */
<commit_msg>Added Stream trait which abstracts over input<commit_after>#![allow(unstable)]

#[derive(Clone, Show, PartialEq)]
pub struct Error;

pub type ParseResult<O, I> = Result<(O, I), Error>;

pub trait Stream {
    type Item;
    fn uncons(self) -> ParseResult<<Self as Stream>::Item, Self>;
}

impl  Stream for I {
    type Item = ::Item;
    fn uncons(mut self) -> ParseResult<::Item, I> {
        match self.next() {
            Some(x) => Ok((x, self)),
            None => Err(Error)
        }
    }
}

impl <'a> Stream for &'a str {
    type Item = char;
    fn uncons(self) -> ParseResult<char, &'a str> {
        match self.slice_shift_char() {
            Some(x) => Ok(x),
            None => Err(Error)
        }
    }
}

impl <'a, T> Stream for &'a [T] {
    type Item = &'a T;
    fn uncons(self) -> ParseResult<&'a T, &'a [T]> {
        match self {
            [ref x, rest..] => Ok((x, rest)),
            [] => Err(Error)
        }
    }
}

pub trait Parser {
    type Input: Clone + Stream;
    type Output;
    fn parse(&mut self, input: <Self as Parser>::Input) -> ParseResult<<Self as Parser>::Output, <Self as Parser>::Input>;
}
impl <'a, I, O, P> Parser for &'a mut P
    where I: Clone + Stream, P: Parser<Input=I, Output=O> {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        (*self).parse(input)
    }
}

pub fn char<'a, I>(input: I) -> ParseResult<char, I>
    where I: Stream<Item=char> + Clone {
    input.uncons()
}

pub struct ManyAppend<'a, O: 'a, P: Parser<Output=O> + 'a> {
    parser: P,
    vec: &'a mut Vec<O>
}
impl <'a, O, P: Parser<Output=O> + 'a> Parser for ManyAppend<'a, O, P> {
    type Input =
::Input;
    type Output = ();
    fn parse(&mut self, mut input:
::Input) -> ParseResult<(),
::Input> {
        loop {
            match self.parser.parse(input.clone()) {
                Ok((x, rest)) => {
                    self.vec.push(x);
                    input = rest;
                }
                Err(_) => break
            }
        }
        Ok(((), input))
    }
}

pub fn many_append<'a, O, P: Parser<Output=O>>(parser: P, vec: &'a mut Vec<O>) -> ManyAppend<'a, O, P> {
    ManyAppend { parser: parser, vec: vec }
}

#[derive(Clone)]
pub struct Many
 {
    parser: P
}
impl
 Parser for Many
 {
    type Input =
::Input;
    type Output = Vec<
::Output>;
    fn parse(&mut self, input:
::Input) -> ParseResult<Vec<
::Output>,
::Input> {
        let mut result = Vec::new();
        let ((), input) = try!(many_append(&mut self.parser, &mut result).parse(input));
        Ok((result, input))
    }
}
pub fn many
(p: P) -> Many
 {
    Many { parser: p }
}

pub fn many1<'a, P: Clone + 'a>(mut p: P) -> Box<Parser<Input=
::Input, Output=Vec<
::Output>> + 'a>
    where P: Parser {
    Box::new(FnParser(move |&mut:input| {
        let (first, input) = try!(p.parse(input));
        let mut result = vec![first];
        let ((), input) = try!(many_append(&mut p, &mut result).parse(input));
        Ok((result, input))
    }))
}

#[derive(Clone)]
pub struct SepBy
 {
    parser: P,
    separator: S
}
impl
 Parser for SepBy

    where P: Parser, S: Parser<Input=
::Input> {

    type Input =
::Input;
    type Output = Vec<
::Output>;
    fn parse(&mut self, mut input:
::Input) -> ParseResult<Vec<
::Output>,
::Input> {
        let mut result = Vec::new();
        match self.parser.parse(input.clone()) {
            Ok((x, rest)) => {
                result.push(x);
                input = rest;
            }
            Err(_) => return Ok((result, input))
        }
        let rest = FnParser(|input| {
            let mut env = Env::new(input);
            try!(env.with(&mut self.separator));
            let v = try!(env.with(&mut self.parser));
            env.result(v)
        });
        let ((), input) = try!(many_append(rest, &mut result).parse(input));
        Ok((result, input))
    }
}
pub fn sep_by
(parser: P, separator: S) -> SepBy
 {
    SepBy { parser: parser, separator: separator }
}

impl <'a, I: Clone + Stream, O> Parser for Box<FnMut(I) -> ParseResult<O, I> + 'a> {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        self(input)
    }
}

#[derive(Clone)]
struct FnParser<'a, I: Stream, O, F: FnMut(I) -> ParseResult<O, I>>(F);

impl <'a, I, O, F> Parser for FnParser<'a, I, O, F>
    where I: Clone + Stream, F: FnMut(I) -> ParseResult<O, I> {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        (self.0)(input)
    }
}

impl <'a, I, O> Parser for fn (I) -> ParseResult<O, I>
    where I: Clone + Stream {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        self(input)
    }
}

#[derive(Clone)]
pub struct Satisfy { pred: Pred }

impl <'a, I, Pred> Parser for Satisfy
    where I: Stream<Item=char> + Clone, Pred: FnMut(char) -> bool {

    type Input = I;
    type Output = char;
    fn parse(&mut self, input: I) -> ParseResult<char, I> {
        match input.uncons() {
            Ok((c, s)) => {
                if (self.pred)(c) { Ok((c, s)) }
                else { Err(Error) }
            }
            Err(err) => Err(err)
        }
    }
}

pub fn satisfy(pred: Pred) -> Satisfy
    where I: Stream + Clone, Pred: FnMut(char) -> bool {
    Satisfy { pred: pred }
}

pub fn space() -> Satisfy bool>
    where I: Stream + Clone {
    satisfy(CharExt::is_whitespace as fn (char) -> bool)
}

#[derive(Clone)]
pub struct StringP<'a, I> { s: &'a str }
impl <'a, 'b, I> Parser for StringP<'b, I>
    where I: Stream<Item=char> + Clone {
    type Input = I;
    type Output = &'b str;
    fn parse(&mut self, mut input: I) -> ParseResult<&'b str, I> {
        for c in self.s.chars() {
            match input.uncons() {
                Ok((other, rest)) => {
                    if c != other { return Err(Error);  }
                    input = rest;
                }
                Err(err) => return Err(err)
            }
        }
        Ok((self.s, input))
    }
}

pub fn string(s: &str) -> StringP
    where I: Stream + Clone {
    StringP { s: s }
}

#[derive(Clone)]
pub struct AndThen<P1, P2>(P1, P2);
impl  Parser for AndThen<P1, P2>
    where I: Clone + Stream, P1: Parser<Input=I, Output=A>, P2: Parser<Input=I, Output=B> {

    type Input = I;
    type Output = (A, B);
    fn parse(&mut self, input: I) -> ParseResult<(A, B), I> {
        let (a, rest) = try!(self.0.parse(input));
        let (b, rest) = try!(self.1.parse(rest));
        Ok(((a, b), rest))
    }
}
pub fn and_then<P1, P2>(p1: P1, p2: P2) -> AndThen<P1, P2>
    where P1: Parser, P2: Parser {
    AndThen(p1, p2)
}

#[derive(Clone)]
pub struct Optional
(P);
impl
 Parser for Optional

    where P: Parser {
    type Input =
::Input;
    type Output = Option<
::Output>;
    fn parse(&mut self, input:
::Input) -> ParseResult<Option<
::Output>,
::Input> {
        match self.0.parse(input.clone()) {
            Ok((x, rest)) => Ok((Some(x), rest)),
            Err(_) => Ok((None, input))
        }
    }
}
pub fn optional
(parser: P) -> Optional
 {
    Optional(parser)
}

pub struct Env {
    input: I
}

impl  Env {
    pub fn new(input: I) -> Env {
        Env { input: input }
    }

    pub fn with
(&mut self, mut parser: P) -> Result<O, Error>
        where P: Parser<Input=I, Output=O> {
        let (o, rest) = try!(parser.parse(self.input.clone()));
        self.input = rest;
        Ok(o)
    }

    pub fn result<O>(self, output: O) -> ParseResult<O, I> {
        Ok((output, self.input))
    }
}

pub fn digit<'a, I>(input: I) -> ParseResult<char, I>
    where I: Stream<Item=char> + Clone {
    match input.uncons() {
        Ok((c, rest)) => {
            if c.is_digit(10) { Ok((c, rest)) }
            else { Err(Error) }
        }
        Err(err) => Err(err)
    }
}

pub trait ParserExt {
    fn and_then
(self, P) -> AndThen<Self, P>
        where P: Parser;
}

impl
 ParserExt for P {
    fn and_then<P2>(self, p: P2) -> AndThen<Self, P2>
        where P2: Parser {
        and_then(self, p)
    }
}

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

    fn integer<'a, I>(input: I) -> ParseResult<i64, I>
        where I: Stream<Item=char> + Clone {
        let mut env = Env::new(input);
        let chars = try!(env.with(many(digit as fn(_) -> _)));
        let mut n = 0;
        for &c in chars.iter() {
            n = n * 10 + (c as i64 - '0' as i64);
        }
        env.result(n)
    }

    #[test]
    fn test_integer() {
        assert_eq!((integer as fn(_) -> _).parse("123"), Ok((123i64, "")));
    }
    #[test]
    fn list() {
        let mut p = sep_by(integer as fn(_) -> _, satisfy(|c| c == ','));
        assert_eq!(p.parse("123,4,56"), Ok((vec![123, 4, 56], "")));
    }
    #[test]
    fn iterator() {
        let result = (integer as fn(_) -> _).parse("123".chars())
            .map(|(i, mut iter)| (i, iter.next()));
        assert_eq!(result, Ok((123i64, None)));
    }
    #[test]
    fn field() {
        let word = many(satisfy(|c| c.is_alphanumeric()));
        let word2 = many(satisfy(|c| c.is_alphanumeric()));
        let spaces = many(space());
        let c_decl = word
            .and_then(spaces.clone())
            .and_then(satisfy(|c| c == ':'))
            .and_then(spaces)
            .and_then(word2)
            .parse("x: int")
            .map(|(((((ret, _), _), _), name), rest)| ((ret, name), rest));
        assert_eq!(c_decl, Ok(((vec!['x'], vec!['i', 'n', 't']), "")));
    }
}
<|endoftext|>