<commit_before>use super::VirtualMachine;
use std::num::Wrapping;

pub fn jump_to_sys_routine(_vm: &mut VirtualMachine, _addr: usize) {
    // Do nothing
}

pub fn clear_display(vm: &mut VirtualMachine) {
    for px in vm.display.iter_mut() {
        *px = 0;
    }
}

pub fn ret_from_subroutine(vm: &mut VirtualMachine) {
    vm.pc = vm.stack[vm.sp as usize];
    vm.sp -= 1;
}

pub fn jump_addr(vm: &mut VirtualMachine, addr: u16) {
    vm.pc = addr;
}

pub fn call_subroutine(vm: &mut VirtualMachine, addr: usize) {
    vm.sp += 1;
    vm.stack[vm.sp as usize] = vm.pc;
    vm.pc = addr as u16;
}

pub fn skip_next_vx_eq(vm: &mut VirtualMachine, x: usize, to: u8) {
    if vm.v[x].0 == to {
        vm.pc += 2;
    }
}

pub fn skip_next_vx_ne(vm: &mut VirtualMachine, x: usize, to: u8) {
    if vm.v[x].0 != to {
        vm.pc += 2;
    }
}

pub fn skip_next_vx_eq_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    if vm.v[x] == vm.v[y] {
        vm.pc += 2;
    }
}

pub fn set_vx_byte(vm: &mut VirtualMachine, x: usize, byte: u8) {
    vm.v[x].0 = byte;
}

pub fn add_vx_byte(vm: &mut VirtualMachine, x: usize, byte: u8) {
    vm.v[x] = vm.v[x] + Wrapping(byte);
}

pub fn set_vx_to_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[y];
}

pub fn set_vx_to_vx_or_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] | vm.v[y];
}

pub fn set_vx_to_vx_and_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] & vm.v[y];
}

pub fn set_vx_to_vx_xor_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] ^ vm.v[y];
}

pub fn add_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[x].0 as u16 + vm.v[y].0 as u16 > 255 {
        1
    } else {
        0
    };
    vm.v[x] = vm.v[x] + vm.v[y];
}

pub fn sub_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[x] > vm.v[y] { 1 } else { 0 };
    vm.v[x] = vm.v[x] - vm.v[y];
}

pub fn subn_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[y] > vm.v[x] { 1 } else { 0 };
    vm.v[x] = vm.v[y] - vm.v[x];
}

pub fn set_vx_to_vy_shr_1(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = nth_bit(vm.v[y].0, 7);
    vm.v[x] = vm.v[y] >> 1;
}

pub fn set_vx_to_vy_shl_1(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = nth_bit(vm.v[y].0, 0);
    vm.v[x] = vm.v[y] << 1;
}

fn nth_bit(byte: u8, pos: usize) -> u8 {
    use bit_utils::BitInformation;
    if byte.has_x_bit(7 - pos) {
        1
    } else {
        0
    }
}

#[test]
fn test_nth_bit() {
    assert_eq!(nth_bit(0b10000000, 0), 1);
    for i in 1..8 {
        assert_eq!(nth_bit(0b10000000, i), 0);
    }
    assert_eq!(nth_bit(0b01000000, 1), 1);
    assert_eq!(nth_bit(0b00100000, 2), 1);
    assert_eq!(nth_bit(0b00010000, 3), 1);
    assert_eq!(nth_bit(0b00001000, 4), 1);
    assert_eq!(nth_bit(0b00000100, 5), 1);
    assert_eq!(nth_bit(0b00000010, 6), 1);
    assert_eq!(nth_bit(0b00000001, 7), 1);
}

pub fn skip_next_vx_ne_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    if vm.v[x] != vm.v[y] {
        vm.pc += 2;
    }
}

pub fn set_i(vm: &mut VirtualMachine, to: u16) {
    vm.i = to;
}

extern crate rand;

pub fn set_vx_rand_and(vm: &mut VirtualMachine, x: usize, to: u8) {
    use self::rand::Rng;
    let mut rgen = rand::thread_rng();
    vm.v[x].0 = rgen.gen::<u8>() & to;
}

pub fn display_sprite(vm: &mut VirtualMachine, vx: usize, vy: usize, n: usize) {
    use super::{DISPLAY_HEIGHT, DISPLAY_WIDTH};

    vm.v[0xF].0 = 0;

    for y in 0..n {
        let b = vm.ram[vm.i as usize + y];
        for x in 0..8 {
            let xx = x + vm.v[vx].0 as usize;
            let yy = y + vm.v[vy].0 as usize;

            if xx < DISPLAY_WIDTH && yy < DISPLAY_HEIGHT {
                let idx = yy * DISPLAY_WIDTH + xx;
                if b & (0b10000000 >> x) != 0 {
                    if vm.display[idx] == 1 {
                        vm.v[0xF].0 = 1;
                    }
                    vm.display[idx] ^= 1;
                }
            }
        }
    }

    vm.display_updated = true;
}

pub fn skip_next_key_vx_not_pressed(vm: &mut VirtualMachine, x: usize) {
    if !vm.keys[vm.v[x].0 as usize] {
        vm.pc += 2;
    }
}

pub fn skip_next_key_vx_pressed(vm: &mut VirtualMachine, x: usize) {
    if vm.keys[vm.v[x].0 as usize] {
        vm.pc += 2;
    }
}

pub fn set_vx_to_delay_timer(vm: &mut VirtualMachine, x: usize) {
    vm.v[x].0 = vm.delay_timer;
}

pub fn wait_for_keypress_store_in_vx(vm: &mut VirtualMachine, x: usize) {
    vm.keypress_wait.wait = true;
    vm.keypress_wait.vx = x;
}

pub fn set_delay_timer(vm: &mut VirtualMachine, x: usize) {
    vm.delay_timer = vm.v[x].0;
}

pub fn set_sound_timer(vm: &mut VirtualMachine, x: usize) {
    vm.sound_timer = vm.v[x].0;
}

pub fn add_vx_to_i(vm: &mut VirtualMachine, x: usize) {
    vm.i += vm.v[x].0 as u16;
}

pub fn set_i_to_loc_of_digit_vx(vm: &mut VirtualMachine, x: usize) {
    vm.i = (vm.v[x] * Wrapping(5)).0 as u16;
}

pub fn store_bcd_of_vx_to_i(vm: &mut VirtualMachine, x: usize) {
    let num = vm.v[x].0; // TODO: Should probably be wrapping
    let h = num / 100;
    let t = (num - h * 100) / 10;
    let o = num - h * 100 - t * 10;
    vm.ram[vm.i as usize] = h;
    vm.ram[vm.i as usize + 1] = t;
    vm.ram[vm.i as usize + 2] = o;
}

pub fn copy_v0_through_vx_to_mem(vm: &mut VirtualMachine, x: usize) {
    for pos in 0...x {
        vm.ram[(vm.i + pos as u16) as usize] = vm.v[pos as usize].0;
    }
    vm.i += (x + 1) as u16;
}

pub fn read_v0_through_vx_from_mem(vm: &mut VirtualMachine, x: usize) {
    for pos in 0...x {
        vm.v[pos as usize].0 = vm.ram[(vm.i + pos as u16) as usize];
    }
    vm.i += (x + 1) as u16;
}

#[test]
fn test_strore_bcd_of_vx_to_i() {
    let mut vm = VirtualMachine::new();
    vm.v[0].0 = 146;
    vm.i = 0;
    store_bcd_of_vx_to_i(&mut vm, 0);
    assert!(vm.ram[0] == 1);
    assert!(vm.ram[1] == 4);
    assert!(vm.ram[2] == 6);
}
<commit_msg>Okay cool<commit_after>use super::VirtualMachine;
use std::num::Wrapping;

pub fn jump_to_sys_routine(_vm: &mut VirtualMachine, _addr: usize) {
    // Do nothing
}

pub fn clear_display(vm: &mut VirtualMachine) {
    for px in vm.display.iter_mut() {
        *px = 0;
    }
}

pub fn ret_from_subroutine(vm: &mut VirtualMachine) {
    vm.pc = vm.stack[vm.sp as usize];
    vm.sp -= 1;
}

pub fn jump_addr(vm: &mut VirtualMachine, addr: u16) {
    vm.pc = addr;
}

pub fn call_subroutine(vm: &mut VirtualMachine, addr: usize) {
    vm.sp += 1;
    vm.stack[vm.sp as usize] = vm.pc;
    vm.pc = addr as u16;
}

pub fn skip_next_vx_eq(vm: &mut VirtualMachine, x: usize, to: u8) {
    if vm.v[x].0 == to {
        vm.pc += 2;
    }
}

pub fn skip_next_vx_ne(vm: &mut VirtualMachine, x: usize, to: u8) {
    if vm.v[x].0 != to {
        vm.pc += 2;
    }
}

pub fn skip_next_vx_eq_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    if vm.v[x] == vm.v[y] {
        vm.pc += 2;
    }
}

pub fn set_vx_byte(vm: &mut VirtualMachine, x: usize, byte: u8) {
    vm.v[x].0 = byte;
}

pub fn add_vx_byte(vm: &mut VirtualMachine, x: usize, byte: u8) {
    vm.v[x] += Wrapping(byte);
}

pub fn set_vx_to_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[y];
}

pub fn set_vx_to_vx_or_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] |= vm.v[y];
}

pub fn set_vx_to_vx_and_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] &= vm.v[y];
}

pub fn set_vx_to_vx_xor_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] ^= vm.v[y];
}

pub fn add_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[x].0 as u16 + vm.v[y].0 as u16 > 255 {
        1
    } else {
        0
    };
    vm.v[x] += vm.v[y];
}

pub fn sub_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[x] > vm.v[y] { 1 } else { 0 };
    vm.v[x] -= vm.v[y];
}

pub fn subn_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[y] > vm.v[x] { 1 } else { 0 };
    vm.v[x] = vm.v[y] - vm.v[x];
}

pub fn set_vx_to_vy_shr_1(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = nth_bit(vm.v[y].0, 7);
    vm.v[x] = vm.v[y] >> 1;
}

pub fn set_vx_to_vy_shl_1(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = nth_bit(vm.v[y].0, 0);
    vm.v[x] = vm.v[y] << 1;
}

fn nth_bit(byte: u8, pos: usize) -> u8 {
    use bit_utils::BitInformation;
    if byte.has_x_bit(7 - pos) {
        1
    } else {
        0
    }
}

#[test]
fn test_nth_bit() {
    assert_eq!(nth_bit(0b10000000, 0), 1);
    for i in 1..8 {
        assert_eq!(nth_bit(0b10000000, i), 0);
    }
    assert_eq!(nth_bit(0b01000000, 1), 1);
    assert_eq!(nth_bit(0b00100000, 2), 1);
    assert_eq!(nth_bit(0b00010000, 3), 1);
    assert_eq!(nth_bit(0b00001000, 4), 1);
    assert_eq!(nth_bit(0b00000100, 5), 1);
    assert_eq!(nth_bit(0b00000010, 6), 1);
    assert_eq!(nth_bit(0b00000001, 7), 1);
}

pub fn skip_next_vx_ne_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    if vm.v[x] != vm.v[y] {
        vm.pc += 2;
    }
}

pub fn set_i(vm: &mut VirtualMachine, to: u16) {
    vm.i = to;
}

extern crate rand;

