<commit_before>use std::fmt::{self, Display, Formatter};
use std::io::{self, prelude::*};
use std::str;

#[derive(Debug, PartialEq)]
pub enum MarkupDisplay<T>
where
    T: Display,
{
    Safe(T),
    Unsafe(T),
}

impl<T> MarkupDisplay<T>
where
    T: Display,
{
    pub fn mark_safe(self) -> MarkupDisplay<T> {
        match self {
            MarkupDisplay::Unsafe(t) => MarkupDisplay::Safe(t),
            _ => self,
        }
    }
}

impl<T> From<T> for MarkupDisplay<T>
where
    T: Display,
{
    fn from(t: T) -> MarkupDisplay<T> {
        MarkupDisplay::Unsafe(t)
    }
}

impl<T> Display for MarkupDisplay<T>
where
    T: Display,
{
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match *self {
            MarkupDisplay::Unsafe(ref t) => {
                let mut w = EscapeWriter { fmt: f };
                write!(w, "{}", t).map_err(|_e| fmt::Error)
            }
            MarkupDisplay::Safe(ref t) => t.fmt(f),
        }
    }
}

pub struct EscapeWriter<'a, 'b: 'a> {
    fmt: &'a mut fmt::Formatter<'b>,
}

impl io::Write for EscapeWriter<'_, '_> {
    fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
        let escaped = Escaped { bytes };
        escaped
            .fmt(self.fmt)
            .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?;
        Ok(bytes.len())
    }

    fn flush(&mut self) -> std::io::Result<()> {
        Ok(())
    }
}

pub fn escape(s: &str) -> Escaped<'_> {
    Escaped {
        bytes: s.as_bytes(),
    }
}

macro_rules! escaping_body {
    ($start:ident, $i:ident, $fmt:ident, $_self:ident, $quote:expr) => {{
        if $start < $i {
            $fmt.write_str(unsafe { str::from_utf8_unchecked(&$_self.bytes[$start..$i]) })?;
        }
        $fmt.write_str($quote)?;
        $start = $i + 1;
    }};
}

pub struct Escaped<'a> {
    bytes: &'a [u8],
}

impl<'a> ::std::fmt::Display for Escaped<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut start = 0;
        for (i, b) in self.bytes.iter().enumerate() {
            if b.wrapping_sub(b'"') <= FLAG {
                match *b {
                    b'<' => escaping_body!(start, i, fmt, self, "<"),
                    b'>' => escaping_body!(start, i, fmt, self, ">"),
                    b'&' => escaping_body!(start, i, fmt, self, "&"),
                    b'"' => escaping_body!(start, i, fmt, self, """),
                    b'\'' => escaping_body!(start, i, fmt, self, "'"),
                    b'/' => escaping_body!(start, i, fmt, self, "/"),
                    _ => (),
                }
            }
        }
        fmt.write_str(unsafe { str::from_utf8_unchecked(&self.bytes[start..]) })?;
        Ok(())
    }
}

const FLAG: u8 = b'>' - b'"';

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_escape() {
        assert_eq!(escape("").to_string(), "");
        assert_eq!(escape("<&>").to_string(), "<&>");
        assert_eq!(escape("bla&").to_string(), "bla&");
        assert_eq!(escape("<foo").to_string(), "<foo");
        assert_eq!(escape("bla&h").to_string(), "bla&h");
    }
}
<commit_msg>Slightly simplify escaping code<commit_after>use std::fmt::{self, Display, Formatter};
use std::io::{self, prelude::*};
use std::str;

#[derive(Debug, PartialEq)]
pub enum MarkupDisplay<T>
where
    T: Display,
{
    Safe(T),
    Unsafe(T),
}

impl<T> MarkupDisplay<T>
where
    T: Display,
{
    pub fn mark_safe(self) -> MarkupDisplay<T> {
        match self {
            MarkupDisplay::Unsafe(t) => MarkupDisplay::Safe(t),
            _ => self,
        }
    }
}

impl<T> From<T> for MarkupDisplay<T>
where
    T: Display,
{
    fn from(t: T) -> MarkupDisplay<T> {
        MarkupDisplay::Unsafe(t)
    }
}

impl<T> Display for MarkupDisplay<T>
where
    T: Display,
{
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match *self {
            MarkupDisplay::Unsafe(ref t) => {
                let mut w = EscapeWriter { fmt: f };
                write!(w, "{}", t).map_err(|_e| fmt::Error)
            }
            MarkupDisplay::Safe(ref t) => t.fmt(f),
        }
    }
}

pub struct EscapeWriter<'a, 'b: 'a> {
    fmt: &'a mut fmt::Formatter<'b>,
}

impl io::Write for EscapeWriter<'_, '_> {
    fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
        write_escaped_str(self.fmt, bytes)
            .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?;
        Ok(bytes.len())
    }

    fn flush(&mut self) -> std::io::Result<()> {
        Ok(())
    }
}

pub fn escape(s: &str) -> Escaped<'_> {
    Escaped {
        bytes: s.as_bytes(),
    }
}

macro_rules! escaping_body {
    ($start:ident, $i:ident, $fmt:ident, $bytes:ident, $quote:expr) => {{
        if $start < $i {
            $fmt.write_str(unsafe { str::from_utf8_unchecked(&$bytes[$start..$i]) })?;
        }
        $fmt.write_str($quote)?;
        $start = $i + 1;
    }};
}

pub struct Escaped<'a> {
    bytes: &'a [u8],
}

impl<'a> ::std::fmt::Display for Escaped<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        write_escaped_str(fmt, self.bytes)
    }
}

fn write_escaped_str(fmt: &mut fmt::Formatter<'_>, bytes: &[u8]) -> fmt::Result {
    let mut start = 0;
    for (i, b) in bytes.iter().enumerate() {
        if b.wrapping_sub(b'"') <= FLAG {
            match *b {
                b'<' => escaping_body!(start, i, fmt, bytes, "<"),
                b'>' => escaping_body!(start, i, fmt, bytes, ">"),
                b'&' => escaping_body!(start, i, fmt, bytes, "&"),
                b'"' => escaping_body!(start, i, fmt, bytes, """),
                b'\'' => escaping_body!(start, i, fmt, bytes, "'"),
                b'/' => escaping_body!(start, i, fmt, bytes, "/"),
                _ => (),
            }
        }
    }
    fmt.write_str(unsafe { str::from_utf8_unchecked(&bytes[start..]) })?;
    Ok(())
}

const FLAG: u8 = b'>' - b'"';

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_escape() {
        assert_eq!(escape("").to_string(), "");
        assert_eq!(escape("<&>").to_string(), "<&>");
        assert_eq!(escape("bla&").to_string(), "bla&");
        assert_eq!(escape("<foo").to_string(), "<foo");
        assert_eq!(escape("bla&h").to_string(), "bla&h");
    }
}
<|endoftext|>


<commit_before>mod debugger_command;
mod http_handlers;
mod breakpoint_map;
mod cpu_snapshot;

use byte_utils::from_lo_hi;
use chan::{self, Receiver, Sender};
use cpu::{Cpu, Interrupt};
use cpu::debugger::breakpoint_map::BreakpointMap;
use cpu::debugger::cpu_snapshot::{CpuSnapshot, MemorySnapshot};
use cpu::debugger::debugger_command::{BreakReason, DebuggerCommand};
use cpu::debugger::http_handlers::*;
use iron::prelude::*;
use memory::{ADDRESSABLE_MEMORY, Memory};
use router::Router;
use screen::Screen;
use serde::Serialize;
use serde_json;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use websocket::{Message as WsMessage, Server as WsServer};

const DEBUGGER_HTTP_ADDR: &'static str = "127.0.0.1:9975";
const DEBUGGER_WS_ADDR: &'static str = "127.0.0.1:9976";

#[derive(Eq, PartialEq)]
pub enum InterruptHandler {
    None,
    Irq,
    Nmi,
}

pub struct HttpDebugger<S: Screen + Serialize, Mem: Memory<S>> {
    ws_tx: Sender<DebuggerCommand<S>>,
    ws_rx: Receiver<DebuggerCommand<S>>,
    cpu: Cpu<S, Mem>,
    breakpoints: Arc<Mutex<BreakpointMap>>,
    cpu_thread_handle: thread::Thread,
    cpu_paused: Arc<AtomicBool>,
    break_on_nmi: Arc<AtomicBool>,
    break_on_trap: Arc<AtomicBool>,
    last_pc: u16,
    last_mem_hash: u64,
}

impl<S: Screen + Serialize, Mem: Memory<S>> HttpDebugger<S, Mem> {
    pub fn new(cpu: Cpu<S, Mem>) -> Self {
        let mut buf = Vec::new();
        cpu.memory.dump(&mut buf);
        let (ws_sender, ws_receiver) = chan::sync(0);
        HttpDebugger {
            ws_tx: ws_sender,
            ws_rx: ws_receiver,
            cpu: cpu,
            breakpoints: Arc::new(Mutex::new(BreakpointMap::new())),
            cpu_thread_handle: thread::current(),
            cpu_paused: Arc::new(AtomicBool::new(true)),
            break_on_nmi: Arc::new(AtomicBool::new(false)),
            break_on_trap: Arc::new(AtomicBool::new(false)),
            last_pc: 0,
            last_mem_hash: 0,
        }
    }

    pub fn start(&mut self) {
        self.start_http_server_thread();
        self.start_websocket_thread();
    }

    pub fn step(&mut self) -> Interrupt {
        if let Some(break_reason) = self.break_reason() {
            let snapshot = self.cpu_snapshot();
            self.ws_tx
                .send(DebuggerCommand::Break(break_reason, snapshot));
            thread::park();
        }
        self.last_pc = self.cpu.registers.pc;
        self.cpu.step()
    }

    fn break_reason(&self) -> Option<BreakReason> {
        if self.interrupt_handler() == InterruptHandler::Nmi &&
           self.break_on_nmi.load(Ordering::Relaxed) {
            debug!("Break on NMI. CPU thread paused.");
            self.cpu_paused
                .compare_and_swap(false, true, Ordering::Relaxed);
            Some(BreakReason::Nmi)
        } else if self.last_pc == self.cpu.registers.pc &&
                  self.break_on_trap.load(Ordering::Relaxed) {
            debug!("Trap detected @ {:0>4X}. CPU thread paused.",
                   self.cpu.registers.pc);
            Some(BreakReason::Trap)
        } else if self.at_breakpoint(self.cpu.registers.pc) {
            debug!("Breakpoint hit @ {:0>4X}. CPU thread paused.",
                   self.cpu.registers.pc);
            Some(BreakReason::Breakpoint)
        } else if self.cpu_paused.load(Ordering::Relaxed) {
            // Stepping deliberately takes the least precedence when determining the break reason
            debug!("Stepping @ {:0>4X}. CPU thread paused.",
                   self.cpu.registers.pc);
            Some(BreakReason::Step)
        } else {
            None
        }
    }

