<commit_before>use bus::{Addressable, OAM_START, OAM_END, VIDEO_RAM_START, VIDEO_RAM_END};
use enum_primitive::FromPrimitive;

pub const LCD_WIDTH: usize = 160;
pub const LCD_HEIGHT: usize = 144;

const ADDR_LCDC: u16 = 0xFF40;
const ADDR_STAT: u16 = 0xFF41;
const ADDR_SCY: u16  = 0xFF42;
const ADDR_SCX: u16  = 0xFF43;
const ADDR_LY: u16   = 0xFF44;
const ADDR_LYC: u16  = 0xFF45;
const ADDR_DMA: u16  = 0xFF46;
const ADDR_BGP: u16  = 0xFF47;
const ADDR_OBP0: u16 = 0xFF48;
const ADDR_OBP1: u16 = 0xFF49;
const ADDR_WY: u16   = 0xFF4A;
const ADDR_WX: u16   = 0xFF4B;

bitflags! {
    flags Lcdc: u8 {
        const LCDC_ENABLED          = 0b1000_0000,
        const LCDC_TILE_TBL_9C      = 0b0100_0000,
        const LCDC_WIN_ENABLED      = 0b0010_0000,
        const LCDC_SIGNED_TILE_DATA = 0b0001_0000,
        const LCDC_BG_TILE_TBL_9C   = 0b0000_1000,
        const LCDC_16PX_SPRITE      = 0b0000_0100,
        const LCDC_SPRITE_DISPLAY   = 0b0000_0010,
        const LCDC_BG_DISPLAY       = 0b0000_0001
    }
}

// STAT is mostly flags, but the lower 2 bits are the current mode
// Mode is will stored separately so the Stat struct is only treated as bitflags.
bitflags! {
    flags Stat: u8 {
        const STAT_COINCIDENCE_INT   = 0b0100_0000,
        const STAT_OAM_INT           = 0b0010_0000,
        const STAT_VBLANK_INT        = 0b0001_0000,
        const STAT_HBLANK_INT        = 0b0000_1000,
        const STAT_COINCIDENCE_EQUAL = 0b0000_0100
    }
}

enum_from_primitive! {
#[derive(Copy, Clone, PartialEq)]
pub enum Mode {
    VBlank   = 0,
    HBlank   = 1,
    Oam      = 2,
    Transfer = 3
}
}

const CYCLES_PER_OAM_READ: usize = 80;
const CYCLES_PER_TRANSFER: usize = 172;
const CYCLES_PER_HBLANK: usize = 204;
const CYCLES_PER_LINE: usize = 456;

const SHADE_WHITE: u8      = 0;
const SHADE_LIGHT_GRAY: u8 = 1;
const SHADE_DARK_GRAY: u8  = 2;
const SHADE_BLACK: u8      = 3;

struct Pallete(u8);

impl Pallete {
    fn shade(&self, idx: u8) -> u8 {
        self.0 >> (idx * 2)
    }

    fn set_shade(&mut self, idx: u8, shade: u8) {
        self.0 = self.0 | shade << (idx * 2);
    }
}

#[derive(Default)]
pub struct StepResult {
    pub int_vblank: bool,
    pub int_stat: bool
}

pub struct Lcd {
    vram: Vec<u8>,
    oam: Vec<u8>,
    lcdc: Lcdc,
    stat: Stat,
    scy: u8,
    scx: u8,
    ly: u8,
    lyc: u8,
    bgp: Pallete,
    obp0: Pallete,
    obp1: Pallete,
    wy: u8,
    wx: u8,

    mode: Mode,
    mode_cycles: usize
}

impl Lcd {
    pub fn new() -> Self {
        Lcd {
            vram: vec![0; (VIDEO_RAM_END - VIDEO_RAM_START) as usize + 1],
            oam: vec![0; (OAM_END - OAM_START) as usize + 1],
            lcdc: Lcdc::from_bits(0x91).unwrap(),
            stat: Stat::empty(),
            scy: 0,
            scx: 0,
            ly: 0,
            lyc: 0,
            bgp: Pallete(0xFC),
            obp0: Pallete(0xFF),
            obp1: Pallete(0xFF),
            wy: 0,
            wx: 0,
            mode: Mode::Oam,
            mode_cycles: 0
        }
    }

    pub fn step(&mut self, cycles: usize) -> StepResult {
        let mut result = StepResult::default();
        let previous_mode = self.mode;

        self.mode_cycles = self.mode_cycles + cycles;

        // Current mode is stored in the lower two bits of the STAT register
        match self.mode {
            Mode::Oam => {
                // Process starts with the LCD controller reading information from OAM.
                // This lasts 77-83 cycles
                if self.mode_cycles >= CYCLES_PER_OAM_READ {
                    // Move onto transfer stage
                    self.mode = Mode::Transfer;
                    self.mode_cycles = 0;
                }
            },
            Mode::Transfer => {
                // Data is being actively read by the LCD driver from OAM & VRAM.
                // This lasts 169-175 cycles
                if self.mode_cycles >= CYCLES_PER_TRANSFER {
                    // Once transfer is complete, enter HBLANK
                    self.mode = Mode::HBlank;
                    self.mode_cycles = 0;
                }
            },
            Mode::HBlank => {
                // LCD has reached the end of a line.
                // HBlank phase lasts 201-207 cycles
                if self.mode_cycles >= CYCLES_PER_HBLANK {
                    // LCD is ready to begin the next line
                    self.ly = self.ly + 1;
                    self.mode_cycles = 0;

                    // If the LCD has line 144, then enter VBLANK. Else, enter OAM read.
                    if self.ly == 144 {
                        self.mode = Mode::VBlank;
                        result.int_vblank = true;
                    } else {
                        self.mode = Mode::Oam;
                    };
                }
            },
            Mode::VBlank => {
                // LCD is writing to VBlank lines
                if self.mode_cycles >= CYCLES_PER_LINE {
                    self.mode_cycles = 0;
                    self.ly = self.ly + 1;

                    if self.ly > 153 {
                        // Finished with VBlank. Enter OAM with the first line.
                        self.ly = 0;
                        self.mode = Mode::Oam;
                    }
                }
            }
        }

        // Check if a new mode has been entered during this step.
        // If so, an interrupt will be raised if the respective flag is set in the STAT register
        if self.mode != previous_mode {
            let flag = match self.mode {
                Mode::VBlank   => Some(STAT_VBLANK_INT),
                Mode::HBlank   => Some(STAT_HBLANK_INT),
                Mode::Oam      => Some(STAT_OAM_INT),
                Mode::Transfer => None
            };

            if flag.is_some() && self.stat.contains(flag.unwrap()) {
                result.int_stat = true;
            }
        }

        result

    }
}

impl Addressable for Lcd {
    fn read(&self, addr: u16) -> u8 {
        match addr {
            VIDEO_RAM_START...VIDEO_RAM_END => self.vram[(addr - VIDEO_RAM_START) as usize],
            OAM_START...OAM_END => self.oam[(addr - OAM_START) as usize],
            ADDR_LCDC => self.lcdc.bits,
            ADDR_STAT => (self.stat.bits & 0b1111_1100) | (self.mode as u8),
            ADDR_SCY => self.scy,
            ADDR_SCX => self.scx,
            ADDR_LY => self.ly,
            ADDR_LYC => self.lyc,
            ADDR_BGP => self.bgp.0,
            ADDR_OBP0 => self.obp0.0,
            ADDR_OBP1 => self.obp1.0,
            ADDR_WY => self.wy,
            ADDR_WX => self.wx,
            _ => { println!("LCD IO read unimplemented ({:#X})", addr); 0 }
        }
    }

    fn write(&mut self, addr: u16, val: u8) {
        match addr {
            VIDEO_RAM_START...VIDEO_RAM_END => self.vram[(addr - VIDEO_RAM_START) as usize] = val,
            OAM_START...OAM_END => self.oam[(addr - OAM_START) as usize] = val,
            ADDR_LCDC => self.lcdc.bits = val,
            ADDR_STAT => {
                self.stat.bits = val & 0b1111_1100;
                self.mode = Mode::from_u8(val & 0b11).unwrap();
            },
            ADDR_SCY => self.scy = val,
            ADDR_SCX => self.scx = val,
            //ADDR_LY => self.ly = val,
            ADDR_LYC => self.lyc = val,
            ADDR_DMA => println!("DMA unimplemented"),
            ADDR_BGP => self.bgp = Pallete(val),
            ADDR_OBP0 => self.obp0 = Pallete(val),
            ADDR_OBP1 => self.obp1 = Pallete(val),
            ADDR_WY => self.wy = val,
            ADDR_WX => self.wx = val,
            _ => println!("LCD IO write unimplemented {:#X} -> {:#X}", val, addr)
        }
    }
}<commit_msg>Added LYC check<commit_after>use bus::{Addressable, OAM_START, OAM_END, VIDEO_RAM_START, VIDEO_RAM_END};
use enum_primitive::FromPrimitive;

pub const LCD_WIDTH: usize = 160;
pub const LCD_HEIGHT: usize = 144;

const ADDR_LCDC: u16 = 0xFF40;
const ADDR_STAT: u16 = 0xFF41;
const ADDR_SCY: u16  = 0xFF42;
const ADDR_SCX: u16  = 0xFF43;
const ADDR_LY: u16   = 0xFF44;
const ADDR_LYC: u16  = 0xFF45;
const ADDR_DMA: u16  = 0xFF46;
const ADDR_BGP: u16  = 0xFF47;
const ADDR_OBP0: u16 = 0xFF48;
const ADDR_OBP1: u16 = 0xFF49;
const ADDR_WY: u16   = 0xFF4A;
const ADDR_WX: u16   = 0xFF4B;

bitflags! {
    flags Lcdc: u8 {
        const LCDC_ENABLED          = 0b1000_0000,
        const LCDC_TILE_TBL_9C      = 0b0100_0000,
        const LCDC_WIN_ENABLED      = 0b0010_0000,
        const LCDC_SIGNED_TILE_DATA = 0b0001_0000,
        const LCDC_BG_TILE_TBL_9C   = 0b0000_1000,
        const LCDC_16PX_SPRITE      = 0b0000_0100,
        const LCDC_SPRITE_DISPLAY   = 0b0000_0010,
        const LCDC_BG_DISPLAY       = 0b0000_0001
    }
}