pub fn set_vx_rand_and(vm: &mut VirtualMachine, x: usize, to: u8) {
    use self::rand::Rng;
    let mut rgen = rand::thread_rng();
    vm.v[x].0 = rgen.gen::<u8>() & to;
}

pub fn display_sprite(vm: &mut VirtualMachine, vx: usize, vy: usize, n: usize) {
    use super::{DISPLAY_HEIGHT, DISPLAY_WIDTH};

    vm.v[0xF].0 = 0;

    for y in 0..n {
        let b = vm.ram[vm.i as usize + y];
        for x in 0..8 {
            let xx = x + vm.v[vx].0 as usize;
            let yy = y + vm.v[vy].0 as usize;

            if xx < DISPLAY_WIDTH && yy < DISPLAY_HEIGHT {
                let idx = yy * DISPLAY_WIDTH + xx;
                if b & (0b10000000 >> x) != 0 {
                    if vm.display[idx] == 1 {
                        vm.v[0xF].0 = 1;
                    }
                    vm.display[idx] ^= 1;
                }
            }
        }
    }

    vm.display_updated = true;
}

pub fn skip_next_key_vx_not_pressed(vm: &mut VirtualMachine, x: usize) {
    if !vm.keys[vm.v[x].0 as usize] {
        vm.pc += 2;
    }
}

pub fn skip_next_key_vx_pressed(vm: &mut VirtualMachine, x: usize) {
    if vm.keys[vm.v[x].0 as usize] {
        vm.pc += 2;
    }
}

pub fn set_vx_to_delay_timer(vm: &mut VirtualMachine, x: usize) {
    vm.v[x].0 = vm.delay_timer;
}

pub fn wait_for_keypress_store_in_vx(vm: &mut VirtualMachine, x: usize) {
    vm.keypress_wait.wait = true;
    vm.keypress_wait.vx = x;
}

pub fn set_delay_timer(vm: &mut VirtualMachine, x: usize) {
    vm.delay_timer = vm.v[x].0;
}

pub fn set_sound_timer(vm: &mut VirtualMachine, x: usize) {
    vm.sound_timer = vm.v[x].0;
}

pub fn add_vx_to_i(vm: &mut VirtualMachine, x: usize) {
    vm.i += vm.v[x].0 as u16;
}

pub fn set_i_to_loc_of_digit_vx(vm: &mut VirtualMachine, x: usize) {
    vm.i = (vm.v[x] * Wrapping(5)).0 as u16;
}

pub fn store_bcd_of_vx_to_i(vm: &mut VirtualMachine, x: usize) {
    let num = vm.v[x].0; // TODO: Should probably be wrapping
    let h = num / 100;
    let t = (num - h * 100) / 10;
    let o = num - h * 100 - t * 10;
    vm.ram[vm.i as usize] = h;
    vm.ram[vm.i as usize + 1] = t;
    vm.ram[vm.i as usize + 2] = o;
}

pub fn copy_v0_through_vx_to_mem(vm: &mut VirtualMachine, x: usize) {
    for pos in 0...x {
        vm.ram[(vm.i + pos as u16) as usize] = vm.v[pos as usize].0;
    }
    vm.i += (x + 1) as u16;
}

pub fn read_v0_through_vx_from_mem(vm: &mut VirtualMachine, x: usize) {
    for pos in 0...x {
        vm.v[pos as usize].0 = vm.ram[(vm.i + pos as u16) as usize];
    }
    vm.i += (x + 1) as u16;
}

#[test]
fn test_strore_bcd_of_vx_to_i() {
    let mut vm = VirtualMachine::new();
    vm.v[0].0 = 146;
    vm.i = 0;
    store_bcd_of_vx_to_i(&mut vm, 0);
    assert!(vm.ram[0] == 1);
    assert!(vm.ram[1] == 4);
    assert!(vm.ram[2] == 6);
}
<|endoftext|>


<commit_before>//! The XPath functionality

use c_signatures::*;
use libc::{c_void, size_t};
use tree::{Document, Node};
use std::ffi::{CString};

///The xpath context
#[derive(Clone)]
pub struct Context {
    ///libxml's `ContextPtr`
    pub context_ptr : *mut c_void,
}

impl Drop for Context {
    ///free xpath context when it goes out of scope
    fn drop(&mut self) {
        unsafe {
            xmlXPathFreeContext(self.context_ptr);
        }
    }
}

///Essentially, the result of the evaluation of some xpath expression
#[derive(Clone)]
pub struct Object {
    ///libxml's `ObjectPtr`
    pub ptr : *mut c_void,
}

impl Context {
    ///create the xpath context for a document
    pub fn new(doc : &Document) -> Result<Context, ()> {
        let ctxtptr : *mut c_void = unsafe {
            xmlXPathNewContext(doc.doc_ptr) };
        if ctxtptr.is_null() {
            Err(())
        } else {
            Ok(Context {context_ptr : ctxtptr })
        }
    }
    ///evaluate an xpath
    pub fn evaluate(&self, xpath: &str) -> Result<Object, ()> {
        let c_xpath = CString::new(xpath).unwrap();
        let result = unsafe { xmlXPathEvalExpression(c_xpath.as_ptr(), self.context_ptr) };
        if result.is_null() {
            Err(())
        } else {
            Ok(Object {ptr : result})
        }
    }
}

impl Drop for Object {
    /// free the memory allocated
    fn drop(&mut self) {
        unsafe {
            xmlFreeXPathObject(self.ptr);
        }
    }
}

impl Object {
    ///get the number of nodes in the result set
    pub fn get_number_of_nodes(&self) -> usize {
        let v = unsafe { xmlXPathObjectNumberOfNodes(self.ptr) };
        if v == -1 {
            panic!("rust-libxml: xpath: Passed in null pointer!");
        }
        if v == -2 {
            // No nodes found!
            return 0;
        }
        if v < -2 {
            panic!("rust-libxml: xpath: expected non-negative number of result nodes");
        }
        v as usize
    }

    /// returns the result set as a vector of node references
    pub fn get_nodes_as_vec(&self) -> Vec<Node> {
        let n = self.get_number_of_nodes();
        let mut vec : Vec<Node> = Vec::with_capacity(n);
        for i in 0..n {
            let ptr : *mut c_void = unsafe {
                xmlXPathObjectGetNode(self.ptr, i as size_t) };
            if ptr.is_null() {
                panic!("rust-libxml: xpath: found null pointer result set");
            }
            vec.push(Node { node_ptr : ptr, });//node_is_inserted : true
        }
        vec
    }
}
<commit_msg>Doc out of scope (#10)<commit_after>//! The XPath functionality

use c_signatures::*;
use libc::{c_void, size_t};
use tree::{Document, Node};
use std::ffi::{CString};

///The xpath context
#[derive(Clone)]
pub struct Context<'a> {
    ///libxml's `ContextPtr`
    pub context_ptr : *mut c_void,
    ///Document contains pointer, needed for ContextPtr, so we need to borrow Document to prevent it's freeing
    pub document: &'a Document,
}

impl<'a> Drop for Context<'a> {
    ///free xpath context when it goes out of scope
    fn drop(&mut self) {
        unsafe {
            xmlXPathFreeContext(self.context_ptr);
        }
    }
}

///Essentially, the result of the evaluation of some xpath expression
#[derive(Clone)]
pub struct Object {
    ///libxml's `ObjectPtr`
    pub ptr : *mut c_void,
}

impl<'a> Context<'a> {
    ///create the xpath context for a document
    pub fn new(doc : &Document) -> Result<Context, ()> {
        let ctxtptr : *mut c_void = unsafe {
            xmlXPathNewContext(doc.doc_ptr) };
        if ctxtptr.is_null() {
            Err(())
        } else {
            Ok(Context {context_ptr : ctxtptr, document: doc })
        }
    }
    ///evaluate an xpath
    pub fn evaluate(&self, xpath: &str) -> Result<Object, ()> {
        let c_xpath = CString::new(xpath).unwrap();
        let result = unsafe { xmlXPathEvalExpression(c_xpath.as_ptr(), self.context_ptr) };
        if result.is_null() {
            Err(())
        } else {
            Ok(Object {ptr : result})
        }
    }
}

impl Drop for Object {
    /// free the memory allocated
    fn drop(&mut self) {
        unsafe {
            xmlFreeXPathObject(self.ptr);
        }
    }
}

impl Object {
    ///get the number of nodes in the result set
    pub fn get_number_of_nodes(&self) -> usize {
        let v = unsafe { xmlXPathObjectNumberOfNodes(self.ptr) };
        if v == -1 {
            panic!("rust-libxml: xpath: Passed in null pointer!");
        }
        if v == -2 {
            // No nodes found!
            return 0;
        }
        if v < -2 {
            panic!("rust-libxml: xpath: expected non-negative number of result nodes");
        }
        v as usize
    }

    /// returns the result set as a vector of node references
    pub fn get_nodes_as_vec(&self) -> Vec<Node> {
        let n = self.get_number_of_nodes();
        let mut vec : Vec<Node> = Vec::with_capacity(n);
        for i in 0..n {
            let ptr : *mut c_void = unsafe {
                xmlXPathObjectGetNode(self.ptr, i as size_t) };
            if ptr.is_null() {
                panic!("rust-libxml: xpath: found null pointer result set");
            }
            vec.push(Node { node_ptr : ptr, });//node_is_inserted : true
        }
        vec
    }
}
<|endoftext|>


<commit_before>//! Duplicate the elements of a list. (easy)
///# Example
///```
///use p99::p14::duplicate;
///assert_eq!(duplicate(&['a','b','c']),vec!['a','a','b','b','c','c'])
///```

pub fn duplicate(list: &[char]) -> Vec<char> {
    let mut result: Vec<char> = vec![];
    for i in list {
        result.push(*i);
        result.push(*i);
    }
    result
}
<commit_msg>other version of p14<commit_after>//! Duplicate the elements of a list. (easy)
///# Example
///```
///use p99::p14::duplicate;
///assert_eq!(duplicate(&['a','b','c']),vec!['a','a','b','b','c','c'])
///```
///# Example
///```
///use p99::p14::duplicate2;
///assert_eq!(duplicate2(&['a','b','c']),vec!['a','a','b','b','c','c'])
///```
///# Example
///```
///use p99::p14::duplicate3;
///assert_eq!(duplicate3(&['a','b','c']),vec!['a','a','b','b','c','c'])
///```

pub fn duplicate(list: &[char]) -> Vec<char> {
    let mut result: Vec<char> = vec![];
    for i in list {
        result.push(*i);
        result.push(*i);
    }
    result
}

pub fn duplicate2(list: &[char]) -> Vec<char> {
    let result: Vec<char> = list.iter().map(|x| vec![*x,*x]).fold(vec![],|sum : Vec<char>, x: Vec<char>| {
        let mut sum = sum.clone();
        let x = &mut x.clone();
        sum.append(x);
        sum
    });
    result
}

pub fn duplicate3(list: &[char]) -> Vec<char> {
    list.iter().flat_map(|x| vec![*x,*x]).collect::<Vec<char>>()
}
<|endoftext|>


<commit_before>// Copyright (C) 2016, 2017 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

use error::{Error, Result, Source};
use html::HtmlRenderer;
use html::Highlight;
use book::{Book, compile_str};
use token::Token;
use renderer::Renderer;
use book_renderer::BookRenderer;
use parser::Parser;
use text_view::view_as_text;