    fn cpu_snapshot(&mut self) -> CpuSnapshot<S> {
        let hash = self.cpu.memory.hash();
        let mem_snapshot = if hash != self.last_mem_hash {
            debug!("Memory altered");
            let mut buf = Vec::with_capacity(ADDRESSABLE_MEMORY);
            self.cpu.memory.dump(&mut buf);
            self.last_mem_hash = hash;
            MemorySnapshot::Updated(hash, buf)
        } else {
            MemorySnapshot::NoChange(hash)
        };

        let screen: S = self.cpu.memory.screen().clone();
        CpuSnapshot::new(mem_snapshot,
                         self.cpu.registers.clone(),
                         screen,
                         self.cpu.cycles)
    }

    fn start_websocket_thread(&mut self) {
        info!("Starting web socket server at {}", DEBUGGER_WS_ADDR);
        let mut ws_server = WsServer::bind(DEBUGGER_WS_ADDR).unwrap();
        info!("Waiting for debugger to attach");
        let connection = match ws_server.accept() {
            Ok(conn) => conn,
            _ => panic!("Panic on debugger accept connection"),
        };
        info!("Debugger attached!");
        let ws_rx = self.ws_rx.clone();
        thread::Builder::new()
            .name("Websocket Server".to_owned())
            .spawn(move || {
                let mut client = connection.accept().unwrap();

                while let Some(debugger_msg) = ws_rx.recv() {
                    let message: WsMessage = WsMessage::text(serde_json::to_string(&debugger_msg)
                                                                 .unwrap());

                    if client.send_message(&message).is_err() {
                        break;
                    }
                }

                info!("Websocket thread is terminating!")
            })
            .unwrap();
    }

    fn start_http_server_thread(&self) {
        info!("Starting http debugger at {}", DEBUGGER_HTTP_ADDR);
        let cpu_thread = self.cpu_thread_handle.clone();
        let breakpoints = self.breakpoints.clone();
        let cpu_paused = self.cpu_paused.clone();
        let break_on_nmi = self.break_on_nmi.clone();

        thread::spawn(move || {
            let mut router = Router::new();
            router.get("/step", StepHandler::new(cpu_thread.clone()), "step");
            router.get("/continue",
                       ContinueHandler::new(cpu_thread, cpu_paused),
                       "continue");
            router.get("/toggle_breakpoint/:addr",
                       ToggleBreakpointHandler::new(breakpoints),
                       "toggle_breakpoint");

            router.get("/toggle_break_on_nmi",
                       ToggleBreakOnNmiHandler::new(break_on_nmi),
                       "toggle_break_on_nmi");
            Iron::new(router).http(DEBUGGER_HTTP_ADDR).unwrap();
        });
    }

    fn at_breakpoint(&self, pc: u16) -> bool {
        let breakpoints = &(*self.breakpoints.lock().unwrap());
        if breakpoints.is_set(pc) {
            self.cpu_paused
                .compare_and_swap(false, true, Ordering::Relaxed);
            true
        } else {
            false
        }
    }

    fn interrupt_handler(&self) -> InterruptHandler {
        if self.cpu.registers.pc == self.peek_mem(super::NMI_VECTOR) {
            InterruptHandler::Nmi
        } else if self.cpu.registers.pc == self.peek_mem(super::BREAK_VECTOR) {
            InterruptHandler::Irq
        } else {
            InterruptHandler::None
        }
    }

    fn peek_mem(&self, addr: u16) -> u16 {
        let low_byte = self.cpu.memory.read(addr);
        let high_byte = self.cpu.memory.read(addr + 1);
        from_lo_hi(low_byte, high_byte)
    }
}
<commit_msg>Get rid of unused code<commit_after>mod debugger_command;
mod http_handlers;
mod breakpoint_map;
mod cpu_snapshot;

use byte_utils::from_lo_hi;
use chan::{self, Receiver, Sender};
use cpu::{Cpu, Interrupt};
use cpu::debugger::breakpoint_map::BreakpointMap;
use cpu::debugger::cpu_snapshot::{CpuSnapshot, MemorySnapshot};
use cpu::debugger::debugger_command::{BreakReason, DebuggerCommand};
use cpu::debugger::http_handlers::*;
use iron::prelude::*;
use memory::{ADDRESSABLE_MEMORY, Memory};
use router::Router;
use screen::Screen;
use serde::Serialize;
use serde_json;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use websocket::{Message as WsMessage, Server as WsServer};

const DEBUGGER_HTTP_ADDR: &'static str = "127.0.0.1:9975";
const DEBUGGER_WS_ADDR: &'static str = "127.0.0.1:9976";

#[derive(Eq, PartialEq)]
pub enum InterruptHandler {
    None,
    Irq,
    Nmi,
}

pub struct HttpDebugger<S: Screen + Serialize, Mem: Memory<S>> {
    ws_tx: Sender<DebuggerCommand<S>>,
    ws_rx: Receiver<DebuggerCommand<S>>,
    cpu: Cpu<S, Mem>,
    breakpoints: Arc<Mutex<BreakpointMap>>,
    cpu_thread_handle: thread::Thread,
    cpu_paused: Arc<AtomicBool>,
    break_on_nmi: Arc<AtomicBool>,
    break_on_trap: Arc<AtomicBool>,
    last_pc: u16,
    last_mem_hash: u64,
}

impl<S: Screen + Serialize, Mem: Memory<S>> HttpDebugger<S, Mem> {
    pub fn new(cpu: Cpu<S, Mem>) -> Self {
        let (ws_sender, ws_receiver) = chan::sync(0);
        HttpDebugger {
            ws_tx: ws_sender,
            ws_rx: ws_receiver,
            cpu: cpu,
            breakpoints: Arc::new(Mutex::new(BreakpointMap::new())),
            cpu_thread_handle: thread::current(),
            cpu_paused: Arc::new(AtomicBool::new(true)),
            break_on_nmi: Arc::new(AtomicBool::new(false)),
            break_on_trap: Arc::new(AtomicBool::new(false)),
            last_pc: 0,
            last_mem_hash: 0,
        }
    }

    pub fn start(&mut self) {
        self.start_http_server_thread();
        self.start_websocket_thread();
    }

    pub fn step(&mut self) -> Interrupt {
        if let Some(break_reason) = self.break_reason() {
            let snapshot = self.cpu_snapshot();
            self.ws_tx
                .send(DebuggerCommand::Break(break_reason, snapshot));
            thread::park();
        }
        self.last_pc = self.cpu.registers.pc;
        self.cpu.step()
    }

    fn break_reason(&self) -> Option<BreakReason> {
        if self.interrupt_handler() == InterruptHandler::Nmi &&
           self.break_on_nmi.load(Ordering::Relaxed) {
            debug!("Break on NMI. CPU thread paused.");
            self.cpu_paused
                .compare_and_swap(false, true, Ordering::Relaxed);
            Some(BreakReason::Nmi)
        } else if self.last_pc == self.cpu.registers.pc &&
                  self.break_on_trap.load(Ordering::Relaxed) {
            debug!("Trap detected @ {:0>4X}. CPU thread paused.",
                   self.cpu.registers.pc);
            Some(BreakReason::Trap)
        } else if self.at_breakpoint(self.cpu.registers.pc) {
            debug!("Breakpoint hit @ {:0>4X}. CPU thread paused.",
                   self.cpu.registers.pc);
            Some(BreakReason::Breakpoint)
        } else if self.cpu_paused.load(Ordering::Relaxed) {
            // Stepping deliberately takes the least precedence when determining the break reason
            debug!("Stepping @ {:0>4X}. CPU thread paused.",
                   self.cpu.registers.pc);
            Some(BreakReason::Step)
        } else {
            None
        }
    }

    fn cpu_snapshot(&mut self) -> CpuSnapshot<S> {
        let hash = self.cpu.memory.hash();
        let mem_snapshot = if hash != self.last_mem_hash {
            debug!("Memory altered");
            let mut buf = Vec::with_capacity(ADDRESSABLE_MEMORY);
            self.cpu.memory.dump(&mut buf);
            self.last_mem_hash = hash;
            MemorySnapshot::Updated(hash, buf)
        } else {
            MemorySnapshot::NoChange(hash)
        };

        let screen: S = self.cpu.memory.screen().clone();
        CpuSnapshot::new(mem_snapshot,
                         self.cpu.registers.clone(),
                         screen,
                         self.cpu.cycles)
    }

    fn start_websocket_thread(&mut self) {
        info!("Starting web socket server at {}", DEBUGGER_WS_ADDR);
        let mut ws_server = WsServer::bind(DEBUGGER_WS_ADDR).unwrap();
        info!("Waiting for debugger to attach");
        let connection = match ws_server.accept() {
            Ok(conn) => conn,
            _ => panic!("Panic on debugger accept connection"),
        };
        info!("Debugger attached!");
        let ws_rx = self.ws_rx.clone();
        thread::Builder::new()
            .name("Websocket Server".to_owned())
            .spawn(move || {
                let mut client = connection.accept().unwrap();

                while let Some(debugger_msg) = ws_rx.recv() {
                    let message: WsMessage = WsMessage::text(serde_json::to_string(&debugger_msg)
                                                                 .unwrap());

                    if client.send_message(&message).is_err() {
                        break;
                    }
                }

                info!("Websocket thread is terminating!")
            })
            .unwrap();
    }

    fn start_http_server_thread(&self) {
        info!("Starting http debugger at {}", DEBUGGER_HTTP_ADDR);
        let cpu_thread = self.cpu_thread_handle.clone();
        let breakpoints = self.breakpoints.clone();
        let cpu_paused = self.cpu_paused.clone();
        let break_on_nmi = self.break_on_nmi.clone();

        thread::spawn(move || {
            let mut router = Router::new();
            router.get("/step", StepHandler::new(cpu_thread.clone()), "step");
            router.get("/continue",
                       ContinueHandler::new(cpu_thread, cpu_paused),
                       "continue");
            router.get("/toggle_breakpoint/:addr",
                       ToggleBreakpointHandler::new(breakpoints),
                       "toggle_breakpoint");

            router.get("/toggle_break_on_nmi",
                       ToggleBreakOnNmiHandler::new(break_on_nmi),
                       "toggle_break_on_nmi");
            Iron::new(router).http(DEBUGGER_HTTP_ADDR).unwrap();
        });
    }

    fn at_breakpoint(&self, pc: u16) -> bool {
        let breakpoints = &(*self.breakpoints.lock().unwrap());
        if breakpoints.is_set(pc) {
            self.cpu_paused
                .compare_and_swap(false, true, Ordering::Relaxed);
            true
        } else {
            false
        }
    }

    fn interrupt_handler(&self) -> InterruptHandler {
        if self.cpu.registers.pc == self.peek_mem(super::NMI_VECTOR) {
            InterruptHandler::Nmi
        } else if self.cpu.registers.pc == self.peek_mem(super::BREAK_VECTOR) {
            InterruptHandler::Irq
        } else {
            InterruptHandler::None
        }
    }

    fn peek_mem(&self, addr: u16) -> u16 {
        let low_byte = self.cpu.memory.read(addr);
        let high_byte = self.cpu.memory.read(addr + 1);
        from_lo_hi(low_byte, high_byte)
    }
}
<|endoftext|>


<commit_before>mod read;

use std::io;

use std::marker::PhantomData;

