<commit_before>use std::any::Any;
use std::io::{Result as IoResult, Error as IoError};
use std::io::Write;
use std::ops::{Deref, DerefMut};
use std::os::raw::{c_void, c_int};
use std::sync::Arc;
use std::sync::atomic::AtomicBool;

use wayland_sys::client::*;
use wayland_sys::common::*;
use {Handler, Proxy};

type ProxyUserData = (*mut EventQueueHandle, Arc<AtomicBool>);

pub struct EventQueueHandle {
    handlers: Vec<Box<Any>>
}

impl EventQueueHandle {
    /// Register a proxy to a handler of this event queue.
    ///
    /// The H type must be provided and match the type of the targetted Handler, or
    /// it will panic.
    ///
    /// This overwrites any precedently set Handler for this proxy.
    pub fn register<P: Proxy, H: Handler<P> + Any + 'static>(&mut self, proxy: &P, handler_id: usize) {
        let h = self.handlers[handler_id].downcast_ref::<H>()
                    .expect("Handler type do not match.");
        unsafe {
            let data: *mut ProxyUserData = ffi_dispatch!(
                WAYLAND_CLIENT_HANDLE,
                wl_proxy_get_user_data,
                proxy.ptr()
            ) as *mut _;
            (&mut *data).0 = self as *const _ as *mut _;
            ffi_dispatch!(
                WAYLAND_CLIENT_HANDLE,
                wl_proxy_add_dispatcher,
                proxy.ptr(),
                dispatch_func::<P,H>,
                h as *const _ as *const c_void,
                self as *const _ as *mut c_void
            );
        }
    }

    /// Insert a new handler to this EventLoop
    ///
    /// Returns the index of this handler in the internal array, needed register
    /// proxies to it.
    pub fn add_handler<H: Any + 'static>(&mut self, handler: H) -> usize {
        self.handlers.push(Box::new(handler) as Box<Any>);
        self.handlers.len() - 1
    }
}

pub struct StateGuard<'evq> {
    evq: &'evq mut EventQueue
}

impl<'evq> StateGuard<'evq> {
    /// Get a reference to a handler
    ///
    /// Provides a reference to a handler stored in this event loop.
    ///
    /// The H type must be provided and match the type of the targetted Handler, or
    /// it will panic.
    pub fn get_handler<H: Any + 'static>(&self, handler_id: usize) -> &H {
        self.evq.handle.handlers[handler_id].downcast_ref::<H>()
            .expect("Handler type do not match.")
    }

    /// Get a mutable reference to a handler
    ///
    /// Provides a reference to a handler stored in this event loop.
    ///
    /// The H type must be provided and match the type of the targetted Handler, or
    /// it will panic.
    pub fn get_mut_handler<H: Any + 'static>(&mut self, handler_id: usize) -> &H {
        self.evq.handle.handlers[handler_id].downcast_mut::<H>()
            .expect("Handler type do not match.")
    }
}

pub struct EventQueue {
    display: *mut wl_display,
    wlevq: Option<*mut wl_event_queue>,
    handle: Box<EventQueueHandle>
}

impl EventQueue {
    /// Dispatches events from the internal buffer.
    ///
    /// Dispatches all events to their appropriate handlers.
    /// If not events were in the internal buffer, will block until
    /// some events are read and dispatch them.
    /// This process can insert events in the internal buffers of
    /// other event queues.
    ///
    /// If an error is returned, your connexion with the wayland
    /// compositor is probably lost.
    pub fn dispatch(&mut self) -> IoResult<u32> {
        let ret = match self.wlevq {
            Some(evq) => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_queue_pending,
                    self.display,
                    evq
                )
            },
            None => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_pending,
                    self.display
                )
            }
        };
        if ret >= 0 {
            Ok(ret as u32)
        } else {
            Err(IoError::last_os_error())
        }
    }

    /// Dispatches pending events from the internal buffer.
    ///
    /// Dispatches all events to their appropriate handlers.
    /// Never blocks, if not events were pending, simply returns
    /// `Ok(0)`.
    ///
    /// If an error is returned, your connexion with the wayland
    /// compositor is probably lost.
    pub fn dispatch_pending(&mut self) -> IoResult<u32> {
        let ret = match self.wlevq {
            Some(evq) => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_queue_pending,
                    self.display,
                    evq
                )
            },
            None => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_pending,
                    self.display
                )
            }
        };
        if ret >= 0 {
            Ok(ret as u32)
        } else {
            Err(IoError::last_os_error())
        }
    }

    /// Synchronous roundtrip
    ///
    /// This call will cause a synchonous roundtrip with the wayland server. It will block until all
    /// pending requests of this queue are send to the server and it has processed all of them and
    /// send the appropriate events.
    ///
    /// Handlers are called as a consequence.
    ///
    /// On success returns the number of dispatched events.
    pub fn sync_roundtrip(&mut self) -> IoResult<i32> {
        let ret = unsafe { match self.wlevq {
            Some(evtq) => {
                ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_roundtrip_queue,
                    self.display, evtq)
            }
            None => {
                ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_roundtrip, self.display)
            }
        }};
        if ret >= 0 { Ok(ret) } else { Err(IoError::last_os_error()) }
    }

    /// Get a handle to the internal state
    ///
    /// The returned guard object allows you to get references
    /// to the handler objects you previously inserted in this
    /// event queue.
    pub fn state(&mut self) -> StateGuard {
        StateGuard { evq: self }
    }
}

impl Deref for EventQueue {
    type Target = EventQueueHandle;
    fn deref(&self) -> &EventQueueHandle {
        &*self.handle
    }
}

impl DerefMut for EventQueue {
    fn deref_mut(&mut self) -> &mut EventQueueHandle {
        &mut *self.handle
    }
}

pub unsafe fn create_event_queue(display: *mut wl_display, evq: Option<*mut wl_event_queue>) -> EventQueue {
    EventQueue {
        display: display,
        wlevq: evq,
        handle: Box::new(EventQueueHandle {
            handlers: Vec::new()
        })
    }
}

unsafe extern "C" fn dispatch_func<P: Proxy, H: Handler<P>>(
    handler: *const c_void,
    proxy: *mut c_void,
    opcode: u32,
    _msg: *const wl_message,
    args: *const wl_argument
) -> c_int {
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        // This cast from *const to *mut is legit because we enforce that a Handler
        // can only be assigned to a single EventQueue.
        // (this is actually the whole point of the design of this lib)
        let handler = &mut *(handler as *const H as *mut H);
        let proxy = P::from_ptr_initialized(proxy as *mut wl_proxy);
        let data = &mut *(ffi_dispatch!(
            WAYLAND_CLIENT_HANDLE, wl_proxy_get_user_data, proxy.ptr()
        ) as *mut ProxyUserData);
        let evqhandle = &mut *data.0;
        handler.message(evqhandle, &proxy, opcode, args)
    });
    match ret {
        Ok(Ok(())) => return 0,   // all went well
        Ok(Err(())) => {
            // an unknown opcode was dispatched, this is not normal
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-client error] Attempted to dispatch unknown opcode {} for {}, aborting.",
                opcode, P::interface_name()
            );
            ::libc::abort();
        }
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-client error] A handler for {} panicked, aborting.",
                P::interface_name()
            );
            ::libc::abort();
        }
    }
}

/// Registers a handler type so it can be used in event queue
///
/// After having implemented the appropriate Handler trait for your type,
/// declare it via this macro, like this:
///
/// ```ignore
/// struct MyHandler;
///
/// impl wl_foo::Handler for MyHandler {
///     ...
/// }
///
/// declare_handler!(MyHandler, wl_foo::Handler, wl_foo::WlFoo);
/// ```
#[macro_export]
macro_rules! declare_handler(
    ($handler_struct: ty, $handler_trait: path, $handled_type: ty) => {
        unsafe impl $crate::Handler<$handled_type> for $handler_struct {
            unsafe fn message(&mut self, evq: &mut $crate::EventQueueHandle, proxy: &$handled_type, opcode: u32, args: *const $crate::sys::wl_argument) -> Result<(),()> {
                <$handler_struct as $handler_trait>::__message(self, evq, proxy, opcode, args)
            }
        }
    }
);
<commit_msg>client: fix segfault in event dispatching<commit_after>use std::any::Any;
use std::io::{Result as IoResult, Error as IoError};
use std::io::Write;
use std::ops::{Deref, DerefMut};
use std::os::raw::{c_void, c_int};
use std::sync::Arc;
use std::sync::atomic::AtomicBool;

use wayland_sys::client::*;
use wayland_sys::common::*;
use {Handler, Proxy};

type ProxyUserData = (*mut EventQueueHandle, Arc<AtomicBool>);

pub struct EventQueueHandle {
    handlers: Vec<Box<Any>>
}