// STAT is mostly flags, but the lower 2 bits are the current mode
// Mode is will stored separately so the Stat struct is only treated as bitflags.
bitflags! {
    flags Stat: u8 {
        const STAT_COINCIDENCE_INT   = 0b0100_0000,
        const STAT_OAM_INT           = 0b0010_0000,
        const STAT_VBLANK_INT        = 0b0001_0000,
        const STAT_HBLANK_INT        = 0b0000_1000,
        const STAT_COINCIDENCE_EQUAL = 0b0000_0100
    }
}

enum_from_primitive! {
#[derive(Copy, Clone, PartialEq)]
pub enum Mode {
    VBlank   = 0,
    HBlank   = 1,
    Oam      = 2,
    Transfer = 3
}
}

const CYCLES_PER_OAM_READ: usize = 80;
const CYCLES_PER_TRANSFER: usize = 172;
const CYCLES_PER_HBLANK: usize = 204;
const CYCLES_PER_LINE: usize = 456;

const SHADE_WHITE: u8      = 0;
const SHADE_LIGHT_GRAY: u8 = 1;
const SHADE_DARK_GRAY: u8  = 2;
const SHADE_BLACK: u8      = 3;

struct Pallete(u8);

impl Pallete {
    fn shade(&self, idx: u8) -> u8 {
        self.0 >> (idx * 2)
    }

    fn set_shade(&mut self, idx: u8, shade: u8) {
        self.0 = self.0 | shade << (idx * 2);
    }
}

#[derive(Default)]
pub struct StepResult {
    pub int_vblank: bool,
    pub int_stat: bool
}

pub struct Lcd {
    vram: Vec<u8>,
    oam: Vec<u8>,
    lcdc: Lcdc,
    stat: Stat,
    scy: u8,
    scx: u8,
    ly: u8,
    lyc: u8,
    bgp: Pallete,
    obp0: Pallete,
    obp1: Pallete,
    wy: u8,
    wx: u8,

    mode: Mode,
    mode_cycles: usize
}

impl Lcd {
    pub fn new() -> Self {
        Lcd {
            vram: vec![0; (VIDEO_RAM_END - VIDEO_RAM_START) as usize + 1],
            oam: vec![0; (OAM_END - OAM_START) as usize + 1],
            lcdc: Lcdc::from_bits(0x91).unwrap(),
            stat: Stat::empty(),
            scy: 0,
            scx: 0,
            ly: 0,
            lyc: 0,
            bgp: Pallete(0xFC),
            obp0: Pallete(0xFF),
            obp1: Pallete(0xFF),
            wy: 0,
            wx: 0,
            mode: Mode::Oam,
            mode_cycles: 0
        }
    }

    pub fn step(&mut self, cycles: usize) -> StepResult {
        let mut result = StepResult::default();
        let previous_mode = self.mode;

        self.mode_cycles = self.mode_cycles + cycles;

        // Current mode is stored in the lower two bits of the STAT register
        match self.mode {
            Mode::Oam => {
                // Process starts with the LCD controller reading information from OAM.
                // This lasts 77-83 cycles
                if self.mode_cycles >= CYCLES_PER_OAM_READ {
                    // Move onto transfer stage
                    self.mode = Mode::Transfer;
                    self.mode_cycles = 0;
                }
            },
            Mode::Transfer => {
                // Data is being actively read by the LCD driver from OAM & VRAM.
                // This lasts 169-175 cycles
                if self.mode_cycles >= CYCLES_PER_TRANSFER {
                    // Once transfer is complete, enter HBLANK
                    self.mode = Mode::HBlank;
                    self.mode_cycles = 0;
                }
            },
            Mode::HBlank => {
                // LCD has reached the end of a line.
                // HBlank phase lasts 201-207 cycles
                if self.mode_cycles >= CYCLES_PER_HBLANK {
                    // LCD is ready to begin the next line
                    self.ly = self.ly + 1;
                    self.mode_cycles = 0;

                    // If the LCD has line 144, then enter VBLANK. Else, enter OAM read.
                    if self.ly == 144 {
                        self.mode = Mode::VBlank;
                        result.int_vblank = true;
                    } else {
                        self.mode = Mode::Oam;
                    };

                    self.check_coincidence(&mut result);
                }
            },
            Mode::VBlank => {
                // LCD is writing to VBlank lines
                if self.mode_cycles >= CYCLES_PER_LINE {
                    self.mode_cycles = 0;
                    self.ly = self.ly + 1;

                    if self.ly > 153 {
                        // Finished with VBlank. Enter OAM with the first line.
                        self.ly = 0;
                        self.mode = Mode::Oam;
                    }

                    self.check_coincidence(&mut result);
                }
            }
        }

        // Check if a new mode has been entered during this step.
        // If so, an interrupt will be raised if the respective flag is set in the STAT register
        if self.mode != previous_mode {
            let flag = match self.mode {
                Mode::VBlank   => Some(STAT_VBLANK_INT),
                Mode::HBlank   => Some(STAT_HBLANK_INT),
                Mode::Oam      => Some(STAT_OAM_INT),
                Mode::Transfer => None
            };

            if flag.is_some() && self.stat.contains(flag.unwrap()) {
                result.int_stat = true;
            }
        }

        result

    }

    fn check_coincidence(&mut self, result: &mut StepResult) {
        if self.stat.contains(STAT_COINCIDENCE_INT) {
            if self.ly == self.lyc {
                self.stat.insert(STAT_COINCIDENCE_EQUAL);
                result.int_stat = true;
            } else {
                self.stat.remove(STAT_COINCIDENCE_EQUAL);
            }
        } else {
            self.stat.remove(STAT_COINCIDENCE_EQUAL);
        }
    }
}

impl Addressable for Lcd {
    fn read(&self, addr: u16) -> u8 {
        match addr {
            VIDEO_RAM_START...VIDEO_RAM_END => self.vram[(addr - VIDEO_RAM_START) as usize],
            OAM_START...OAM_END => self.oam[(addr - OAM_START) as usize],
            ADDR_LCDC => self.lcdc.bits,
            ADDR_STAT => (self.stat.bits & 0b1111_1100) | (self.mode as u8),
            ADDR_SCY => self.scy,
            ADDR_SCX => self.scx,
            ADDR_LY => self.ly,
            ADDR_LYC => self.lyc,
            ADDR_BGP => self.bgp.0,
            ADDR_OBP0 => self.obp0.0,
            ADDR_OBP1 => self.obp1.0,
            ADDR_WY => self.wy,
            ADDR_WX => self.wx,
            _ => { println!("LCD IO read unimplemented ({:#X})", addr); 0 }
        }
    }

    fn write(&mut self, addr: u16, val: u8) {
        match addr {
            VIDEO_RAM_START...VIDEO_RAM_END => self.vram[(addr - VIDEO_RAM_START) as usize] = val,
            OAM_START...OAM_END => self.oam[(addr - OAM_START) as usize] = val,
            ADDR_LCDC => self.lcdc.bits = val,
            ADDR_STAT => {
                self.stat.bits = val & 0b1111_1100;
                self.mode = Mode::from_u8(val & 0b11).unwrap();
            },
            ADDR_SCY => self.scy = val,
            ADDR_SCX => self.scx = val,
            //ADDR_LY => self.ly = val,
            ADDR_LYC => self.lyc = val,
            ADDR_DMA => println!("DMA unimplemented"),
            ADDR_BGP => self.bgp = Pallete(val),
            ADDR_OBP0 => self.obp0 = Pallete(val),
            ADDR_OBP1 => self.obp1 = Pallete(val),
            ADDR_WY => self.wy = val,
            ADDR_WX => self.wx = val,
            _ => println!("LCD IO write unimplemented {:#X} -> {:#X}", val, addr)
        }
    }
}<|endoftext|>


<commit_before>//! Tokenization of source code.

use std::result::Result::{Ok, Err};
use std::str::Chars;
use std::{error, result};
use std::fmt;
use std::error::Error as StdError;

/// Result of a lexer operation.
pub type Result<T> = result::Result<T, Error>;

/// Possible errors due to a lexer operation.
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Error {
    UnknownEscape,
    IncompleteEscape,
    UnknownToken,
    UnclosedComment,
    UnclosedString,
    MalformedNumber,
}

impl Error {
    /// Whether this error recoverable if more input is provided.
    pub fn is_recoverable(&self) -> bool {
        match *self {
            Error::IncompleteEscape
                | Error::UnclosedComment
                | Error::UnclosedString => true,
            _ => false,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::UnknownEscape => "Unknown character escape",
            Error::IncompleteEscape => "Incomplete character escape",
            Error::UnknownToken => "Unknown token",
            Error::UnclosedComment => "Unclosed comment",
            Error::UnclosedString => "Unclosed string",
            Error::MalformedNumber => "Malformed integer or float",
        }
    }
}

/// Yield chars while allowing one char to be "replaced" to be yielded again.
///
/// In the case that a char must be popped in order to determine
/// if it belongs in the current token, replace can be used to
/// remember it for the start of the next token. This works
/// as long as the lexer grammar needs only one char of lookahead.
struct ReplaceOneChars<'a> {
    chars: Chars<'a>,
    replaced: Option<char>,
}

impl<'a> ReplaceOneChars<'a> {
    pub fn new(chars: Chars<'a>) -> ReplaceOneChars<'a> {
        ReplaceOneChars {
            chars: chars,
            replaced: None,
        }
    }

    pub fn replace(&mut self, c: char) {
        self.replaced = Some(c);
    }
}

impl<'a> Iterator for ReplaceOneChars<'a> {
    type Item = char;

    fn next(&mut self) -> Option<char> {
        match self.replaced.take() {
            Some(c) => Some(c),
            None => self.chars.next(),
        }
    }
}

/// Input tokens produced by lexer.
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Token {
    Integer(String),
    Float(String),
    String(String),
    Symbol(String),
    Call(String),
    OpenBrace,
    CloseBrace,
    Whitespace,
    Comment,
}

/// The lexer is a tokenizer implemented as an iterator over a string.
/// Iteration  proceeds until the source is successfully tokenized,
/// or an error is encountered.
pub struct Lexer<'a> {
    chars: ReplaceOneChars<'a>,
}

const DECIMAL: u32 = 10u32;

#[inline(always)]
fn is_whitespace_or_close_brace(c: char) -> bool {
    c.is_whitespace() || c == '}'
}