use {ParseResult, Input};
use internal::input;
use internal::{State, ParseResultModify};

pub use self::read::Buffer;

#[derive(Debug)]
pub enum ParseError<'a, I, E>
  where I: 'a {
    ParseError(&'a [I], E),
    Incomplete(usize),
    IoError(io::Error),
    EndOfInput,
    Retry,
}

impl<'a, I, E> PartialEq for ParseError<'a, I, E>
  where E: PartialEq, I: PartialEq {
    fn eq(&self, other: &ParseError<'a, I, E>) -> bool {
        match (self, other) {
            (&ParseError::ParseError(ref b1, ref e1), &ParseError::ParseError(ref b2, ref e2)) => b1 == b2 && e1 == e2,
            (&ParseError::Incomplete(n1), &ParseError::Incomplete(n2))         => n1 == n2,
            _ => false,
        }
    }
}

/// Runs the provided parser ``p`` on the input slice.
///
pub fn parse_slice<'a, I, T, E, P>(i: &'a [I], p: P) -> Result<T, ParseError<'a, I, E>>
  where P: FnOnce(Input<'a, I>) -> ParseResult<'a, I, T, E>,
        T: 'a,
        E: 'a {
    use internal::ParseResultModify;
    use internal::State;

    match p(input::new(input::END_OF_INPUT, i)).internal() {
        State::Data(_, t)    => Ok(t),
        State::Error(b, e)   => Err(ParseError::ParseError(b, e)),
        State::Incomplete(n) => Err(ParseError::Incomplete(n)),
    }
}

pub trait Source<'a, 'i, I> {
    fn parse<F, T, E>(&'a mut self, f: F) -> Result<T, ParseError<'i, I, E>>
      where F: FnOnce(Input<'i, I>) -> ParseResult<'i, I, T, E>,
            T: 'i,
            E: 'i;
}

pub trait IntoSource<'a, 'i> {
    type Item;
    type Into: Source<'a, 'i, Self::Item>;

    fn into_source(self) -> Self::Into;
}

impl<'a, 'i, I: 'i> IntoSource<'a, 'i> for &'i [I] {
    type Item = I;
    type Into = SliceSource<'a, 'i, I>;

    fn into_source(self) -> SliceSource<'a, 'i, I> {
        SliceSource(self, PhantomData)
    }
}

/// Source implementation for slices.
///
/// ```
/// # #[macro_use] extern crate chomp;
/// # fn main() {
/// use chomp::{IntoSource, Source, token, take};
///
/// let i = b"foo";
///
/// let r = i.into_source().parse(parser!{
///     token(b'f');
///     take(2);
/// });
///
/// assert_eq!(r, Ok(b"oo" as &[u8]));
/// # }
/// ```
///
/// ```
/// # #[macro_use] extern crate chomp;
/// # fn main() {
/// use chomp::{IntoSource, Source, token, many, take};
///
/// let i = b"foofoo";
///
/// let r = i.into_source().parse(parser!{many(parser!{
///     token(b'f');
///     take(2);
/// })});
///
/// assert_eq!(r, Ok(vec![b"oo" as &[u8], b"oo" as &[u8]]));
/// # }
/// ```
pub struct SliceSource<'a, 'i, I: 'i>(&'i [I], PhantomData<&'a u8>);

impl<'a, 'i, I> Source<'a, 'i, I> for SliceSource<'a, 'i, I> {
    fn parse<F, T, E>(&'a mut self, f: F) -> Result<T, ParseError<'i, I, E>>
      where F: FnOnce(Input<'i, I>) -> ParseResult<'i, I, T, E>,
            T: 'i,
            E: 'i {
        match f(input::new(input::END_OF_INPUT, self.0)).internal() {
            State::Data(_, t)    => Ok(t),
            State::Error(b, e)   => Err(ParseError::ParseError(b, e)),
            State::Incomplete(n) => Err(ParseError::Incomplete(n)),
        }
    }
}

#[macro_export]
macro_rules! source_for_each {
    ( $parser:expr; $value:ident in $source:expr; $body:expr ) => {
        {
            let ref mut s = &mut $source;
            loop {
                match s.parse($parser) {
                    Ok($value) => $body,
                    Err(ParseError::Retry)      => {},
                    Err(ParseError::EndOfInput) => break,
                    Err(e)                      => { println!("{:?}", e); break; },
                }
            }
        }
    }
}
<commit_msg>Removed parse_slice<commit_after>mod read;

use std::io;

use std::marker::PhantomData;

use {ParseResult, Input};
use internal::input;
use internal::{State, ParseResultModify};

pub use self::read::Buffer;

#[derive(Debug)]
pub enum ParseError<'a, I, E>
  where I: 'a {
    ParseError(&'a [I], E),
    Incomplete(usize),
    IoError(io::Error),
    EndOfInput,
    Retry,
}

impl<'a, I, E> PartialEq for ParseError<'a, I, E>
  where E: PartialEq, I: PartialEq {
    fn eq(&self, other: &ParseError<'a, I, E>) -> bool {
        match (self, other) {
            (&ParseError::ParseError(ref b1, ref e1), &ParseError::ParseError(ref b2, ref e2)) => b1 == b2 && e1 == e2,
            (&ParseError::Incomplete(n1), &ParseError::Incomplete(n2))         => n1 == n2,
            _ => false,
        }
    }
}

/// Trait wrapping the state management in reading from a data source while parsing.
pub trait Source<'a, 'i, I> {
    fn parse<F, T, E>(&'a mut self, f: F) -> Result<T, ParseError<'i, I, E>>
      where F: FnOnce(Input<'i, I>) -> ParseResult<'i, I, T, E>,
            T: 'i,
            E: 'i;
}

/// Trait for conversion into a `Source`.
pub trait IntoSource<'a, 'i> {
    type Item;
    type Into: Source<'a, 'i, Self::Item>;

    fn into_source(self) -> Self::Into;
}

impl<'a, 'i, I: 'i> IntoSource<'a, 'i> for &'i [I] {
    type Item = I;
    type Into = SliceSource<'a, 'i, I>;

    fn into_source(self) -> SliceSource<'a, 'i, I> {
        SliceSource(self, PhantomData)
    }
}

/// Source implementation for slices.
///
/// ```
/// # #[macro_use] extern crate chomp;
/// # fn main() {
/// use chomp::{IntoSource, Source, token, take};
///
/// let i = b"foo";
///
/// let r = i.into_source().parse(parser!{
///     token(b'f');
///     take(2);
/// });
///
/// assert_eq!(r, Ok(b"oo" as &[u8]));
/// # }
/// ```
///
/// ```
/// # #[macro_use] extern crate chomp;
/// # fn main() {
/// use chomp::{IntoSource, Source, token, many, take};
///
/// let i = b"foofoo";
///
/// let r = i.into_source().parse(parser!{many(parser!{
///     token(b'f');
///     take(2);
/// })});
///
/// assert_eq!(r, Ok(vec![b"oo" as &[u8], b"oo" as &[u8]]));
/// # }
/// ```
pub struct SliceSource<'a, 'i, I: 'i>(&'i [I], PhantomData<&'a u8>);

impl<'a, 'i, I> Source<'a, 'i, I> for SliceSource<'a, 'i, I> {
    fn parse<F, T, E>(&'a mut self, f: F) -> Result<T, ParseError<'i, I, E>>
      where F: FnOnce(Input<'i, I>) -> ParseResult<'i, I, T, E>,
            T: 'i,
            E: 'i {
        match f(input::new(input::END_OF_INPUT, self.0)).internal() {
            State::Data(_, t)    => Ok(t),
            State::Error(b, e)   => Err(ParseError::ParseError(b, e)),
            State::Incomplete(n) => Err(ParseError::Incomplete(n)),
        }
    }
}

#[macro_export]
macro_rules! source_for_each {
    ( $parser:expr; $value:ident in $source:expr; $body:expr ) => {
        {
            let ref mut s = &mut $source;
            loop {
                match s.parse($parser) {
                    Ok($value) => $body,
                    Err(ParseError::Retry)      => {},
                    Err(ParseError::EndOfInput) => break,
                    Err(e)                      => { println!("{:?}", e); break; },
                }
            }
        }
    }
}
<|endoftext|>


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

use crate::cache::{Cache, CacheRead, CacheWrite, Storage};
use crate::lru_disk_cache::Error as LruError;
use crate::lru_disk_cache::LruDiskCache;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};

use crate::errors::*;

/// A cache that stores entries at local disk paths.
#[derive(Clone)]
pub struct DiskCache {
    /// `LruDiskCache` does all the real work here.
    lru: Arc<Mutex<LruDiskCache>>,
    /// Thread pool to execute disk I/O
    pool: tokio::runtime::Handle,
}

impl DiskCache {
    /// Create a new `DiskCache` rooted at `root`, with `max_size` as the maximum cache size on-disk, in bytes.
    pub fn new<T: AsRef<OsStr>>(
        root: &T,
        max_size: u64,
        pool: &tokio::runtime::Handle,
    ) -> DiskCache {
        DiskCache {
            //TODO: change this function to return a Result
            lru: Arc::new(Mutex::new(
                LruDiskCache::new(root, max_size).expect("Couldn't instantiate disk cache!"),
            )),
            pool: pool.clone(),
        }
    }
}

/// Make a path to the cache entry with key `key`.
fn make_key_path(key: &str) -> PathBuf {
    Path::new(&key[0..1]).join(&key[1..2]).join(key)
}

#[async_trait]
impl Storage for DiskCache {
    async fn get(&self, key: &str) -> Result<Cache> {
        trace!("DiskCache::get({})", key);
        let path = make_key_path(key);
        let lru = self.lru.clone();
        let key = key.to_owned();

        self.pool
            .spawn_blocking(move || {
                let mut lru = lru.lock().unwrap();
                let io = match lru.get(&path) {
                    Ok(f) => f,
                    Err(LruError::FileNotInCache) => {
                        trace!("DiskCache::get({}): FileNotInCache", key);
                        return Ok(Cache::Miss);
                    }
                    Err(LruError::Io(e)) => {
                        trace!("DiskCache::get({}): IoError: {:?}", key, e);
                        return Err(e.into());
                    }
                    Err(_) => unreachable!(),
                };
                let hit = CacheRead::from(io)?;
                Ok(Cache::Hit(hit))
            })
            .await?
    }

    async fn put(&self, key: &str, entry: CacheWrite) -> Result<Duration> {
        // We should probably do this on a background thread if we're going to buffer
        // everything in memory...
        trace!("DiskCache::finish_put({})", key);
        let lru = self.lru.clone();
        let key = make_key_path(key);

        self.pool
            .spawn_blocking(move || {
                let start = Instant::now();
                let v = entry.finish()?;
                lru.lock().unwrap().insert_bytes(key, &v)?;
                Ok(start.elapsed())
            })
            .await?
    }

    fn location(&self) -> String {
        format!("Local disk: {:?}", self.lru.lock().unwrap().path())
    }

    async fn current_size(&self) -> Result<Option<u64>> {
        Ok(Some(self.lru.lock().unwrap().size()))
    }
    async fn max_size(&self) -> Result<Option<u64>> {
        Ok(Some(self.lru.lock().unwrap().capacity()))
    }
}
<commit_msg>disk: initialize the LruDiskCache in a background thread (#868)<commit_after>// Copyright 2016 Mozilla Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::cache::{Cache, CacheRead, CacheWrite, Storage};
use crate::lru_disk_cache::Error as LruError;
use crate::lru_disk_cache::LruDiskCache;
use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};

use crate::errors::*;

enum LazyDiskCache {
    Uninit { root: OsString, max_size: u64 },
    Init(LruDiskCache),
}

impl LazyDiskCache {
    fn get_or_init(&mut self) -> Result<&mut LruDiskCache> {
        match self {
            LazyDiskCache::Uninit { root, max_size } => {
                *self = LazyDiskCache::Init(LruDiskCache::new(&root, *max_size)?);
                self.get_or_init()
            }
            LazyDiskCache::Init(d) => Ok(d),
        }
    }

    fn get(&mut self) -> Option<&mut LruDiskCache> {
        match self {
            LazyDiskCache::Uninit { .. } => None,
            LazyDiskCache::Init(d) => Some(d),
        }
    }

    fn path(&self) -> &Path {
        match self {
            LazyDiskCache::Uninit { root, .. } => root.as_ref(),
            LazyDiskCache::Init(d) => d.path(),
        }
    }
}

/// A cache that stores entries at local disk paths.
pub struct DiskCache {
    /// `LruDiskCache` does all the real work here.
    lru: Arc<Mutex<LazyDiskCache>>,
    /// Thread pool to execute disk I/O
    pool: tokio::runtime::Handle,
}

impl DiskCache {
    /// Create a new `DiskCache` rooted at `root`, with `max_size` as the maximum cache size on-disk, in bytes.
    pub fn new<T: AsRef<OsStr>>(
        root: T,
        max_size: u64,
        pool: &tokio::runtime::Handle,
    ) -> DiskCache {
        DiskCache {
            lru: Arc::new(Mutex::new(LazyDiskCache::Uninit {
                root: root.as_ref().to_os_string(),
                max_size,
            })),
            pool: pool.clone(),
        }
    }
}

/// Make a path to the cache entry with key `key`.
fn make_key_path(key: &str) -> PathBuf {
    Path::new(&key[0..1]).join(&key[1..2]).join(key)
}

#[async_trait]
impl Storage for DiskCache {
    async fn get(&self, key: &str) -> Result<Cache> {
        trace!("DiskCache::get({})", key);
        let path = make_key_path(key);
        let lru = self.lru.clone();
        let key = key.to_owned();

        self.pool
            .spawn_blocking(move || {
                let mut lru = lru.lock().unwrap();
                let io = match lru.get_or_init()?.get(&path) {
                    Ok(f) => f,
                    Err(LruError::FileNotInCache) => {
                        trace!("DiskCache::get({}): FileNotInCache", key);
                        return Ok(Cache::Miss);
                    }
                    Err(LruError::Io(e)) => {
                        trace!("DiskCache::get({}): IoError: {:?}", key, e);
                        return Err(e.into());
                    }
                    Err(_) => unreachable!(),
                };
                let hit = CacheRead::from(io)?;
                Ok(Cache::Hit(hit))
            })
            .await?
    }

    async fn put(&self, key: &str, entry: CacheWrite) -> Result<Duration> {
        // We should probably do this on a background thread if we're going to buffer
        // everything in memory...
        trace!("DiskCache::finish_put({})", key);
        let lru = self.lru.clone();
        let key = make_key_path(key);

        self.pool
            .spawn_blocking(move || {
                let start = Instant::now();
                let v = entry.finish()?;
                lru.lock().unwrap().get_or_init()?.insert_bytes(key, &v)?;
                Ok(start.elapsed())
            })
            .await?
    }

    fn location(&self) -> String {
        format!("Local disk: {:?}", self.lru.lock().unwrap().path())
    }

    async fn current_size(&self) -> Result<Option<u64>> {
        Ok(self.lru.lock().unwrap().get().map(|l| l.size()))
    }
    async fn max_size(&self) -> Result<Option<u64>> {
        Ok(self.lru.lock().unwrap().get().map(|l| l.capacity()))
    }
}
<|endoftext|>


<commit_before>
macro_rules! return_if {
  ($e:expr, $r:expr) => {
    if $e {
      return $r;
    }
  }
}

pub struct Square {
  a: usize,
  data: Vec<usize>
}

pub enum Diagonal {
  First,
  Second
}

pub enum SquareLine {
  Row(usize),
  Col(usize),
  Diag(Diagonal)
}

pub struct SquareIter<'a> {
  square: &'a Square,
  start: usize,
  jump: usize,
  i: usize
}

impl<'a> Iterator for SquareIter<'a> {
  type Item = &'a usize;

  fn next(&mut self) -> Option<&'a usize> {

    if self.i >= self.square.a {
      return None;
    }

    let value = &self.square.data[self.start + self.i * self.jump];
    self.i = self.i + 1;

    Some(value)

  }
}

impl Square {
  pub fn new(data: Vec<usize>) -> Square {
    let len = data.len();
    let a_candidate = (len as f64).sqrt().floor() as usize;

    assert_eq!(a_candidate * a_candidate, len);

    Square {
      a: a_candidate,
      data: data
    }
  }

  pub fn is_magic(&self) -> bool {
    for i in 0..self.a {
      let row_sum = self.row_sum(i);
      let col_sum = self.col_sum(i);
      return_if!(row_sum != 15, false);
      return_if!(col_sum != 15, false);
    }

    {
      let sum = self.diag_sum(&Diagonal::First);
      return_if!(sum != 15, false);
    }

    {
      let sum = self.diag_sum(&Diagonal::Second);
      return_if!(sum != 15, false);
    }

    return true;
  }

  pub fn sum_of(&self, line: &SquareLine) -> usize {
    self.get_iter(line).fold(0, |acc, &x| acc + x)
  }

  pub fn get_iter<'a, 'b>(&'a self, line: &'b SquareLine) -> SquareIter<'a> {
    match line {
      &SquareLine::Row(r) => self.row(r),
      &SquareLine::Col(c) => self.col(c),
      &SquareLine::Diag(ref d) => self.diag(d)
    }
  }

  pub fn row<'a>(&'a self, r: usize) -> SquareIter<'a> {
    SquareIter {
      square: self,
      start: r * self.a,
      jump: 1,
      i: 0
    }
  }