impl EventQueueHandle {
    /// Register a proxy to a handler of this event queue.
    ///
    /// The H type must be provided and match the type of the targetted Handler, or
    /// it will panic.
    ///
    /// This overwrites any precedently set Handler for this proxy.
    pub fn register<P: Proxy, H: Handler<P> + Any + 'static>(&mut self, proxy: &P, handler_id: usize) {
        let h = self.handlers[handler_id].downcast_ref::<H>()
                    .expect("Handler type do not match.");
        unsafe {
            let data: *mut ProxyUserData = ffi_dispatch!(
                WAYLAND_CLIENT_HANDLE,
                wl_proxy_get_user_data,
                proxy.ptr()
            ) as *mut _;
            (&mut *data).0 = self as *const _ as *mut _;
            ffi_dispatch!(
                WAYLAND_CLIENT_HANDLE,
                wl_proxy_add_dispatcher,
                proxy.ptr(),
                dispatch_func::<P,H>,
                h as *const _ as *const c_void,
                data as *mut c_void
            );
        }
    }

    /// Insert a new handler to this EventLoop
    ///
    /// Returns the index of this handler in the internal array, needed register
    /// proxies to it.
    pub fn add_handler<H: Any + 'static>(&mut self, handler: H) -> usize {
        self.handlers.push(Box::new(handler) as Box<Any>);
        self.handlers.len() - 1
    }
}

pub struct StateGuard<'evq> {
    evq: &'evq mut EventQueue
}

impl<'evq> StateGuard<'evq> {
    /// Get a reference to a handler
    ///
    /// Provides a reference to a handler stored in this event loop.
    ///
    /// The H type must be provided and match the type of the targetted Handler, or
    /// it will panic.
    pub fn get_handler<H: Any + 'static>(&self, handler_id: usize) -> &H {
        self.evq.handle.handlers[handler_id].downcast_ref::<H>()
            .expect("Handler type do not match.")
    }

    /// Get a mutable reference to a handler
    ///
    /// Provides a reference to a handler stored in this event loop.
    ///
    /// The H type must be provided and match the type of the targetted Handler, or
    /// it will panic.
    pub fn get_mut_handler<H: Any + 'static>(&mut self, handler_id: usize) -> &H {
        self.evq.handle.handlers[handler_id].downcast_mut::<H>()
            .expect("Handler type do not match.")
    }
}

pub struct EventQueue {
    display: *mut wl_display,
    wlevq: Option<*mut wl_event_queue>,
    handle: Box<EventQueueHandle>
}

impl EventQueue {
    /// Dispatches events from the internal buffer.
    ///
    /// Dispatches all events to their appropriate handlers.
    /// If not events were in the internal buffer, will block until
    /// some events are read and dispatch them.
    /// This process can insert events in the internal buffers of
    /// other event queues.
    ///
    /// If an error is returned, your connexion with the wayland
    /// compositor is probably lost.
    pub fn dispatch(&mut self) -> IoResult<u32> {
        let ret = match self.wlevq {
            Some(evq) => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_queue_pending,
                    self.display,
                    evq
                )
            },
            None => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_pending,
                    self.display
                )
            }
        };
        if ret >= 0 {
            Ok(ret as u32)
        } else {
            Err(IoError::last_os_error())
        }
    }

    /// Dispatches pending events from the internal buffer.
    ///
    /// Dispatches all events to their appropriate handlers.
    /// Never blocks, if not events were pending, simply returns
    /// `Ok(0)`.
    ///
    /// If an error is returned, your connexion with the wayland
    /// compositor is probably lost.
    pub fn dispatch_pending(&mut self) -> IoResult<u32> {
        let ret = match self.wlevq {
            Some(evq) => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_queue_pending,
                    self.display,
                    evq
                )
            },
            None => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_pending,
                    self.display
                )
            }
        };
        if ret >= 0 {
            Ok(ret as u32)
        } else {
            Err(IoError::last_os_error())
        }
    }

    /// Synchronous roundtrip
    ///
    /// This call will cause a synchonous roundtrip with the wayland server. It will block until all
    /// pending requests of this queue are send to the server and it has processed all of them and
    /// send the appropriate events.
    ///
    /// Handlers are called as a consequence.
    ///
    /// On success returns the number of dispatched events.
    pub fn sync_roundtrip(&mut self) -> IoResult<i32> {
        let ret = unsafe { match self.wlevq {
            Some(evtq) => {
                ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_roundtrip_queue,
                    self.display, evtq)
            }
            None => {
                ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_roundtrip, self.display)
            }
        }};
        if ret >= 0 { Ok(ret) } else { Err(IoError::last_os_error()) }
    }

    /// Get a handle to the internal state
    ///
    /// The returned guard object allows you to get references
    /// to the handler objects you previously inserted in this
    /// event queue.
    pub fn state(&mut self) -> StateGuard {
        StateGuard { evq: self }
    }
}

impl Deref for EventQueue {
    type Target = EventQueueHandle;
    fn deref(&self) -> &EventQueueHandle {
        &*self.handle
    }
}

impl DerefMut for EventQueue {
    fn deref_mut(&mut self) -> &mut EventQueueHandle {
        &mut *self.handle
    }
}

pub unsafe fn create_event_queue(display: *mut wl_display, evq: Option<*mut wl_event_queue>) -> EventQueue {
    EventQueue {
        display: display,
        wlevq: evq,
        handle: Box::new(EventQueueHandle {
            handlers: Vec::new()
        })
    }
}

unsafe extern "C" fn dispatch_func<P: Proxy, H: Handler<P>>(
    handler: *const c_void,
    proxy: *mut c_void,
    opcode: u32,
    _msg: *const wl_message,
    args: *const wl_argument
) -> c_int {
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        // This cast from *const to *mut is legit because we enforce that a Handler
        // can only be assigned to a single EventQueue.
        // (this is actually the whole point of the design of this lib)
        let handler = &mut *(handler as *const H as *mut H);
        let proxy = P::from_ptr_initialized(proxy as *mut wl_proxy);
        let data = &mut *(ffi_dispatch!(
            WAYLAND_CLIENT_HANDLE, wl_proxy_get_user_data, proxy.ptr()
        ) as *mut ProxyUserData);
        let evqhandle = &mut *data.0;
        handler.message(evqhandle, &proxy, opcode, args)
    });
    match ret {
        Ok(Ok(())) => return 0,   // all went well
        Ok(Err(())) => {
            // an unknown opcode was dispatched, this is not normal
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-client error] Attempted to dispatch unknown opcode {} for {}, aborting.",
                opcode, P::interface_name()
            );
            ::libc::abort();
        }
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-client error] A handler for {} panicked, aborting.",
                P::interface_name()
            );
            ::libc::abort();
        }
    }
}

/// Registers a handler type so it can be used in event queue
///
/// After having implemented the appropriate Handler trait for your type,
/// declare it via this macro, like this:
///
/// ```ignore
/// struct MyHandler;
///
/// impl wl_foo::Handler for MyHandler {
///     ...
/// }
///
/// declare_handler!(MyHandler, wl_foo::Handler, wl_foo::WlFoo);
/// ```
#[macro_export]
macro_rules! declare_handler(
    ($handler_struct: ty, $handler_trait: path, $handled_type: ty) => {
        unsafe impl $crate::Handler<$handled_type> for $handler_struct {
            unsafe fn message(&mut self, evq: &mut $crate::EventQueueHandle, proxy: &$handled_type, opcode: u32, args: *const $crate::sys::wl_argument) -> Result<(),()> {
                <$handler_struct as $handler_trait>::__message(self, evq, proxy, opcode, args)
            }
        }
    }
);
<|endoftext|>


<commit_before>pub use self::token::Token::*;

pub mod ast;
pub mod lexer;
pub mod token;

pub struct Parser {
    pub current: token::Token,
    pub lexer: lexer::Lexer,
    pub peeked: Option<token::Token>,
}

impl Parser {
    pub fn new(input: &str) -> Parser {
        let l = lexer::Lexer::new(input);
        let p = Parser {
            current: EOF,
            peeked: None,
            lexer: l
        };
        p
    }

    pub fn parse(&mut self) -> Result<Box<ast::Node>, String> {
        self.expr(1)
    }

    pub fn expr(&mut self, prec: usize) -> Result<Box<ast::Node>, String> {
        let mut lhs = try!(self.atom());
        //println!("expr {:?}", self.current);
        let mut rhs;
        loop {
            let curr = try!(self.peek_token());
            //println!("{:?}", curr);
            if token::is_eof(&curr) {
                //println!("breaking out of expr loop");
                break;
            }
            let info_tuple = curr.info();
            if info_tuple.is_none() {
                break;
            }
            let (op_prec, op_assoc) = info_tuple.unwrap();
            if op_prec < prec {
                break;
            }
            try!(self.next_token());
            match op_assoc {
                0 => {
                    rhs = try!(self.expr(op_prec + 1));
                }
                _  => {
                    rhs = try!(self.expr(op_prec));
                }
            }
            lhs = self.op(curr, lhs, rhs);

        }
        Ok(lhs)
    }