impl<'a> Lexer<'a> {
    /// Create a new lexer over the provided source code.
    pub fn new(src: &'a str) -> Lexer<'a> {
        Lexer {
            chars: ReplaceOneChars::new(src.chars()),
        }
    }

    /// Consume any remaining chars in underlying source.
    fn consume(&mut self) {
        for _ in &mut self.chars { }
    }

    fn whitespace(&mut self) -> Result<Token> {
        loop {
            match self.chars.next() {
                Some(c) => if !c.is_whitespace() {
                    self.chars.replace(c);
                    return Ok(Token::Whitespace);
                },
                None => return Ok(Token::Whitespace),
            }
        }
    }

    fn number(&mut self) -> Result<Token> {
        let mut s = String::new();
        let mut is_float = false;
        loop {
            match self.chars.next() {
                Some(c) => if c.is_digit(DECIMAL) {
                    s.push(c);
                } else if !is_float && c == '.' {
                    is_float = true;
                    s.push(c);
                } else if is_whitespace_or_close_brace(c) {
                    self.chars.replace(c);
                    break;
                } else {
                    return Err(Error::MalformedNumber);
                },
                None => break,
            }
        }
        Ok(if is_float {
            Token::Float(s)
        } else {
            Token::Integer(s)
        })
    }

    fn comment(&mut self) -> Result<Token> {
        loop {
            match self.chars.next() {
                Some('\n') | None => return Ok(Token::Comment),
                _ => continue,
            }
        }
    }

    fn multi_comment(&mut self) -> Result<Token> {
        loop {
            match self.chars.next() {
                Some(c) => if c == ')' {
                    return Ok(Token::Comment);
                },
                None => return Err(Error::UnclosedComment),
            }
        }
    }

    fn escape(&mut self) -> Result<char> {
        match self.chars.next() {
            Some(c) => return match c {
                '"' => Ok('"'),
                'n' => Ok('\n'),
                'r' => Ok('\r'),
                't' => Ok('\t'),
                _ => Err(Error::UnknownEscape),
            },
            None => return Err(Error::IncompleteEscape),
        }
    }

    fn string(&mut self) -> Result<Token> {
        let mut s = String::new();
        loop {
            match self.chars.next() {
                Some(c) => match c {
                    '\\' => s.push(try!(self.escape())),
                    '"' => return Ok(Token::String(s)),
                    _ => s.push(c),
                },
                None => return Err(Error::UnclosedString),
            }
        }
    }

    fn symbol(&mut self) -> Result<String> {
        let mut s = String::new();
        loop {
            match self.chars.next() {
                Some(c) => if is_whitespace_or_close_brace(c) {
                    return Ok(s);
                } else {
                    s.push(c);
                },
                None => return Ok(s),
            }
        }
    }
}

impl<'a> Iterator for Lexer<'a> {
    type Item = Result<Token>;

    fn next(&mut self) -> Option<Result<Token>> {
        loop {
            let c = match self.chars.next() {
                Some(c) => c,
                None => return None,
            };
            let result = if c.is_whitespace() {
                self.whitespace()
            } else if c.is_digit(DECIMAL) {
                self.chars.replace(c);
                self.number()
            } else if c == '#' {
                self.comment()
            } else if c == '(' {
                self.multi_comment()
            } else if c == '"' {
                self.string()
            } else if c == '{' {
                Ok(Token::OpenBrace)
            } else if c == '}' {
                Ok(Token::CloseBrace)
            } else if c == ':' {
                self.symbol().map(|s| Token::Symbol(s))
            } else {
                self.chars.replace(c);
                self.symbol().map(|s| Token::Call(s))
            };
            // If we have errored, the rest of the source is invalid.
            if result.is_err() {
                self.consume();
            }
            return Some(result);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Lexer, Token, Error};

    #[test]
    fn test_empty_string_is_none() {
        assert_eq!(Lexer::new("").next(), None);
    }

    #[test]
    fn test_whitespace() {
        assert_eq!(Lexer::new(" ").collect::<Vec<_>>(),
            vec![Ok(Token::Whitespace)]);
        assert_eq!(Lexer::new("  \t\t\n\n").collect::<Vec<_>>(),
            vec![Ok(Token::Whitespace)]);
    }

    #[test]
    fn test_number() {
        assert_eq!(Lexer::new("0").collect::<Vec<_>>(),
            vec![Ok(Token::Integer("0".to_string()))]);
        assert_eq!(Lexer::new("1.0").collect::<Vec<_>>(),
            vec![Ok(Token::Float("1.0".to_string()))]);
    }

    #[test]
    fn test_comment() {
        assert_eq!(Lexer::new("(this is a comment)").collect::<Vec<_>>(),
            vec![Ok(Token::Comment)]);
        assert_eq!(Lexer::new("(this is an unclosed comment")
                   .collect::<Vec<_>>(),
            vec![Err(Error::UnclosedComment)]);
    }
    #[test]
    fn test_string() {
        assert_eq!(Lexer::new("\"this is a string\"").collect::<Vec<_>>(),
            vec![Ok(Token::String("this is a string".to_string()))]);
        assert_eq!(Lexer::new("\"this is an unclosed string").collect::<Vec<_>>(),
            vec![Err(Error::UnclosedString)]);
    }

    #[test]
    fn test_call() {
        assert_eq!(Lexer::new("this-is-a-call").collect::<Vec<_>>(),
            vec![Ok(Token::Call("this-is-a-call".to_string()))]);
    }
}
<commit_msg>Fix parsing of symbols and calls to replace char<commit_after>//! Tokenization of source code.

use std::result::Result::{Ok, Err};
use std::str::Chars;
use std::{error, result};
use std::fmt;
use std::error::Error as StdError;

/// Result of a lexer operation.
pub type Result<T> = result::Result<T, Error>;

/// Possible errors due to a lexer operation.
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Error {
    UnknownEscape,
    IncompleteEscape,
    UnknownToken,
    UnclosedComment,
    UnclosedString,
    MalformedNumber,
}

impl Error {
    /// Whether this error recoverable if more input is provided.
    pub fn is_recoverable(&self) -> bool {
        match *self {
            Error::IncompleteEscape
                | Error::UnclosedComment
                | Error::UnclosedString => true,
            _ => false,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::UnknownEscape => "Unknown character escape",
            Error::IncompleteEscape => "Incomplete character escape",
            Error::UnknownToken => "Unknown token",
            Error::UnclosedComment => "Unclosed comment",
            Error::UnclosedString => "Unclosed string",
            Error::MalformedNumber => "Malformed integer or float",
        }
    }
}

/// Yield chars while allowing one char to be "replaced" to be yielded again.
///
/// In the case that a char must be popped in order to determine
/// if it belongs in the current token, replace can be used to
/// remember it for the start of the next token. This works
/// as long as the lexer grammar needs only one char of lookahead.
struct ReplaceOneChars<'a> {
    chars: Chars<'a>,
    replaced: Option<char>,
}

impl<'a> ReplaceOneChars<'a> {
    pub fn new(chars: Chars<'a>) -> ReplaceOneChars<'a> {
        ReplaceOneChars {
            chars: chars,
            replaced: None,
        }
    }

    pub fn replace(&mut self, c: char) {
        self.replaced = Some(c);
    }
}

impl<'a> Iterator for ReplaceOneChars<'a> {
    type Item = char;

    fn next(&mut self) -> Option<char> {
        match self.replaced.take() {
            Some(c) => Some(c),
            None => self.chars.next(),
        }
    }
}

/// Input tokens produced by lexer.
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Token {
    Integer(String),
    Float(String),
    String(String),
    Symbol(String),
    Call(String),
    OpenBrace,
    CloseBrace,
    Whitespace,
    Comment,
}

/// The lexer is a tokenizer implemented as an iterator over a string.
/// Iteration  proceeds until the source is successfully tokenized,
/// or an error is encountered.
pub struct Lexer<'a> {
    chars: ReplaceOneChars<'a>,
}

const DECIMAL: u32 = 10u32;

#[inline(always)]
fn is_whitespace_or_close_brace(c: char) -> bool {
    c.is_whitespace() || c == '}'
}

impl<'a> Lexer<'a> {
    /// Create a new lexer over the provided source code.
    pub fn new(src: &'a str) -> Lexer<'a> {
        Lexer {
            chars: ReplaceOneChars::new(src.chars()),
        }
    }

    /// Consume any remaining chars in underlying source.
    fn consume(&mut self) {
        for _ in &mut self.chars { }
    }

    fn whitespace(&mut self) -> Result<Token> {
        loop {
            match self.chars.next() {
                Some(c) => if !c.is_whitespace() {
                    self.chars.replace(c);
                    return Ok(Token::Whitespace);
                },
                None => return Ok(Token::Whitespace),
            }
        }
    }

    fn number(&mut self) -> Result<Token> {
        let mut s = String::new();
        let mut is_float = false;
        loop {
            match self.chars.next() {
                Some(c) => if c.is_digit(DECIMAL) {
                    s.push(c);
                } else if !is_float && c == '.' {
                    is_float = true;
                    s.push(c);
                } else if is_whitespace_or_close_brace(c) {
                    self.chars.replace(c);
                    break;
                } else {
                    return Err(Error::MalformedNumber);
                },
                None => break,
            }
        }
        Ok(if is_float {
            Token::Float(s)
        } else {
            Token::Integer(s)
        })
    }

    fn comment(&mut self) -> Result<Token> {
        loop {
            match self.chars.next() {
                Some('\n') | None => return Ok(Token::Comment),
                _ => continue,
            }
        }
    }

    fn multi_comment(&mut self) -> Result<Token> {
        loop {
            match self.chars.next() {
                Some(c) => if c == ')' {
                    return Ok(Token::Comment);
                },
                None => return Err(Error::UnclosedComment),
            }
        }
    }

    fn escape(&mut self) -> Result<char> {
        match self.chars.next() {
            Some(c) => return match c {
                '"' => Ok('"'),
                'n' => Ok('\n'),
                'r' => Ok('\r'),
                't' => Ok('\t'),
                _ => Err(Error::UnknownEscape),
            },
            None => return Err(Error::IncompleteEscape),
        }
    }

    fn string(&mut self) -> Result<Token> {
        let mut s = String::new();
        loop {
            match self.chars.next() {
                Some(c) => match c {
                    '\\' => s.push(try!(self.escape())),
                    '"' => return Ok(Token::String(s)),
                    _ => s.push(c),
                },
                None => return Err(Error::UnclosedString),
            }
        }
    }

    fn symbol(&mut self) -> Result<String> {
        let mut s = String::new();
        loop {
            match self.chars.next() {
                Some(c) => if is_whitespace_or_close_brace(c) {
                    self.chars.replace(c);
                    return Ok(s);
                } else {
                    s.push(c);
                },
                None => return Ok(s),
            }
        }
    }
}

impl<'a> Iterator for Lexer<'a> {
    type Item = Result<Token>;