  pub fn col<'a>(&'a self, c: usize) -> SquareIter<'a> {
    SquareIter {
      square: self,
      start: c,
      jump: self.a,
      i: 0
    }
  }

  pub fn diag<'a>(&'a self, d: &Diagonal) -> SquareIter<'a> {
    match d {
      &Diagonal::First => SquareIter {
        square: self,
        start: 0,
        jump: self.a + 1,
        i: 0
      },

      &Diagonal::Second => SquareIter {
        square: self,
        start: self.a - 1,
        jump: self.a - 1,
        i: 0
      }
    }
  }

  fn row_sum(&self, r: usize) -> usize {
    self.row(r).fold(0, |acc, &x| acc + x)
  }

  fn col_sum(&self, c: usize) -> usize {
    self.col(c).fold(0, |acc, &x| acc + x)
  }

  fn diag_sum(&self, d: &Diagonal) -> usize {
    self.diag(d).fold(0, |acc, &x| acc + x)
  }

}

#[cfg(test)]
mod test {

  use super::*;

  fn test_square() -> Square {
    Square::new(vec![8, 1, 6, 3, 5, 7, 4, 9, 2])
  }

  #[test]
  #[should_panic]
  fn test_non_square() {
    Square::new(vec![1, 2]);
  }

  #[test]
  fn test_row_iterator() {
    let square = test_square();

    assert_eq!(vec![8, 1, 6], square.row(0).map(|v| v.clone()).collect::<Vec<usize>>());
  }

  #[test]
  fn test_col_iterator() {
    let square = test_square();

    assert_eq!(vec![8, 3, 4], square.col(0).map(|v| v.clone()).collect::<Vec<usize>>());
  }

  #[test]
  fn test_diag_iterator() {
    let square = test_square();

    assert_eq!(vec![8, 5, 2], square.diag(&Diagonal::First).map(|v| v.clone()).collect::<Vec<usize>>());
    assert_eq!(vec![6, 5, 4], square.diag(&Diagonal::Second).map(|v| v.clone()).collect::<Vec<usize>>());
  }

  #[test]
  fn test_first_example() {
    let square = Square::new(vec![8, 1, 6, 3, 5, 7, 4, 9, 2]);

    assert_eq!(true, square.is_magic());
  }

  #[test]
  fn test_second_example() {
    let square = Square::new(vec![2, 7, 6, 9, 5, 1, 4, 3, 8]);

    assert_eq!(true, square.is_magic());
  }

  #[test]
  fn test_third_example() {
    let square = Square::new(vec![3, 5, 7, 8, 1, 6, 4, 9, 2]);

    assert_eq!(false, square.is_magic());
  }

  #[test]
  fn test_fourth_example() {
    let square = Square::new(vec![8, 1, 6, 7, 5, 3, 4, 9, 2]);

    assert_eq!(false, square.is_magic());
  }
}
<commit_msg>full iterators<commit_after>
macro_rules! return_if {
  ($e:expr, $r:expr) => {
    if $e {
      return $r;
    }
  }
}

pub struct Square {
  a: usize,
  data: Vec<usize>
}

pub enum Diagonal {
  First,
  Second
}

impl From<usize> for Diagonal {
  fn from(d: usize) -> Diagonal {
    match d {
      0 => Diagonal::First,
      1 => Diagonal::Second,
      _ => panic!()
    }
  }
}

pub enum SquareLine {
  Row(usize),
  Col(usize),
  Diag(Diagonal)
}

impl SquareLine {
  pub fn sum(&self, square: &Square) -> usize {
    square.sum_of(self)
  }
}

pub struct LineIter {
  a: usize,
  i: usize,
  is_col: bool
}

impl Iterator for LineIter {
  type Item = SquareLine;

  fn next(&mut self) -> Option<SquareLine> {
    if self.i >= self.a + 2 {
      return None;
    }

    if self.i >= self.a {
      let diag = self.i - self.a;
      self.i = self.i + 1;
      return Some(SquareLine::Diag(Diagonal::from(diag)));
    }

    if self.is_col {
      let result = SquareLine::Col(self.i);

      self.is_col = false;
      self.i = self.i + 1;

      return Some(result);
    } else {
      let result = SquareLine::Row(self.i);

      self.is_col = true;

      return Some(result);
    }
  }
}

impl<'a> From<&'a Square> for LineIter {
  fn from(square: &'a Square) -> LineIter {
    LineIter {
      a: square.a,
      i: 0,
      is_col: false
    }
  }
}

pub struct SquareIter<'a> {
  square: &'a Square,
  start: usize,
  jump: usize,
  i: usize
}

impl<'a> Iterator for SquareIter<'a> {
  type Item = &'a usize;

  fn next(&mut self) -> Option<&'a usize> {

    if self.i >= self.square.a {
      return None;
    }