    pub fn atom(&mut self) -> Result<Box<ast::Node>, String> {

        match try!(self.peek_token()) {
            EOF => { Ok(Box::new( ast::Num {num: 0f64})) }
            LPAREN => {
                self.expect('(');
                let e = try!(self.expr(1));
                self.expect(')');
                Ok(e)
            }
            NUMBER(val) => {
                try!(self.next_token());
                Ok(Box::new( ast::Num { num: val }))
            }
            SYMBOL(val) => {
                //only allow math functions for now, no variables
                try!(self.next_token());
                match try!(self.peek_token()) {
                    LPAREN => {
                        self.expect('(');
                        let e = try!(self.expr(1));
                        self.expect(')');
                        Ok(self.function(val,e))
                    }
                    SYMBOL(name) => {
                        match &val[..] {
                            "let" => {
                                try!(self.next_token());
                                self.expect('=');
                                let expr = try!(self.expr(1));
                                Ok(Box::new( ast::Assignment { name: name, value: expr}))
                            }
                            _ => {
                                Err("Error: two consecutive symbols".to_string())
                            }
                        }
                   }
                   _ => {
                       Ok(Box::new( ast::Var { name: val }))
                   }
                }
            }
            a => {
                Err(format!("unrecognized atom: {:?}", a))
            }
        }
    }

    pub fn op (&self, op: token::Token, lhs: Box<ast::Node>, rhs: Box<ast::Node>)
            -> Box<ast::Node> {
        match op {
            ADD => {
                Box::new( ast::Add {
                    left: lhs,
                    right: rhs
                })
            }
            SUB => {
                Box::new( ast::Sub {
                    left: lhs,
                    right: rhs
                })
            }
            MUL => {
                Box::new( ast::Mul {
                    left: lhs,
                    right: rhs
                })
            }
            DIV => {
                Box::new( ast::Div {
                    left: lhs,
                    right: rhs
                })
            }
            CARET => {
                Box::new( ast::Pow {
                    base: lhs,
                    exponent: rhs
                })
            }
            o => {
                panic!("unrecognized op: {:?}", o);
            }
        }
    }

    pub fn function<'a>(&'a self, op: String, arg: Box<ast::Node>) -> Box<ast::Node> {
        match &op[..] {
            "sin" | "sine" => {
                Box::new( ast::Sin {
                    arg: arg
                })
            }
            "sqrt" | "SQRT" => {
                Box::new( ast::Sqrt {
                    arg: arg
                })
            }
            "cos" | "cosine" => {
                Box::new( ast::Cos {
                    arg: arg
                })
            }
            "print" => {
                Box::new( ast::Print {
                    arg: arg
                })
            }
            _ => {
                panic!("unrecognized function!");
            }
        }
    }
}

impl Parser {
    pub fn expect(&mut self, tok: char) {
        self.next_token();
        if self.current.to_char() != tok {
            panic!("expected {:?} but found {}", tok, self.current.to_char());
        }
    }
    pub fn peek_token(&mut self) -> Result<token::Token, String> {
        if self.peeked.is_none() {
            self.peeked = Some(try!(self.lexer.next_token()));
        }
        Ok(self.peeked.clone().unwrap())
    }
    pub fn next_token(&mut self) -> Result<(), String> {
        match self.peeked {
            Some(ref mut pk) => {
                self.current = pk.clone();
            }
            None => {
                self.current = try!(self.lexer.next_token());
            }
        }
        self.peeked = None;
        Ok(())
    }
}
<commit_msg>Finish error handling. no longer panics in expect<commit_after>pub use self::token::Token::*;

pub mod ast;
pub mod lexer;
pub mod token;

pub struct Parser {
    pub current: token::Token,
    pub lexer: lexer::Lexer,
    pub peeked: Option<token::Token>,
}

impl Parser {
    pub fn new(input: &str) -> Parser {
        let l = lexer::Lexer::new(input);
        let p = Parser {
            current: EOF,
            peeked: None,
            lexer: l
        };
        p
    }

    pub fn parse(&mut self) -> Result<Box<ast::Node>, String> {
        self.expr(1)
    }

    pub fn expr(&mut self, prec: usize) -> Result<Box<ast::Node>, String> {
        let mut lhs = try!(self.atom());
        //println!("expr {:?}", self.current);
        let mut rhs;
        loop {
            let curr = try!(self.peek_token());
            //println!("{:?}", curr);
            if token::is_eof(&curr) {
                //println!("breaking out of expr loop");
                break;
            }
            let info_tuple = curr.info();
            if info_tuple.is_none() {
                break;
            }
            let (op_prec, op_assoc) = info_tuple.unwrap();
            if op_prec < prec {
                break;
            }
            try!(self.next_token());
            match op_assoc {
                0 => {
                    rhs = try!(self.expr(op_prec + 1));
                }
                _  => {
                    rhs = try!(self.expr(op_prec));
                }
            }
            lhs = self.op(curr, lhs, rhs);

        }
        Ok(lhs)
    }

    pub fn atom(&mut self) -> Result<Box<ast::Node>, String> {

        match try!(self.peek_token()) {
            EOF => { Ok(Box::new( ast::Num {num: 0f64})) }
            LPAREN => {
                try!(self.expect('('));
                let e = try!(self.expr(1));
                try!(self.expect(')'));
                Ok(e)
            }
            NUMBER(val) => {
                try!(self.next_token());
                Ok(Box::new( ast::Num { num: val }))
            }
            SYMBOL(val) => {
                //only allow math functions for now, no variables
                try!(self.next_token());
                match try!(self.peek_token()) {
                    LPAREN => {
                        try!(self.expect('('));
                        let e = try!(self.expr(1));
                        try!(self.expect(')'));
                        Ok(self.function(val,e))
                    }
                    SYMBOL(name) => {
                        match &val[..] {
                            "let" => {
                                try!(self.next_token());
                                try!(self.expect('='));
                                let expr = try!(self.expr(1));
                                Ok(Box::new( ast::Assignment { name: name, value: expr}))
                            }
                            _ => {
                                Err("Error: two consecutive symbols".to_string())
                            }
                        }
                   }
                   _ => {
                       Ok(Box::new( ast::Var { name: val }))
                   }
                }
            }
            a => {
                Err(format!("unrecognized atom: {:?}", a))
            }
        }
    }

    pub fn op (&self, op: token::Token, lhs: Box<ast::Node>, rhs: Box<ast::Node>)
            -> Box<ast::Node> {
        match op {
            ADD => {
                Box::new( ast::Add {
                    left: lhs,
                    right: rhs
                })
            }
            SUB => {
                Box::new( ast::Sub {
                    left: lhs,
                    right: rhs
                })
            }
            MUL => {
                Box::new( ast::Mul {
                    left: lhs,
                    right: rhs
                })
            }
            DIV => {
                Box::new( ast::Div {
                    left: lhs,
                    right: rhs
                })
            }
            CARET => {
                Box::new( ast::Pow {
                    base: lhs,
                    exponent: rhs
                })
            }
            o => {
                panic!("unrecognized op: {:?}", o);
            }
        }
    }

    pub fn function<'a>(&'a self, op: String, arg: Box<ast::Node>) -> Box<ast::Node> {
        match &op[..] {
            "sin" | "sine" => {
                Box::new( ast::Sin {
                    arg: arg
                })
            }
            "sqrt" | "SQRT" => {
                Box::new( ast::Sqrt {
                    arg: arg
                })
            }
            "cos" | "cosine" => {
                Box::new( ast::Cos {
                    arg: arg
                })
            }
            "print" => {
                Box::new( ast::Print {
                    arg: arg
                })
            }
            _ => {
                panic!("unrecognized function!");
            }
        }
    }
}

impl Parser {
    pub fn expect(&mut self, tok: char) -> Result<(), String> {
        try!(self.next_token());
        if self.current.to_char() != tok {
            return Err(format!("expected {:?} but found {}", tok, self.current.to_char()));
        }
        Ok(())
    }
    pub fn peek_token(&mut self) -> Result<token::Token, String> {
        if self.peeked.is_none() {
            self.peeked = Some(try!(self.lexer.next_token()));
        }
        Ok(self.peeked.clone().unwrap())
    }
    pub fn next_token(&mut self) -> Result<(), String> {
        match self.peeked {
            Some(ref mut pk) => {
                self.current = pk.clone();
            }
            None => {
                self.current = try!(self.lexer.next_token());
            }
        }
        self.peeked = None;
        Ok(())
    }
}
<|endoftext|>


<commit_before>use nom::{hex_digit};
use std::{str, i32};

// Temporarly use a f64 to represent JS numbers
type JSNumber = f64;

fn bytes_to_hex(bytes: &[u8]) -> JSNumber {
    // TODO: Fix this unwrap
    let string = str::from_utf8(bytes).unwrap();

    println!("SOMETHING !!! {} SOMETHING !!!", string);

    // TODO: Fix this unwrap
    // Rust does not support 0x in hexadecimal, so just skip it
    i32::from_str_radix(&string[2..], 16).unwrap() as JSNumber
}