    fn next(&mut self) -> Option<Result<Token>> {
        loop {
            let c = match self.chars.next() {
                Some(c) => c,
                None => return None,
            };
            let result = if c.is_whitespace() {
                self.whitespace()
            } else if c.is_digit(DECIMAL) {
                self.chars.replace(c);
                self.number()
            } else if c == '#' {
                self.comment()
            } else if c == '(' {
                self.multi_comment()
            } else if c == '"' {
                self.string()
            } else if c == '{' {
                Ok(Token::OpenBrace)
            } else if c == '}' {
                Ok(Token::CloseBrace)
            } else if c == ':' {
                self.symbol().map(|s| Token::Symbol(s))
            } else {
                self.chars.replace(c);
                self.symbol().map(|s| Token::Call(s))
            };
            // If we have errored, the rest of the source is invalid.
            if result.is_err() {
                self.consume();
            }
            return Some(result);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Lexer, Token, Error};

    #[test]
    fn test_empty_string_is_none() {
        assert_eq!(Lexer::new("").next(), None);
    }

    #[test]
    fn test_whitespace() {
        assert_eq!(Lexer::new(" ").collect::<Vec<_>>(),
            vec![Ok(Token::Whitespace)]);
        assert_eq!(Lexer::new("  \t\t\n\n").collect::<Vec<_>>(),
            vec![Ok(Token::Whitespace)]);
    }

    #[test]
    fn test_number() {
        assert_eq!(Lexer::new("0").collect::<Vec<_>>(),
            vec![Ok(Token::Integer("0".to_string()))]);
        assert_eq!(Lexer::new("1.0").collect::<Vec<_>>(),
            vec![Ok(Token::Float("1.0".to_string()))]);
    }

    #[test]
    fn test_comment() {
        assert_eq!(Lexer::new("(this is a comment)").collect::<Vec<_>>(),
            vec![Ok(Token::Comment)]);
        assert_eq!(Lexer::new("(this is an unclosed comment")
                   .collect::<Vec<_>>(),
            vec![Err(Error::UnclosedComment)]);
    }
    #[test]
    fn test_string() {
        assert_eq!(Lexer::new("\"this is a string\"").collect::<Vec<_>>(),
            vec![Ok(Token::String("this is a string".to_string()))]);
        assert_eq!(Lexer::new("\"this is an unclosed string").collect::<Vec<_>>(),
            vec![Err(Error::UnclosedString)]);
    }

    #[test]
    fn test_call() {
        assert_eq!(Lexer::new("this-is-a-call").collect::<Vec<_>>(),
            vec![Ok(Token::Call("this-is-a-call".to_string()))]);
    }
}
<|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.

//! Types dealing with dynamic mutability

use cast;
use clone::Clone;
use cmp::Eq;
use fmt;
use kinds::{marker, Copy};
use ops::{Deref, DerefMut, Drop};
use option::{None, Option, Some};
use ty::Unsafe;

/// A mutable memory location that admits only `Copy` data.
pub struct Cell<T> {
    value: Unsafe<T>,
    noshare: marker::NoShare,
}

impl<T:Copy> Cell<T> {
    /// Creates a new `Cell` containing the given value.
    pub fn new(value: T) -> Cell<T> {
        Cell {
            value: Unsafe::new(value),
            noshare: marker::NoShare,
        }
    }

    /// Returns a copy of the contained value.
    #[inline]
    pub fn get(&self) -> T {
        unsafe{ *self.value.get() }
    }

    /// Sets the contained value.
    #[inline]
    pub fn set(&self, value: T) {
        unsafe {
            *self.value.get() = value;
        }
    }
}

impl<T:Copy> Clone for Cell<T> {
    fn clone(&self) -> Cell<T> {
        Cell::new(self.get())
    }
}

impl<T:Eq + Copy> Eq for Cell<T> {
    fn eq(&self, other: &Cell<T>) -> bool {
        self.get() == other.get()
    }
}

impl<T: fmt::Show> fmt::Show for Cell<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f.buf, r"Cell \{ value: {} \}", unsafe{*&self.value.get()})
    }
}

/// A mutable memory location with dynamically checked borrow rules
pub struct RefCell<T> {
    value: Unsafe<T>,
    borrow: BorrowFlag,
    nocopy: marker::NoCopy,
    noshare: marker::NoShare,
}

// Values [1, MAX-1] represent the number of `Ref` active
// (will not outgrow its range since `uint` is the size of the address space)
type BorrowFlag = uint;
static UNUSED: BorrowFlag = 0;
static WRITING: BorrowFlag = -1;

impl<T> RefCell<T> {
    /// Create a new `RefCell` containing `value`
    pub fn new(value: T) -> RefCell<T> {
        RefCell {
            value: Unsafe::new(value),
            nocopy: marker::NoCopy,
            noshare: marker::NoShare,
            borrow: UNUSED,
        }
    }

    /// Consumes the `RefCell`, returning the wrapped value.
    pub fn unwrap(self) -> T {
        assert!(self.borrow == UNUSED);
        unsafe{self.value.unwrap()}
    }

    unsafe fn as_mut<'a>(&'a self) -> &'a mut RefCell<T> {
        cast::transmute_mut(self)
    }

    /// Attempts to immutably borrow the wrapped value.
    ///
    /// The borrow lasts until the returned `Ref` exits scope. Multiple
    /// immutable borrows can be taken out at the same time.
    ///
    /// Returns `None` if the value is currently mutably borrowed.
    pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
        match self.borrow {
            WRITING => None,
            _ => {
                unsafe { self.as_mut().borrow += 1; }
                Some(Ref { parent: self })
            }
        }
    }

    /// Immutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `Ref` exits scope. Multiple
    /// immutable borrows can be taken out at the same time.
    ///
    /// # Failure
    ///
    /// Fails if the value is currently mutably borrowed.
    pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
        match self.try_borrow() {
            Some(ptr) => ptr,
            None => fail!("RefCell<T> already mutably borrowed")
        }
    }

    /// Mutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `RefMut` exits scope. The value
    /// cannot be borrowed while this borrow is active.
    ///
    /// Returns `None` if the value is currently borrowed.
    pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
        match self.borrow {
            UNUSED => unsafe {
                let mut_self = self.as_mut();
                mut_self.borrow = WRITING;
                Some(RefMut { parent: mut_self })
            },
            _ => None
        }
    }

    /// Mutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `RefMut` exits scope. The value
    /// cannot be borrowed while this borrow is active.
    ///
    /// # Failure
    ///
    /// Fails if the value is currently borrowed.
    pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
        match self.try_borrow_mut() {
            Some(ptr) => ptr,
            None => fail!("RefCell<T> already borrowed")
        }
    }

    /// Sets the value, replacing what was there.
    ///
    /// # Failure
    ///
    /// Fails if the value is currently borrowed.
    #[inline]
    pub fn set(&self, value: T) {
        *self.borrow_mut() = value;
    }
}

impl<T:Clone> RefCell<T> {
    /// Returns a copy of the contained value.
    ///
    /// # Failure
    ///
    /// Fails if the value is currently mutably borrowed.
    #[inline]
    pub fn get(&self) -> T {
        (*self.borrow()).clone()
    }
}

impl<T: Clone> Clone for RefCell<T> {
    fn clone(&self) -> RefCell<T> {
        RefCell::new(self.get())
    }
}

impl<T: Eq> Eq for RefCell<T> {
    fn eq(&self, other: &RefCell<T>) -> bool {
        *self.borrow() == *other.borrow()
    }
}

/// Wraps a borrowed reference to a value in a `RefCell` box.
pub struct Ref<'b, T> {
    parent: &'b RefCell<T>
}

#[unsafe_destructor]
impl<'b, T> Drop for Ref<'b, T> {
    fn drop(&mut self) {
        assert!(self.parent.borrow != WRITING && self.parent.borrow != UNUSED);
        unsafe { self.parent.as_mut().borrow -= 1; }
    }
}

impl<'b, T> Deref<T> for Ref<'b, T> {
    #[inline]
    fn deref<'a>(&'a self) -> &'a T {
        unsafe{ &*self.parent.value.get() }
    }
}

/// Wraps a mutable borrowed reference to a value in a `RefCell` box.
pub struct RefMut<'b, T> {
    parent: &'b mut RefCell<T>
}

#[unsafe_destructor]
impl<'b, T> Drop for RefMut<'b, T> {
    fn drop(&mut self) {
        assert!(self.parent.borrow == WRITING);
        self.parent.borrow = UNUSED;
    }
}

impl<'b, T> Deref<T> for RefMut<'b, T> {
    #[inline]
    fn deref<'a>(&'a self) -> &'a T {
        unsafe{ &*self.parent.value.get() }
    }
}

impl<'b, T> DerefMut<T> for RefMut<'b, T> {
    #[inline]
    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe{ &mut *self.parent.value.get() }
    }
}

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

    #[test]
    fn smoketest_cell() {
        let x = Cell::new(10);
        assert_eq!(x, Cell::new(10));
        assert_eq!(x.get(), 10);
        x.set(20);
        assert_eq!(x, Cell::new(20));
        assert_eq!(x.get(), 20);

        let y = Cell::new((30, 40));
        assert_eq!(y, Cell::new((30, 40)));
        assert_eq!(y.get(), (30, 40));
    }

    #[test]
    fn double_imm_borrow() {
        let x = RefCell::new(0);
        let _b1 = x.borrow();
        x.borrow();
    }

    #[test]
    fn no_mut_then_imm_borrow() {
        let x = RefCell::new(0);
        let _b1 = x.borrow_mut();
        assert!(x.try_borrow().is_none());
    }

    #[test]
    fn no_imm_then_borrow_mut() {
        let x = RefCell::new(0);
        let _b1 = x.borrow();
        assert!(x.try_borrow_mut().is_none());
    }

    #[test]
    fn no_double_borrow_mut() {
        let x = RefCell::new(0);
        let _b1 = x.borrow_mut();
        assert!(x.try_borrow_mut().is_none());
    }

    #[test]
    fn imm_release_borrow_mut() {
        let x = RefCell::new(0);
        {
            let _b1 = x.borrow();
        }
        x.borrow_mut();
    }

    #[test]
    fn mut_release_borrow_mut() {
        let x = RefCell::new(0);
        {
            let _b1 = x.borrow_mut();
        }
        x.borrow();
    }

    #[test]
    fn double_borrow_single_release_no_borrow_mut() {
        let x = RefCell::new(0);
        let _b1 = x.borrow();
        {
            let _b2 = x.borrow();
        }
        assert!(x.try_borrow_mut().is_none());
    }

    #[test]
    #[should_fail]
    fn discard_doesnt_unborrow() {
        let x = RefCell::new(0);
        let _b = x.borrow();
        let _ = _b;
        let _b = x.borrow_mut();
    }
}
<commit_msg>std: fix Cell's Show instance.<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.