use rustc_serialize::base64::{self, ToBase64};

use std::convert::{AsMut, AsRef};
use std::io;
use std::mem;

/// Interactive fiction HTML renderer
///
/// Renders a standalone, self-contained HTML file
pub struct HtmlIfRenderer<'a> {
    html: HtmlRenderer<'a>,
    n_fn: u32,
    curr_init: String,
    fn_defs: String,
}

impl<'a> HtmlIfRenderer<'a> {
    /// Creates a new HtmlIfRenderer
    pub fn new(book: &'a Book) -> Result<HtmlIfRenderer<'a>> {
        let mut html = HtmlRenderer::new(book,
                                         book.options
                                         .get_str("html.highlight.theme")
                                         .unwrap_or_else(|_| book.options.get_str("rendering.highlight.theme").unwrap()))?;
        html.handler.set_images_mapping(true);
        html.handler.set_base64(true);
        Ok(
            HtmlIfRenderer {
                html: html,
                n_fn: 0,
                curr_init: String::new(),
                fn_defs: String::new(),
            }
        )
    }

    /// Renders a token
    ///
    /// Used by render_token implementation of Renderer trait. Separate function
    /// because we need to be able to call it from other renderers.
    ///
    /// See http://lise-henry.github.io/articles/rust_inheritance.html
    #[doc(hidden)]
    pub fn static_render_token<T>(this: &mut T, token: &Token) -> Result<String>
    where T: AsMut<HtmlIfRenderer<'a>>+AsRef<HtmlIfRenderer<'a>> +
        AsMut<HtmlRenderer<'a>>+AsRef<HtmlRenderer<'a>> + Renderer
    {
        match *token {
            Token::CodeBlock(ref language, ref v) if language == "" => {
                let mut html_if: &mut HtmlIfRenderer = this.as_mut();
                let code = view_as_text(v);
                let mut gen_code = String::new();
                let mut i = 0;
                while let Some(begin) = code[i..].find("@\"") {
                    let begin = i + begin;
                    if let Some(len) = code[begin..].find("\"@") {
                        let end = begin + len;
                        gen_code.push_str(&code[i..begin]);
                        gen_code.push('"');
                        gen_code.push_str(&html_if.render_vec(
                            &Parser::new()
                                .parse(&code[begin+2..end])?)?
                                          .replace('"', "\\\"")
                                          .replace('\n', "\\\n"));
                        gen_code.push('"');
                        i = end + 2;
                    }  else {
                        gen_code.push_str(&code[i..begin+2]);
                        i = begin + 2;
                    }
                }
                gen_code.push_str(&code[i..]);
                let id = html_if.n_fn;
                html_if.fn_defs
                    .push_str(&format!("function fn_{id}() {{
    {code}
}}\n",
                                       id = id,
                                       code = gen_code));
                html_if.curr_init
                    .push_str(&format!("    result = fn_{id}();
    if (result != undefined) {{
        document.getElementById(\"result_{id}\").innerHTML = fn_{id}();
    }}\n",
                                       id = id));
                let content = format!("

\n",
                                      (html_if.n_fn));
                html_if.n_fn += 1;
                Ok(content)

            },
            _ => HtmlRenderer::static_render_token(this, token)
        }
    }

    /// Render books as a standalone HTML file
    pub fn render_book(&mut self) -> Result<String> {
        let mut content = String::new();

        let mut titles = vec![];
        let mut chapters = vec![];
        let render_notes_chapter = true;

        for (i, chapter) in self.html.book.chapters.iter().enumerate() {
            self.html.handler.add_link(chapter.filename.as_ref(),
                                       format!("#chapter-{}", i));
        }

        for (i, chapter) in self.html.book.chapters.iter().enumerate() {
            let n = chapter.number;
            let v = &chapter.content;
            self.html.chapter_config(i, n, String::new());

            let mut title = String::new();
            for token in v {
                match *token {
                    Token::Header(1, ref vec) => {
                        if self.html.current_hide || self.html.current_numbering == 0 {
                            title = self.html.render_vec(vec)?;
                        } else {
                            title = self.html
                                .book
                                .get_chapter_header(self.html.current_chapter[1] + 1,
                                                    self.html.render_vec(vec)?,
                                                    |s| {
                                                        self.render_vec(&Parser::new()
                                                            .parse_inline(s)?)
                                                    })?
                                .text;
                        }
                        break;
                    }
                    _ => {
                        continue;
                    }
                }
            }
            titles.push(title);

            chapters.push(format!("

  {}

",
                                  i,
                                  HtmlRenderer::render_html(self, v, render_notes_chapter)?));
            self.fn_defs.push_str(&format!("initFns.push(function () {{
    {code}
}})\n",
                                           code = self.curr_init));
            self.curr_init = String::new();
        }

        self.html.source = Source::empty();

        for chapter in &chapters {
            content.push_str(chapter);
        }
        self.html.render_end_notes(&mut content);

        // Render the CSS
        let template_css = compile_str(self.html.book.get_template("html.css")?
                                       .as_ref(),
                                       &self.html.book.source,
                                       "html.css")?;
        let mut data = self.html
            .book
            .get_metadata(|s| self.render_vec(&Parser::new().parse_inline(s)?))?
            .insert_str("colours",
                        self.html.book.get_template("html.css.colours")?);
        if let Ok(html_css_add) = self.html.book.options.get_str("html.css.add") {
            data = data.insert_str("additional_code", html_css_add);
        }
        let data = data.build();
        let mut res: Vec<u8> = vec![];
        template_css.render_data(&mut res, &data)?;
        let css = String::from_utf8_lossy(&res);

        // Render the JS
        let template_js =
            compile_str(self.html.book.get_template("html.if.js")?.as_ref(),
                        &self.html.book.source,
                        "html.standalone.js")?;
        let data = self.html.book.get_metadata(|s| Ok(s.to_owned()))?
            .insert_bool("one_chapter", true)
            .insert_str("js_prelude", mem::replace(&mut self.fn_defs, String::new()))
            .insert_str("common_script",
                        self.html.book.get_template("html.js").unwrap().as_ref())
            .build();
        let mut res: Vec<u8> = vec![];
        template_js.render_data(&mut res, &data)?;
        let js = String::from_utf8_lossy(&res);

        // Render the HTML document
        let mut mapbuilder = self.html
            .book
            .get_metadata(|s| self.render_vec(&Parser::new().parse_inline(s)?))?
            .insert_str("content", content)
            .insert_str("script", js)
            .insert_bool(self.html.book.options.get_str("lang").unwrap(), true)
            .insert_bool("one_chapter", true)
            .insert_str("style", css.as_ref())
            .insert_str("print_style",
                        self.html.book.get_template("html.css.print").unwrap())
            .insert_str("footer", HtmlRenderer::get_footer(self)?)
            .insert_str("header", HtmlRenderer::get_header(self)?)
            .insert_bool("has_toc", false);
        if let Ok(favicon) = self.html.book.options.get_path("html.icon") {
                let favicon = self.html.handler.map_image(&self.html.book.source, favicon)?;
                mapbuilder = mapbuilder.insert_str("favicon", format!("<link rel = \"icon\" href = \"{}\">", favicon));
            }
        if self.html.highlight == Highlight::Js {
            let highlight_js = self.html.book.get_template("html.highlight.js")?
                .as_bytes()
                .to_base64(base64::STANDARD);
            let highlight_js = format!("data:text/javascript;base64,{}", highlight_js);
            mapbuilder = mapbuilder.insert_bool("highlight_code", true)
                .insert_str("highlight_css",
                            self.html.book.get_template("html.highlight.css")?)
                .insert_str("highlight_js", highlight_js);
        }
        let data = mapbuilder.build();
        let template = compile_str(self.html.book.get_template("html.standalone.template")?
                                   .as_ref(),
                                   &self.html.book.source,
                                   "html.standalone.template")?;
        let mut res = vec![];
        template.render_data(&mut res, &data)?;
        Ok(String::from_utf8_lossy(&res).into_owned())
    }
}

derive_html!{HtmlIfRenderer<'a>, HtmlIfRenderer::static_render_token}

pub struct HtmlIf {}

impl BookRenderer for HtmlIf {
    fn render(&self, book: &Book, to: &mut io::Write) -> Result<()> {
        let mut html = HtmlIfRenderer::new(book)?;
        let result = html.render_book()?;
        to.write_all(result.as_bytes())
            .map_err(|e| {
                Error::render(&book.source,
                              lformat!("problem when writing interactive fiction: {error}", error = e))
            })?;
        Ok(())
    }
}
<commit_msg>Make code block in IF generate p container if no markdown code is generated<commit_after>// Copyright (C) 2016, 2017 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

use error::{Error, Result, Source};
use html::HtmlRenderer;
use html::Highlight;
use book::{Book, compile_str};
use token::Token;
use renderer::Renderer;
use book_renderer::BookRenderer;
use parser::Parser;
use text_view::view_as_text;

use rustc_serialize::base64::{self, ToBase64};

use std::convert::{AsMut, AsRef};
use std::io;
use std::mem;

/// Interactive fiction HTML renderer
///
/// Renders a standalone, self-contained HTML file
pub struct HtmlIfRenderer<'a> {
    html: HtmlRenderer<'a>,
    n_fn: u32,
    curr_init: String,
    fn_defs: String,
}

impl<'a> HtmlIfRenderer<'a> {
    /// Creates a new HtmlIfRenderer
    pub fn new(book: &'a Book) -> Result<HtmlIfRenderer<'a>> {
        let mut html = HtmlRenderer::new(book,
                                         book.options
                                         .get_str("html.highlight.theme")
                                         .unwrap_or_else(|_| book.options.get_str("rendering.highlight.theme").unwrap()))?;
        html.handler.set_images_mapping(true);
        html.handler.set_base64(true);
        Ok(
            HtmlIfRenderer {
                html: html,
                n_fn: 0,
                curr_init: String::new(),
                fn_defs: String::new(),
            }
        )
    }

    /// Renders a token
    ///
    /// Used by render_token implementation of Renderer trait. Separate function
    /// because we need to be able to call it from other renderers.
    ///
    /// See http://lise-henry.github.io/articles/rust_inheritance.html
    #[doc(hidden)]
    pub fn static_render_token<T>(this: &mut T, token: &Token) -> Result<String>
    where T: AsMut<HtmlIfRenderer<'a>>+AsRef<HtmlIfRenderer<'a>> +
        AsMut<HtmlRenderer<'a>>+AsRef<HtmlRenderer<'a>> + Renderer
    {
        match *token {
            Token::CodeBlock(ref language, ref v) if language == "" => {
                let mut html_if: &mut HtmlIfRenderer = this.as_mut();
                let code = view_as_text(v);
                let mut gen_code = String::new();
                let mut i = 0;
                while let Some(begin) = code[i..].find("@\"") {
                    let begin = i + begin;
                    if let Some(len) = code[begin..].find("\"@") {
                        let end = begin + len;
                        gen_code.push_str(&code[i..begin]);
                        gen_code.push('"');
                        gen_code.push_str(&html_if.render_vec(
                            &Parser::new()
                                .parse(&code[begin+2..end])?)?
                                          .replace('"', "\\\"")
                                          .replace('\n', "\\\n"));
                        gen_code.push('"');
                        i = end + 2;
                    }  else {
                        gen_code.push_str(&code[i..begin+2]);
                        i = begin + 2;
                    }
                }
                gen_code.push_str(&code[i..]);
                let container = if i == 0 {
                    "p"
                } else {
                    "div"
                };
                let id = html_if.n_fn;
                html_if.fn_defs
                    .push_str(&format!("function fn_{id}() {{
    {code}
}}\n",
                                       id = id,
                                       code = gen_code));
                html_if.curr_init
                    .push_str(&format!("    result = fn_{id}();
    if (result != undefined) {{
        document.getElementById(\"result_{id}\").innerHTML = result;
    }}\n",
                                       id = id));
                let content = format!("<{container} id = \"result_{id}\"></{container}>\n",
                                      id = (html_if.n_fn),
                                      container = container);
                html_if.n_fn += 1;
                Ok(content)

            },
            _ => HtmlRenderer::static_render_token(this, token)
        }
    }