    let value = &self.square.data[self.start + self.i * self.jump];
    self.i = self.i + 1;

    Some(value)
  }
}

impl Square {
  pub fn new(data: Vec<usize>) -> Square {
    let len = data.len();
    let a_candidate = (len as f64).sqrt().floor() as usize;

    assert_eq!(a_candidate * a_candidate, len);

    Square {
      a: a_candidate,
      data: data
    }
  }

  pub fn get_expected_sum(&self) -> usize {
    (self.a * ( (self.a * self.a) + 1)) / 2
  }

  pub fn is_magic(&self) -> bool {
    let expected_sum = self.get_expected_sum();

    for line in LineIter::from(self) {
      let sum = line.sum(self);
      return_if!(sum != expected_sum, false);
    }

    return true;
  }

  pub fn sum_of(&self, line: &SquareLine) -> usize {
    self.get_iter(line).fold(0, |acc, &x| acc + x)
  }

  pub fn get_iter<'a, 'b>(&'a self, line: &'b SquareLine) -> SquareIter<'a> {
    match line {
      &SquareLine::Row(r) => self.row(r),
      &SquareLine::Col(c) => self.col(c),
      &SquareLine::Diag(ref d) => self.diag(d)
    }
  }

  pub fn row<'a>(&'a self, r: usize) -> SquareIter<'a> {
    assert!(r < self.a);

    SquareIter {
      square: self,
      start: r * self.a,
      jump: 1,
      i: 0
    }
  }

  pub fn col<'a>(&'a self, c: usize) -> SquareIter<'a> {
    assert!(c < self.a);

    SquareIter {
      square: self,
      start: c,
      jump: self.a,
      i: 0
    }
  }

  pub fn diag<'a>(&'a self, d: &Diagonal) -> SquareIter<'a> {
    match d {
      &Diagonal::First => SquareIter {
        square: self,
        start: 0,
        jump: self.a + 1,
        i: 0
      },

      &Diagonal::Second => SquareIter {
        square: self,
        start: self.a - 1,
        jump: self.a - 1,
        i: 0
      }
    }
  }
}

#[cfg(test)]
mod test {

  use super::*;

  fn test_square() -> Square {
    Square::new(vec![8, 1, 6, 3, 5, 7, 4, 9, 2])
  }

  #[test]
  #[should_panic]
  fn test_non_square() {
    Square::new(vec![1, 2]);
  }

  #[test]
  fn test_row_iterator() {
    let square = test_square();

    assert_eq!(vec![8, 1, 6], square.row(0).map(|v| v.clone()).collect::<Vec<usize>>());
  }

  #[test]
  fn test_col_iterator() {
    let square = test_square();

    assert_eq!(vec![8, 3, 4], square.col(0).map(|v| v.clone()).collect::<Vec<usize>>());
  }

  #[test]
  fn test_diag_iterator() {
    let square = test_square();

    assert_eq!(vec![8, 5, 2], square.diag(&Diagonal::First).map(|v| v.clone()).collect::<Vec<usize>>());
    assert_eq!(vec![6, 5, 4], square.diag(&Diagonal::Second).map(|v| v.clone()).collect::<Vec<usize>>());
  }

  #[test]
  fn test_first_example() {
    let square = Square::new(vec![8, 1, 6, 3, 5, 7, 4, 9, 2]);

    assert_eq!(true, square.is_magic());
  }

  #[test]
  fn test_second_example() {
    let square = Square::new(vec![2, 7, 6, 9, 5, 1, 4, 3, 8]);

    assert_eq!(true, square.is_magic());
  }

  #[test]
  fn test_third_example() {
    let square = Square::new(vec![3, 5, 7, 8, 1, 6, 4, 9, 2]);

    assert_eq!(false, square.is_magic());
  }

  #[test]
  fn test_fourth_example() {
    let square = Square::new(vec![8, 1, 6, 7, 5, 3, 4, 9, 2]);

    assert_eq!(false, square.is_magic());
  }

  #[test]
  fn test_big() {
    let square = Square::new(vec![25, 13, 1, 19, 7, 16, 9, 22, 15, 3, 12, 5,
            18, 6, 24, 8, 21, 14, 2, 20, 4, 17, 10, 23, 11]);

    assert_eq!(true, square.is_magic());
  }
}
<|endoftext|>


<commit_before>//! Use this module to interact with Kraken exchange.
//! Please see examples for more informations.

use crypto::digest::Digest;
use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::sha2::{Sha256, Sha512};

use hyper_native_tls::NativeTlsClient;
use hyper::Client;
use hyper::header;
use hyper::net::HttpsConnector;

use rustc_serialize::base64::{STANDARD, ToBase64, FromBase64};

use serde_json;
use serde_json::Value;
use serde_json::value::Map;

use std::collections::HashMap;
use std::io::Read;
use std::thread;
use std::time::Duration;
use std::path::PathBuf;
use std::fs::File;
use std::str;

use helpers;

header! { (KeyHeader, "API-Key") => [String] }
header! { (SignHeader, "API-Sign") => [String] }

pub struct KrakenApi {
    last_request: i64, // unix timestamp in ms, to avoid ban
    api_key: String,
    api_secret: String,
    http_client: Client,
}

impl KrakenApi {
    /// Create a new KrakenApi by providing an API key & API secret
    pub fn new(api_key: &str, api_secret: &str) -> KrakenApi {
        let ssl = NativeTlsClient::new().unwrap();
        let connector = HttpsConnector::new(ssl);

        KrakenApi {
            last_request: 0,
            api_key: api_key.to_string(),
            api_secret: api_secret.to_string(),
            http_client: Client::with_connector(connector),
        }
    }

    /// Create a new KrakenApi from a json configuration file. This file must follow this structure:
    ///
    /// ```ignore
    /// {
    ///     "account_kraken": {
    ///         "exchange"  : "kraken",
    ///         "api_key"   : "123456789ABCDEF",
    ///         "api_secret": "ABC&EF?abcdef"
    ///     },
    ///     "account_poloniex": {
    ///         "exchange"  : "poloniex",
    ///         "api_key"   : "XYXY-XYXY-XYXY-XY",
    ///         "api_secret": "A0A0B1B1C2C2"
    ///     }
    /// }
    /// ```
    /// For this example, you could use load your Kraken account with
    /// `new_from_file("account_kraken", Path::new("/keys.json"))`
    pub fn new_from_file(config_name: &str, path: PathBuf) -> KrakenApi {
        let mut f = File::open(&path).unwrap();
        let mut buffer = String::new();
        f.read_to_string(&mut buffer).unwrap();

        let data: Value = serde_json::from_str(&buffer).unwrap();
        let json_obj = data.as_object().unwrap().get(config_name).unwrap();
        let api_key = json_obj.get("api_key").unwrap().as_str().unwrap();
        let api_secret = json_obj.get("api_secret").unwrap().as_str().unwrap();

        KrakenApi::new(api_key, api_secret)
    }

    fn block_or_continue(&self) {
        let threshold = 2000; // 1 request/2sec
        let delay = helpers::get_unix_timestamp_ms() - self.last_request;
        if delay < threshold {
            let duration_ms = Duration::from_millis(delay as u64);
            thread::sleep(duration_ms);
        }
    }

    fn deserialize_json(&mut self, json_string: String) -> Option<Map<String, Value>> {
        let data: Value = serde_json::from_str(&json_string).unwrap();

        match data.as_object() {
            Some(value) => Some(value.clone()),
            None => None,
        }
    }

    fn public_query(&mut self, method: &str, params: &HashMap<&str, &str>) -> Option<Map<String, Value>> {
        let url = "https://api.kraken.com/0/public/".to_string() + method + "?" +
        &helpers::url_encode_hashmap(params);

        self.block_or_continue();
        let mut response = self.http_client.get(&url).send().unwrap();
        self.last_request = helpers::get_unix_timestamp_ms();
        let mut buffer = String::new();
        response.read_to_string(&mut buffer).unwrap();
        return self.deserialize_json(buffer);
    }

    fn private_query(&mut self, method: &str, params: &HashMap<&str, &str>) -> Option<Map<String, Value>> {
        let url = "https://api.kraken.com/0/private/".to_string() + method;

        let urlpath = "/0/private/".to_string() + method;

        // Create header
        let nonce = helpers::get_unix_timestamp_ms().to_string();
        let mut params = params.clone();

        params.insert("nonce", &nonce);

        let postdata = helpers::url_encode_hashmap(&params);
        let signature = self.create_signature(urlpath, &postdata, &nonce);

        let mut custom_header = header::Headers::new();
        custom_header.set(KeyHeader(self.api_key.clone()));
        custom_header.set(SignHeader(signature));

        let mut res = self.http_client
        .post(&url)
        .body(&postdata)
        .headers(custom_header)
        .send()
        .unwrap();

        let mut buffer = String::new();
        res.read_to_string(&mut buffer).unwrap();
        return self.deserialize_json(buffer);
    }

    fn create_signature(&self, urlpath: String, postdata: &str, nonce: &str) -> String {
        let message_presha256 = nonce.to_string() + postdata;
        println!("message {:?}", message_presha256);

        let mut sha256 = Sha256::new();
        sha256.input_str(&message_presha256);
        let final_sha = sha256.result_str();

        let message_premac = urlpath + &final_sha;

        let hmac_key = self.api_secret.from_base64().unwrap();
        let mut hmac = Hmac::new(Sha512::new(), &hmac_key);
        hmac.input(message_premac.as_bytes());
        hmac.result().code().to_base64(STANDARD)
    }

    /// Result: Server's time
    ///
    /// ```ignore
    /// unixtime =  as unix timestamp
    /// rfc1123 = as RFC 1123 time format
    /// ```
    /// Note: This is to aid in approximating the skew time between the server and client.
    pub fn get_server_time(&mut self) -> Option<Map<String, Value>> {
        let params = HashMap::new();
        self.public_query("Time", &params)
    }

    /// Input:
    ///
    /// ```ignore
    /// info = info to retrieve (optional):
    ///     info = all info (default)
    /// aclass = asset class (optional):
    ///     currency (default)
    /// asset = comma delimited list of assets to get info on (optional.  default = all for given asset class)
    /// ```
    /// Result: array of asset names and their info:
    ///
    /// ```ignore
    /// <asset_name> = asset name
    /// altname = alternate name
    /// aclass = asset class
    /// decimals = scaling decimal places for record keeping
    /// display_decimals = scaling decimal places for output display
    /// ```
    pub fn get_asset_info(&mut self) -> Option<Map<String, Value>> {
        let params = HashMap::new();
        self.public_query("Assets", &params)
    }