//! Types dealing with dynamic mutability

use cast;
use clone::Clone;
use cmp::Eq;
use fmt;
use kinds::{marker, Copy};
use ops::{Deref, DerefMut, Drop};
use option::{None, Option, Some};
use ty::Unsafe;

/// A mutable memory location that admits only `Copy` data.
pub struct Cell<T> {
    value: Unsafe<T>,
    noshare: marker::NoShare,
}

impl<T:Copy> Cell<T> {
    /// Creates a new `Cell` containing the given value.
    pub fn new(value: T) -> Cell<T> {
        Cell {
            value: Unsafe::new(value),
            noshare: marker::NoShare,
        }
    }

    /// Returns a copy of the contained value.
    #[inline]
    pub fn get(&self) -> T {
        unsafe{ *self.value.get() }
    }

    /// Sets the contained value.
    #[inline]
    pub fn set(&self, value: T) {
        unsafe {
            *self.value.get() = value;
        }
    }
}

impl<T:Copy> Clone for Cell<T> {
    fn clone(&self) -> Cell<T> {
        Cell::new(self.get())
    }
}

impl<T:Eq + Copy> Eq for Cell<T> {
    fn eq(&self, other: &Cell<T>) -> bool {
        self.get() == other.get()
    }
}

impl<T: Copy + fmt::Show> fmt::Show for Cell<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f.buf, r"Cell \{ value: {} \}", self.get())
    }
}

/// A mutable memory location with dynamically checked borrow rules
pub struct RefCell<T> {
    value: Unsafe<T>,
    borrow: BorrowFlag,
    nocopy: marker::NoCopy,
    noshare: marker::NoShare,
}

// Values [1, MAX-1] represent the number of `Ref` active
// (will not outgrow its range since `uint` is the size of the address space)
type BorrowFlag = uint;
static UNUSED: BorrowFlag = 0;
static WRITING: BorrowFlag = -1;

impl<T> RefCell<T> {
    /// Create a new `RefCell` containing `value`
    pub fn new(value: T) -> RefCell<T> {
        RefCell {
            value: Unsafe::new(value),
            nocopy: marker::NoCopy,
            noshare: marker::NoShare,
            borrow: UNUSED,
        }
    }

    /// Consumes the `RefCell`, returning the wrapped value.
    pub fn unwrap(self) -> T {
        assert!(self.borrow == UNUSED);
        unsafe{self.value.unwrap()}
    }

    unsafe fn as_mut<'a>(&'a self) -> &'a mut RefCell<T> {
        cast::transmute_mut(self)
    }

    /// Attempts to immutably borrow the wrapped value.
    ///
    /// The borrow lasts until the returned `Ref` exits scope. Multiple
    /// immutable borrows can be taken out at the same time.
    ///
    /// Returns `None` if the value is currently mutably borrowed.
    pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
        match self.borrow {
            WRITING => None,
            _ => {
                unsafe { self.as_mut().borrow += 1; }
                Some(Ref { parent: self })
            }
        }
    }

    /// Immutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `Ref` exits scope. Multiple
    /// immutable borrows can be taken out at the same time.
    ///
    /// # Failure
    ///
    /// Fails if the value is currently mutably borrowed.
    pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
        match self.try_borrow() {
            Some(ptr) => ptr,
            None => fail!("RefCell<T> already mutably borrowed")
        }
    }

    /// Mutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `RefMut` exits scope. The value
    /// cannot be borrowed while this borrow is active.
    ///
    /// Returns `None` if the value is currently borrowed.
    pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
        match self.borrow {
            UNUSED => unsafe {
                let mut_self = self.as_mut();
                mut_self.borrow = WRITING;
                Some(RefMut { parent: mut_self })
            },
            _ => None
        }
    }

    /// Mutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `RefMut` exits scope. The value
    /// cannot be borrowed while this borrow is active.
    ///
    /// # Failure
    ///
    /// Fails if the value is currently borrowed.
    pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
        match self.try_borrow_mut() {
            Some(ptr) => ptr,
            None => fail!("RefCell<T> already borrowed")
        }
    }

    /// Sets the value, replacing what was there.
    ///
    /// # Failure
    ///
    /// Fails if the value is currently borrowed.
    #[inline]
    pub fn set(&self, value: T) {
        *self.borrow_mut() = value;
    }
}

impl<T:Clone> RefCell<T> {
    /// Returns a copy of the contained value.
    ///
    /// # Failure
    ///
    /// Fails if the value is currently mutably borrowed.
    #[inline]
    pub fn get(&self) -> T {
        (*self.borrow()).clone()
    }
}

impl<T: Clone> Clone for RefCell<T> {
    fn clone(&self) -> RefCell<T> {
        RefCell::new(self.get())
    }
}

impl<T: Eq> Eq for RefCell<T> {
    fn eq(&self, other: &RefCell<T>) -> bool {
        *self.borrow() == *other.borrow()
    }
}

/// Wraps a borrowed reference to a value in a `RefCell` box.
pub struct Ref<'b, T> {
    parent: &'b RefCell<T>
}

#[unsafe_destructor]
impl<'b, T> Drop for Ref<'b, T> {
    fn drop(&mut self) {
        assert!(self.parent.borrow != WRITING && self.parent.borrow != UNUSED);
        unsafe { self.parent.as_mut().borrow -= 1; }
    }
}

impl<'b, T> Deref<T> for Ref<'b, T> {
    #[inline]
    fn deref<'a>(&'a self) -> &'a T {
        unsafe{ &*self.parent.value.get() }
    }
}

/// Wraps a mutable borrowed reference to a value in a `RefCell` box.
pub struct RefMut<'b, T> {
    parent: &'b mut RefCell<T>
}

#[unsafe_destructor]
impl<'b, T> Drop for RefMut<'b, T> {
    fn drop(&mut self) {
        assert!(self.parent.borrow == WRITING);
        self.parent.borrow = UNUSED;
    }
}

impl<'b, T> Deref<T> for RefMut<'b, T> {
    #[inline]
    fn deref<'a>(&'a self) -> &'a T {
        unsafe{ &*self.parent.value.get() }
    }
}

impl<'b, T> DerefMut<T> for RefMut<'b, T> {
    #[inline]
    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe{ &mut *self.parent.value.get() }
    }
}

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

    #[test]
    fn smoketest_cell() {
        let x = Cell::new(10);
        assert_eq!(x, Cell::new(10));
        assert_eq!(x.get(), 10);
        x.set(20);
        assert_eq!(x, Cell::new(20));
        assert_eq!(x.get(), 20);

        let y = Cell::new((30, 40));
        assert_eq!(y, Cell::new((30, 40)));
        assert_eq!(y.get(), (30, 40));
    }

    #[test]
    fn cell_has_sensible_show() {
        use str::StrSlice;

        let x = Cell::new("foo bar");
        assert!(format!("{}", x).contains(x.get()));

        x.set("baz qux");
        assert!(format!("{}", x).contains(x.get()));
    }

    #[test]
    fn double_imm_borrow() {
        let x = RefCell::new(0);
        let _b1 = x.borrow();
        x.borrow();
    }

    #[test]
    fn no_mut_then_imm_borrow() {
        let x = RefCell::new(0);
        let _b1 = x.borrow_mut();
        assert!(x.try_borrow().is_none());
    }

    #[test]
    fn no_imm_then_borrow_mut() {
        let x = RefCell::new(0);
        let _b1 = x.borrow();
        assert!(x.try_borrow_mut().is_none());
    }

    #[test]
    fn no_double_borrow_mut() {
        let x = RefCell::new(0);
        let _b1 = x.borrow_mut();
        assert!(x.try_borrow_mut().is_none());
    }

    #[test]
    fn imm_release_borrow_mut() {
        let x = RefCell::new(0);
        {
            let _b1 = x.borrow();
        }
        x.borrow_mut();
    }

    #[test]
    fn mut_release_borrow_mut() {
        let x = RefCell::new(0);
        {
            let _b1 = x.borrow_mut();
        }
        x.borrow();
    }

    #[test]
    fn double_borrow_single_release_no_borrow_mut() {
        let x = RefCell::new(0);
        let _b1 = x.borrow();
        {
            let _b2 = x.borrow();
        }
        assert!(x.try_borrow_mut().is_none());
    }

    #[test]
    #[should_fail]
    fn discard_doesnt_unborrow() {
        let x = RefCell::new(0);
        let _b = x.borrow();
        let _ = _b;
        let _b = x.borrow_mut();
    }
}
<|endoftext|>


<commit_before>use std::{fmt, iter};
use std::ops::{Index, IndexMut};
use std::str::FromStr;

use geom::{Geom, Point, Size, Matrix};

pub type Hint = Option<u8>;
#[derive(Copy, Clone, Show, Eq, PartialEq)]
pub enum Side { In, Out }
#[derive(Copy, Clone, Show, Eq, PartialEq)]
pub enum Edge { Line, Cross }

#[derive(Clone, Show, Eq, PartialEq)]
pub struct Board {
    size: Size,
    hint: Matrix<Hint>,
    side: Matrix<Option<Side>>,
    edge_v: Matrix<Option<Edge>>,
    edge_h: Matrix<Option<Edge>>
}

impl Board {
    pub fn new(size: Size) -> Board {
        assert!(size.0 > 0 && size.1 > 0);
        let hint = Matrix::new_empty(size, None, None);
        let side = Matrix::new_empty(size, Some(Side::Out), None);
        let edge_v = Matrix::new_empty(Size(size.0, size.1 + 1), Some(Edge::Cross), None);
        let edge_h = Matrix::new_empty(Size(size.0 + 1, size.1), Some(Edge::Cross), None);
        Board { size: size, hint: hint, side: side, edge_v: edge_v, edge_h: edge_h }
    }

    fn with_data(size: Size, hint: Vec<Hint>, side: Vec<Option<Side>>,
                 edge_v: Vec<Option<Edge>>, edge_h: Vec<Option<Edge>>) -> Board {
        assert!(size.0 > 0 && size.1 > 0);
        let hint = Matrix::new(size, None, hint);
        let side = Matrix::new(size, Some(Side::Out), side);
        let edge_v = Matrix::new(Size(size.0, size.1 + 1), Some(Edge::Cross), edge_v);
        let edge_h = Matrix::new(Size(size.0 + 1, size.1), Some(Edge::Cross), edge_h);
        Board { size: size, hint: hint, side: side, edge_v: edge_v, edge_h: edge_h }
    }