    /// Render books as a standalone HTML file
    pub fn render_book(&mut self) -> Result<String> {
        let mut content = String::new();

        let mut titles = vec![];
        let mut chapters = vec![];
        let render_notes_chapter = true;

        for (i, chapter) in self.html.book.chapters.iter().enumerate() {
            self.html.handler.add_link(chapter.filename.as_ref(),
                                       format!("#chapter-{}", i));
        }

        for (i, chapter) in self.html.book.chapters.iter().enumerate() {
            let n = chapter.number;
            let v = &chapter.content;
            self.html.chapter_config(i, n, String::new());

            let mut title = String::new();
            for token in v {
                match *token {
                    Token::Header(1, ref vec) => {
                        if self.html.current_hide || self.html.current_numbering == 0 {
                            title = self.html.render_vec(vec)?;
                        } else {
                            title = self.html
                                .book
                                .get_chapter_header(self.html.current_chapter[1] + 1,
                                                    self.html.render_vec(vec)?,
                                                    |s| {
                                                        self.render_vec(&Parser::new()
                                                            .parse_inline(s)?)
                                                    })?
                                .text;
                        }
                        break;
                    }
                    _ => {
                        continue;
                    }
                }
            }
            titles.push(title);

            chapters.push(format!("

  {}

",
                                  i,
                                  HtmlRenderer::render_html(self, v, render_notes_chapter)?));
            self.fn_defs.push_str(&format!("initFns.push(function () {{
    {code}
}})\n",
                                           code = self.curr_init));
            self.curr_init = String::new();
        }

        self.html.source = Source::empty();

        for chapter in &chapters {
            content.push_str(chapter);
        }
        self.html.render_end_notes(&mut content);

        // Render the CSS
        let template_css = compile_str(self.html.book.get_template("html.css")?
                                       .as_ref(),
                                       &self.html.book.source,
                                       "html.css")?;
        let mut data = self.html
            .book
            .get_metadata(|s| self.render_vec(&Parser::new().parse_inline(s)?))?
            .insert_str("colours",
                        self.html.book.get_template("html.css.colours")?);
        if let Ok(html_css_add) = self.html.book.options.get_str("html.css.add") {
            data = data.insert_str("additional_code", html_css_add);
        }
        let data = data.build();
        let mut res: Vec<u8> = vec![];
        template_css.render_data(&mut res, &data)?;
        let css = String::from_utf8_lossy(&res);

        // Render the JS
        let template_js =
            compile_str(self.html.book.get_template("html.if.js")?.as_ref(),
                        &self.html.book.source,
                        "html.standalone.js")?;
        let data = self.html.book.get_metadata(|s| Ok(s.to_owned()))?
            .insert_bool("one_chapter", true)
            .insert_str("js_prelude", mem::replace(&mut self.fn_defs, String::new()))
            .insert_str("common_script",
                        self.html.book.get_template("html.js").unwrap().as_ref())
            .build();
        let mut res: Vec<u8> = vec![];
        template_js.render_data(&mut res, &data)?;
        let js = String::from_utf8_lossy(&res);

        // Render the HTML document
        let mut mapbuilder = self.html
            .book
            .get_metadata(|s| self.render_vec(&Parser::new().parse_inline(s)?))?
            .insert_str("content", content)
            .insert_str("script", js)
            .insert_bool(self.html.book.options.get_str("lang").unwrap(), true)
            .insert_bool("one_chapter", true)
            .insert_str("style", css.as_ref())
            .insert_str("print_style",
                        self.html.book.get_template("html.css.print").unwrap())
            .insert_str("footer", HtmlRenderer::get_footer(self)?)
            .insert_str("header", HtmlRenderer::get_header(self)?)
            .insert_bool("has_toc", false);
        if let Ok(favicon) = self.html.book.options.get_path("html.icon") {
                let favicon = self.html.handler.map_image(&self.html.book.source, favicon)?;
                mapbuilder = mapbuilder.insert_str("favicon", format!("<link rel = \"icon\" href = \"{}\">", favicon));
            }
        if self.html.highlight == Highlight::Js {
            let highlight_js = self.html.book.get_template("html.highlight.js")?
                .as_bytes()
                .to_base64(base64::STANDARD);
            let highlight_js = format!("data:text/javascript;base64,{}", highlight_js);
            mapbuilder = mapbuilder.insert_bool("highlight_code", true)
                .insert_str("highlight_css",
                            self.html.book.get_template("html.highlight.css")?)
                .insert_str("highlight_js", highlight_js);
        }
        let data = mapbuilder.build();
        let template = compile_str(self.html.book.get_template("html.standalone.template")?
                                   .as_ref(),
                                   &self.html.book.source,
                                   "html.standalone.template")?;
        let mut res = vec![];
        template.render_data(&mut res, &data)?;
        Ok(String::from_utf8_lossy(&res).into_owned())
    }
}

derive_html!{HtmlIfRenderer<'a>, HtmlIfRenderer::static_render_token}

pub struct HtmlIf {}

impl BookRenderer for HtmlIf {
    fn render(&self, book: &Book, to: &mut io::Write) -> Result<()> {
        let mut html = HtmlIfRenderer::new(book)?;
        let result = html.render_book()?;
        to.write_all(result.as_bytes())
            .map_err(|e| {
                Error::render(&book.source,
                              lformat!("problem when writing interactive fiction: {error}", error = e))
            })?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Core operators

#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];

#[lang="drop"]
pub trait Drop {
    fn finalize(&self);  // XXX: Rename to "drop"? --pcwalton
}

#[lang="add"]
pub trait Add<RHS,Result> {
    pure fn add(&self, rhs: &RHS) -> Result;
}

#[lang="sub"]
pub trait Sub<RHS,Result> {
    pure fn sub(&self, rhs: &RHS) -> Result;
}

#[lang="mul"]
pub trait Mul<RHS,Result> {
    pure fn mul(&self, rhs: &RHS) -> Result;
}

#[lang="div"]
pub trait Div<RHS,Result> {
    pure fn div(&self, rhs: &RHS) -> Result;
}

#[lang="modulo"]
pub trait Modulo<RHS,Result> {
    pure fn modulo(&self, rhs: &RHS) -> Result;
}

#[lang="neg"]
pub trait Neg<Result> {
    pure fn neg(&self) -> Result;
}

#[lang="bitand"]
pub trait BitAnd<RHS,Result> {
    pure fn bitand(&self, rhs: &RHS) -> Result;
}

#[lang="bitor"]
pub trait BitOr<RHS,Result> {
    pure fn bitor(&self, rhs: &RHS) -> Result;
}

#[lang="bitxor"]
pub trait BitXor<RHS,Result> {
    pure fn bitxor(&self, rhs: &RHS) -> Result;
}

#[lang="shl"]
pub trait Shl<RHS,Result> {
    pure fn shl(&self, rhs: &RHS) -> Result;
}

#[lang="shr"]
pub trait Shr<RHS,Result> {
    pure fn shr(&self, rhs: &RHS) -> Result;
}

#[lang="index"]
pub trait Index<Index,Result> {
    pure fn index(&self, index: Index) -> Result;
}

<commit_msg>core: convert an XXX into a FIXME.<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Core operators

#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];

#[lang="drop"]
pub trait Drop {
    fn finalize(&self);  // FIXME(#4332): Rename to "drop"? --pcwalton
}

#[lang="add"]
pub trait Add<RHS,Result> {
    pure fn add(&self, rhs: &RHS) -> Result;
}

#[lang="sub"]
pub trait Sub<RHS,Result> {
    pure fn sub(&self, rhs: &RHS) -> Result;
}

#[lang="mul"]
pub trait Mul<RHS,Result> {
    pure fn mul(&self, rhs: &RHS) -> Result;
}

#[lang="div"]
pub trait Div<RHS,Result> {
    pure fn div(&self, rhs: &RHS) -> Result;
}

#[lang="modulo"]
pub trait Modulo<RHS,Result> {
    pure fn modulo(&self, rhs: &RHS) -> Result;
}

#[lang="neg"]
pub trait Neg<Result> {
    pure fn neg(&self) -> Result;
}

#[lang="bitand"]
pub trait BitAnd<RHS,Result> {
    pure fn bitand(&self, rhs: &RHS) -> Result;
}

#[lang="bitor"]
pub trait BitOr<RHS,Result> {
    pure fn bitor(&self, rhs: &RHS) -> Result;
}

#[lang="bitxor"]
pub trait BitXor<RHS,Result> {
    pure fn bitxor(&self, rhs: &RHS) -> Result;
}

#[lang="shl"]
pub trait Shl<RHS,Result> {
    pure fn shl(&self, rhs: &RHS) -> Result;
}

#[lang="shr"]
pub trait Shr<RHS,Result> {
    pure fn shr(&self, rhs: &RHS) -> Result;
}

#[lang="index"]
pub trait Index<Index,Result> {
    pure fn index(&self, index: Index) -> Result;
}

<|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * Concurrency-enabled mechanisms and primitives.
 */

#[crate_id = "sync#0.10-pre"];
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
      html_root_url = "http://static.rust-lang.org/doc/master")];
#[feature(phase)];

#[cfg(test)] #[phase(syntax, link)] extern crate log;

pub use arc::{Arc, MutexArc, RWArc, RWWriteMode, RWReadMode, ArcCondvar, CowArc};
pub use sync::{Mutex, RWLock, Condvar, Semaphore, RWLockWriteMode,
               RWLockReadMode, Barrier, one, mutex};
pub use comm::{DuplexStream, SyncSender, SyncReceiver, rendezvous, duplex};
pub use task_pool::TaskPool;
pub use future::Future;

mod arc;
mod sync;
mod comm;
mod task_pool;
mod future;
<commit_msg>sync: Wire up all of the previous commits<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * Concurrency-enabled mechanisms and primitives.
 */

#[crate_id = "sync#0.10-pre"];
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
      html_root_url = "http://static.rust-lang.org/doc/master")];
#[feature(phase)];
#[deny(missing_doc, deprecated_owned_vector)];

#[cfg(test)]
#[phase(syntax, link)] extern crate log;

pub use comm::{DuplexStream, SyncSender, SyncReceiver, rendezvous, duplex};
pub use task_pool::TaskPool;
pub use future::Future;
pub use arc::{Arc, Weak};
pub use lock::{Mutex, MutexGuard, Condvar, Barrier,
               RWLock, RWLockReadGuard, RWLockWriteGuard};