    /// Input:
    ///
    /// ```ignore
    /// info = info to retrieve (optional):
    ///     info = all info (default)
    ///     leverage = leverage info
    ///     fees = fees schedule
    ///     margin = margin info
    /// pair = comma delimited list of asset pairs to get info on (optional.  default = all)
    /// ```
    ///
    /// Result: array of pair names and their info
    ///
    /// ```ignore
    /// <pair_name> = pair name
    ///     altname = alternate pair name
    ///     aclass_base = asset class of base component
    ///     base = asset id of base component
    ///     aclass_quote = asset class of quote component
    ///     quote = asset id of quote component
    ///     lot = volume lot size
    ///     pair_decimals = scaling decimal places for pair
    ///     lot_decimals = scaling decimal places for volume
    ///     lot_multiplier = amount to multiply lot volume by to get currency volume
    ///     leverage_buy = array of leverage amounts available when buying
    ///     leverage_sell = array of leverage amounts available when selling
    ///     fees = fee schedule array in [volume, percent fee] tuples
    ///     fees_maker = maker fee schedule array in [volume, percent fee] tuples (if on maker/taker)
    ///     fee_volume_currency = volume discount currency
    ///     margin_call = margin call level
    ///     margin_stop = stop-out/liquidation margin level
    /// ```
    pub fn get_tradable_asset_pairs(&mut self) -> Option<Map<String, Value>> {
        let params = HashMap::new();
        self.public_query("AssetPairs", &params)
    }

    /// Input: pair = comma delimited list of asset pairs to get info on
    /// Result: array of pair names and their ticker info
    ///
    /// ```ignore
    /// <pair_name> = pair name
    /// a = ask array(<price>, <whole lot volume>, <lot volume>),
    /// b = bid array(<price>, <whole lot volume>, <lot volume>),
    /// c = last trade closed array(<price>, <lot volume>),
    /// v = volume array(<today>, <last 24 hours>),
    /// p = volume weighted average price array(<today>, <last 24 hours>),
    /// t = number of trades array(<today>, <last 24 hours>),
    /// l = low array(<today>, <last 24 hours>),
    /// h = high array(<today>, <last 24 hours>),
    /// o = today's opening price
    /// ```
    pub fn get_ticker_information(&mut self, pair: &str) -> Option<Map<String, Value>> {
        let mut params = HashMap::new();
        params.insert("pair", pair);
        self.public_query("Ticker", &params)
    }

    /// Input:
    ///
    /// ```ignore
    /// pair = asset pair to get OHLC data for
    /// interval = time frame interval in minutes (optional):
    /// 	1 (default), 5, 15, 30, 60, 240, 1440, 10080, 21600
    /// since = return committed OHLC data since given id (optional.  exclusive)
    /// ```
    ///
    /// Result: array of pair name and OHLC data
    ///
    /// ```ignore
    /// <pair_name> = pair name
    ///     array of array entries(<time>, <open>, <high>, <low>, <close>, <vwap>, <volume>, <count>)
    /// last = id to be used as since when polling for new, committed OHLC data
    /// ```
    ///
    /// Note: the last entry in the OHLC array is for the current, not-yet-committed frame and will always be present, regardless of the value of "since".
    pub fn get_ohlc_data(&mut self, pair: &str, interval: &str, since: &str) -> Option<Map<String, Value>> {
        let mut params = HashMap::new();
        params.insert("pair", pair);
        params.insert("interval", interval);
        params.insert("since", since);
        self.public_query("OHLC", &params)
    }

    /// Input:
    ///
    /// ```ignore
    /// pair = asset pair to get market depth for
    /// count = maximum number of asks/bids (optional)
    /// ```
    /// Result: array of pair name and market depth
    ///
    /// ```ignore
    /// <pair_name> = pair name
    ///     asks = ask side array of array entries(<price>, <volume>, <timestamp>)
    ///     bids = bid side array of array entries(<price>, <volume>, <timestamp>)
    /// ```
    pub fn get_order_book(&mut self, pair: &str, count: &str) -> Option<Map<String, Value>> {
        let mut params = HashMap::new();
        params.insert("pair", pair);
        params.insert("count", count);
        self.public_query("Depth", &params)
    }

    /// Input:
    ///
    /// ```ignore
    /// pair = asset pair to get trade data for
    /// since = return trade data since given id (optional.  exclusive)
    /// ```
    /// Result: array of pair name and recent trade data
    ///
    /// ```ignore
    /// <pair_name> = pair name
    ///     array of array entries(<price>, <volume>, <time>, <buy/sell>, <market/limit>, <miscellaneous>)
    /// last = id to be used as since when polling for new trade data
    /// ```
    pub fn get_recent_trades(&mut self, pair: &str, since: &str) -> Option<Map<String, Value>> {
        let mut params = HashMap::new();
        params.insert("pair", pair);
        params.insert("since", since);
        self.public_query("Trades", &params)
    }

    /// Input:
    ///
    /// ```ignore
    /// pair = asset pair to get spread data for
    /// since = return spread data since given id (optional.  inclusive)
    /// ```
    ///
    /// Result: array of pair name and recent spread data
    ///
    /// ```ignore
    /// <pair_name> = pair name
    ///     array of array entries(<time>, <bid>, <ask>)
    /// last = id to be used as since when polling for new spread data
    /// ```
    /// Note: "since" is inclusive so any returned data with the same time as the previous set should overwrite all of the previous set's entries at that time
    pub fn get_recent_spread_data(&mut self, pair: &str, since: &str) -> Option<Map<String, Value>> {
        let mut params = HashMap::new();
        params.insert("pair", pair);
        params.insert("since", since);
        self.public_query("Spread", &params)
    }

    /// Result: array of asset names and balance amount
    pub fn get_account_balance(&mut self) -> Option<Map<String, Value>> {
        let params = HashMap::new();
        self.private_query("Balance", &params)
    }
}
<commit_msg>Fix private Kraken methods.<commit_after>//! Use this module to interact with Kraken exchange.
//! Please see examples for more informations.

use crypto::digest::Digest;
use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::sha2::{Sha256, Sha512};

use hyper_native_tls::NativeTlsClient;
use hyper::Client;
use hyper::header;
use hyper::net::HttpsConnector;

use rustc_serialize::base64::{STANDARD, ToBase64, FromBase64};

use serde_json;
use serde_json::Value;
use serde_json::value::Map;

use std::collections::HashMap;
use std::io::Read;
use std::thread;
use std::time::Duration;
use std::path::PathBuf;
use std::fs::File;
use std::str;
use std::iter::repeat;

use helpers;

header! { (KeyHeader, "API-Key") => [String] }
header! { (SignHeader, "API-Sign") => [String] }

pub struct KrakenApi {
    last_request: i64, // unix timestamp in ms, to avoid ban
    api_key: String,
    api_secret: String,
    http_client: Client,
}

impl KrakenApi {
    /// Create a new KrakenApi by providing an API key & API secret
    pub fn new(api_key: &str, api_secret: &str) -> KrakenApi {
        let ssl = NativeTlsClient::new().unwrap();
        let connector = HttpsConnector::new(ssl);

        KrakenApi {
            last_request: 0,
            api_key: api_key.to_string(),
            api_secret: api_secret.to_string(),
            http_client: Client::with_connector(connector),
        }
    }

    /// Create a new KrakenApi from a json configuration file. This file must follow this structure:
    ///
    /// ```ignore
    /// {
    ///     "account_kraken": {
    ///         "exchange"  : "kraken",
    ///         "api_key"   : "123456789ABCDEF",
    ///         "api_secret": "ABC&EF?abcdef"
    ///     },
    ///     "account_poloniex": {
    ///         "exchange"  : "poloniex",
    ///         "api_key"   : "XYXY-XYXY-XYXY-XY",
    ///         "api_secret": "A0A0B1B1C2C2"
    ///     }
    /// }
    /// ```
    /// For this example, you could use load your Kraken account with
    /// `new_from_file("account_kraken", Path::new("/keys.json"))`
    pub fn new_from_file(config_name: &str, path: PathBuf) -> KrakenApi {
        let mut f = File::open(&path).unwrap();
        let mut buffer = String::new();
        f.read_to_string(&mut buffer).unwrap();

        let data: Value = serde_json::from_str(&buffer).unwrap();
        let json_obj = data.as_object().unwrap().get(config_name).unwrap();
        let api_key = json_obj.get("api_key").unwrap().as_str().unwrap();
        let api_secret = json_obj.get("api_secret").unwrap().as_str().unwrap();

        KrakenApi::new(api_key, api_secret)
    }

    fn block_or_continue(&self) {
        let threshold = 2000; // 1 request/2sec
        let delay = helpers::get_unix_timestamp_ms() - self.last_request;
        if delay < threshold {
            let duration_ms = Duration::from_millis(delay as u64);
            thread::sleep(duration_ms);
        }
    }

    fn deserialize_json(&mut self, json_string: String) -> Option<Map<String, Value>> {
        let data: Value = serde_json::from_str(&json_string).unwrap();

        match data.as_object() {
            Some(value) => Some(value.clone()),
            None => None,
        }
    }

    fn public_query(&mut self, method: &str, params: &HashMap<&str, &str>) -> Option<Map<String, Value>> {
        let url = "https://api.kraken.com/0/public/".to_string() + method + "?" +
        &helpers::url_encode_hashmap(params);

        self.block_or_continue();
        let mut response = self.http_client.get(&url).send().unwrap();
        self.last_request = helpers::get_unix_timestamp_ms();
        let mut buffer = String::new();
        response.read_to_string(&mut buffer).unwrap();
        return self.deserialize_json(buffer);
    }

    fn private_query(&mut self, method: &str, params: &HashMap<&str, &str>) -> Option<Map<String, Value>> {
        let url = "https://api.kraken.com/0/private/".to_string() + method;

        let urlpath = "/0/private/".to_string() + method;

        // Create header
        let nonce = helpers::get_unix_timestamp_ms().to_string();
        let mut params = params.clone();

        params.insert("nonce", &nonce);

        let postdata = helpers::url_encode_hashmap(&params);
        let signature = self.create_signature(urlpath, &postdata, &nonce);

        let mut custom_header = header::Headers::new();
        custom_header.set(KeyHeader(self.api_key.clone()));
        custom_header.set(SignHeader(signature));

        let mut res = self.http_client
        .post(&url)
        .body(&postdata)
        .headers(custom_header)
        .send()
        .unwrap();

        let mut buffer = String::new();
        res.read_to_string(&mut buffer).unwrap();
        return self.deserialize_json(buffer);
    }

    fn create_signature(&self, urlpath: String, postdata: &str, nonce: &str) -> String {
        let message_presha256 = nonce.to_string() + postdata;

        let mut sha256 = Sha256::new();
        sha256.input_str(&message_presha256);
        let mut buffer: Vec<u8> = repeat(0).take((sha256.output_bits()+7)/8).collect();
        sha256.result(&mut buffer);

        let mut concatenated = urlpath.as_bytes().to_vec();
        for elem in buffer {
            concatenated.push(elem);
        }

        let hmac_key = self.api_secret.from_base64().unwrap();
        let mut hmac = Hmac::new(Sha512::new(), &hmac_key);
        hmac.input(&concatenated);
        let hmac_result = hmac.result().code().to_base64(STANDARD);
        hmac_result
    }

    /// Result: Server's time
    ///
    /// ```ignore
    /// unixtime =  as unix timestamp
    /// rfc1123 = as RFC 1123 time format
    /// ```
    /// Note: This is to aid in approximating the skew time between the server and client.
    pub fn get_server_time(&mut self) -> Option<Map<String, Value>> {
        let params = HashMap::new();
        self.public_query("Time", &params)
    }