    pub fn hint(&self) -> &Matrix<Hint> { &self.hint }
    pub fn side(&self) -> &Matrix<Option<Side>> { &self.side }
    pub fn edge_h(&self) -> &Matrix<Option<Edge>> { &self.edge_h }
    pub fn edge_v(&self) -> &Matrix<Option<Edge>> { &self.edge_v }

    pub fn hint_mut(&mut self) -> &mut Matrix<Hint> { &mut self.hint }
    pub fn side_mut(&mut self) -> &mut Matrix<Option<Side>> { &mut self.side }
    pub fn edge_h_mut(&mut self) -> &mut Matrix<Option<Edge>> { &mut self.edge_h }
    pub fn edge_v_mut(&mut self) -> &mut Matrix<Option<Edge>> { &mut self.edge_v }
}

impl Geom for Board {
    fn size(&self) -> Size { self.size }
}

impl Index<Point> for Board {
    type Output = Hint;

    fn index(&self, p: &Point) -> &Hint {
        &self.hint[*p]
    }
}

impl IndexMut<Point> for Board {
    type Output = Hint;

    fn index_mut(&mut self, p: &Point) -> &mut Hint {
        &mut self.hint[*p]
    }
}

impl FromStr for Board {
    fn from_str(s: &str) -> Option<Board> {
        let mut mat = s.lines()
            .map(|l| l.trim_matches('\n'))
            .map(|l| l.chars().collect::<Vec<_>>())
            .skip_while(|l| l.is_empty())
            .collect::<Vec<_>>();

        while mat.last().map(|l| l.len()) == Some(0) {
            let _ = mat.pop();
        }

        if mat.len() == 0 { return None }

        fn parse_pat1(mat: Vec<Vec<char>>) -> Option<Board> {
            let rows = mat.iter()
                .enumerate()
                .filter(|&(_, cs)| cs[0] == '+')
                .map(|(i, _)| i)
                .collect::<Vec<_>>();
            let cols = mat[0].iter()
                .enumerate()
                .filter(|&(_, &c)| c == '+')
                .map(|(i, _)| i)
                .collect::<Vec<_>>();

            if rows.len() <= 1 { return None }
            if cols.len() <= 1 { return None }

            for &r in rows.iter() {
                if mat[r].iter().position(|&c| c == '+') != Some(cols[0]) {
                    return None
                }
                if mat[r].iter().rposition(|&c| c == '+') != Some(cols[cols.len() - 1]) {
                    return None
                }
                for &c in cols.iter() {
                    if mat[r].len() <= c {
                        return None
                    }
                    if mat[r][c] != '+' {
                        return None
                    }
                }
            }

            let mut edge_v = vec![];
            for (&rs, &re) in rows.iter().zip(rows[1 ..].iter()) {
                for &c in cols.iter() {
                    let s = mat[rs + 1 .. re]
                        .iter()
                        .map(|row| row[c])
                        .collect::<String>();
                    let edge = if s.len() == 0 {
                        None
                    } else if s.chars().all(|c| c == 'x') {
                        Some(Edge::Cross)
                    } else if s.chars().all(|c| c == '|') {
                        Some(Edge::Line)
                    } else {
                        None
                    };
                    edge_v.push(edge);
                }
            }

            let mut edge_h = vec!{};
            for &r in rows.iter() {
                for (&cs, &ce) in cols.iter().zip(cols[1 ..].iter()) {
                    let s = mat[r][cs + 1 .. ce]
                        .iter()
                        .cloned()
                        .collect::<String>();
                    let edge = if s.len() == 0 {
                        None
                    } else if s.chars().all(|c| c == 'x') {
                        Some(Edge::Cross)
                    } else if s.chars().all(|c| c == '-') {
                        Some(Edge::Line)
                    } else {
                        None
                    };
                    edge_h.push(edge);
                }
            }

            let mut hint = vec![];
            for (&rs, &re) in rows.iter().zip(rows[1 ..].iter()) {
                for (&cs, &ce) in cols.iter().zip(cols[1 ..].iter()) {
                    let s = mat[rs + 1 .. re]
                        .iter()
                        .flat_map(|row| row[cs + 1 .. ce].iter())
                        .cloned()
                        .collect::<String>();
                    let cell = match s.trim_matches(' ') {
                        "0" => Some(0),
                        "1" => Some(1),
                        "2" => Some(2),
                        "3" => Some(3),
                        _ => None
                    };
                    hint.push(cell);
                }
            }

            let size = Size((rows.len() - 1) as i32, (cols.len() - 1) as i32);
            let side = iter::repeat(None).take((rows.len() - 1) * (cols.len() - 1)).collect();
            Some(Board::with_data(size, hint, side, edge_v, edge_h))
        }

        fn parse_pat2(mat: Vec<Vec<char>>) -> Option<Board> {
            let row = mat.len();
            if row == 0 { return None }
            let col = mat[0].len();
            if col == 0 { return None }
            if mat[1 ..].iter().any(|r| r.len() != col) { return None }

            let hint = mat.iter().flat_map(|line| {
                line.iter().filter_map(|&c| {
                    match c {
                        '0' => Some(Some(0)),
                        '1' => Some(Some(1)),
                        '2' => Some(Some(2)),
                        '3' => Some(Some(3)),
                        '_' => Some(None),
                        _ => None
                    }
                })
            }).collect::<Vec<_>>();
            if hint.len() != row * col { return None }

            let size = Size(row as i32, col as i32);
            let side = iter::repeat(None).take(row * col).collect();
            let edge_v = iter::repeat(None).take(row * (col + 1)).collect();
            let edge_h = iter::repeat(None).take((row + 1) * col).collect();
            Some(Board::with_data(size, hint, side, edge_v, edge_h))
        }

        if mat[0].iter().any(|&c| c == '+') {
            parse_pat1(mat)
        } else {
            parse_pat2(mat)
        }
    }
}

struct Cross;
impl fmt::String for Cross {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "+")
    }
}

struct HEdge<'a>(&'a Board, Point);
impl<'a> fmt::String for HEdge<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let HEdge(board, p) = *self;
        match board.edge_h[p] {
            Some(Edge::Cross) => try!(write!(f, "x")),
            Some(Edge::Line) => try!(write!(f, "-")),
            None => try!(write!(f, " "))
        }
        Ok(())
    }
}

struct VEdge<'a>(&'a Board, Point);
impl<'a> fmt::String for VEdge<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let VEdge(board, p) = *self;
        match board.edge_v[p] {
            Some(Edge::Cross) => try!(write!(f, "x")),
            Some(Edge::Line) => try!(write!(f, "|")),
            None => try!(write!(f, " "))
        }
        Ok(())
    }
}

struct EdgeRow<'a>(&'a Board, i32);
impl<'a> fmt::String for EdgeRow<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let EdgeRow(board, r) = *self;
        for c in (0 .. board.column()) {
            let p = Point(r, c);
            try!(write!(f, "{}", Cross));
            try!(write!(f, "{}", HEdge(board, p)));
        }
        try!(write!(f, "{}", Cross));
        Ok(())
    }
}

struct CellRow<'a>(&'a Board, i32);
impl<'a> fmt::String for CellRow<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let CellRow(board, r) = *self;
        for c in (0 .. board.column()) {
            let p = Point(r, c);
            try!(write!(f, "{}", VEdge(board, p)));
            match board.hint[p] {
                Some(n) => try!(write!(f, "{}", n)),
                None => try!(write!(f, " "))
            }
        }
        try!(write!(f, "{}", VEdge(board, Point(r, board.column()))));
        Ok(())
    }
}

impl fmt::String for Board {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for r in (0 .. self.row()) {
            try!(writeln!(f, "{}", EdgeRow(self, r)));
            try!(writeln!(f, "{}", CellRow(self, r)));
        }
        try!(writeln!(f, "{}", EdgeRow(self, self.row())));
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::Board;
    use geom::{Geom, Size, Point};

    #[test]
    fn parse() {
        let input = "123___
______
3_____
";
        let hint = input.parse::<Board>().unwrap();
        assert_eq!(Size(3, 6), hint.size());
        assert_eq!(Some(1), hint[Point(0, 0)]);
        assert_eq!(Some(2), hint[Point(0, 1)]);
        assert_eq!(Some(3), hint[Point(0, 2)]);
        assert_eq!(None, hint[Point(0, 3)]);
        assert_eq!(None, hint[Point(0, 4)]);
        assert_eq!(None, hint[Point(0, 5)]);
        assert_eq!(None, hint[Point(1, 0)]);
        assert_eq!(None, hint[Point(1, 1)]);
        assert_eq!(None, hint[Point(1, 2)]);
        assert_eq!(None, hint[Point(1, 3)]);
        assert_eq!(None, hint[Point(1, 4)]);
        assert_eq!(None, hint[Point(1, 5)]);
        assert_eq!(Some(3), hint[Point(2, 0)]);
        assert_eq!(None, hint[Point(2, 1)]);
        assert_eq!(None, hint[Point(2, 2)]);
        assert_eq!(None, hint[Point(2, 3)]);
        assert_eq!(None, hint[Point(2, 4)]);
        assert_eq!(None, hint[Point(2, 5)]);

        assert_eq!(Some(&hint), hint.to_string().parse::<Board>().as_ref());

        assert_eq!(None, "1243".parse::<Board>());

        let input = "
+--+ +-+!!+asdf
+  + + +  +
|  |1|    |
|  | |  2 |
+  + + +  +
";
        let output = "+-+ +-+ +

+ + + + +
| |1|  2|
+ + + + +
";

        let hint = input.parse::<Board>().unwrap();
        assert_eq!(Some(1), hint[Point(1, 1)]);
        assert_eq!(Some(2), hint[Point(1, 3)]);
        assert_eq!(output, hint.to_string());

        assert_eq!(None, "".parse::<Board>());
    }
}
<commit_msg>board: fix from_str<commit_after>use std::{fmt, iter};
use std::ops::{Index, IndexMut};
use std::str::FromStr;

use geom::{Geom, Point, Size, Matrix};

pub type Hint = Option<u8>;
#[derive(Copy, Clone, Show, Eq, PartialEq)]
pub enum Side { In, Out }
#[derive(Copy, Clone, Show, Eq, PartialEq)]
pub enum Edge { Line, Cross }