// The mutex/rwlock in this module are not meant for reexport
pub use raw::{Semaphore, SemaphoreGuard};

mod arc;
mod comm;
mod future;
mod lock;
mod mpsc_intrusive;
mod task_pool;

pub mod raw;
pub mod mutex;
pub mod one;
<|endoftext|>


<commit_before>use super::{Tm, ParseError, NSEC_PER_SEC};
use super::ParseError::*;

/// Parses the time from the string according to the format string.
pub fn strptime(mut s: &str, format: &str) -> Result<Tm, ParseError> {
    let mut tm = Tm {
        tm_sec: 0,
        tm_min: 0,
        tm_hour: 0,
        tm_mday: 0,
        tm_mon: 0,
        tm_year: 0,
        tm_wday: 0,
        tm_yday: 0,
        tm_isdst: 0,
        tm_utcoff: 0,
        tm_nsec: 0,
    };
    let mut chars = format.chars();

    while let Some(ch) = chars.next() {
        if ch == '%' {
            if let Some(ch) = chars.next() {
                try!(parse_type(&mut s, ch, &mut tm));
            }
        } else {
            try!(parse_char(&mut s, ch));
        }
    }

    Ok(tm)
}

fn parse_type(s: &mut &str, ch: char, tm: &mut Tm) -> Result<(), ParseError> {
    match ch {
        'A' => match match_strs(s, &[("Sunday", 0),
                                     ("Monday", 1),
                                     ("Tuesday", 2),
                                     ("Wednesday", 3),
                                     ("Thursday", 4),
                                     ("Friday", 5),
                                     ("Saturday", 6)]) {
            Some(v) => { tm.tm_wday = v; Ok(()) }
            None => Err(ParseError::InvalidDay)
        },
        'a' => match match_strs(s, &[("Sun", 0),
                                     ("Mon", 1),
                                     ("Tue", 2),
                                     ("Wed", 3),
                                     ("Thu", 4),
                                     ("Fri", 5),
                                     ("Sat", 6)]) {
            Some(v) => { tm.tm_wday = v; Ok(()) }
            None => Err(ParseError::InvalidDay)
        },
        'B' => match match_strs(s, &[("January", 0),
                                     ("February", 1),
                                     ("March", 2),
                                     ("April", 3),
                                     ("May", 4),
                                     ("June", 5),
                                     ("July", 6),
                                     ("August", 7),
                                     ("September", 8),
                                     ("October", 9),
                                     ("November", 10),
                                     ("December", 11)]) {
            Some(v) => { tm.tm_mon = v; Ok(()) }
            None => Err(ParseError::InvalidMonth)
        },
        'b' | 'h' => match match_strs(s, &[("Jan", 0),
                                           ("Feb", 1),
                                           ("Mar", 2),
                                           ("Apr", 3),
                                           ("May", 4),
                                           ("Jun", 5),
                                           ("Jul", 6),
                                           ("Aug", 7),
                                           ("Sep", 8),
                                           ("Oct", 9),
                                           ("Nov", 10),
                                           ("Dec", 11)]) {
            Some(v) => { tm.tm_mon = v; Ok(()) }
            None => Err(ParseError::InvalidMonth)
        },
        'C' => match match_digits_in_range(s, 1, 2, false, 0, 99) {
            Some(v) => { tm.tm_year += (v * 100) - 1900; Ok(()) }
            None => Err(ParseError::InvalidYear)
        },
        'c' => {
            parse_type(s, 'a', tm)
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'b', tm))
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'e', tm))
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'T', tm))
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'Y', tm))
        }
        'D' | 'x' => {
            parse_type(s, 'm', tm)
                .and_then(|()| parse_char(s, '/'))
                .and_then(|()| parse_type(s, 'd', tm))
                .and_then(|()| parse_char(s, '/'))
                .and_then(|()| parse_type(s, 'y', tm))
        }
        'd' => match match_digits_in_range(s, 1, 2, false, 1, 31) {
            Some(v) => { tm.tm_mday = v; Ok(()) }
            None => Err(ParseError::InvalidDayOfMonth)
        },
        'e' => match match_digits_in_range(s, 1, 2, true, 1, 31) {
            Some(v) => { tm.tm_mday = v; Ok(()) }
            None => Err(ParseError::InvalidDayOfMonth)
        },
        'f' => {
            tm.tm_nsec = match_fractional_seconds(s);
            Ok(())
        }
        'F' => {
            parse_type(s, 'Y', tm)
                .and_then(|()| parse_char(s, '-'))
                .and_then(|()| parse_type(s, 'm', tm))
                .and_then(|()| parse_char(s, '-'))
                .and_then(|()| parse_type(s, 'd', tm))
        }
        'H' => {
            match match_digits_in_range(s, 1, 2, false, 0, 23) {
                Some(v) => { tm.tm_hour = v; Ok(()) }
                None => Err(ParseError::InvalidHour)
            }
        }
        'I' => {
            match match_digits_in_range(s, 1, 2, false, 1, 12) {
                Some(v) => { tm.tm_hour = if v == 12 { 0 } else { v }; Ok(()) }
                None => Err(ParseError::InvalidHour)
            }
        }
        'j' => {
            match match_digits_in_range(s, 1, 3, false, 1, 366) {
                Some(v) => { tm.tm_yday = v - 1; Ok(()) }
                None => Err(ParseError::InvalidDayOfYear)
            }
        }
        'k' => {
            match match_digits_in_range(s, 1, 2, true, 0, 23) {
                Some(v) => { tm.tm_hour = v; Ok(()) }
                None => Err(ParseError::InvalidHour)
            }
        }
        'l' => {
            match match_digits_in_range(s, 1, 2, true, 1, 12) {
                Some(v) => { tm.tm_hour = if v == 12 { 0 } else { v }; Ok(()) }
                None => Err(ParseError::InvalidHour)
            }
        }
        'M' => {
            match match_digits_in_range(s, 1, 2, false, 0, 59) {
                Some(v) => { tm.tm_min = v; Ok(()) }
                None => Err(ParseError::InvalidMinute)
            }
        }
        'm' => {
            match match_digits_in_range(s, 1, 2, false, 1, 12) {
                Some(v) => { tm.tm_mon = v - 1; Ok(()) }
                None => Err(ParseError::InvalidMonth)
            }
        }
        'n' => parse_char(s, '\n'),
        'P' => match match_strs(s, &[("am", 0), ("pm", 12)]) {
            Some(v) => { tm.tm_hour += v; Ok(()) }
            None => Err(ParseError::InvalidHour)
        },
        'p' => match match_strs(s, &[("AM", 0), ("PM", 12)]) {
            Some(v) => { tm.tm_hour += v; Ok(()) }
            None => Err(ParseError::InvalidHour)
        },
        'R' => {
            parse_type(s, 'H', tm)
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'M', tm))
        }
        'r' => {
            parse_type(s, 'I', tm)
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'M', tm))
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'S', tm))
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'p', tm))
        }
        'S' => {
            match match_digits_in_range(s, 1, 2, false, 0, 60) {
                Some(v) => { tm.tm_sec = v; Ok(()) }
                None => Err(ParseError::InvalidSecond)
            }
        }
        //'s' {}
        'T' | 'X' => {
            parse_type(s, 'H', tm)
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'M', tm))
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'S', tm))
        }
        't' => parse_char(s, '\t'),
        'u' => {
            match match_digits_in_range(s, 1, 1, false, 1, 7) {
                Some(v) => { tm.tm_wday = if v == 7 { 0 } else { v }; Ok(()) }
                None => Err(ParseError::InvalidDayOfWeek)
            }
        }
        'v' => {
            parse_type(s, 'e', tm)
                .and_then(|()| parse_char(s, '-'))
                .and_then(|()| parse_type(s, 'b', tm))
                .and_then(|()| parse_char(s, '-'))
                .and_then(|()| parse_type(s, 'Y', tm))
        }
        //'W' {}
        'w' => {
            match match_digits_in_range(s, 1, 1, false, 0, 6) {
                Some(v) => { tm.tm_wday = v; Ok(()) }
                None => Err(ParseError::InvalidDayOfWeek)
            }
        }
        'Y' => {
            match match_digits(s, 4, 4, false) {
                Some(v) => { tm.tm_year = v - 1900; Ok(()) }
                None => Err(ParseError::InvalidYear)
            }
        }
        'y' => {
            match match_digits_in_range(s, 1, 2, false, 0, 99) {
                Some(v) => { tm.tm_year = v; Ok(()) }
                None => Err(ParseError::InvalidYear)
            }
        }
        'Z' => {
            if match_str(s, "UTC") || match_str(s, "GMT") {
                tm.tm_utcoff = 0;
                Ok(())
            } else {
                // It's odd, but to maintain compatibility with c's
                // strptime we ignore the timezone.
                for (i, ch) in s.char_indices() {
                    if ch == ' ' {
                        *s = &s[i..];
                        return Ok(())
                    }
                }
                *s = "";
                Ok(())
            }
        }
        'z' => {
            let sign = if parse_char(s, '+').is_ok() {1}
                       else if parse_char(s, '-').is_ok() {-1}
                       else { return Err(ParseError::InvalidZoneOffset) };

            let mut hours = 0;
            let mut minutes = 0;

            match match_digits(s, 2, 2, false) {
                Some(h) => hours = h,
                None => return Err(ParseError::InvalidZoneOffset)
            }

            // consume the colon if its present,
            // just ignore it otherwise
            let _ = parse_char(s, ':');

            match match_digits(s, 2, 2, false) {
                Some(m) => minutes = m,
                None => return Err(ParseError::InvalidZoneOffset)
            }

            tm.tm_utcoff = sign * (hours * 60 * 60 + minutes * 60);
            Ok(())
        }
        '%' => parse_char(s, '%'),
        ch => Err(ParseError::InvalidFormatSpecifier(ch))
    }
}

fn match_str(s: &mut &str, needle: &str) -> bool {
    if s.starts_with(needle) {
        *s = &s[needle.len()..];
        true
    } else {
        false
    }
}

fn match_strs(ss: &mut &str, strs: &[(&str, i32)]) -> Option<i32> {
    for &(needle, value) in strs.iter() {
        if match_str(ss, needle) {
            return Some(value)
        }
    }
    None
}

fn match_digits(ss: &mut &str, min_digits : usize, max_digits: usize, ws: bool) -> Option<i32> {
    let mut value = 0;
    let mut n = 0;
    if ws {
        let s2 = ss.trim_left_matches(" ");
        n = ss.len() - s2.len();
        if n > max_digits { return None }
    }
    let chars = ss[n..].char_indices();
    for (_, ch) in chars.take(max_digits - n) {
        match ch {
            '0' ... '9' => value = value * 10 + (ch as i32 - '0' as i32),
            _ => break,
        }
        n += 1;
    }

    if n >= min_digits && n <= max_digits {
        *ss = &ss[n..];
        Some(value)
    } else {
        None
    }
}

fn match_fractional_seconds(ss: &mut &str) -> i32 {
    let mut value = 0;
    let mut multiplier = NSEC_PER_SEC / 10;

    let mut chars = ss.char_indices();
    let orig = *ss;
    for (i, ch) in &mut chars {
        *ss = &orig[i..];
        match ch {
            '0' ... '9' => {
                // This will drop digits after the nanoseconds place
                let digit = ch as i32 - '0' as i32;
                value += digit * multiplier;
                multiplier /= 10;
            }
            _ => break
        }
    }

    value
}