    /// Input:
    ///
    /// ```ignore
    /// info = info to retrieve (optional):
    ///     info = all info (default)
    /// aclass = asset class (optional):
    ///     currency (default)
    /// asset = comma delimited list of assets to get info on (optional.  default = all for given asset class)
    /// ```
    /// Result: array of asset names and their info:
    ///
    /// ```ignore
    /// <asset_name> = asset name
    /// altname = alternate name
    /// aclass = asset class
    /// decimals = scaling decimal places for record keeping
    /// display_decimals = scaling decimal places for output display
    /// ```
    pub fn get_asset_info(&mut self) -> Option<Map<String, Value>> {
        let params = HashMap::new();
        self.public_query("Assets", &params)
    }

    /// Input:
    ///
    /// ```ignore
    /// info = info to retrieve (optional):
    ///     info = all info (default)
    ///     leverage = leverage info
    ///     fees = fees schedule
    ///     margin = margin info
    /// pair = comma delimited list of asset pairs to get info on (optional.  default = all)
    /// ```
    ///
    /// Result: array of pair names and their info
    ///
    /// ```ignore
    /// <pair_name> = pair name
    ///     altname = alternate pair name
    ///     aclass_base = asset class of base component
    ///     base = asset id of base component
    ///     aclass_quote = asset class of quote component
    ///     quote = asset id of quote component
    ///     lot = volume lot size
    ///     pair_decimals = scaling decimal places for pair
    ///     lot_decimals = scaling decimal places for volume
    ///     lot_multiplier = amount to multiply lot volume by to get currency volume
    ///     leverage_buy = array of leverage amounts available when buying
    ///     leverage_sell = array of leverage amounts available when selling
    ///     fees = fee schedule array in [volume, percent fee] tuples
    ///     fees_maker = maker fee schedule array in [volume, percent fee] tuples (if on maker/taker)
    ///     fee_volume_currency = volume discount currency
    ///     margin_call = margin call level
    ///     margin_stop = stop-out/liquidation margin level
    /// ```
    pub fn get_tradable_asset_pairs(&mut self) -> Option<Map<String, Value>> {
        let params = HashMap::new();
        self.public_query("AssetPairs", &params)
    }

    /// Input: pair = comma delimited list of asset pairs to get info on
    /// Result: array of pair names and their ticker info
    ///
    /// ```ignore
    /// <pair_name> = pair name
    /// a = ask array(<price>, <whole lot volume>, <lot volume>),
    /// b = bid array(<price>, <whole lot volume>, <lot volume>),
    /// c = last trade closed array(<price>, <lot volume>),
    /// v = volume array(<today>, <last 24 hours>),
    /// p = volume weighted average price array(<today>, <last 24 hours>),
    /// t = number of trades array(<today>, <last 24 hours>),
    /// l = low array(<today>, <last 24 hours>),
    /// h = high array(<today>, <last 24 hours>),
    /// o = today's opening price
    /// ```
    pub fn get_ticker_information(&mut self, pair: &str) -> Option<Map<String, Value>> {
        let mut params = HashMap::new();
        params.insert("pair", pair);
        self.public_query("Ticker", &params)
    }

    /// Input:
    ///
    /// ```ignore
    /// pair = asset pair to get OHLC data for
    /// interval = time frame interval in minutes (optional):
    /// 	1 (default), 5, 15, 30, 60, 240, 1440, 10080, 21600
    /// since = return committed OHLC data since given id (optional.  exclusive)
    /// ```
    ///
    /// Result: array of pair name and OHLC data
    ///
    /// ```ignore
    /// <pair_name> = pair name
    ///     array of array entries(<time>, <open>, <high>, <low>, <close>, <vwap>, <volume>, <count>)
    /// last = id to be used as since when polling for new, committed OHLC data
    /// ```
    ///
    /// Note: the last entry in the OHLC array is for the current, not-yet-committed frame and will always be present, regardless of the value of "since".
    pub fn get_ohlc_data(&mut self, pair: &str, interval: &str, since: &str) -> Option<Map<String, Value>> {
        let mut params = HashMap::new();
        params.insert("pair", pair);
        params.insert("interval", interval);
        params.insert("since", since);
        self.public_query("OHLC", &params)
    }

    /// Input:
    ///
    /// ```ignore
    /// pair = asset pair to get market depth for
    /// count = maximum number of asks/bids (optional)
    /// ```
    /// Result: array of pair name and market depth
    ///
    /// ```ignore
    /// <pair_name> = pair name
    ///     asks = ask side array of array entries(<price>, <volume>, <timestamp>)
    ///     bids = bid side array of array entries(<price>, <volume>, <timestamp>)
    /// ```
    pub fn get_order_book(&mut self, pair: &str, count: &str) -> Option<Map<String, Value>> {
        let mut params = HashMap::new();
        params.insert("pair", pair);
        params.insert("count", count);
        self.public_query("Depth", &params)
    }

    /// Input:
    ///
    /// ```ignore
    /// pair = asset pair to get trade data for
    /// since = return trade data since given id (optional.  exclusive)
    /// ```
    /// Result: array of pair name and recent trade data
    ///
    /// ```ignore
    /// <pair_name> = pair name
    ///     array of array entries(<price>, <volume>, <time>, <buy/sell>, <market/limit>, <miscellaneous>)
    /// last = id to be used as since when polling for new trade data
    /// ```
    pub fn get_recent_trades(&mut self, pair: &str, since: &str) -> Option<Map<String, Value>> {
        let mut params = HashMap::new();
        params.insert("pair", pair);
        params.insert("since", since);
        self.public_query("Trades", &params)
    }

    /// Input:
    ///
    /// ```ignore
    /// pair = asset pair to get spread data for
    /// since = return spread data since given id (optional.  inclusive)
    /// ```
    ///
    /// Result: array of pair name and recent spread data
    ///
    /// ```ignore
    /// <pair_name> = pair name
    ///     array of array entries(<time>, <bid>, <ask>)
    /// last = id to be used as since when polling for new spread data
    /// ```
    /// Note: "since" is inclusive so any returned data with the same time as the previous set should overwrite all of the previous set's entries at that time
    pub fn get_recent_spread_data(&mut self, pair: &str, since: &str) -> Option<Map<String, Value>> {
        let mut params = HashMap::new();
        params.insert("pair", pair);
        params.insert("since", since);
        self.public_query("Spread", &params)
    }