#[derive(Clone, Show, Eq, PartialEq)]
pub struct Board {
    size: Size,
    hint: Matrix<Hint>,
    side: Matrix<Option<Side>>,
    edge_v: Matrix<Option<Edge>>,
    edge_h: Matrix<Option<Edge>>
}

impl Board {
    pub fn new(size: Size) -> Board {
        assert!(size.0 > 0 && size.1 > 0);
        let hint = Matrix::new_empty(size, None, None);
        let side = Matrix::new_empty(size, Some(Side::Out), None);
        let edge_v = Matrix::new_empty(Size(size.0, size.1 + 1), Some(Edge::Cross), None);
        let edge_h = Matrix::new_empty(Size(size.0 + 1, size.1), Some(Edge::Cross), None);
        Board { size: size, hint: hint, side: side, edge_v: edge_v, edge_h: edge_h }
    }

    fn with_data(size: Size, hint: Vec<Hint>, side: Vec<Option<Side>>,
                 edge_v: Vec<Option<Edge>>, edge_h: Vec<Option<Edge>>) -> Board {
        assert!(size.0 > 0 && size.1 > 0);
        let hint = Matrix::new(size, None, hint);
        let side = Matrix::new(size, Some(Side::Out), side);
        let edge_v = Matrix::new(Size(size.0, size.1 + 1), Some(Edge::Cross), edge_v);
        let edge_h = Matrix::new(Size(size.0 + 1, size.1), Some(Edge::Cross), edge_h);
        Board { size: size, hint: hint, side: side, edge_v: edge_v, edge_h: edge_h }
    }

    pub fn hint(&self) -> &Matrix<Hint> { &self.hint }
    pub fn side(&self) -> &Matrix<Option<Side>> { &self.side }
    pub fn edge_h(&self) -> &Matrix<Option<Edge>> { &self.edge_h }
    pub fn edge_v(&self) -> &Matrix<Option<Edge>> { &self.edge_v }

    pub fn hint_mut(&mut self) -> &mut Matrix<Hint> { &mut self.hint }
    pub fn side_mut(&mut self) -> &mut Matrix<Option<Side>> { &mut self.side }
    pub fn edge_h_mut(&mut self) -> &mut Matrix<Option<Edge>> { &mut self.edge_h }
    pub fn edge_v_mut(&mut self) -> &mut Matrix<Option<Edge>> { &mut self.edge_v }
}

impl Geom for Board {
    fn size(&self) -> Size { self.size }
}

impl Index<Point> for Board {
    type Output = Hint;

    fn index(&self, p: &Point) -> &Hint {
        &self.hint[*p]
    }
}

impl IndexMut<Point> for Board {
    type Output = Hint;

    fn index_mut(&mut self, p: &Point) -> &mut Hint {
        &mut self.hint[*p]
    }
}

impl FromStr for Board {
    fn from_str(s: &str) -> Option<Board> {
        let mut mat = s.lines()
            .map(|l| l.trim_matches('\n'))
            .map(|l| l.chars().collect::<Vec<_>>())
            .skip_while(|l| l.is_empty())
            .collect::<Vec<_>>();

        while mat.last().map(|l| l.len()) == Some(0) {
            let _ = mat.pop();
        }

        if mat.len() == 0 { return None }

        fn parse_pat1(mat: Vec<Vec<char>>) -> Option<Board> {
            let rows = mat.iter()
                .enumerate()
                .filter(|&(_, cs)| cs[0] == '+')
                .map(|(i, _)| i)
                .collect::<Vec<_>>();
            let cols = mat[rows[0]].iter()
                .enumerate()
                .filter(|&(_, &c)| c == '+')
                .map(|(i, _)| i)
                .collect::<Vec<_>>();

            if rows.len() <= 1 { return None }
            if cols.len() <= 1 { return None }

            for &r in rows.iter() {
                if mat[r].iter().position(|&c| c == '+') != Some(cols[0]) {
                    return None
                }
                if mat[r].iter().rposition(|&c| c == '+') != Some(cols[cols.len() - 1]) {
                    return None
                }
                for &c in cols.iter() {
                    if mat[r].len() <= c {
                        return None
                    }
                    if mat[r][c] != '+' {
                        return None
                    }
                }
            }

            let mut edge_v = vec![];
            for (&rs, &re) in rows.iter().zip(rows[1 ..].iter()) {
                for &c in cols.iter() {
                    let s = mat[rs + 1 .. re]
                        .iter()
                        .map(|row| if c < row.len() { row[c] } else { ' ' })
                        .collect::<String>();
                    let edge = if s.len() == 0 {
                        None
                    } else if s.chars().all(|c| c == 'x') {
                        Some(Edge::Cross)
                    } else if s.chars().all(|c| c == '|') {
                        Some(Edge::Line)
                    } else {
                        None
                    };
                    edge_v.push(edge);
                }
            }

            let mut edge_h = vec!{};
            for &r in rows.iter() {
                for (&cs, &ce) in cols.iter().zip(cols[1 ..].iter()) {
                    let s = mat[r][cs + 1 .. ce]
                        .iter()
                        .cloned()
                        .collect::<String>();
                    let edge = if s.len() == 0 {
                        None
                    } else if s.chars().all(|c| c == 'x') {
                        Some(Edge::Cross)
                    } else if s.chars().all(|c| c == '-') {
                        Some(Edge::Line)
                    } else {
                        None
                    };
                    edge_h.push(edge);
                }
            }

            let mut hint = vec![];
            for (&rs, &re) in rows.iter().zip(rows[1 ..].iter()) {
                for (&cs, &ce) in cols.iter().zip(cols[1 ..].iter()) {
                    let s = mat[rs + 1 .. re]
                        .iter()
                        .flat_map(|row| row[cs + 1 .. ce].iter())
                        .cloned()
                        .collect::<String>();
                    let cell = match s.trim_matches(' ') {
                        "0" => Some(0),
                        "1" => Some(1),
                        "2" => Some(2),
                        "3" => Some(3),
                        _ => None
                    };
                    hint.push(cell);
                }
            }

            let size = Size((rows.len() - 1) as i32, (cols.len() - 1) as i32);
            let side = iter::repeat(None).take((rows.len() - 1) * (cols.len() - 1)).collect();
            Some(Board::with_data(size, hint, side, edge_v, edge_h))
        }

        fn parse_pat2(mat: Vec<Vec<char>>) -> Option<Board> {
            let row = mat.len();
            if row == 0 { return None }
            let col = mat[0].len();
            if col == 0 { return None }
            if mat[1 ..].iter().any(|r| r.len() != col) { return None }

            let hint = mat.iter().flat_map(|line| {
                line.iter().filter_map(|&c| {
                    match c {
                        '0' => Some(Some(0)),
                        '1' => Some(Some(1)),
                        '2' => Some(Some(2)),
                        '3' => Some(Some(3)),
                        '_' => Some(None),
                        _ => None
                    }
                })
            }).collect::<Vec<_>>();
            if hint.len() != row * col { return None }

            let size = Size(row as i32, col as i32);
            let side = iter::repeat(None).take(row * col).collect();
            let edge_v = iter::repeat(None).take(row * (col + 1)).collect();
            let edge_h = iter::repeat(None).take((row + 1) * col).collect();
            Some(Board::with_data(size, hint, side, edge_v, edge_h))
        }

        if mat[0].iter().any(|&c| c == '+') {
            parse_pat1(mat)
        } else {
            parse_pat2(mat)
        }
    }
}

struct Cross;
impl fmt::String for Cross {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "+")
    }
}

struct HEdge<'a>(&'a Board, Point);
impl<'a> fmt::String for HEdge<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let HEdge(board, p) = *self;
        match board.edge_h[p] {
            Some(Edge::Cross) => try!(write!(f, "x")),
            Some(Edge::Line) => try!(write!(f, "-")),
            None => try!(write!(f, " "))
        }
        Ok(())
    }
}

struct VEdge<'a>(&'a Board, Point);
impl<'a> fmt::String for VEdge<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let VEdge(board, p) = *self;
        match board.edge_v[p] {
            Some(Edge::Cross) => try!(write!(f, "x")),
            Some(Edge::Line) => try!(write!(f, "|")),
            None => try!(write!(f, " "))
        }
        Ok(())
    }
}

struct EdgeRow<'a>(&'a Board, i32);
impl<'a> fmt::String for EdgeRow<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let EdgeRow(board, r) = *self;
        for c in (0 .. board.column()) {
            let p = Point(r, c);
            try!(write!(f, "{}", Cross));
            try!(write!(f, "{}", HEdge(board, p)));
        }
        try!(write!(f, "{}", Cross));
        Ok(())
    }
}

struct CellRow<'a>(&'a Board, i32);
impl<'a> fmt::String for CellRow<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let CellRow(board, r) = *self;
        for c in (0 .. board.column()) {
            let p = Point(r, c);
            try!(write!(f, "{}", VEdge(board, p)));
            match board.hint[p] {
                Some(n) => try!(write!(f, "{}", n)),
                None => try!(write!(f, " "))
            }
        }
        try!(write!(f, "{}", VEdge(board, Point(r, board.column()))));
        Ok(())
    }
}

impl fmt::String for Board {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for r in (0 .. self.row()) {
            try!(writeln!(f, "{}", EdgeRow(self, r)));
            try!(writeln!(f, "{}", CellRow(self, r)));
        }
        try!(writeln!(f, "{}", EdgeRow(self, self.row())));
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::Board;
    use geom::{Geom, Size, Point};