fn match_digits_in_range(ss: &mut &str,
                         min_digits : usize, max_digits : usize,
                         ws: bool, min: i32, max: i32) -> Option<i32> {
    let before = *ss;
    match match_digits(ss, min_digits, max_digits, ws) {
        Some(val) if val >= min && val <= max => Some(val),
        _ => { *ss = before; None }
    }
}

fn parse_char(s: &mut &str, c: char) -> Result<(), ParseError> {
    match s.char_indices().next() {
        Some((i, c2)) => {
            if c == c2 {
                *s = &s[i + c2.len_utf8()..];
                Ok(())
            } else {
                Err(ParseError::UnexpectedCharacter(c, c2))
            }
        }
        None => Err(ParseError::InvalidTime),
    }
}
<commit_msg>Fix compile warnings<commit_after>use super::{Tm, ParseError, NSEC_PER_SEC};
use super::ParseError::*;

/// Parses the time from the string according to the format string.
pub fn strptime(mut s: &str, format: &str) -> Result<Tm, ParseError> {
    let mut tm = Tm {
        tm_sec: 0,
        tm_min: 0,
        tm_hour: 0,
        tm_mday: 0,
        tm_mon: 0,
        tm_year: 0,
        tm_wday: 0,
        tm_yday: 0,
        tm_isdst: 0,
        tm_utcoff: 0,
        tm_nsec: 0,
    };
    let mut chars = format.chars();

    while let Some(ch) = chars.next() {
        if ch == '%' {
            if let Some(ch) = chars.next() {
                try!(parse_type(&mut s, ch, &mut tm));
            }
        } else {
            try!(parse_char(&mut s, ch));
        }
    }

    Ok(tm)
}

fn parse_type(s: &mut &str, ch: char, tm: &mut Tm) -> Result<(), ParseError> {
    match ch {
        'A' => match match_strs(s, &[("Sunday", 0),
                                     ("Monday", 1),
                                     ("Tuesday", 2),
                                     ("Wednesday", 3),
                                     ("Thursday", 4),
                                     ("Friday", 5),
                                     ("Saturday", 6)]) {
            Some(v) => { tm.tm_wday = v; Ok(()) }
            None => Err(ParseError::InvalidDay)
        },
        'a' => match match_strs(s, &[("Sun", 0),
                                     ("Mon", 1),
                                     ("Tue", 2),
                                     ("Wed", 3),
                                     ("Thu", 4),
                                     ("Fri", 5),
                                     ("Sat", 6)]) {
            Some(v) => { tm.tm_wday = v; Ok(()) }
            None => Err(ParseError::InvalidDay)
        },
        'B' => match match_strs(s, &[("January", 0),
                                     ("February", 1),
                                     ("March", 2),
                                     ("April", 3),
                                     ("May", 4),
                                     ("June", 5),
                                     ("July", 6),
                                     ("August", 7),
                                     ("September", 8),
                                     ("October", 9),
                                     ("November", 10),
                                     ("December", 11)]) {
            Some(v) => { tm.tm_mon = v; Ok(()) }
            None => Err(ParseError::InvalidMonth)
        },
        'b' | 'h' => match match_strs(s, &[("Jan", 0),
                                           ("Feb", 1),
                                           ("Mar", 2),
                                           ("Apr", 3),
                                           ("May", 4),
                                           ("Jun", 5),
                                           ("Jul", 6),
                                           ("Aug", 7),
                                           ("Sep", 8),
                                           ("Oct", 9),
                                           ("Nov", 10),
                                           ("Dec", 11)]) {
            Some(v) => { tm.tm_mon = v; Ok(()) }
            None => Err(ParseError::InvalidMonth)
        },
        'C' => match match_digits_in_range(s, 1, 2, false, 0, 99) {
            Some(v) => { tm.tm_year += (v * 100) - 1900; Ok(()) }
            None => Err(ParseError::InvalidYear)
        },
        'c' => {
            parse_type(s, 'a', tm)
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'b', tm))
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'e', tm))
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'T', tm))
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'Y', tm))
        }
        'D' | 'x' => {
            parse_type(s, 'm', tm)
                .and_then(|()| parse_char(s, '/'))
                .and_then(|()| parse_type(s, 'd', tm))
                .and_then(|()| parse_char(s, '/'))
                .and_then(|()| parse_type(s, 'y', tm))
        }
        'd' => match match_digits_in_range(s, 1, 2, false, 1, 31) {
            Some(v) => { tm.tm_mday = v; Ok(()) }
            None => Err(ParseError::InvalidDayOfMonth)
        },
        'e' => match match_digits_in_range(s, 1, 2, true, 1, 31) {
            Some(v) => { tm.tm_mday = v; Ok(()) }
            None => Err(ParseError::InvalidDayOfMonth)
        },
        'f' => {
            tm.tm_nsec = match_fractional_seconds(s);
            Ok(())
        }
        'F' => {
            parse_type(s, 'Y', tm)
                .and_then(|()| parse_char(s, '-'))
                .and_then(|()| parse_type(s, 'm', tm))
                .and_then(|()| parse_char(s, '-'))
                .and_then(|()| parse_type(s, 'd', tm))
        }
        'H' => {
            match match_digits_in_range(s, 1, 2, false, 0, 23) {
                Some(v) => { tm.tm_hour = v; Ok(()) }
                None => Err(ParseError::InvalidHour)
            }
        }
        'I' => {
            match match_digits_in_range(s, 1, 2, false, 1, 12) {
                Some(v) => { tm.tm_hour = if v == 12 { 0 } else { v }; Ok(()) }
                None => Err(ParseError::InvalidHour)
            }
        }
        'j' => {
            match match_digits_in_range(s, 1, 3, false, 1, 366) {
                Some(v) => { tm.tm_yday = v - 1; Ok(()) }
                None => Err(ParseError::InvalidDayOfYear)
            }
        }
        'k' => {
            match match_digits_in_range(s, 1, 2, true, 0, 23) {
                Some(v) => { tm.tm_hour = v; Ok(()) }
                None => Err(ParseError::InvalidHour)
            }
        }
        'l' => {
            match match_digits_in_range(s, 1, 2, true, 1, 12) {
                Some(v) => { tm.tm_hour = if v == 12 { 0 } else { v }; Ok(()) }
                None => Err(ParseError::InvalidHour)
            }
        }
        'M' => {
            match match_digits_in_range(s, 1, 2, false, 0, 59) {
                Some(v) => { tm.tm_min = v; Ok(()) }
                None => Err(ParseError::InvalidMinute)
            }
        }
        'm' => {
            match match_digits_in_range(s, 1, 2, false, 1, 12) {
                Some(v) => { tm.tm_mon = v - 1; Ok(()) }
                None => Err(ParseError::InvalidMonth)
            }
        }
        'n' => parse_char(s, '\n'),
        'P' => match match_strs(s, &[("am", 0), ("pm", 12)]) {
            Some(v) => { tm.tm_hour += v; Ok(()) }
            None => Err(ParseError::InvalidHour)
        },
        'p' => match match_strs(s, &[("AM", 0), ("PM", 12)]) {
            Some(v) => { tm.tm_hour += v; Ok(()) }
            None => Err(ParseError::InvalidHour)
        },
        'R' => {
            parse_type(s, 'H', tm)
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'M', tm))
        }
        'r' => {
            parse_type(s, 'I', tm)
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'M', tm))
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'S', tm))
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'p', tm))
        }
        'S' => {
            match match_digits_in_range(s, 1, 2, false, 0, 60) {
                Some(v) => { tm.tm_sec = v; Ok(()) }
                None => Err(ParseError::InvalidSecond)
            }
        }
        //'s' {}
        'T' | 'X' => {
            parse_type(s, 'H', tm)
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'M', tm))
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'S', tm))
        }
        't' => parse_char(s, '\t'),
        'u' => {
            match match_digits_in_range(s, 1, 1, false, 1, 7) {
                Some(v) => { tm.tm_wday = if v == 7 { 0 } else { v }; Ok(()) }
                None => Err(ParseError::InvalidDayOfWeek)
            }
        }
        'v' => {
            parse_type(s, 'e', tm)
                .and_then(|()| parse_char(s, '-'))
                .and_then(|()| parse_type(s, 'b', tm))
                .and_then(|()| parse_char(s, '-'))
                .and_then(|()| parse_type(s, 'Y', tm))
        }
        //'W' {}
        'w' => {
            match match_digits_in_range(s, 1, 1, false, 0, 6) {
                Some(v) => { tm.tm_wday = v; Ok(()) }
                None => Err(ParseError::InvalidDayOfWeek)
            }
        }
        'Y' => {
            match match_digits(s, 4, 4, false) {
                Some(v) => { tm.tm_year = v - 1900; Ok(()) }
                None => Err(ParseError::InvalidYear)
            }
        }
        'y' => {
            match match_digits_in_range(s, 1, 2, false, 0, 99) {
                Some(v) => { tm.tm_year = v; Ok(()) }
                None => Err(ParseError::InvalidYear)
            }
        }
        'Z' => {
            if match_str(s, "UTC") || match_str(s, "GMT") {
                tm.tm_utcoff = 0;
                Ok(())
            } else {
                // It's odd, but to maintain compatibility with c's
                // strptime we ignore the timezone.
                for (i, ch) in s.char_indices() {
                    if ch == ' ' {
                        *s = &s[i..];
                        return Ok(())
                    }
                }
                *s = "";
                Ok(())
            }
        }
        'z' => {
            let sign = if parse_char(s, '+').is_ok() {1}
                       else if parse_char(s, '-').is_ok() {-1}
                       else { return Err(ParseError::InvalidZoneOffset) };

            let hours;
            let minutes;

            match match_digits(s, 2, 2, false) {
                Some(h) => hours = h,
                None => return Err(ParseError::InvalidZoneOffset)
            }

            // consume the colon if its present,
            // just ignore it otherwise
            let _ = parse_char(s, ':');

            match match_digits(s, 2, 2, false) {
                Some(m) => minutes = m,
                None => return Err(ParseError::InvalidZoneOffset)
            }

            tm.tm_utcoff = sign * (hours * 60 * 60 + minutes * 60);
            Ok(())
        }
        '%' => parse_char(s, '%'),
        ch => Err(ParseError::InvalidFormatSpecifier(ch))
    }
}

fn match_str(s: &mut &str, needle: &str) -> bool {
    if s.starts_with(needle) {
        *s = &s[needle.len()..];
        true
    } else {
        false
    }
}

fn match_strs(ss: &mut &str, strs: &[(&str, i32)]) -> Option<i32> {
    for &(needle, value) in strs.iter() {
        if match_str(ss, needle) {
            return Some(value)
        }
    }
    None
}

fn match_digits(ss: &mut &str, min_digits : usize, max_digits: usize, ws: bool) -> Option<i32> {
    let mut value = 0;
    let mut n = 0;
    if ws {
        let s2 = ss.trim_left_matches(" ");
        n = ss.len() - s2.len();
        if n > max_digits { return None }
    }
    let chars = ss[n..].char_indices();
    for (_, ch) in chars.take(max_digits - n) {
        match ch {
            '0' ... '9' => value = value * 10 + (ch as i32 - '0' as i32),
            _ => break,
        }
        n += 1;
    }

    if n >= min_digits && n <= max_digits {
        *ss = &ss[n..];
        Some(value)
    } else {
        None
    }
}