    /// Result: array of asset names and balance amount
    pub fn get_account_balance(&mut self) -> Option<Map<String, Value>> {
        let params = HashMap::new();
        self.private_query("Balance", &params)
    }
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::io::{Result, Read, Write};
use ctx::{FromCtx, IntoCtx, SizeWith};
use error::{self};

/// An extension trait to `std::io::Read` streams; this only deserializes simple types, like `u8`, `i32`, `f32`, `usize`, etc.
///
/// If you implement [`FromCtx`](trait.FromCtx.html) and [`SizeWith`](ctx/trait.SizeWith.html) for your type, you can then `lread::<YourType>()` on a `Read`.  Note: [`FromCtx`](trait.FromCtx.html) is only meant for very simple types, and should _never_ fail.
///
/// **NB** You should probably add `repr(packed)` or `repr(C)` and be very careful how you implement [`SizeWith`](ctx/trait.SizeWith.html), otherwise you
/// will get IO errors failing to fill entire buffer (the size you specified in `SizeWith`), or out of bound errors (depending on your impl) in `from_ctx`
///
/// # Example
/// ```rust
/// use std::io::Cursor;
/// use scroll::{self, ctx, Pread, Lread};
///
/// #[repr(packed)]
/// struct Foo {
///     foo: usize,
///     bar: u32,
/// }
///
/// impl ctx::FromCtx<scroll::Endian> for Foo {
///     fn from_ctx(bytes: &[u8], ctx: scroll::Endian) -> Self {
///         Foo { foo: bytes.pread_with::<usize>(0, ctx).unwrap(), bar: bytes.pread_with::<u32>(8, ctx).unwrap() }
///     }
/// }
///
/// impl ctx::SizeWith<scroll::Endian> for Foo {
///     type Units = usize;
///     // our parsing context doesn't influence our size
///     fn size_with(_: &scroll::Endian) -> Self::Units {
///         ::std::mem::size_of::<Foo>()
///     }
/// }
///
/// let bytes_ = [0x0b,0x0b,0x00,0x00,0x00,0x00,0x00,0x00, 0xef,0xbe,0x00,0x00,];
/// let mut bytes = Cursor::new(bytes_);
/// let foo = bytes.lread::<usize>().unwrap();
/// let bar = bytes.lread::<u32>().unwrap();
/// assert_eq!(foo, 0xb0b);
/// assert_eq!(bar, 0xbeef);
/// let error = bytes.lread::<f64>();
/// assert!(error.is_err());
/// let mut bytes = Cursor::new(bytes_);
/// let foo_ = bytes.lread::<Foo>().unwrap();
/// assert_eq!(foo_.foo, foo);
/// assert_eq!(foo_.bar, bar);
/// ```
///
pub trait Lread<Ctx = super::Endian, E = error::Error> : Read
 where
    Ctx: Copy + Default + Debug,
    E: Debug,
{
    /// Reads the type `N` from `Self`, with a default parsing context.
    /// For the primitive numeric types, this will be at the host machine's endianness.
    ///
    /// # Example
    /// ```rust
    /// use scroll::Lread;
    /// use std::io::Cursor;
    /// let bytes = [0xef, 0xbe];
    /// let mut bytes = Cursor::new(&bytes[..]);
    /// let beef = bytes.lread::<u16>().unwrap();
    /// assert_eq!(0xbeef, beef);
    /// ```
    #[inline]
    fn lread<N: FromCtx<Ctx> + SizeWith<Ctx, Units = usize>>(&mut self) -> Result<N> {
        let ctx = Ctx::default();
        self.lread_with(ctx)
    }

    /// Reads the type `N` from `Self`, with the parsing context `ctx`.
    /// **NB**: this will panic if the type you're reading has a size greater than 256. Plans are to have this allocate in larger cases.
    ///
    /// For the primitive numeric types, this will be at the host machine's endianness.
    ///
    /// # Example
    /// ```rust
    /// use scroll::{Lread, LE, BE};
    /// use std::io::Cursor;
    /// let bytes = [0xef, 0xbe, 0xb0, 0xb0, 0xfe, 0xed, 0xde, 0xad];
    /// let mut bytes = Cursor::new(&bytes[..]);
    /// let beef = bytes.lread_with::<u16>(LE).unwrap();
    /// assert_eq!(0xbeef, beef);
    /// let b0 = bytes.lread::<u8>().unwrap();
    /// assert_eq!(0xb0, b0);
    /// let b0 = bytes.lread::<u8>().unwrap();
    /// assert_eq!(0xb0, b0);
    /// let feeddead = bytes.lread_with::<u32>(BE).unwrap();
    /// assert_eq!(0xfeeddead, feeddead);
    /// ```
    #[inline]
    fn lread_with<N: FromCtx<Ctx> + SizeWith<Ctx, Units = usize>>(&mut self, ctx: Ctx) -> Result<N> {
        let mut scratch = [0u8; 256];
        let size = N::size_with(&ctx);
        let mut buf = &mut scratch[0..size];
        self.read_exact(&mut buf)?;
        Ok(N::from_ctx(buf, ctx))
    }
}

/// Types that implement `Read` get methods defined in `Lread`
/// for free.
impl<R: Read + ?Sized> Lread for R {}

/// An extension trait to `std::io::Write` streams; this only serializes simple types, like `u8`, `i32`, `f32`, `usize`, etc.
///
/// To write custom types with a single `lwrite::<YourType>` call, implement [`IntoCtx`](trait.IntoCtx.html) and [`SizeWith`](ctx/trait.SizeWith.html) for `YourType`.
pub trait Lwrite<Ctx = super::Endian, E = error::Error>: Write
    where
          Ctx: Copy + Default + Debug,
          E: Debug,
{
    /// Writes the type `N` into `Self`, with the parsing context `ctx`.
    /// **NB**: this will panic if the type you're writing has a size greater than 256. Plans are to have this allocate in larger cases.
    ///
    /// For the primitive numeric types, this will be at the host machine's endianness.
    ///
    /// # Example
    /// ```rust
    /// use scroll::Lwrite;
    /// use std::io::Cursor;
    ///
    /// let mut bytes = [0x0u8; 4];
    /// let mut bytes = Cursor::new(&mut bytes[..]);
    /// bytes.lwrite(0xdeadbeef as u32).unwrap();
    /// assert_eq!(bytes.into_inner(), [0xef, 0xbe, 0xad, 0xde,]);
    /// ```
    #[inline]
    fn lwrite<N: SizeWith<Ctx, Units = usize> + IntoCtx<Ctx>>(&mut self, n: N) -> Result<()> {
        let ctx = Ctx::default();
        self.lwrite_with(n, ctx)
    }

    /// Writes the type `N` into `Self`, with the parsing context `ctx`.
    /// **NB**: this will panic if the type you're writing has a size greater than 256. Plans are to have this allocate in larger cases.
    ///
    /// For the primitive numeric types, this will be at the host machine's endianness.
    ///
    /// # Example
    /// ```rust
    /// use scroll::{Lwrite, LE, BE};
    /// use std::io::{Write, Cursor};
    ///
    /// let mut bytes = [0x0u8; 10];
    /// let mut cursor = Cursor::new(&mut bytes[..]);
    /// cursor.write_all(b"hello").unwrap();
    /// cursor.lwrite_with(0xdeadbeef as u32, BE).unwrap();
    /// assert_eq!(cursor.into_inner(), [0x68, 0x65, 0x6c, 0x6c, 0x6f, 0xde, 0xad, 0xbe, 0xef, 0x0]);
    /// ```
    #[inline]
    fn lwrite_with<N: SizeWith<Ctx, Units = usize> + IntoCtx<Ctx>>(&mut self, n: N, ctx: Ctx) -> Result<()> {
        let mut buf = [0u8; 256];
        let size = N::size_with(&ctx);
        let mut buf = &mut buf[0..size];
        n.into_ctx(buf, ctx);
        self.write_all(buf)?;
        Ok(())
    }
}

/// Types that implement `Write` get methods defined in `Lwrite`
/// for free.
impl<W: Write + ?Sized> Lwrite for W {}
<commit_msg>lesser: generify lesser, remove unnecessary bounds<commit_after>use std::io::{Result, Read, Write};
use ctx::{FromCtx, IntoCtx, SizeWith};

/// An extension trait to `std::io::Read` streams; this only deserializes simple types, like `u8`, `i32`, `f32`, `usize`, etc.
///
/// If you implement [`FromCtx`](trait.FromCtx.html) and [`SizeWith`](ctx/trait.SizeWith.html) for your type, you can then `lread::<YourType>()` on a `Read`.  Note: [`FromCtx`](trait.FromCtx.html) is only meant for very simple types, and should _never_ fail.
///
/// **NB** You should probably add `repr(packed)` or `repr(C)` and be very careful how you implement [`SizeWith`](ctx/trait.SizeWith.html), otherwise you
/// will get IO errors failing to fill entire buffer (the size you specified in `SizeWith`), or out of bound errors (depending on your impl) in `from_ctx`
///
/// # Example
/// ```rust
/// use std::io::Cursor;
/// use scroll::{self, ctx, Pread, Lread};
///
/// #[repr(packed)]
/// struct Foo {
///     foo: usize,
///     bar: u32,
/// }
///
/// impl ctx::FromCtx<scroll::Endian> for Foo {
///     fn from_ctx(bytes: &[u8], ctx: scroll::Endian) -> Self {
///         Foo { foo: bytes.pread_with::<usize>(0, ctx).unwrap(), bar: bytes.pread_with::<u32>(8, ctx).unwrap() }
///     }
/// }
///
/// impl ctx::SizeWith<scroll::Endian> for Foo {
///     type Units = usize;
///     // our parsing context doesn't influence our size
///     fn size_with(_: &scroll::Endian) -> Self::Units {
///         ::std::mem::size_of::<Foo>()
///     }
/// }
///
/// let bytes_ = [0x0b,0x0b,0x00,0x00,0x00,0x00,0x00,0x00, 0xef,0xbe,0x00,0x00,];
/// let mut bytes = Cursor::new(bytes_);
/// let foo = bytes.lread::<usize>().unwrap();
/// let bar = bytes.lread::<u32>().unwrap();
/// assert_eq!(foo, 0xb0b);
/// assert_eq!(bar, 0xbeef);
/// let error = bytes.lread::<f64>();
/// assert!(error.is_err());
/// let mut bytes = Cursor::new(bytes_);
/// let foo_ = bytes.lread::<Foo>().unwrap();
/// assert_eq!(foo_.foo, foo);
/// assert_eq!(foo_.bar, bar);
/// ```
///
pub trait Lread<Ctx: Copy, E> : Read
{
    /// Reads the type `N` from `Self`, with a default parsing context.
    /// For the primitive numeric types, this will be at the host machine's endianness.
    ///
    /// # Example
    /// ```rust
    /// use scroll::Lread;
    /// use std::io::Cursor;
    /// let bytes = [0xef, 0xbe];
    /// let mut bytes = Cursor::new(&bytes[..]);
    /// let beef = bytes.lread::<u16>().unwrap();
    /// assert_eq!(0xbeef, beef);
    /// ```
    #[inline]
    fn lread<N: FromCtx<Ctx> + SizeWith<Ctx, Units = usize>>(&mut self) -> Result<N> where Ctx: Default {
        let ctx = Ctx::default();
        self.lread_with(ctx)
    }

    /// Reads the type `N` from `Self`, with the parsing context `ctx`.
    /// **NB**: this will panic if the type you're reading has a size greater than 256. Plans are to have this allocate in larger cases.
    ///
    /// For the primitive numeric types, this will be at the host machine's endianness.
    ///
    /// # Example
    /// ```rust
    /// use scroll::{Lread, LE, BE};
    /// use std::io::Cursor;
    /// let bytes = [0xef, 0xbe, 0xb0, 0xb0, 0xfe, 0xed, 0xde, 0xad];
    /// let mut bytes = Cursor::new(&bytes[..]);
    /// let beef = bytes.lread_with::<u16>(LE).unwrap();
    /// assert_eq!(0xbeef, beef);
    /// let b0 = bytes.lread::<u8>().unwrap();
    /// assert_eq!(0xb0, b0);
    /// let b0 = bytes.lread::<u8>().unwrap();
    /// assert_eq!(0xb0, b0);
    /// let feeddead = bytes.lread_with::<u32>(BE).unwrap();
    /// assert_eq!(0xfeeddead, feeddead);
    /// ```
    #[inline]
    fn lread_with<N: FromCtx<Ctx> + SizeWith<Ctx, Units = usize>>(&mut self, ctx: Ctx) -> Result<N> {
        let mut scratch = [0u8; 256];
        let size = N::size_with(&ctx);
        let mut buf = &mut scratch[0..size];
        self.read_exact(&mut buf)?;
        Ok(N::from_ctx(buf, ctx))
    }
}

/// Types that implement `Read` get methods defined in `Lread`
/// for free.
impl<Ctx: Copy, E, R: Read + ?Sized> Lread<Ctx, E> for R {}

/// An extension trait to `std::io::Write` streams; this only serializes simple types, like `u8`, `i32`, `f32`, `usize`, etc.
///
/// To write custom types with a single `lwrite::<YourType>` call, implement [`IntoCtx`](trait.IntoCtx.html) and [`SizeWith`](ctx/trait.SizeWith.html) for `YourType`.
pub trait Lwrite<Ctx: Copy, E>: Write
{
    /// Writes the type `N` into `Self`, with the parsing context `ctx`.
    /// **NB**: this will panic if the type you're writing has a size greater than 256. Plans are to have this allocate in larger cases.
    ///
    /// For the primitive numeric types, this will be at the host machine's endianness.
    ///
    /// # Example
    /// ```rust
    /// use scroll::Lwrite;
    /// use std::io::Cursor;
    ///
    /// let mut bytes = [0x0u8; 4];
    /// let mut bytes = Cursor::new(&mut bytes[..]);
    /// bytes.lwrite(0xdeadbeef as u32).unwrap();
    /// assert_eq!(bytes.into_inner(), [0xef, 0xbe, 0xad, 0xde,]);
    /// ```
    #[inline]
    fn lwrite<N: SizeWith<Ctx, Units = usize> + IntoCtx<Ctx>>(&mut self, n: N) -> Result<()> where Ctx: Default {
        let ctx = Ctx::default();
        self.lwrite_with(n, ctx)
    }

    /// Writes the type `N` into `Self`, with the parsing context `ctx`.
    /// **NB**: this will panic if the type you're writing has a size greater than 256. Plans are to have this allocate in larger cases.
    ///
    /// For the primitive numeric types, this will be at the host machine's endianness.
    ///
    /// # Example
    /// ```rust
    /// use scroll::{Lwrite, LE, BE};
    /// use std::io::{Write, Cursor};
    ///
    /// let mut bytes = [0x0u8; 10];
    /// let mut cursor = Cursor::new(&mut bytes[..]);
    /// cursor.write_all(b"hello").unwrap();
    /// cursor.lwrite_with(0xdeadbeef as u32, BE).unwrap();
    /// assert_eq!(cursor.into_inner(), [0x68, 0x65, 0x6c, 0x6c, 0x6f, 0xde, 0xad, 0xbe, 0xef, 0x0]);
    /// ```
    #[inline]
    fn lwrite_with<N: SizeWith<Ctx, Units = usize> + IntoCtx<Ctx>>(&mut self, n: N, ctx: Ctx) -> Result<()> {
        let mut buf = [0u8; 256];
        let size = N::size_with(&ctx);
        let mut buf = &mut buf[0..size];
        n.into_ctx(buf, ctx);
        self.write_all(buf)?;
        Ok(())
    }
}

/// Types that implement `Write` get methods defined in `Lwrite`
/// for free.
impl<Ctx: Copy, E, W: Write + ?Sized> Lwrite<Ctx, E> for W {}
<|endoftext|>