    #[test]
    fn parse() {
        let input = "123___
______
3_____
";
        let hint = input.parse::<Board>().unwrap();
        assert_eq!(Size(3, 6), hint.size());
        assert_eq!(Some(1), hint[Point(0, 0)]);
        assert_eq!(Some(2), hint[Point(0, 1)]);
        assert_eq!(Some(3), hint[Point(0, 2)]);
        assert_eq!(None, hint[Point(0, 3)]);
        assert_eq!(None, hint[Point(0, 4)]);
        assert_eq!(None, hint[Point(0, 5)]);
        assert_eq!(None, hint[Point(1, 0)]);
        assert_eq!(None, hint[Point(1, 1)]);
        assert_eq!(None, hint[Point(1, 2)]);
        assert_eq!(None, hint[Point(1, 3)]);
        assert_eq!(None, hint[Point(1, 4)]);
        assert_eq!(None, hint[Point(1, 5)]);
        assert_eq!(Some(3), hint[Point(2, 0)]);
        assert_eq!(None, hint[Point(2, 1)]);
        assert_eq!(None, hint[Point(2, 2)]);
        assert_eq!(None, hint[Point(2, 3)]);
        assert_eq!(None, hint[Point(2, 4)]);
        assert_eq!(None, hint[Point(2, 5)]);

        assert_eq!(Some(&hint), hint.to_string().parse::<Board>().as_ref());

        assert_eq!(None, "1243".parse::<Board>());

        let input = "
+--+ +-+!!+asdf
+  + + +  +
|  |1|    |
|  | |  2 |
+  + + +  +
";
        let output = "+-+ +-+ +

+ + + + +
| |1|  2|
+ + + + +
";

        let hint = input.parse::<Board>().unwrap();
        assert_eq!(Some(1), hint[Point(1, 1)]);
        assert_eq!(Some(2), hint[Point(1, 3)]);
        assert_eq!(output, hint.to_string());

        assert_eq!(None, "".parse::<Board>());

        let input = "
+ + + +
 1 2 3
+ + + +
";
        let hint = input.parse::<Board>().unwrap();
        assert_eq!(Some(1), hint[Point(0, 0)]);
        assert_eq!(Some(2), hint[Point(0, 1)]);
        assert_eq!(Some(3), hint[Point(0, 2)]);
    }
}
<|endoftext|>


<commit_before>//! Complex numbers

#![deny(missing_docs, warnings)]

extern crate onezero;

use std::fmt;
use std::num::FloatMath;
use std::rand::{Rand, Rng};

use onezero::{One, Zero};

/// A complex number in Cartesian form.
#[repr(C)]
#[deriving(PartialEq)]
pub struct Complex<T> {
    /// The real part
    pub re: T,
    /// The imaginary part
    pub im: T,
}

#[allow(non_camel_case_types)]
pub type c64 = Complex<f32>;
#[allow(non_camel_case_types)]
pub type c128 = Complex<f64>;

impl<T> Complex<T> {
    /// Create a new complex number
    pub fn new(re: T, im: T) -> Complex<T> {
        Complex {
            im: im,
            re: re,
        }
    }
}

impl<T> Complex<T> where T: Clone + Neg<T> {
    /// Returns the complex conjugate
    pub fn conj(&self) -> Complex<T> {
        Complex {
            re: self.re.clone(),
            im: -self.im,
        }
    }
}

impl<T> Complex<T> where T: Add<T, T> + Mul<T, T> {
    /// Returns the square of the norm
    pub fn norm_sqr(&self) -> T {
        self.re * self.re + self.im * self.im
    }
}

impl<T> Complex<T> where T: FloatMath {
    /// Returns the absolute value
    pub fn abs(&self) -> T {
        self.re.hypot(self.im)
    }

    /// Returns the argument
    pub fn arg(&self) -> T {
        self.im.atan2(self.re)
    }
}

impl<T> Add<T, Complex<T>> for Complex<T> where T: Add<T, T> + Clone {
    fn add(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.add(rhs),
            im: self.im.clone(),
        }
    }
}

impl<T> Add<Complex<T>, Complex<T>> for Complex<T> where T: Add<T, T> {
    fn add(&self, rhs: &Complex<T>) -> Complex<T> {
        Complex {
            re: self.re + rhs.re,
            im: self.im + rhs.im,
        }
    }
}

impl<T> Div<T, Complex<T>> for Complex<T> where T: Div<T, T> {
    fn div(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.div(rhs),
            im: self.im.div(rhs),
        }
    }
}

impl<T> Div<Complex<T>, Complex<T>> for Complex<T> where
    T: Add<T, T> + Div<T, T> + Mul<T, T> + Sub<T, T>
{
    fn div(&self, rhs: &Complex<T>) -> Complex<T> {
        let den = rhs.norm_sqr();

        Complex {
            re: (self.re * rhs.re + self.im + rhs.im) / den,
            im: (self.im * rhs.re - self.re * rhs.im) / den,
        }
    }
}

impl<T> Mul<T, Complex<T>> for Complex<T> where T: Mul<T, T> {
    fn mul(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.mul(rhs),
            im: self.im.mul(rhs),
        }
    }
}

impl<T> Mul<Complex<T>, Complex<T>> for Complex<T> where T: Add<T, T> + Mul<T, T> + Sub<T, T> {
    fn mul(&self, rhs: &Complex<T>) -> Complex<T> {
        Complex {
            re: self.re * rhs.re - self.im * rhs.im,
            im: self.re * rhs.im + self.im * rhs.re,
        }
    }
}

impl<T> One for Complex<T> where T: Mul<T, T> + One + Sub<T, T> + Zero {
    fn one() -> Complex<T> {
        Complex {
            re: One::one(),
            im: Zero::zero(),
        }
    }
}

impl<T> Rand for Complex<T> where T: Rand {
    fn rand<R>(rng: &mut R) -> Complex<T> where R: Rng {
        Complex::new(rng.gen(), rng.gen())
    }
}

impl<T> fmt::Show for Complex<T> where T: PartialOrd + fmt::Show + Zero {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < Zero::zero() {
            write!(f, "{}-{}i", self.re, self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}

impl<T> Sub<T, Complex<T>> for Complex<T> where T: Clone + Sub<T, T> {
    fn sub(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.sub(rhs),
            im: self.im.clone(),
        }
    }
}

impl<T> Sub<Complex<T>, Complex<T>> for Complex<T> where T: Sub<T, T> {
    fn sub(&self, rhs: &Complex<T>) -> Complex<T> {
        Complex {
            re: self.re - rhs.re,
            im: self.im - rhs.im,
        }
    }
}

impl<T> Zero for Complex<T> where T: Zero {
    fn zero() -> Complex<T> {
        Complex {
            re: Zero::zero(),
            im: Zero::zero(),
        }
    }
}
<commit_msg>feat(Complex): implement Neg<commit_after>//! Complex numbers

#![deny(missing_docs, warnings)]

extern crate onezero;

use std::fmt;
use std::num::FloatMath;
use std::rand::{Rand, Rng};

use onezero::{One, Zero};

/// A complex number in Cartesian form.
#[repr(C)]
#[deriving(PartialEq)]
pub struct Complex<T> {
    /// The real part
    pub re: T,
    /// The imaginary part
    pub im: T,
}

#[allow(non_camel_case_types)]
pub type c64 = Complex<f32>;
#[allow(non_camel_case_types)]
pub type c128 = Complex<f64>;

impl<T> Complex<T> {
    /// Create a new complex number
    pub fn new(re: T, im: T) -> Complex<T> {
        Complex {
            im: im,
            re: re,
        }
    }
}

impl<T> Complex<T> where T: Clone + Neg<T> {
    /// Returns the complex conjugate
    pub fn conj(&self) -> Complex<T> {
        Complex {
            re: self.re.clone(),
            im: -self.im,
        }
    }
}

impl<T> Complex<T> where T: Add<T, T> + Mul<T, T> {
    /// Returns the square of the norm
    pub fn norm_sqr(&self) -> T {
        self.re * self.re + self.im * self.im
    }
}

impl<T> Complex<T> where T: FloatMath {
    /// Returns the absolute value
    pub fn abs(&self) -> T {
        self.re.hypot(self.im)
    }

    /// Returns the argument
    pub fn arg(&self) -> T {
        self.im.atan2(self.re)
    }
}

impl<T> Add<T, Complex<T>> for Complex<T> where T: Add<T, T> + Clone {
    fn add(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.add(rhs),
            im: self.im.clone(),
        }
    }
}

impl<T> Add<Complex<T>, Complex<T>> for Complex<T> where T: Add<T, T> {
    fn add(&self, rhs: &Complex<T>) -> Complex<T> {
        Complex {
            re: self.re + rhs.re,
            im: self.im + rhs.im,
        }
    }
}

impl<T> Div<T, Complex<T>> for Complex<T> where T: Div<T, T> {
    fn div(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.div(rhs),
            im: self.im.div(rhs),
        }
    }
}

impl<T> Div<Complex<T>, Complex<T>> for Complex<T> where
    T: Add<T, T> + Div<T, T> + Mul<T, T> + Sub<T, T>
{
    fn div(&self, rhs: &Complex<T>) -> Complex<T> {
        let den = rhs.norm_sqr();

        Complex {
            re: (self.re * rhs.re + self.im + rhs.im) / den,
            im: (self.im * rhs.re - self.re * rhs.im) / den,
        }
    }
}

impl<T> Mul<T, Complex<T>> for Complex<T> where T: Mul<T, T> {
    fn mul(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.mul(rhs),
            im: self.im.mul(rhs),
        }
    }
}

impl<T> Mul<Complex<T>, Complex<T>> for Complex<T> where T: Add<T, T> + Mul<T, T> + Sub<T, T> {
    fn mul(&self, rhs: &Complex<T>) -> Complex<T> {
        Complex {
            re: self.re * rhs.re - self.im * rhs.im,
            im: self.re * rhs.im + self.im * rhs.re,
        }
    }
}

impl<T> Neg<Complex<T>> for Complex<T> where T: Neg<T> {
    fn neg(&self) -> Complex<T> {
        Complex {
            re: self.re.neg(),
            im: self.im.neg(),
        }
    }
}

impl<T> One for Complex<T> where T: Mul<T, T> + One + Sub<T, T> + Zero {
    fn one() -> Complex<T> {
        Complex {
            re: One::one(),
            im: Zero::zero(),
        }
    }
}

impl<T> Rand for Complex<T> where T: Rand {
    fn rand<R>(rng: &mut R) -> Complex<T> where R: Rng {
        Complex::new(rng.gen(), rng.gen())
    }
}

impl<T> fmt::Show for Complex<T> where T: PartialOrd + fmt::Show + Zero {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < Zero::zero() {
            write!(f, "{}-{}i", self.re, self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}

impl<T> Sub<T, Complex<T>> for Complex<T> where T: Clone + Sub<T, T> {
    fn sub(&self, rhs: &T) -> Complex<T> {
        Complex {
            re: self.re.sub(rhs),
            im: self.im.clone(),
        }
    }
}

impl<T> Sub<Complex<T>, Complex<T>> for Complex<T> where T: Sub<T, T> {
    fn sub(&self, rhs: &Complex<T>) -> Complex<T> {
        Complex {
            re: self.re - rhs.re,
            im: self.im - rhs.im,
        }
    }
}

impl<T> Zero for Complex<T> where T: Zero {
    fn zero() -> Complex<T> {
        Complex {
            re: Zero::zero(),
            im: Zero::zero(),
        }
    }
}
<|endoftext|>