fn match_fractional_seconds(ss: &mut &str) -> i32 {
    let mut value = 0;
    let mut multiplier = NSEC_PER_SEC / 10;

    let mut chars = ss.char_indices();
    let orig = *ss;
    for (i, ch) in &mut chars {
        *ss = &orig[i..];
        match ch {
            '0' ... '9' => {
                // This will drop digits after the nanoseconds place
                let digit = ch as i32 - '0' as i32;
                value += digit * multiplier;
                multiplier /= 10;
            }
            _ => break
        }
    }

    value
}

fn match_digits_in_range(ss: &mut &str,
                         min_digits : usize, max_digits : usize,
                         ws: bool, min: i32, max: i32) -> Option<i32> {
    let before = *ss;
    match match_digits(ss, min_digits, max_digits, ws) {
        Some(val) if val >= min && val <= max => Some(val),
        _ => { *ss = before; None }
    }
}

fn parse_char(s: &mut &str, c: char) -> Result<(), ParseError> {
    match s.char_indices().next() {
        Some((i, c2)) => {
            if c == c2 {
                *s = &s[i + c2.len_utf8()..];
                Ok(())
            } else {
                Err(ParseError::UnexpectedCharacter(c, c2))
            }
        }
        None => Err(ParseError::InvalidTime),
    }
}
<|endoftext|>


<commit_before>fn odeint(f: &Fn(f64, f64) -> f64) -> Vec<f64> {
    Vec::<f64>::new()
}

#[cfg(test)]
mod tests_rk4 {

    #[test]
    fn rk4_compiles() {
    }
}
<commit_msg>Implemented a simple RK4 method.<commit_after>/*
 * Given a differential function dx(x, t),
 * initial condition x0,
 * and a list of times t,
 * find x(t) at each point in t
 */
pub fn odeint(dx: (&Fn(f64, f64) -> f64), x0: f64, t_vec: Vec<f64>) -> Vec<f64> {
    // Need there to be at least two times for this method to work
    assert!(t_vec.len() >= 2);

    // Collect x values in this vector
    let mut result = Vec::<f64>::new();
    result.push(x0);

    // Need to get step size by taking the difference between
    // two adjacent times
    for i in 0..(t_vec.len() - 1) { // Subtracting 1 from the length isn't a typo
        // This implementation is from Wikipedia
        let ti = t_vec[i];
        let tnext = t_vec[i+1];
        let h = tnext - ti;

        let xi = result.pop().unwrap();

        let k1 = dx(xi, ti);
        let k2 = dx(xi + h/2.0*k1, ti + h/2.0);
        let k3 = dx(xi + h/2.0*k2, ti + h/2.0);
        let k4 = dx(xi + h*k3, ti + h);

        let xnext = xi + h/6.0*(k1 + 2.0*k2 + 2.0*k3 + k4);

        result.push(xi);
        result.push(xnext);
    }
    result
}

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

    // Test differential to give to odeint
    fn velocity_one(x: f64, t: f64) -> f64 {
        1.0 // Velocity of particle is 1
    }

    #[test]
    fn rk4_compiles() {
    }

    #[test]
    fn test_velocity_one() {
        let threshold = 0.000001;

        let t = vec![0.0, 1.0];
        let x0 = 0.0;

        let mut result = odeint(&velocity_one, x0, t);

        assert!((result.pop().unwrap() - 1.0).abs() < threshold);
    }

    #[test]
    fn length_test() {
        let t = vec![0.0, 1.0, 2.0];
        let x0 = 0.0;

        let result = odeint(&velocity_one, x0, t);
        assert_eq!(result.len(), 3);
    }
}
<|endoftext|>


<commit_before>//! Serialize a Rust data structure into UBJSON data.

use std::io::Write;

use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
use serde::ser::{self, Serialize};

use error::{Error, Result};

/// Serialize the given value as a UBJSON byte vector.
pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
    where T: Serialize
{
    let mut serializer = Serializer::new(Vec::new());
    value.serialize(&mut serializer)?;
    Ok(serializer.into_inner())
}

/// Serialize the given value as UBJSON into the IO stream.
pub fn to_writer<T, W>(writer: W, value: &T) -> Result<()>
    where W: Write,
          T: Serialize
{
    let mut serializer = Serializer::new(writer);
    value.serialize(&mut serializer)?;
    Ok(())
}

/// Structure for serializing Rust values into UBJSON.
pub struct Serializer<W> {
    inner: W,
}

impl<W> Serializer<W>
    where W: Write
{
    /// Creates a new UBJSON serializer.
    pub fn new(writer: W) -> Self {
        Serializer { inner: writer }
    }

    /// Consumes the serializer and returns the writer it wrapped.
    fn into_inner(self) -> W {
        self.inner
    }
}

impl<'a, W> ser::Serializer for &'a mut Serializer<W> {
    type Ok = ();
    type Error = Error;

    fn serialize_bool(self, v: bool) -> Result<()> {
        self.inner
            .write_u8(match v {
                          true => b'T',
                          false => b'F',
                      })
            .map_err(|err| Error::Io(err))
    }

    fn serialize_i8(self, v: i8) -> Result<()> {
        self.inner
            .write_u8(b'i')
            .and_then(|_| self.inner.write_i8(v))
            .map_err(|err| Error::Io(err))
    }

    fn serialize_i16(self, v: i16) -> Result<()> {
        if (i8::min_value() as i16 <= v) && (v <= i8::max_value() as i16) {
            self.serialize_i8(v as i8)
        } else {
            self.inner
                .write_u8(b'I')
                .and_then(|_| self.inner.write_i16::<BigEndian>(v))
                .map_err(|err| Error::Io(err))
        }
    }

    fn serialize_i32(self, v: i32) -> Result<()> {
        if (i16::min_value() as i32 <= v) && (v <= i16::max_value() as i32) {
            self.serialize_i16(v as i16)
        } else {
            self.inner
                .write_u8(b'l')
                .and_then(|_| self.inner.write_i32::<BigEndian>(v))
                .map_err(|err| Error::Io(err))
        }
    }

    fn serialize_i64(self, v: i64) -> Result<()> {
        if (i32::min_value() as i64 <= v) && (v <= i32::max_value() as i64) {
            self.serialize_i32(v as i32)
        } else {
            self.inner
                .write_u8(b'L')
                .and_then(|_| self.inner.write_i64::<BigEndian>(v))
                .map_err(|err| Error::io(err))
        }
    }

    fn serialize_u8(self, v: u8) -> Result<()> {
        self.inner
            .write_u8(b'U')
            .and_then(|_| self.inner.write_u8(v))
            .map_err(|err| Error::Io(err))
    }

    fn serialize_u16(self, v: u16) -> Result<()> {
        if v <= u8::max_value() as u16 {
            self.serialize_u8(v as u8)
        } else if v <= i16::max_value() as u16 {
            self.serialize_i16(v as i16)
        } else {
            self.serialize_i32(v as i32)
        }
    }

    fn serialize_u32(self, v: u32) -> Result<()> {
        if v <= u16::max_value() as u32 {
            self.serialize_u16(v as u16)
        } else if v <= i32::max_value() as u32 {
            self.serialize_i32(v as i32)
        } else {
            self.serialize_i64(v as i64)
        }
    }

    fn serialize_u64(self, v: u64) -> Result<()> {
        if v <= u32::max_value() as u64 {
            self.serialize_u32(v as u32)
        } else if v <= i64::max_value() as u64 {
            self.serialize_i64(v as i64)
        } else {
            let v = v.to_string();
            self.inner
                .write_u8(b'H')
                .map_err(|err| Error::Io(err))
                .and_then(|_| self.serialize_u64(v.len()))
                .and_then(|_| self.inner.write(v.as_bytes()).map_err(|err| Error::Io(err)))
        }
    }

    fn serialize_f32(self, v: f32) -> Result<()> {
        self.inner
            .write_u8(b'd')
            .and_then(|_| self.inner.write_f32::<BigEndian>(v))
            .map_err(|err| Error::Io(err))
    }

    fn serialize_f64(self, v: f64) -> Result<()> {
        self.inner
            .write_u8(b'D')
            .and_then(|_| self.inner.write_f64::<BigEndian>(v))
            .map_err(|err| Error::Io(err))
    }

    fn serialize_char(self, v: char) -> Result<()> {
        let v: u32 = v.into();
        if v <= u8::max_value() as u32 {
            self.inner
                .write_u8(b'C')
                .and_then(|_| self.inner.write_u8(v as u8))
                .map_err(|err| Error::Io(err))
        } else {
            self.serialize_u32(v)
        }
    }

    fn serialize_str(self, v: &str) -> Result<()> {
        self.inner
            .write_u8(b'S')
            .map_err(|err| Error::Io(err))
            .and_then(|_| self.serialize_u64(v.len() as u64))
            .and_then(|_| self.inner.write(v.as_bytes()).map_err(|err| Error::Io(err)))
    }

    fn serialize_bytes(self, v: &[u8]) -> Result<()> {
        unimplemented!()
    }

    fn serialize_none(self) -> Result<()> {
        unimplemented!()
    }

    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<()>
        where T: Serialize
    {
        unimplemented!()
    }

    fn serialize_unit(self) -> Result<()> {
        unimplemented!()
    }

    fn serialize_unit_struct(self, name: &'static str) -> Result<()> {
        unimplemented!()
    }

    fn serialize_unit_variant(self,
                              name: &'static str,
                              variant_index: u32,
                              variant: &'static str)
                              -> Result<()> {
        unimplemented!()
    }

    fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<()>
        where T: Serialize
    {
        unimplemented!()
    }

    fn serialize_newtype_variant<T: ?Sized>(self,
                                            name: &'static str,
                                            variant_index: u32,
                                            variant: &'static str,
                                            value: &T)
                                            -> Result<()>
        where T: Serialize
    {
        unimplemented!()
    }
}
<commit_msg>Implement serialize_bytes<commit_after>//! Serialize a Rust data structure into UBJSON data.

use std::io::Write;

use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
use serde::ser::{self, Serialize};

use error::{Error, Result};

/// Serialize the given value as a UBJSON byte vector.
pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
    where T: Serialize
{
    let mut serializer = Serializer::new(Vec::new());
    value.serialize(&mut serializer)?;
    Ok(serializer.into_inner())
}

/// Serialize the given value as UBJSON into the IO stream.
pub fn to_writer<T, W>(writer: W, value: &T) -> Result<()>
    where W: Write,
          T: Serialize
{
    let mut serializer = Serializer::new(writer);
    value.serialize(&mut serializer)?;
    Ok(())
}

/// Structure for serializing Rust values into UBJSON.
pub struct Serializer<W> {
    inner: W,
}

impl<W> Serializer<W>
    where W: Write
{
    /// Creates a new UBJSON serializer.
    pub fn new(writer: W) -> Self {
        Serializer { inner: writer }
    }

    /// Consumes the serializer and returns the writer it wrapped.
    fn into_inner(self) -> W {
        self.inner
    }
}

impl<'a, W> ser::Serializer for &'a mut Serializer<W> {
    type Ok = ();
    type Error = Error;