named!(pub hex_digits_literal<&[u8], JSNumber>,
    map!(
        recognize!(
            tuple!(
                alt!(tag!("0x") | tag!("0X")),
                hex_digit,
                opt!(complete!(hex_digit))
            )
        ),
        bytes_to_hex
    )
);<commit_msg>Remove message<commit_after>use nom::{hex_digit};
use std::{str, i32};

// Temporarly use a f64 to represent JS numbers
type JSNumber = f64;

fn bytes_to_hex(bytes: &[u8]) -> JSNumber {
    // TODO: Fix this unwrap
    let string = str::from_utf8(bytes).unwrap();

    // TODO: Fix this unwrap
    // Rust does not support 0x in hexadecimal, so just skip it
    i32::from_str_radix(&string[2..], 16).unwrap() as JSNumber
}

named!(pub hex_digits_literal<&[u8], JSNumber>,
    map!(
        recognize!(
            tuple!(
                alt!(tag!("0x") | tag!("0X")),
                hex_digit,
                opt!(complete!(hex_digit))
            )
        ),
        bytes_to_hex
    )
);<|endoftext|>


<commit_before>// Copyright 2014 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.

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::ops::{Add, AddAssign, Deref};

use fmt;
use string::String;

use self::Cow::*;

#[stable(feature = "rust1", since = "1.0.0")]
pub use core::borrow::{Borrow, BorrowMut};

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B>
    where B: ToOwned,
          <B as ToOwned>::Owned: 'a
{
    fn borrow(&self) -> &B {
        &**self
    }
}

/// A generalization of `Clone` to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Creates owned data from borrowed data, usually by cloning.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let s = "a"; // &str
    /// let ss = s.to_owned(); // String
    ///
    /// let v = &[1, 2]; // slice
    /// let vv = v.to_owned(); // Vec
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T
    where T: Clone
{
    type Owned = T;
    fn to_owned(&self) -> T {
        self.clone()
    }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable reference to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // Clones into a vector if not already owned.
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
///
/// // No clone occurs because `input` doesn't need to be mutated.
/// let slice = [0, 1, 2];
/// let mut input = Cow::from(&slice[..]);
/// abs_all(&mut input);
///
/// // Clone occurs because `input` needs to be mutated.
/// let slice = [-1, 0, 1];
/// let mut input = Cow::from(&slice[..]);
/// abs_all(&mut input);
///
/// // No clone occurs because `input` is already owned.
/// let mut input = Cow::from(vec![-1, 0, 1]);
/// abs_all(&mut input);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a>
    where B: ToOwned
{
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(#[stable(feature = "rust1", since = "1.0.0")]
             &'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(#[stable(feature = "rust1", since = "1.0.0")]
          <B as ToOwned>::Owned),
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B>
    where B: ToOwned
{
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            }
        }
    }
}