    fn serialize_bool(self, v: bool) -> Result<()> {
        self.inner
            .write_u8(match v {
                          true => b'T',
                          false => b'F',
                      })
            .map_err(|err| Error::Io(err))
    }

    fn serialize_i8(self, v: i8) -> Result<()> {
        self.inner
            .write_u8(b'i')
            .and_then(|_| self.inner.write_i8(v))
            .map_err(|err| Error::Io(err))
    }

    fn serialize_i16(self, v: i16) -> Result<()> {
        if (i8::min_value() as i16 <= v) && (v <= i8::max_value() as i16) {
            self.serialize_i8(v as i8)
        } else {
            self.inner
                .write_u8(b'I')
                .and_then(|_| self.inner.write_i16::<BigEndian>(v))
                .map_err(|err| Error::Io(err))
        }
    }

    fn serialize_i32(self, v: i32) -> Result<()> {
        if (i16::min_value() as i32 <= v) && (v <= i16::max_value() as i32) {
            self.serialize_i16(v as i16)
        } else {
            self.inner
                .write_u8(b'l')
                .and_then(|_| self.inner.write_i32::<BigEndian>(v))
                .map_err(|err| Error::Io(err))
        }
    }

    fn serialize_i64(self, v: i64) -> Result<()> {
        if (i32::min_value() as i64 <= v) && (v <= i32::max_value() as i64) {
            self.serialize_i32(v as i32)
        } else {
            self.inner
                .write_u8(b'L')
                .and_then(|_| self.inner.write_i64::<BigEndian>(v))
                .map_err(|err| Error::io(err))
        }
    }

    fn serialize_u8(self, v: u8) -> Result<()> {
        self.inner
            .write_u8(b'U')
            .and_then(|_| self.inner.write_u8(v))
            .map_err(|err| Error::Io(err))
    }

    fn serialize_u16(self, v: u16) -> Result<()> {
        if v <= u8::max_value() as u16 {
            self.serialize_u8(v as u8)
        } else if v <= i16::max_value() as u16 {
            self.serialize_i16(v as i16)
        } else {
            self.serialize_i32(v as i32)
        }
    }

    fn serialize_u32(self, v: u32) -> Result<()> {
        if v <= u16::max_value() as u32 {
            self.serialize_u16(v as u16)
        } else if v <= i32::max_value() as u32 {
            self.serialize_i32(v as i32)
        } else {
            self.serialize_i64(v as i64)
        }
    }

    fn serialize_u64(self, v: u64) -> Result<()> {
        if v <= u32::max_value() as u64 {
            self.serialize_u32(v as u32)
        } else if v <= i64::max_value() as u64 {
            self.serialize_i64(v as i64)
        } else {
            let v = v.to_string();
            self.inner
                .write_u8(b'H')
                .map_err(|err| Error::Io(err))
                .and_then(|_| self.serialize_u64(v.len()))
                .and_then(|_| self.inner.write(v.as_bytes()).map_err(|err| Error::Io(err)))
        }
    }

    fn serialize_f32(self, v: f32) -> Result<()> {
        self.inner
            .write_u8(b'd')
            .and_then(|_| self.inner.write_f32::<BigEndian>(v))
            .map_err(|err| Error::Io(err))
    }

    fn serialize_f64(self, v: f64) -> Result<()> {
        self.inner
            .write_u8(b'D')
            .and_then(|_| self.inner.write_f64::<BigEndian>(v))
            .map_err(|err| Error::Io(err))
    }

    fn serialize_char(self, v: char) -> Result<()> {
        let v: u32 = v.into();
        if v <= u8::max_value() as u32 {
            self.inner
                .write_u8(b'C')
                .and_then(|_| self.inner.write_u8(v as u8))
                .map_err(|err| Error::Io(err))
        } else {
            self.serialize_u32(v)
        }
    }

    fn serialize_str(self, v: &str) -> Result<()> {
        self.inner
            .write_u8(b'S')
            .map_err(|err| Error::Io(err))
            .and_then(|_| self.serialize_u64(v.len() as u64))
            .and_then(|_| {
                          self.inner
                              .write(v.as_bytes())
                              .map(|_| ())
                              .map_err(|err| Error::Io(err))
                      })
    }

    fn serialize_bytes(self, v: &[u8]) -> Result<()> {
        self.inner
            .write(b"[$U")
            .map(|_| ())
            .map_err(|err| Error::Io(err))
            .and_then(|_| self.serialize_u64(v.len() as u64))
            .and_then(|_| {
                          self.inner
                              .write(v)
                              .map(|_| ())
                              .map_err(|err| Error::Io(err))
                      })
    }

    fn serialize_none(self) -> Result<()> {
        self.inner.write_u8(b'Z').map_err(|err| Error::Io(err))
    }

    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<()>
        where T: Serialize
    {
        unimplemented!()
    }

    fn serialize_unit(self) -> Result<()> {
        unimplemented!()
    }

    fn serialize_unit_struct(self, name: &'static str) -> Result<()> {
        unimplemented!()
    }

    fn serialize_unit_variant(self,
                              name: &'static str,
                              variant_index: u32,
                              variant: &'static str)
                              -> Result<()> {
        unimplemented!()
    }

    fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<()>
        where T: Serialize
    {
        unimplemented!()
    }

    fn serialize_newtype_variant<T: ?Sized>(self,
                                            name: &'static str,
                                            variant_index: u32,
                                            variant: &'static str,
                                            value: &T)
                                            -> Result<()>
        where T: Serialize
    {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::string::ToString;

use self::Sym::*;

use class::ClassId;
use ctxt::*;
use interner::Name;
use ty::BuiltinType;

#[derive(Debug)]
pub struct SymTable {
    levels: Vec<SymLevel>
}

impl SymTable {
    pub fn new() -> SymTable {
        SymTable {
            levels: vec![SymLevel::new()]
        }
    }

    pub fn push_level(&mut self) {
        self.levels.push(SymLevel::new());
    }

    pub fn pop_level(&mut self) {
        assert!(self.levels.len() > 1);

        self.levels.pop();
    }

    pub fn get(&self, name: Name) -> Option<Sym> {
        for level in self.levels.iter().rev() {
            if let Some(val) = level.get(name) {
                return Some(val.clone());
            }
        }

        None
    }

    pub fn get_var(&self, name: Name) -> Option<VarId> {
        self.get(name).and_then(|n| n.to_var())
    }

    pub fn get_type(&self, name: Name) -> Option<BuiltinType> {
        self.get(name).and_then(|n| n.to_type())
    }

    pub fn get_function(&self, name: Name) -> Option<FctId> {
        self.get(name).and_then(|n| n.to_function())
    }

    pub fn insert(&mut self, name: Name, sym: Sym) -> Option<Sym> {
        self.levels.last_mut().unwrap().insert(name, sym)
    }
}

#[derive(Debug)]
struct SymLevel {
    map: HashMap<Name, Sym>
}

impl SymLevel {
    // creates a new table
    fn new() -> SymLevel {
        SymLevel {
            map: HashMap::new()
        }
    }

    // finds symbol in table
    fn get(&self, name: Name) -> Option<&Sym> {
        self.map.get(&name)
    }

    fn insert(&mut self, name: Name, sym: Sym) -> Option<Sym> {
        self.map.insert(name, sym)
    }
}

#[derive(Debug, Copy, Clone)]
pub enum SymEntry {
    Empty, Type, Function, Var
}

impl SymEntry {
    pub fn is_empty(self) -> bool {
        match self {
            SymEntry::Empty => true,
            _ => false
        }
    }

    pub fn is_type(self) -> bool {
        match self {
            SymEntry::Type => true,
            _ => false
        }
    }

    pub fn is_function(self) -> bool {
        match self {
            SymEntry::Function => true,
            _ => false
        }
    }

    pub fn is_var(self) -> bool {
        match self {
            SymEntry::Var => true,
            _ => false
        }
    }
}

#[derive(Debug, Clone)]
pub enum Sym {
    SymType(BuiltinType),
    SymFunction(FctId),
    SymVar(VarId),
}

impl Sym {
    pub fn is_type(&self) -> bool {
        match *self {
            SymType(_) => true,
            _ => false
        }
    }

    pub fn to_type(&self) -> Option<BuiltinType> {
        match *self {
            SymType(builtin) => Some(builtin),
            _ => None
        }
    }

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

    pub fn to_function(&self) -> Option<FctId> {
        match *self {
            SymFunction(id) => Some(id),
            _ => None
        }
    }

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

    pub fn to_var(&self) -> Option<VarId> {
        match *self {
            SymVar(id) => Some(id),
            _ => None
        }
    }
}
<commit_msg>sym: removed SymEntry<commit_after>use std::collections::HashMap;
use std::string::ToString;

use self::Sym::*;

use class::ClassId;
use ctxt::*;
use interner::Name;
use ty::BuiltinType;

#[derive(Debug)]
pub struct SymTable {
    levels: Vec<SymLevel>
}

impl SymTable {
    pub fn new() -> SymTable {
        SymTable {
            levels: vec![SymLevel::new()]
        }
    }

    pub fn push_level(&mut self) {
        self.levels.push(SymLevel::new());
    }

    pub fn pop_level(&mut self) {
        assert!(self.levels.len() > 1);

        self.levels.pop();
    }

    pub fn get(&self, name: Name) -> Option<Sym> {
        for level in self.levels.iter().rev() {
            if let Some(val) = level.get(name) {
                return Some(val.clone());
            }
        }

        None
    }

    pub fn get_var(&self, name: Name) -> Option<VarId> {
        self.get(name).and_then(|n| n.to_var())
    }

    pub fn get_type(&self, name: Name) -> Option<BuiltinType> {
        self.get(name).and_then(|n| n.to_type())
    }

    pub fn get_function(&self, name: Name) -> Option<FctId> {
        self.get(name).and_then(|n| n.to_function())
    }

    pub fn insert(&mut self, name: Name, sym: Sym) -> Option<Sym> {
        self.levels.last_mut().unwrap().insert(name, sym)
    }
}

#[derive(Debug)]
struct SymLevel {
    map: HashMap<Name, Sym>
}

impl SymLevel {
    // creates a new table
    fn new() -> SymLevel {
        SymLevel {
            map: HashMap::new()
        }
    }

    // finds symbol in table
    fn get(&self, name: Name) -> Option<&Sym> {
        self.map.get(&name)
    }

    fn insert(&mut self, name: Name, sym: Sym) -> Option<Sym> {
        self.map.insert(name, sym)
    }
}

#[derive(Debug, Clone)]
pub enum Sym {
    SymType(BuiltinType),
    SymFunction(FctId),
    SymVar(VarId),
}

impl Sym {
    pub fn is_type(&self) -> bool {
        match *self {
            SymType(_) => true,
            _ => false
        }
    }

    pub fn to_type(&self) -> Option<BuiltinType> {
        match *self {
            SymType(builtin) => Some(builtin),
            _ => None
        }
    }

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

    pub fn to_function(&self) -> Option<FctId> {
        match *self {
            SymFunction(id) => Some(id),
            _ => None
        }
    }

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

    pub fn to_var(&self) -> Option<VarId> {
        match *self {
            SymVar(id) => Some(id),
            _ => None
        }
    }
}
<|endoftext|>