impl<'a, B: ?Sized> Cow<'a, B>
    where B: ToOwned
{
    /// Acquires a mutable reference to the owned form of the data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.to_mut();
    ///
    /// assert_eq!(hello, &[1, 2, 3]);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                match *self {
                    Borrowed(..) => unreachable!(),
                    Owned(ref mut owned) => owned,
                }
            }
            Owned(ref mut owned) => owned,
        }
    }

    /// Extracts the owned data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.into_owned();
    ///
    /// assert_eq!(vec![1, 2, 3], hello);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B>
    where B: ToOwned
{
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow(),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B>
    where B: Ord + ToOwned
{
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B>
    where B: PartialEq<C> + ToOwned,
          C: ToOwned
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B>
    where B: PartialOrd + ToOwned
{
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B>
    where B: fmt::Debug + ToOwned,
          <B as ToOwned>::Owned: fmt::Debug
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B>
    where B: fmt::Display + ToOwned,
          <B as ToOwned>::Owned: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "default", since = "1.11.0")]
impl<'a, B: ?Sized> Default for Cow<'a, B>
    where B: ToOwned,
          <B as ToOwned>::Owned: Default
{
    /// Creates an owned Cow<'a, B> with the default value for the contained owned value.
    fn default() -> Cow<'a, B> {
        Owned(<B as ToOwned>::Owned::default())
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B>
    where B: Hash + ToOwned
{
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> Add<&'a str> for Cow<'a, str> {
    type Output = Cow<'a, str>;

    #[inline]
    fn add(mut self, rhs: &'a str) -> Self::Output {
        self += rhs;
        self
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> Add<Cow<'a, str>> for Cow<'a, str> {
    type Output = Cow<'a, str>;

    #[inline]
    fn add(mut self, rhs: Cow<'a, str>) -> Self::Output {
        self += rhs;
        self
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> AddAssign<&'a str> for Cow<'a, str> {
    fn add_assign(&mut self, rhs: &'a str) {
        if self.is_empty() {
            *self = Cow::Borrowed(rhs)
        } else if rhs.is_empty() {
            return;
        } else {
            if let Cow::Borrowed(lhs) = *self {
                let mut s = String::with_capacity(lhs.len() + rhs.len());
                s.push_str(lhs);
                *self = Cow::Owned(s);
            }
            self.to_mut().push_str(rhs);
        }
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> AddAssign<Cow<'a, str>> for Cow<'a, str> {
    fn add_assign(&mut self, rhs: Cow<'a, str>) {
        if self.is_empty() {
            *self = rhs
        } else if rhs.is_empty() {
            return;
        } else {
            if let Cow::Borrowed(lhs) = *self {
                let mut s = String::with_capacity(lhs.len() + rhs.len());
                s.push_str(lhs);
                *self = Cow::Owned(s);
            }
            self.to_mut().push_str(&rhs);
        }
    }
}
<commit_msg>fix types in to_owned doctest<commit_after>// Copyright 2014 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.

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::ops::{Add, AddAssign, Deref};

use fmt;
use string::String;

use self::Cow::*;

#[stable(feature = "rust1", since = "1.0.0")]
pub use core::borrow::{Borrow, BorrowMut};

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B>
    where B: ToOwned,
          <B as ToOwned>::Owned: 'a
{
    fn borrow(&self) -> &B {
        &**self
    }
}

/// A generalization of `Clone` to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Creates owned data from borrowed data, usually by cloning.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let s: &str = "a";
    /// let ss: String = s.to_owned();
    ///
    /// let v: &[i32] = &[1, 2];
    /// let vv: Vec<i32> = v.to_owned();
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T
    where T: Clone
{
    type Owned = T;
    fn to_owned(&self) -> T {
        self.clone()
    }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable reference to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // Clones into a vector if not already owned.
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
///
/// // No clone occurs because `input` doesn't need to be mutated.
/// let slice = [0, 1, 2];
/// let mut input = Cow::from(&slice[..]);
/// abs_all(&mut input);
///
/// // Clone occurs because `input` needs to be mutated.
/// let slice = [-1, 0, 1];
/// let mut input = Cow::from(&slice[..]);
/// abs_all(&mut input);
///
/// // No clone occurs because `input` is already owned.
/// let mut input = Cow::from(vec![-1, 0, 1]);
/// abs_all(&mut input);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a>
    where B: ToOwned
{
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(#[stable(feature = "rust1", since = "1.0.0")]
             &'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(#[stable(feature = "rust1", since = "1.0.0")]
          <B as ToOwned>::Owned),
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B>
    where B: ToOwned
{
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            }
        }
    }
}

impl<'a, B: ?Sized> Cow<'a, B>
    where B: ToOwned
{
    /// Acquires a mutable reference to the owned form of the data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.to_mut();
    ///
    /// assert_eq!(hello, &[1, 2, 3]);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                match *self {
                    Borrowed(..) => unreachable!(),
                    Owned(ref mut owned) => owned,
                }
            }
            Owned(ref mut owned) => owned,
        }
    }

    /// Extracts the owned data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.into_owned();
    ///
    /// assert_eq!(vec![1, 2, 3], hello);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B>
    where B: ToOwned
{
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow(),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B>
    where B: Ord + ToOwned
{
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B>
    where B: PartialEq<C> + ToOwned,
          C: ToOwned
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B>
    where B: PartialOrd + ToOwned
{
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B>
    where B: fmt::Debug + ToOwned,
          <B as ToOwned>::Owned: fmt::Debug
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B>
    where B: fmt::Display + ToOwned,
          <B as ToOwned>::Owned: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "default", since = "1.11.0")]
impl<'a, B: ?Sized> Default for Cow<'a, B>
    where B: ToOwned,
          <B as ToOwned>::Owned: Default
{
    /// Creates an owned Cow<'a, B> with the default value for the contained owned value.
    fn default() -> Cow<'a, B> {
        Owned(<B as ToOwned>::Owned::default())
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B>
    where B: Hash + ToOwned
{
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> Add<&'a str> for Cow<'a, str> {
    type Output = Cow<'a, str>;

    #[inline]
    fn add(mut self, rhs: &'a str) -> Self::Output {
        self += rhs;
        self
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> Add<Cow<'a, str>> for Cow<'a, str> {
    type Output = Cow<'a, str>;

    #[inline]
    fn add(mut self, rhs: Cow<'a, str>) -> Self::Output {
        self += rhs;
        self
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> AddAssign<&'a str> for Cow<'a, str> {
    fn add_assign(&mut self, rhs: &'a str) {
        if self.is_empty() {
            *self = Cow::Borrowed(rhs)
        } else if rhs.is_empty() {
            return;
        } else {
            if let Cow::Borrowed(lhs) = *self {
                let mut s = String::with_capacity(lhs.len() + rhs.len());
                s.push_str(lhs);
                *self = Cow::Owned(s);
            }
            self.to_mut().push_str(rhs);
        }
    }
}

#[stable(feature = "cow_add", since = "1.14.0")]
impl<'a> AddAssign<Cow<'a, str>> for Cow<'a, str> {
    fn add_assign(&mut self, rhs: Cow<'a, str>) {
        if self.is_empty() {
            *self = rhs
        } else if rhs.is_empty() {
            return;
        } else {
            if let Cow::Borrowed(lhs) = *self {
                let mut s = String::with_capacity(lhs.len() + rhs.len());
                s.push_str(lhs);
                *self = Cow::Owned(s);
            }
            self.to_mut().push_str(&rhs);
        }
    }
}
<|endoftext|>


<commit_before>use super::mode::{
    Mode,
};
use super::util;
use std::old_io as io;

pub use self::Doc::{
    Nil,
    Append,
    Group,
    Nest,
    Newline,
    Text,
};

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum Doc {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Group(Box<Doc>),
    Nest(u64, Box<Doc>),
    Newline,
    Text(String),
}

type Cmd<'a> = (u64, Mode, &'a Doc);

#[inline]
fn fitting<'a>(
       next: Cmd<'a>,
      bcmds: &Vec<Cmd<'a>>,
      fcmds: &mut Vec<Cmd<'a>>,
    mut rem: i64
) -> bool {
    let mut bidx = bcmds.len();
    let mut fits = true;

    fcmds.clear();      // clear from previous calls from best
    fcmds.push(next);

    loop {
        if rem < 0 {
            fits = false;
            break;
        }
        match fcmds.pop() {
            None => {
                if bidx == 0 {
                    break;
                } else {
                    fcmds.push(bcmds[ bidx - 1 ]);
                    bidx -= 1;
                }
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(ref ldoc, ref rdoc) => {
                    fcmds.push((ind, mode, rdoc));
                    fcmds.push((ind, mode, ldoc));
                },
                &Group(ref doc) => {
                    fcmds.push((ind, mode, doc));
                },
                &Nest(off, ref doc) => {
                    fcmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    fits = true;
                },
                &Text(ref str) => {
                    rem -= str.len() as i64;
                },
            }
        }
    }

    fits
}

#[inline]
pub fn best<W: io::Writer>(
      doc: &Doc,
    width: u64,
      out: &mut W
) -> io::IoResult<()> {
    let mut res   = Ok(());
    let mut pos   = 0;
    let mut bcmds = vec![(0, Mode::Break, doc)];
    let mut fcmds = vec![];

    while res.is_ok() {
        match bcmds.pop() {
            None => {
                break;
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(ref ldoc, ref rdoc) => {
                    bcmds.push((ind, mode, rdoc));
                    bcmds.push((ind, mode, ldoc));
                },
                &Group(ref doc) => match mode {
                    Mode::Flat => {
                        bcmds.push((ind, Mode::Flat, doc));
                    },
                    Mode::Break => {
                        let next = (ind, Mode::Flat, &**doc);
                        let rem  = width as i64 - pos as i64;
                        if fitting(next, &bcmds, &mut fcmds, rem) {
                            bcmds.push(next);
                        } else {
                            bcmds.push((ind, Mode::Break, doc));
                        }
                    }
                },
                &Nest(off, ref doc) => {
                    bcmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    res = out.write_str(&util::string::nl_spaces(ind as usize));
                    pos = ind;
                },
                &Text(ref s) => {
                    res = out.write_str(&s);
                    pos += s.len() as u64;
                },
            }
        }
    }

    res
}
<commit_msg>More formatting<commit_after>use super::mode::{
    Mode,
};
use super::util;
use std::old_io as io;

pub use self::Doc::{
    Nil,
    Append,
    Group,
    Nest,
    Newline,
    Text,
};

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum Doc {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Group(Box<Doc>),
    Nest(u64, Box<Doc>),
    Newline,
    Text(String),
}

type Cmd<'a> = (u64, Mode, &'a Doc);

#[inline]
fn fitting<'a>(
       next:          Cmd<'a>,
      bcmds: &    Vec<Cmd<'a>>,
      fcmds: &mut Vec<Cmd<'a>>,
    mut rem: i64
) -> bool {
    let mut bidx = bcmds.len();
    let mut fits = true;

    fcmds.clear();      // clear from previous calls from best
    fcmds.push(next);

    loop {
        if rem < 0 {
            fits = false;
            break;
        }
        match fcmds.pop() {
            None => {
                if bidx == 0 {
                    break;
                } else {
                    fcmds.push(bcmds[ bidx - 1 ]);
                    bidx -= 1;
                }
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(ref ldoc, ref rdoc) => {
                    fcmds.push((ind, mode, rdoc));
                    fcmds.push((ind, mode, ldoc));
                },
                &Group(ref doc) => {
                    fcmds.push((ind, mode, doc));
                },
                &Nest(off, ref doc) => {
                    fcmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    fits = true;
                },
                &Text(ref str) => {
                    rem -= str.len() as i64;
                },
            }
        }
    }

    fits
}

#[inline]
pub fn best<W: io::Writer>(
      doc: &Doc,
    width: u64,
      out: &mut W
) -> io::IoResult<()> {
    let mut res   = Ok(());
    let mut pos   = 0;
    let mut bcmds = vec![(0, Mode::Break, doc)];
    let mut fcmds = vec![];

    while res.is_ok() {
        match bcmds.pop() {
            None => {
                break;
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(ref ldoc, ref rdoc) => {
                    bcmds.push((ind, mode, rdoc));
                    bcmds.push((ind, mode, ldoc));
                },
                &Group(ref doc) => match mode {
                    Mode::Flat => {
                        bcmds.push((ind, Mode::Flat, doc));
                    },
                    Mode::Break => {
                        let next = (ind, Mode::Flat, &**doc);
                        let rem  = width as i64 - pos as i64;
                        if fitting(next, &bcmds, &mut fcmds, rem) {
                            bcmds.push(next);
                        } else {
                            bcmds.push((ind, Mode::Break, doc));
                        }
                    }
                },
                &Nest(off, ref doc) => {
                    bcmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    res = out.write_str(&util::string::nl_spaces(ind as usize));
                    pos = ind;
                },
                &Text(ref s) => {
                    res  = out.write_str(&s);
                    pos += s.len() as u64;
                },
            }
        }
    }

    res
}
<|endoftext|>


<commit_before>#![feature(test)]
extern crate test;
extern crate rand_jitter;

use test::Bencher;
use rand_jitter::rand_core::RngCore;

#[bench]
fn bench_add_two(b: &mut Bencher) {
    let mut rng = rand_jitter::JitterRng::new().unwrap();
    let mut buf = [0u8; 1024];
    b.iter(|| {
        rng.fill_bytes(&mut buf[..]);
        test::black_box(&buf);
    });
    b.bytes = buf.len() as u64;
}

<commit_msg>rand_jitter: Fix benchmark for no_std<commit_after>#![feature(test)]
#![cfg(std)]
extern crate test;
extern crate rand_jitter;

use test::Bencher;
use rand_jitter::rand_core::RngCore;

#[bench]
fn bench_add_two(b: &mut Bencher) {
    let mut rng = rand_jitter::JitterRng::new().unwrap();
    let mut buf = [0u8; 1024];
    b.iter(|| {
        rng.fill_bytes(&mut buf[..]);
        test::black_box(&buf);
    });
    b.bytes = buf.len() as u64;
}

<|endoftext|>


<commit_before>use std::iter::FromIterator;

#[derive(Clone, Debug)]
pub struct Plugboard {
    mapping: Vec<char>,
}

impl Plugboard {
    pub fn new(pairs: &str) -> Plugboard {
        let alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        let mut mapping = Vec::from_iter(alpha.chars());

        for pair in pairs.split_whitespace() {
            let a = pair.chars().nth(0).unwrap();
            let b = pair.chars().nth(1).unwrap();

            mapping[a as usize - 65] = b;
            mapping[b as usize - 65] = a;
        }

        Plugboard {
            mapping: mapping,
        }
    }

    pub fn map(&self, c: char) -> char {
        self.mapping[c as usize - 65]
    }
}

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

    #[test]
    fn no_connections() {
        let plugboard = Plugboard::new("");
        assert_eq!(plugboard.map('A'), 'A');
    }

    #[test]
    fn single_connection() {
        let plugboard = Plugboard::new("AB");
        assert_eq!(plugboard.map('A'), 'B');
        assert_eq!(plugboard.map('B'), 'A');
        assert_eq!(plugboard.map('C'), 'C');
    }

    #[test]
    fn multiple_connections() {
        let plugboard = Plugboard::new("AB CD");
        assert_eq!(plugboard.map('A'), 'B');
        assert_eq!(plugboard.map('B'), 'A');
        assert_eq!(plugboard.map('C'), 'D');
        assert_eq!(plugboard.map('E'), 'E');
    }
}
<commit_msg>Use CharIndex trait in plugboard module<commit_after>use std::iter::FromIterator;

use super::CharIndex;

#[derive(Clone, Debug)]
pub struct Plugboard {
    mapping: Vec<char>,
}

impl Plugboard {
    pub fn new(pairs: &str) -> Plugboard {
        let alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        let mut mapping = Vec::from_iter(alpha.chars());

        for pair in pairs.split_whitespace() {
            let a = pair.chars().nth(0).unwrap();
            let b = pair.chars().nth(1).unwrap();

            mapping[a.index()] = b;
            mapping[b.index()] = a;
        }

        Plugboard {
            mapping: mapping,
        }
    }

    pub fn map(&self, c: char) -> char {
        self.mapping[c.index()]
    }
}

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

    #[test]
    fn no_connections() {
        let plugboard = Plugboard::new("");
        assert_eq!(plugboard.map('A'), 'A');
    }

    #[test]
    fn single_connection() {
        let plugboard = Plugboard::new("AB");
        assert_eq!(plugboard.map('A'), 'B');
        assert_eq!(plugboard.map('B'), 'A');
        assert_eq!(plugboard.map('C'), 'C');
    }

    #[test]
    fn multiple_connections() {
        let plugboard = Plugboard::new("AB CD");
        assert_eq!(plugboard.map('A'), 'B');
        assert_eq!(plugboard.map('B'), 'A');
        assert_eq!(plugboard.map('C'), 'D');
        assert_eq!(plugboard.map('E'), 'E');
    }
}
<|endoftext|>


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

#[derive(Clone, Debug)]
pub struct Plugboard {
    mapping: HashMap<char, char>,
}

impl Plugboard {
    pub fn new(pairs: &str) -> Plugboard {
        let mut mapping = HashMap::new();

        for pair in pairs.split_whitespace() {
            let a = pair.chars().nth(0).unwrap();
            let b = pair.chars().nth(1).unwrap();
            mapping.insert(a, b);
            mapping.insert(b, a);
        }

        Plugboard {
            mapping: mapping,
        }
    }

    pub fn map(&self, c: char) -> char {
        *self.mapping.get(&c).unwrap_or(&c)
    }
}

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

    #[test]
    fn plugboard_map() {
        let plugboard = Plugboard::new("AB CD");
        assert_eq!(plugboard.map('A'), 'B');
        assert_eq!(plugboard.map('B'), 'A');
        assert_eq!(plugboard.map('C'), 'D');
        assert_eq!(plugboard.map('E'), 'E');
        assert_eq!(plugboard.map(' '), ' ');
    }
}
<commit_msg>Store plugboard mapping as vector<commit_after>use std::iter::FromIterator;

#[derive(Clone, Debug)]
pub struct Plugboard {
    mapping: Vec<char>,
}

impl Plugboard {
    pub fn new(pairs: &str) -> Plugboard {
        let alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        let mut mapping = Vec::from_iter(alpha.chars());

        for pair in pairs.split_whitespace() {
            let a = pair.chars().nth(0).unwrap();
            let b = pair.chars().nth(1).unwrap();

            mapping[a as usize - 65] = b;
            mapping[b as usize - 65] = a;
        }

        Plugboard {
            mapping: mapping,
        }
    }

    pub fn map(&self, c: char) -> char {
        self.mapping[c as usize - 65]
    }
}

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

    #[test]
    fn plugboard_map() {
        let plugboard = Plugboard::new("AB CD");
        assert_eq!(plugboard.map('A'), 'B');
        assert_eq!(plugboard.map('B'), 'A');
        assert_eq!(plugboard.map('C'), 'D');
        assert_eq!(plugboard.map('E'), 'E');
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::iter;

use crate::pp::utils::*;
use crate::pp::PrettyPrinter;
use crate::prelude::*;

pub struct ErlangPrettyPrinter {
    indent_width: usize,
    max_terms_per_line: usize,
    terminator: &'static str,
}

impl PrettyPrinter for ErlangPrettyPrinter {
    fn write(&self, term: &BertTerm, mut w: Box<dyn io::Write>) -> Result<()> {
        self.write_term(term, &mut w, 0)?;
        writeln!(w, "{}", self.terminator)?;
        return Ok(());
    }
}

impl ErlangPrettyPrinter {
    /// Creates a pretty printer for `term` where sub-terms
    /// are indented with a width of `indent_width` and a
    /// maximum of `max_terms_per_line` basic terms (i.e.,
    /// integers, floats, strings) can be printed per line.
    pub fn new(indent_width: usize, max_terms_per_line: usize, terminator: &'static str) -> Self {
        ErlangPrettyPrinter {
            indent_width,
            max_terms_per_line,
            terminator,
        }
    }

    fn write_term<W: io::Write>(&self, term: &BertTerm, w: &mut W, depth: usize) -> io::Result<()> {
        match *term {
            BertTerm::Nil => w.write_all(b"[]"),
            BertTerm::Int(n) => itoa::write(w, n).map(|_| ()),
            BertTerm::BigInt(ref n) => write!(w, "{}", n),
            BertTerm::Float(x) => {
                let mut buf = ryu::Buffer::new();
                w.write_all(buf.format(x).as_bytes())
            }
            BertTerm::Atom(ref s) => w.write_all(s.as_bytes()),
            BertTerm::String(ref bytes) => self.write_string(bytes, w, b"\"", b"\""),
            BertTerm::Binary(ref bytes) => self.write_string(bytes, w, b"<<\"", b"\">>"),
            BertTerm::List(ref terms) => self.write_collection(terms, w, depth, b"[", b"]"),
            BertTerm::Tuple(ref terms) => self.write_collection(terms, w, depth, b"{", b"}"),
            BertTerm::Map(ref keys, ref vals) => self.write_map(keys, vals, w, depth),
        }
    }

    fn write_string<W: io::Write>(
        &self,
        bytes: &[u8],
        w: &mut W,
        open: &[u8],
        close: &[u8],
    ) -> io::Result<()> {
        let mut start = 0;
        w.write_all(open)?;

        for (i, &b) in bytes.iter().enumerate() {
            if must_be_escaped(b) {
                w.write_all(&bytes[start..i])?;
                start = i + 1;
                write!(w, "\\{}", b as char)?;
            } else if !is_printable(b) {
                w.write_all(&bytes[start..i])?;
                start = i + 1;
                write!(w, "\\x{:02x}", b)?;
            }
        }

        // Write remaining bytes
        w.write_all(&bytes[start..])?;
        w.write_all(close)
    }

    fn write_collection<W: io::Write>(
        &self,
        terms: &[BertTerm],
        w: &mut W,
        depth: usize,
        open: &[u8],
        close: &[u8],
    ) -> io::Result<()> {
        let multi_line = !self.is_small_collection(terms);

        // Every element will have the same indentation,
        // so pre-compute it once.
        let prefix = if multi_line {
            self.indentation(depth + 1)
        } else {
            String::new()
        };

        w.write_all(open)?;
        let mut comma = "";
        for t in terms {
            w.write_all(comma.as_bytes())?;
            w.write_all(prefix.as_bytes())?;
            self.write_term(t, w, depth + 1)?;
            comma = ", ";
        }

        if multi_line {
            w.write_all(&self.indentation(depth).as_bytes())?;
        }

        w.write_all(close)
    }

    fn write_map<W: io::Write>(
        &self,
        keys: &[BertTerm],
        vals: &[BertTerm],
        w: &mut W,
        depth: usize,
    ) -> io::Result<()> {
        let multi_line = !self.is_small_collection(keys) || !self.is_small_collection(vals);
        let prefix = if multi_line {
            self.indentation(depth + 1)
        } else {
            String::new()
        };

        w.write_all(b"#{")?;
        let mut comma = "";
        for i in 0..keys.len() {
            w.write_all(comma.as_bytes())?;
            w.write_all(prefix.as_bytes())?;
            self.write_term(&keys[i], w, depth + 1)?;
            w.write_all(b" => ")?;
            self.write_term(&vals[i], w, depth + 1)?;
            comma = ", ";
        }

        if multi_line {
            w.write_all(&self.indentation(depth).as_bytes())?;
        }
        w.write_all(b"}")
    }

    fn is_small_collection(&self, terms: &[BertTerm]) -> bool {
        terms.len() <= self.max_terms_per_line && terms.iter().all(BertTerm::is_basic)
    }

    fn indentation(&self, depth: usize) -> String {
        let nl = iter::once('\n');
        let spaces = iter::repeat(' ').take(depth * self.indent_width);
        nl.chain(spaces).collect()
    }
}
<commit_msg>Improve performance of ErlangPrettyPrinter::indentation<commit_after>use std::io;

use crate::pp::utils::*;
use crate::pp::PrettyPrinter;
use crate::prelude::*;

const SPACES: [u8; 4096] = [b' '; 4096];

pub struct ErlangPrettyPrinter {
    indent_width: usize,
    max_terms_per_line: usize,
    terminator: &'static str,
}

impl PrettyPrinter for ErlangPrettyPrinter {
    fn write(&self, term: &BertTerm, mut w: Box<dyn io::Write>) -> Result<()> {
        self.write_term(term, &mut w, 0)?;
        writeln!(w, "{}", self.terminator)?;
        return Ok(());
    }
}

impl ErlangPrettyPrinter {
    /// Creates a pretty printer for `term` where sub-terms
    /// are indented with a width of `indent_width` and a
    /// maximum of `max_terms_per_line` basic terms (i.e.,
    /// integers, floats, strings) can be printed per line.
    pub fn new(indent_width: usize, max_terms_per_line: usize, terminator: &'static str) -> Self {
        ErlangPrettyPrinter {
            indent_width,
            max_terms_per_line,
            terminator,
        }
    }

    fn write_term<W: io::Write>(&self, term: &BertTerm, w: &mut W, depth: usize) -> io::Result<()> {
        match *term {
            BertTerm::Nil => w.write_all(b"[]"),
            BertTerm::Int(n) => itoa::write(w, n).map(|_| ()),
            BertTerm::BigInt(ref n) => write!(w, "{}", n),
            BertTerm::Float(x) => {
                let mut buf = ryu::Buffer::new();
                w.write_all(buf.format(x).as_bytes())
            }
            BertTerm::Atom(ref s) => w.write_all(s.as_bytes()),
            BertTerm::String(ref bytes) => self.write_string(bytes, w, b"\"", b"\""),
            BertTerm::Binary(ref bytes) => self.write_string(bytes, w, b"<<\"", b"\">>"),
            BertTerm::List(ref terms) => self.write_collection(terms, w, depth, b"[", b"]"),
            BertTerm::Tuple(ref terms) => self.write_collection(terms, w, depth, b"{", b"}"),
            BertTerm::Map(ref keys, ref vals) => self.write_map(keys, vals, w, depth),
        }
    }

    fn write_string<W: io::Write>(
        &self,
        bytes: &[u8],
        w: &mut W,
        open: &[u8],
        close: &[u8],
    ) -> io::Result<()> {
        let mut start = 0;
        w.write_all(open)?;

        for (i, &b) in bytes.iter().enumerate() {
            if must_be_escaped(b) {
                w.write_all(&bytes[start..i])?;
                start = i + 1;
                write!(w, "\\{}", b as char)?;
            } else if !is_printable(b) {
                w.write_all(&bytes[start..i])?;
                start = i + 1;
                write!(w, "\\x{:02x}", b)?;
            }
        }

        // Write remaining bytes
        w.write_all(&bytes[start..])?;
        w.write_all(close)
    }

    fn write_collection<W: io::Write>(
        &self,
        terms: &[BertTerm],
        w: &mut W,
        depth: usize,
        open: &[u8],
        close: &[u8],
    ) -> io::Result<()> {
        let multi_line = !self.is_small_collection(terms);

        // Every element will have the same indentation,
        // so pre-compute it once.
        let prefix = if multi_line {
            self.indentation(depth + 1)
        } else {
            &[]
        };

        w.write_all(open)?;
        let mut comma: &[u8] = b"";
        for t in terms {
            w.write_all(comma)?;
            w.write_all(prefix)?;
            self.write_term(t, w, depth + 1)?;
            comma = b", ";
        }

        if multi_line {
            w.write_all(&self.indentation(depth))?;
        }

        w.write_all(close)
    }

    fn write_map<W: io::Write>(
        &self,
        keys: &[BertTerm],
        vals: &[BertTerm],
        w: &mut W,
        depth: usize,
    ) -> io::Result<()> {
        let multi_line = !self.is_small_collection(keys) || !self.is_small_collection(vals);
        let prefix = if multi_line {
            self.indentation(depth + 1)
        } else {
            &[]
        };

        w.write_all(b"#{")?;
        let mut comma: &[u8] = b"";
        for i in 0..keys.len() {
            w.write_all(comma)?;
            w.write_all(prefix)?;
            self.write_term(&keys[i], w, depth + 1)?;
            w.write_all(b" => ")?;
            self.write_term(&vals[i], w, depth + 1)?;
            comma = b", ";
        }

        if multi_line {
            w.write_all(&self.indentation(depth))?;
        }
        w.write_all(b"}")
    }

    fn is_small_collection(&self, terms: &[BertTerm]) -> bool {
        terms.len() <= self.max_terms_per_line && terms.iter().all(BertTerm::is_basic)
    }

    fn indentation(&self, depth: usize) -> &[u8] {
        let n = usize::min(SPACES.len(), depth * self.indent_width);
        return &SPACES[..n];
    }
}
<|endoftext|>


<commit_before>//! A Module for accessing Blizzard's WoW API.
//! The exposed functionality of this module has been structured
//! around the particular needs of blood-money: Not all fields are
//! represented and it's probably not generally useful.
//! TODO: Add support for locales.
extern crate hyper;
extern crate serde_json;

use std::collections::BTreeMap;
use std::io::Read;
use std::time::Duration;

use hyper::client::{Client, Response};
use rustc_serialize::{Decodable, json};
use serde::de::Deserialize;
use thread_throttler::ThreadThrottler;

/// The content we care about in the realm status response.
#[derive(Debug, Serialize, Deserialize, RustcDecodable)]
pub struct RealmInfo {
    pub name: String,
    pub slug: String,
    pub connected_realms: Vec<String>,
}

/// Content we care about in an item info response.
#[derive(Debug, Deserialize, RustcDecodable)]
pub struct ItemInfo {
    pub id: u64,
    pub name: String,
    pub icon: String,
}

/// Represents the reply from blizzard's auction data urls.
#[derive(Debug, Deserialize, RustcDecodable)]
struct AuctionListingsReply {
    realms: Vec<BTreeMap<String, String>>,  // Can't re-use RealmInfo because no connected_realms.
    auctions: Vec<AuctionListing>,
}

/// Represents the JSON reply from the auction data status endpoint.
#[derive(Debug, Deserialize, RustcDecodable)]
#[allow(non_snake_case)]
struct AuctionDataPointer {
    url: String,
    lastModified: u64,
}

#[derive(Debug, Deserialize, RustcDecodable)]
struct AuctionDataReply {
    files: Vec<AuctionDataPointer>, // Will always be 1 element.
}

/// The fields we care about in blizzard's auction reply.
#[derive(Debug, Deserialize, RustcDecodable)]
pub struct AuctionListing {
    pub item: u64,
    pub buyout: u64,
    pub quantity: u64,
}

pub struct BattleNetApiClient {
    pub token: String,
    client: Client,
    tt: ThreadThrottler,
}

impl BattleNetApiClient {
    pub fn new(token: &str) -> BattleNetApiClient {
        BattleNetApiClient {
            token: token.to_owned(),
            client: Client::new(),
            tt: ThreadThrottler::new(100, Duration::new(1, 0)),
        }
    }

    /// Try to retrieve something from the Blizzard API. Will retry indefinitely.
    /// Returns the body as a String.
    /// `task` will be used for error messages.
    /// TODO: Really this should try to decode the json as well and be type
    /// inferred from context.
    fn make_blizzard_api_call<T: Decodable>(&self, url: &str, task: &str) -> T {
        let mut s = String::new();
        let mut retries = 0;

        loop {
            let mut res: Response;
            retries += 1;

            self.tt.pass_through_or_block();
            match self.client.get(url).send() {
                Ok(r) => res = r,
                Err(e) => {
                    println!("Error downloading {}: {}. Retry {}.", task, e, retries);
                    continue;
                },
            }
            // TODO: 404 should really be handled differently here. Maybe make this return a Result<T>?
            // That would let us account for unrecoverable errors.
            if res.status != hyper::Ok {
                println!("Error downloading {}: {}. Retry {}.", task, res.status, retries);
                continue;
            }
            match res.read_to_string(&mut s) {
                Ok(_) => (),
                Err(e) => {
                    println!("Failed to process {}: {}. Retry {}.", task, e, retries);
                    continue;
                },
            }
            // TODO: Fix this file to use serde instead.
            //Sometimes the auction listings contain invalid unicode. Strip that:
            // s = String::from_utf8_lossy(s.as_bytes()).into_owned();
            // But even then, we're getting json errors. Until we solve that, use
            // rustc_serialize.
            match json::decode(&s) {
                Ok(obj) => return obj,
                Err(e) => {
                    println!("Failed to decode json for {}: {}. Retry {}.", task, e, retries);
                },
            }
        }
    }

    /// Downloads a list of realms from the Blizzard API.
    pub fn get_realms(&self) -> Vec<RealmInfo> {
        let mut realm_data: BTreeMap<String, Vec<RealmInfo>> =
            self.make_blizzard_api_call(&format!("https://eu.api.battle.net/wow/realm/status?locale=en_GB&apikey={}", self.token), "realm status");
        realm_data.remove("realms").expect("Malformed realm response.")
    }

    /// Downloads the auction listings for the specified realm, or None if the listings haven't
    /// been updated since `cutoff`.
    pub fn get_auction_listings(&self, realm_slug: &str, cutoff: u64) -> Option<(u64, Vec<AuctionListing>)> {
        let mut auction_data_reply: AuctionDataReply =
            self.make_blizzard_api_call(
                &format!("https://eu.api.battle.net/wow/auction/data/{}?locale=en_GB&apikey={}", realm_slug, self.token),
                &format!("auction data for {}", realm_slug)
            );
        let auction_data_pointer = auction_data_reply.files.pop().unwrap();
        if auction_data_pointer.lastModified <= cutoff {
            return None
        }
        let auction_listings_data: AuctionListingsReply =
            self.make_blizzard_api_call(&auction_data_pointer.url, &format!("auction listings for {}", realm_slug));
        Some((auction_data_pointer.lastModified, auction_listings_data.auctions))
    }

    /// Helpler function to process a vec of RealmInfo's into vec's of slugs for
    /// connected realms. Connected realms share an auction house.
    pub fn process_connected_realms(realm_infos: &Vec<RealmInfo>) -> Vec<Vec<String>> {
        let mut realm_sets: Vec<Vec<String>> = realm_infos.into_iter().map(|r|
            r.connected_realms.clone()
        ).collect();

        // This dedup logic relies on the ordering within a connected realms list being the same
        // for all realms in the list.
        realm_sets.sort_by(|a, b| a.iter().next().unwrap().cmp(b.iter().next().unwrap()));
        realm_sets.dedup();
        return realm_sets;
    }

    pub fn get_item_info(&self, id: u64) -> ItemInfo {
        self.make_blizzard_api_call::<ItemInfo>(&format!("https://eu.api.battle.net/wow/item/{}?locale=en_GB&apikey={}", id, self.token), "item info")
    }
}
<commit_msg>Add some utf-8 stripping<commit_after>//! A Module for accessing Blizzard's WoW API.
//! The exposed functionality of this module has been structured
//! around the particular needs of blood-money: Not all fields are
//! represented and it's probably not generally useful.
//! TODO: Add support for locales.
extern crate hyper;
extern crate serde_json;

use std::collections::BTreeMap;
use std::io::Read;
use std::time::Duration;

use hyper::client::{Client, Response};
use rustc_serialize::{Decodable, json};
use serde::de::Deserialize;
use thread_throttler::ThreadThrottler;

/// The content we care about in the realm status response.
#[derive(Debug, Serialize, Deserialize, RustcDecodable)]
pub struct RealmInfo {
    pub name: String,
    pub slug: String,
    pub connected_realms: Vec<String>,
}

/// Content we care about in an item info response.
#[derive(Debug, Deserialize, RustcDecodable)]
pub struct ItemInfo {
    pub id: u64,
    pub name: String,
    pub icon: String,
}

/// Represents the reply from blizzard's auction data urls.
#[derive(Debug, Deserialize, RustcDecodable)]
struct AuctionListingsReply {
    realms: Vec<BTreeMap<String, String>>,  // Can't re-use RealmInfo because no connected_realms.
    auctions: Vec<AuctionListing>,
}

/// Represents the JSON reply from the auction data status endpoint.
#[derive(Debug, Deserialize, RustcDecodable)]
#[allow(non_snake_case)]
struct AuctionDataPointer {
    url: String,
    lastModified: u64,
}

#[derive(Debug, Deserialize, RustcDecodable)]
struct AuctionDataReply {
    files: Vec<AuctionDataPointer>, // Will always be 1 element.
}

/// The fields we care about in blizzard's auction reply.
#[derive(Debug, Deserialize, RustcDecodable)]
pub struct AuctionListing {
    pub item: u64,
    pub buyout: u64,
    pub quantity: u64,
}

pub struct BattleNetApiClient {
    pub token: String,
    client: Client,
    tt: ThreadThrottler,
}

impl BattleNetApiClient {
    pub fn new(token: &str) -> BattleNetApiClient {
        BattleNetApiClient {
            token: token.to_owned(),
            client: Client::new(),
            tt: ThreadThrottler::new(100, Duration::new(1, 0)),
        }
    }

    /// Try to retrieve something from the Blizzard API. Will retry indefinitely.
    /// Returns the body as a String.
    /// `task` will be used for error messages.
    /// TODO: Add an option to strip non-ascii entirely? i.e. If `zealous_clean` is true,
    /// then extra effort will be made to strip non-ascii characters from the json before decoding it.
    fn make_blizzard_api_call<T: Decodable>(&self, url: &str, task: &str) -> T {
        let mut s = String::new();
        let mut retries = 0;

        loop {
            let mut res: Response;
            retries += 1;

            self.tt.pass_through_or_block();
            match self.client.get(url).send() {
                Ok(r) => res = r,
                Err(e) => {
                    println!("Error downloading {}: {}. Retry {}.", task, e, retries);
                    continue;
                },
            }
            // TODO: 404 should really be handled differently here. Maybe make this return a Result<T>?
            // That would let us account for unrecoverable errors.
            if res.status != hyper::Ok {
                println!("Error downloading {}: {}. Retry {}.", task, res.status, retries);
                continue;
            }
            match res.read_to_string(&mut s) {
                Ok(_) => (),
                Err(e) => {
                    println!("Failed to process {}: {}. Retry {}.", task, e, retries);
                    continue;
                },
            }
            // TODO: Fix this file to use serde instead.
            //Sometimes the auction listings contain invalid unicode. Strip that:
            // s = String::from_utf8_lossy(s.as_bytes()).into_owned();
            // But even then, we're getting json errors. Until we solve that, use
            // rustc_serialize.
            s = String::from_utf8_lossy(s.as_bytes()).into_owned();
            match json::decode(&s) {
                Ok(obj) => return obj,
                Err(e) => {
                    println!("Failed to decode json for {}: {}. Retry {}.", task, e, retries);
                },
            }
        }
    }

    /// Downloads a list of realms from the Blizzard API.
    pub fn get_realms(&self) -> Vec<RealmInfo> {
        let mut realm_data: BTreeMap<String, Vec<RealmInfo>> =
            self.make_blizzard_api_call(&format!("https://eu.api.battle.net/wow/realm/status?locale=en_GB&apikey={}", self.token), "realm status");
        realm_data.remove("realms").expect("Malformed realm response.")
    }

    /// Downloads the auction listings for the specified realm, or None if the listings haven't
    /// been updated since `cutoff`.
    pub fn get_auction_listings(&self, realm_slug: &str, cutoff: u64) -> Option<(u64, Vec<AuctionListing>)> {
        let mut auction_data_reply: AuctionDataReply =
            self.make_blizzard_api_call(
                &format!("https://eu.api.battle.net/wow/auction/data/{}?locale=en_GB&apikey={}", realm_slug, self.token),
                &format!("auction data for {}", realm_slug)
            );
        let auction_data_pointer = auction_data_reply.files.pop().unwrap();
        if auction_data_pointer.lastModified <= cutoff {
            return None
        }
        let auction_listings_data: AuctionListingsReply =
            self.make_blizzard_api_call(&auction_data_pointer.url, &format!("auction listings for {}", realm_slug));
        Some((auction_data_pointer.lastModified, auction_listings_data.auctions))
    }

    /// Helpler function to process a vec of RealmInfo's into vec's of slugs for
    /// connected realms. Connected realms share an auction house.
    pub fn process_connected_realms(realm_infos: &Vec<RealmInfo>) -> Vec<Vec<String>> {
        let mut realm_sets: Vec<Vec<String>> = realm_infos.into_iter().map(|r|
            r.connected_realms.clone()
        ).collect();

        // This dedup logic relies on the ordering within a connected realms list being the same
        // for all realms in the list.
        realm_sets.sort_by(|a, b| a.iter().next().unwrap().cmp(b.iter().next().unwrap()));
        realm_sets.dedup();
        return realm_sets;
    }

    pub fn get_item_info(&self, id: u64) -> ItemInfo {
        self.make_blizzard_api_call::<ItemInfo>(&format!("https://eu.api.battle.net/wow/item/{}?locale=en_GB&apikey={}", id, self.token), "item info")
    }
}
<|endoftext|>