<commit_before>

use EventLoopHandle;

use std::io::Error as IoError;
use std::io::Write;
use std::os::raw::{c_int, c_void};

use std::os::unix::io::RawFd;
use wayland_sys::server::*;

// fd_event_source
//

/// A handle to a registered FD event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct FdEventSource {
    ptr: *mut wl_event_source,
    _data: Box<(*mut c_void, *mut EventLoopHandle)>,
}

bitflags!{
    /// Flags to register interest on a file descriptor
    pub struct FdInterest: u32 {
        /// Interest to be notified when the file descriptor is readable
        const READ  = 0x01;
        /// Interest to be notified when the file descriptor is writable
        const WRITE = 0x02;
    }
}

pub fn make_fd_event_source(ptr: *mut wl_event_source, data: Box<(*mut c_void, *mut EventLoopHandle)>)
                            -> FdEventSource {
    FdEventSource {
        ptr: ptr,
        _data: data,
    }
}

impl FdEventSource {
    /// Change the registered interest for this FD
    pub fn update_mask(&mut self, mask: FdInterest) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_event_source_fd_update,
                self.ptr,
                mask.bits()
            );
        }
    }

    /// Remove this event source from its event loop
    pub fn remove(self) {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
        }
    }
}

/// Trait for handlers for FD events
pub trait FdEventSourceHandler {
    /// The FD is ready to be read/written
    ///
    /// Details of the capability state are given as argument.
    fn ready(&mut self, evlh: &mut EventLoopHandle, fd: RawFd, mask: FdInterest);
    /// An error occured with this FD
    ///
    /// Most likely it won't be usable any longer
    fn error(&mut self, evlh: &mut EventLoopHandle, fd: RawFd, error: IoError);
}

pub unsafe extern "C" fn event_source_fd_dispatcher<H>(fd: c_int, mask: u32, data: *mut c_void) -> c_int
where
    H: FdEventSourceHandler,
{
    // 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 || {
        let (handler_ptr, evlh_ptr) = *(data as *mut (*mut c_void, *mut EventLoopHandle));
        let handler = &mut *(handler_ptr as *mut H);
        let evlh = &mut *(evlh_ptr);
        if mask & 0x04 > 0 {
            // EPOLLERR
            use nix::sys::socket;
            let err = match socket::getsockopt(fd, socket::sockopt::SocketError) {
                Ok(err) => err,
                Err(_) => {
                    // error while retrieving the error code ???
                    let _ = write!(
                        ::std::io::stderr(),
                        "[wayland-server error] Error while retrieving error code on socket {}, aborting.",
                        fd
                    );
                    ::libc::abort();
                }
            };
            handler.error(evlh, fd, IoError::from_raw_os_error(err));
        } else if mask & 0x03 > 0 {
            // EPOLLHUP
            handler.error(
                evlh,
                fd,
                IoError::new(::std::io::ErrorKind::ConnectionAborted, ""),
            )
        } else {
            let mut bits = FdInterest::empty();
            if mask & 0x02 > 0 {
                bits = bits | WRITE;
            }
            if mask & 0x01 > 0 {
                bits = bits | READ;
            }
            handler.ready(evlh, fd, bits)
        }
    });
    match ret {
        Ok(()) => return 0,   // all went well
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for fd {} event source panicked, aborting.",
                fd
            );
            ::libc::abort();
        }
    }
}

// timer_event_source
//

/// A handle to a registered timer event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct TimerEventSource {
    ptr: *mut wl_event_source,
    _data: Box<(*mut c_void, *mut EventLoopHandle)>,
}

pub fn make_timer_event_source(ptr: *mut wl_event_source, data: Box<(*mut c_void, *mut EventLoopHandle)>)
                               -> TimerEventSource {
    TimerEventSource {
        ptr: ptr,
        _data: data,
    }
}

impl TimerEventSource {
    /// Set the delay of this timer
    ///
    /// The handler will be called during the next dispatch of the
    /// event loop after this time (in milliseconds) is elapsed.
    pub fn set_delay_ms(&mut self, delay: i32) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_event_source_timer_update,
                self.ptr,
                delay
            );
        }
    }

    /// Remove this event source from its event loop
    pub fn remove(self) {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
        }
    }
}

/// Trait for handlers for timer event sources
pub trait TimerEventSourceHandler {
    /// The countdown has reached zero
    fn timeout(&mut self, evlh: &mut EventLoopHandle);
}

pub unsafe extern "C" fn event_source_timer_dispatcher<H>(data: *mut c_void) -> c_int
where
    H: TimerEventSourceHandler,
{
    // 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 || {
        let (handler_ptr, evlh_ptr) = *(data as *mut (*mut c_void, *mut EventLoopHandle));
        let handler = &mut *(handler_ptr as *mut H);
        let evlh = &mut *(evlh_ptr);
        handler.timeout(evlh);
    });
    match ret {
        Ok(()) => return 0,   // all went well
        Err(_) => {
            // a panic occured
            let _ =
                write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}

// signal_event_source
//

/// A handle to a registered signal event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct SignalEventSource {
    ptr: *mut wl_event_source,
    _data: Box<(*mut c_void, *mut EventLoopHandle)>,
}

pub fn make_signal_event_source(ptr: *mut wl_event_source, data: Box<(*mut c_void, *mut EventLoopHandle)>)
                                -> SignalEventSource {
    SignalEventSource {
        ptr: ptr,
        _data: data,
    }
}

impl SignalEventSource {
    /// Remove this event source from its event loop
    pub fn remove(self) {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
        }
    }
}

/// Trait for handlers of signal event sources
pub trait SignalEventSourceHandler {
    /// A signal has been received
    ///
    /// The signal number is given has argument
    fn signal(&mut self, evlh: &mut EventLoopHandle, signal: ::nix::sys::signal::Signal);
}

pub unsafe extern "C" fn event_source_signal_dispatcher<H>(signal: c_int, data: *mut c_void) -> c_int
where
    H: SignalEventSourceHandler,
{
    // 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 || {
        let (handler_ptr, evlh_ptr) = *(data as *mut (*mut c_void, *mut EventLoopHandle));
        let handler = &mut *(handler_ptr as *mut H);
        let evlh = &mut *(evlh_ptr);
        let sig = match ::nix::sys::signal::Signal::from_c_int(signal) {
            Ok(sig) => sig,
            Err(_) => {
                // Actually, this cannot happen, as we cannot register an event source for
                // an unknown signal...
                let _ = write!(
                    ::std::io::stderr(),
                    "[wayland-server error] Unknown signal in signal event source: {}, aborting.",
                    signal
                );
                ::libc::abort();
            }
        };
        handler.signal(evlh, sig);
    });
    match ret {
        Ok(()) => return 0,   // all went well
        Err(_) => {
            // a panic occured
            let _ =
                write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}
<commit_msg>Fix use-after-free for dropped FdEventSource<commit_after>

use EventLoopHandle;

use std::io::Error as IoError;
use std::io::Write;
use std::os::raw::{c_int, c_void};

use std::os::unix::io::RawFd;
use wayland_sys::server::*;

// fd_event_source
//

/// A handle to a registered FD event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct FdEventSource {
    ptr: *mut wl_event_source,
    data: *mut (*mut c_void, *mut EventLoopHandle),
}

bitflags!{
    /// Flags to register interest on a file descriptor
    pub struct FdInterest: u32 {
        /// Interest to be notified when the file descriptor is readable
        const READ  = 0x01;
        /// Interest to be notified when the file descriptor is writable
        const WRITE = 0x02;
    }
}

pub fn make_fd_event_source(ptr: *mut wl_event_source, data: Box<(*mut c_void, *mut EventLoopHandle)>)
                            -> FdEventSource {
    FdEventSource {
        ptr: ptr,
        data: Box::into_raw(data),
    }
}

impl FdEventSource {
    /// Change the registered interest for this FD
    pub fn update_mask(&mut self, mask: FdInterest) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_event_source_fd_update,
                self.ptr,
                mask.bits()
            );
        }
    }

    /// Remove this event source from its event loop
    pub fn remove(self) {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
            let _ = Box::from_raw(self.data);
        }
    }
}

/// Trait for handlers for FD events
pub trait FdEventSourceHandler {
    /// The FD is ready to be read/written
    ///
    /// Details of the capability state are given as argument.
    fn ready(&mut self, evlh: &mut EventLoopHandle, fd: RawFd, mask: FdInterest);
    /// An error occured with this FD
    ///
    /// Most likely it won't be usable any longer
    fn error(&mut self, evlh: &mut EventLoopHandle, fd: RawFd, error: IoError);
}

pub unsafe extern "C" fn event_source_fd_dispatcher<H>(fd: c_int, mask: u32, data: *mut c_void) -> c_int
where
    H: FdEventSourceHandler,
{
    // 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 || {
        let (handler_ptr, evlh_ptr) = *(data as *mut (*mut c_void, *mut EventLoopHandle));
        let handler = &mut *(handler_ptr as *mut H);
        let evlh = &mut *(evlh_ptr);
        if mask & 0x04 > 0 {
            // EPOLLERR
            use nix::sys::socket;
            let err = match socket::getsockopt(fd, socket::sockopt::SocketError) {
                Ok(err) => err,
                Err(_) => {
                    // error while retrieving the error code ???
                    let _ = write!(
                        ::std::io::stderr(),
                        "[wayland-server error] Error while retrieving error code on socket {}, aborting.",
                        fd
                    );
                    ::libc::abort();
                }
            };
            handler.error(evlh, fd, IoError::from_raw_os_error(err));
        } else if mask & 0x03 > 0 {
            // EPOLLHUP
            handler.error(
                evlh,
                fd,
                IoError::new(::std::io::ErrorKind::ConnectionAborted, ""),
            )
        } else {
            let mut bits = FdInterest::empty();
            if mask & 0x02 > 0 {
                bits = bits | WRITE;
            }
            if mask & 0x01 > 0 {
                bits = bits | READ;
            }
            handler.ready(evlh, fd, bits)
        }
    });
    match ret {
        Ok(()) => return 0,   // all went well
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for fd {} event source panicked, aborting.",
                fd
            );
            ::libc::abort();
        }
    }
}

// timer_event_source
//

/// A handle to a registered timer event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct TimerEventSource {
    ptr: *mut wl_event_source,
    _data: Box<(*mut c_void, *mut EventLoopHandle)>,
}

pub fn make_timer_event_source(ptr: *mut wl_event_source, data: Box<(*mut c_void, *mut EventLoopHandle)>)
                               -> TimerEventSource {
    TimerEventSource {
        ptr: ptr,
        _data: data,
    }
}

impl TimerEventSource {
    /// Set the delay of this timer
    ///
    /// The handler will be called during the next dispatch of the
    /// event loop after this time (in milliseconds) is elapsed.
    pub fn set_delay_ms(&mut self, delay: i32) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_event_source_timer_update,
                self.ptr,
                delay
            );
        }
    }

    /// Remove this event source from its event loop
    pub fn remove(self) {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
        }
    }
}

/// Trait for handlers for timer event sources
pub trait TimerEventSourceHandler {
    /// The countdown has reached zero
    fn timeout(&mut self, evlh: &mut EventLoopHandle);
}

pub unsafe extern "C" fn event_source_timer_dispatcher<H>(data: *mut c_void) -> c_int
where
    H: TimerEventSourceHandler,
{
    // 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 || {
        let (handler_ptr, evlh_ptr) = *(data as *mut (*mut c_void, *mut EventLoopHandle));
        let handler = &mut *(handler_ptr as *mut H);
        let evlh = &mut *(evlh_ptr);
        handler.timeout(evlh);
    });
    match ret {
        Ok(()) => return 0,   // all went well
        Err(_) => {
            // a panic occured
            let _ =
                write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}

// signal_event_source
//

/// A handle to a registered signal event source
///
/// Dropping this struct does not remove the event source,
/// use the `remove` method for that.
pub struct SignalEventSource {
    ptr: *mut wl_event_source,
    _data: Box<(*mut c_void, *mut EventLoopHandle)>,
}

pub fn make_signal_event_source(ptr: *mut wl_event_source, data: Box<(*mut c_void, *mut EventLoopHandle)>)
                                -> SignalEventSource {
    SignalEventSource {
        ptr: ptr,
        _data: data,
    }
}

impl SignalEventSource {
    /// Remove this event source from its event loop
    pub fn remove(self) {
        unsafe {
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_source_remove, self.ptr);
        }
    }
}

/// Trait for handlers of signal event sources
pub trait SignalEventSourceHandler {
    /// A signal has been received
    ///
    /// The signal number is given has argument
    fn signal(&mut self, evlh: &mut EventLoopHandle, signal: ::nix::sys::signal::Signal);
}

pub unsafe extern "C" fn event_source_signal_dispatcher<H>(signal: c_int, data: *mut c_void) -> c_int
where
    H: SignalEventSourceHandler,
{
    // 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 || {
        let (handler_ptr, evlh_ptr) = *(data as *mut (*mut c_void, *mut EventLoopHandle));
        let handler = &mut *(handler_ptr as *mut H);
        let evlh = &mut *(evlh_ptr);
        let sig = match ::nix::sys::signal::Signal::from_c_int(signal) {
            Ok(sig) => sig,
            Err(_) => {
                // Actually, this cannot happen, as we cannot register an event source for
                // an unknown signal...
                let _ = write!(
                    ::std::io::stderr(),
                    "[wayland-server error] Unknown signal in signal event source: {}, aborting.",
                    signal
                );
                ::libc::abort();
            }
        };
        handler.signal(evlh, sig);
    });
    match ret {
        Ok(()) => return 0,   // all went well
        Err(_) => {
            // a panic occured
            let _ =
                write!(
                ::std::io::stderr(),
                "[wayland-server error] A handler for a timer event source panicked, aborting.",
            );
            ::libc::abort();
        }
    }
}
<|endoftext|>


<commit_before>//! http server for semantic engines
//!
//! Provide semantic completion, definition look-up, and compilation warning/error JSON API over
//! HTTP. Endpoints currently assume the `Racer` engine.
//!
//! # Definition lookup
//!
//! `POST /find_definition`
//!
//! ## Request
//!
//! ```json
//! {
//!     "file_path": "src.rs",
//!     "buffers": [{
//!         "contents": "<some rust code>",
//!         "file_path": "src.rs"
//!     }],
//!     "line": 4,
//!     "column": 3
//! }
//! ```
//!
//! ## Response
//!
//! ```json
//! {
//!     "file_path": "maybe_other_src.rs",
//!     "text": "fn foo() {}",
//!     "line": 4,
//!     "column": 3
//! }
//! ```
//!
//! # Planned features
//! ✓ Definition lookup
//!
//! ☐ HMAC Auth for all endpoints
//!
//! ☐ Code completions
//!
//! ☐ File compilation

use iron::prelude::*;

use ::Config;

pub mod definition;
mod file;
mod completion;
mod ping;

use ::engine::SemanticEngine;

use iron::typemap::Key;
use iron_hmac::Hmac256Authentication;

/// Errors occurring in the http module
#[derive(Debug)]
pub enum Error {
    /// Error occurred in underlying http server lib
    HttpServer(::hyper::Error),
    // Error occurred in http framework layer
    // HttpApp(::iron::IronError),
}

impl From<::hyper::Error> for Error {
    fn from(err: ::hyper::Error) -> Error {
        Error::HttpServer(err)
    }
}

pub type Result<T> = ::std::result::Result<T, Error>;

// -------------------------------------------------------------------------------------------------
// This is the middleware which attaches a completion engine to a given request
#[derive(Debug, Clone)]
pub struct EngineProvider;

impl Key for EngineProvider {
    type Value = Box<SemanticEngine + Send + Sync>;
}

// -------------------------------------------------------------------------------------------------

/// Start the http server using the given configuration
///
/// `serve` is non-blocking.
///
/// # Example
///
/// ```no_run
/// # use libracerd::{Config};
/// let mut cfg = Config::new();
/// cfg.port = 3000;
///
/// let engine = ::libracerd::engine::Racer::new();
///
/// let mut server = ::libracerd::http::serve(&cfg, engine).unwrap();
/// // ... later
/// server.close().unwrap();
/// ```
///
pub fn serve<E: SemanticEngine + 'static>(config: &Config, engine: E) -> Result<Server> {
    use persistent::{Read, Write};
    use logger::Logger;

    let mut chain = Chain::new(router!(
        post "/parse_file"       => file::parse,
        post "/find_definition"  => definition::find,
        post "/list_completions" => completion::list,
        get  "/ping"             => ping::pong));

    // Logging middleware
    let (log_before, log_after) = Logger::new(None);

    // log_before must be first middleware in before chain
    if config.print_http_logs {
        chain.link_before(log_before);
    }

    // Get HMAC Middleware
    let (hmac_before, hmac_after) = if config.secret_file.is_some() {
        let secret = config.read_secret_file();
        let hmac_header = "x-racerd-hmac";
        let (before, after) = Hmac256Authentication::middleware(secret, hmac_header);
        (Some(before), Some(after))
    } else {
        (None, None)
    };

    // This middleware provides a semantic engine to the request handlers
    chain.link_before(Write::<EngineProvider>::one(Box::new(engine)));

    // Body parser middlerware
    chain.link_before(Read::<::bodyparser::MaxBodyLength>::one(1024 * 1024 * 10));

    // Maybe link hmac middleware
    if let Some(hmac) = hmac_before {
        chain.link_before(hmac);
    }

    if let Some(hmac) = hmac_after {
        chain.link_after(hmac);
    }

    // log_after must be last middleware in after chain
    if config.print_http_logs {
        chain.link_after(log_after);
    }

    let app = Iron::new(chain);

    Ok(Server {
        inner: try!(app.http(("localhost", config.port)))
    })
}

/// Wrapper type with information and control of the underlying HTTP server
///
/// This type can only be created via the [`serve`](fn.serve.html) function.
#[derive(Debug)]
pub struct Server {
    inner: ::hyper::server::Listening,
}

impl Server {
    /// Stop accepting connections
    pub fn close(&mut self) -> Result<()> {
        Ok(try!(self.inner.close()))
    }

    /// Get listening address of server (eg. "127.0.0.1:59369")
    ///
    /// # Example
    /// ```no_run
    /// let mut config = ::libracerd::Config::new();
    /// config.port = 3000;
    ///
    /// let engine = ::libracerd::engine::Racer::new();
    /// let server = ::libracerd::http::serve(&config, engine).unwrap();
    ///
    /// assert_eq!(server.addr(), "0.0.0.0:3000");
    /// ```
    pub fn addr(&self) -> String {
        format!("{}", self.inner.socket)
    }
}
<commit_msg>Remove API docs from http module<commit_after>//! http server for semantic engines

use iron::prelude::*;

use ::Config;

mod definition;
mod file;
mod completion;
mod ping;

use ::engine::SemanticEngine;

use iron::typemap::Key;
use iron_hmac::Hmac256Authentication;

/// Errors occurring in the http module
#[derive(Debug)]
pub enum Error {
    /// Error occurred in underlying http server lib
    HttpServer(::hyper::Error),
    // Error occurred in http framework layer
    // HttpApp(::iron::IronError),
}

impl From<::hyper::Error> for Error {
    fn from(err: ::hyper::Error) -> Error {
        Error::HttpServer(err)
    }
}

pub type Result<T> = ::std::result::Result<T, Error>;

// -------------------------------------------------------------------------------------------------
/// Iron middleware responsible for attaching a semantic engine to each request
#[derive(Debug, Clone)]
pub struct EngineProvider;

impl Key for EngineProvider {
    type Value = Box<SemanticEngine + Send + Sync>;
}

// -------------------------------------------------------------------------------------------------

/// Start the http server using the given configuration
///
/// `serve` is non-blocking.
///
/// # Example
///
/// ```no_run
/// # use libracerd::{Config};
/// let mut cfg = Config::new();
/// cfg.port = 3000;
///
/// let engine = ::libracerd::engine::Racer::new();
///
/// let mut server = ::libracerd::http::serve(&cfg, engine).unwrap();
/// // ... later
/// server.close().unwrap();
/// ```
///
pub fn serve<E: SemanticEngine + 'static>(config: &Config, engine: E) -> Result<Server> {
    use persistent::{Read, Write};
    use logger::Logger;

    let mut chain = Chain::new(router!(
        post "/parse_file"       => file::parse,
        post "/find_definition"  => definition::find,
        post "/list_completions" => completion::list,
        get  "/ping"             => ping::pong));

    // Logging middleware
    let (log_before, log_after) = Logger::new(None);

    // log_before must be first middleware in before chain
    if config.print_http_logs {
        chain.link_before(log_before);
    }

    // Get HMAC Middleware
    let (hmac_before, hmac_after) = if config.secret_file.is_some() {
        let secret = config.read_secret_file();
        let hmac_header = "x-racerd-hmac";
        let (before, after) = Hmac256Authentication::middleware(secret, hmac_header);
        (Some(before), Some(after))
    } else {
        (None, None)
    };

    // This middleware provides a semantic engine to the request handlers
    chain.link_before(Write::<EngineProvider>::one(Box::new(engine)));

    // Body parser middlerware
    chain.link_before(Read::<::bodyparser::MaxBodyLength>::one(1024 * 1024 * 10));

    // Maybe link hmac middleware
    if let Some(hmac) = hmac_before {
        chain.link_before(hmac);
    }

    if let Some(hmac) = hmac_after {
        chain.link_after(hmac);
    }

    // log_after must be last middleware in after chain
    if config.print_http_logs {
        chain.link_after(log_after);
    }

    let app = Iron::new(chain);

    Ok(Server {
        inner: try!(app.http(("localhost", config.port)))
    })
}

/// Wrapper type with information and control of the underlying HTTP server
///
/// This type can only be created via the [`serve`](fn.serve.html) function.
#[derive(Debug)]
pub struct Server {
    inner: ::hyper::server::Listening,
}

impl Server {
    /// Stop accepting connections
    pub fn close(&mut self) -> Result<()> {
        Ok(try!(self.inner.close()))
    }

    /// Get listening address of server (eg. "127.0.0.1:59369")
    ///
    /// # Example
    /// ```no_run
    /// let mut config = ::libracerd::Config::new();
    /// config.port = 3000;
    ///
    /// let engine = ::libracerd::engine::Racer::new();
    /// let server = ::libracerd::http::serve(&config, engine).unwrap();
    ///
    /// assert_eq!(server.addr(), "0.0.0.0:3000");
    /// ```
    pub fn addr(&self) -> String {
        format!("{}", self.inner.socket)
    }
}
<|endoftext|>


<commit_before>use cocoa::base::{class, id};
use objc::runtime::{BOOL, Class, Protocol, YES};

macro_rules! convertible_enum {
    ($(#[$top_lvl_attrs:meta])* pub enum $enum_nm:ident : $convert:ident {
        $($(#[$arm_attrs:meta])* $arm:ident => $other:ident),*
    }) => (
        $(#[$top_lvl_attrs])*
        pub enum $enum_nm {
            $($(#[$arm_attrs])* $arm),*
        }

        convertible_enum!(@_impl conversion from $enum_nm to $convert {
            $($arm => $other),*
        });
    );

    ($(#[$top_lvl_attrs:meta])* enum $enum_nm:ident : $convert:ident {
        $($(#[$arm_attrs:meta])* $arm:ident => $other:ident),*
    }) => (
        $(#[$top_lvl_attrs])*
        enum $enum_nm {
            $($(#[$arm_attrs])* $arm),*
        }

        convertible_enum!(@_impl conversion from $enum_nm to $convert {
            $($arm => $other),*
        });
    );

    (@_impl conversion from $enum_nm:ident to $convert:ident {
        $($arm:ident => $other:ident),*
    }) => (
        impl ::std::convert::Into<$convert> for $enum_nm {
            fn into(self) -> $convert {
                match self {
                    $($enum_nm::$arm => $convert::$other),*
                }
            }
        }

        impl ::std::convert::From<$convert> for $enum_nm {
            fn from(other: $convert) -> Self {
                match other {
                    $($convert::$other => $enum_nm::$arm),*
                }
            }
        }
    );
}

pub fn conforms_to_protocol(object: id, protocol_name: &str) -> bool {
    match Protocol::get(protocol_name) {
        Some(protocol) => unsafe { &*object }.class().conforms_to(protocol),
        None => false
    }
}

pub fn is_kind_of_class(object: id, class_name: &str) -> bool {
    match Class::get(class_name) {
        None => false,
        Some(class) => {
            let is_class: BOOL = unsafe {
                msg_send![object, isKindOfClass:class]
            };
            is_class == YES
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use cocoa::base::nil;
    use cocoa::foundation::NSString;

    #[test]
    fn test_conforms_to_protocol() {
        unsafe {
            let nsstr = NSString::alloc(nil).init_str("Hello, world");
            assert!(conforms_to_protocol(nsstr, "NSCopying"));
        }
    }

    #[test]
    fn test_doesnt_conform_to_protocol() {
        unsafe {
            let nsstr = NSString::alloc(nil).init_str("blah");
            assert!(!conforms_to_protocol(nsstr, "MTLDevice"));
        }
    }

    #[test]
    fn test_is_kind_of_class() {
        let nsstr = unsafe { NSString::alloc(nil).init_str("Hello, world") };
        assert!(is_kind_of_class(nsstr, "NSString"));
    }

    #[test]
    fn test_is_not_kind_of_class() {
        use sys::MTLCompileOptions;
        let compile_opts = unsafe { MTLCompileOptions::new(nil) };
        assert!(!is_kind_of_class(compile_opts, "NSString"));
    }
}
<commit_msg>Use the conformsToProtocol: message rather than the objc crate methods<commit_after>use cocoa::base::{class, id};
use objc::runtime::{BOOL, Class, Protocol, YES};

macro_rules! convertible_enum {
    ($(#[$top_lvl_attrs:meta])* pub enum $enum_nm:ident : $convert:ident {
        $($(#[$arm_attrs:meta])* $arm:ident => $other:ident),*
    }) => (
        $(#[$top_lvl_attrs])*
        pub enum $enum_nm {
            $($(#[$arm_attrs])* $arm),*
        }

        convertible_enum!(@_impl conversion from $enum_nm to $convert {
            $($arm => $other),*
        });
    );

    ($(#[$top_lvl_attrs:meta])* enum $enum_nm:ident : $convert:ident {
        $($(#[$arm_attrs:meta])* $arm:ident => $other:ident),*
    }) => (
        $(#[$top_lvl_attrs])*
        enum $enum_nm {
            $($(#[$arm_attrs])* $arm),*
        }

        convertible_enum!(@_impl conversion from $enum_nm to $convert {
            $($arm => $other),*
        });
    );

    (@_impl conversion from $enum_nm:ident to $convert:ident {
        $($arm:ident => $other:ident),*
    }) => (
        impl ::std::convert::Into<$convert> for $enum_nm {
            fn into(self) -> $convert {
                match self {
                    $($enum_nm::$arm => $convert::$other),*
                }
            }
        }

        impl ::std::convert::From<$convert> for $enum_nm {
            fn from(other: $convert) -> Self {
                match other {
                    $($convert::$other => $enum_nm::$arm),*
                }
            }
        }
    );
}

pub fn conforms_to_protocol(object: id, protocol_name: &str) -> bool {
    match Protocol::get(protocol_name) {
        Some(protocol) => {
            let does_conform: BOOL = unsafe {
                msg_send![object, conformsToProtocol:protocol]
            };
            does_conform == YES
        }
        None => false
    }
}

pub fn is_kind_of_class(object: id, class_name: &str) -> bool {
    match Class::get(class_name) {
        None => false,
        Some(class) => {
            let is_class: BOOL = unsafe {
                msg_send![object, isKindOfClass:class]
            };
            is_class == YES
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use cocoa::base::nil;
    use cocoa::foundation::NSString;

    #[test]
    fn test_conforms_to_protocol() {
        unsafe {
            let nsstr = NSString::alloc(nil).init_str("Hello, world");
            assert!(conforms_to_protocol(nsstr, "NSCopying"));
        }
    }

    #[test]
    fn test_doesnt_conform_to_protocol() {
        unsafe {
            let nsstr = NSString::alloc(nil).init_str("blah");
            assert!(!conforms_to_protocol(nsstr, "MTLDevice"));
        }
    }

    #[test]
    fn test_is_kind_of_class() {
        let nsstr = unsafe { NSString::alloc(nil).init_str("Hello, world") };
        assert!(is_kind_of_class(nsstr, "NSString"));
    }

    #[test]
    fn test_is_not_kind_of_class() {
        use sys::MTLCompileOptions;
        let compile_opts = unsafe { MTLCompileOptions::new(nil) };
        assert!(!is_kind_of_class(compile_opts, "NSString"));
    }
}
<|endoftext|>


<commit_before>use id3::Tag;
use chill;
use super::{Index, Indexer};
use walkdir::{DirEntry, WalkDir};
use {DecodedTrack, User, Error, FileBackend, Uri, FileUri, MACHINE_ID};

impl Indexer<FileBackend> for Index {
    fn index(db: &chill::Client, user: &User, backend: &FileBackend) -> Result<(), Error> {

        let mut tracks: Vec<DecodedTrack> = Vec::new();

        for path in &backend.paths {
            for entry in walk_path(&path) {
                if let Ok(tag) = Tag::read_from_path(entry.path()) {
                    if let Some(file_path) = entry.path().to_str() {
                        let uri = FileUri::new(&MACHINE_ID.to_string(), file_path);

                        tracks.push(DecodedTrack {
                            artist: tag.artist().unwrap_or("").into(),
                            album: tag.album().unwrap_or("").into(),
                            name: tag.title().unwrap_or("").into(),
                            number: tag.track().unwrap_or(0),
                            uri: Uri::File(uri),
                        });
                    }
                }
            }
        }

        Index::take_result(db, &user.db_name(), tracks)?;
        Ok(())
    }
}

fn is_file_type(e: &DirEntry, ext: &str) -> bool {
    let p = e.path();
    p.is_file() && p.extension().map_or(false, |s| s == ext)
}

fn is_music(e: &DirEntry) -> bool {
    is_file_type(e, "mp3") || is_file_type(e, "ogg")
}

fn walk_path(path: &str) -> Vec<DirEntry> {
    WalkDir::new(path)
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|e| is_music(e))
        .collect()
}
<commit_msg>fix(index): ignore files without metadata<commit_after>use id3::Tag;
use chill;
use super::{Index, Indexer};
use walkdir::{DirEntry, WalkDir};
use {DecodedTrack, User, Error, FileBackend, Uri, FileUri, MACHINE_ID};

impl Indexer<FileBackend> for Index {
    fn index(db: &chill::Client, user: &User, backend: &FileBackend) -> Result<(), Error> {

        let mut tracks: Vec<DecodedTrack> = Vec::new();

        for path in &backend.paths {
            for entry in walk_path(&path) {
                if let Ok(tag) = Tag::read_from_path(entry.path()) {
                    if let Some(file_path) = entry.path().to_str() {
                        let uri = FileUri::new(&MACHINE_ID.to_string(), file_path);

                        let artist = match tag.artist() {
                            Some(artist) => artist,
                            None => break
                        };

                        let album = match tag.album() {
                            Some(album) => album,
                            None => break
                        };

                        let name = match tag.title() {
                            Some(name) => name,
                            None => break
                        };

                        let number = match tag.track() {
                            Some(number) => number,
                            None => break
                        };

                        tracks.push(DecodedTrack {
                            artist: artist.into(),
                            album: album.into(),
                            name: name.into(),
                            number: number,
                            uri: Uri::File(uri),
                        });
                    }
                }
            }
        }

        Index::take_result(db, &user.db_name(), tracks)?;
        Ok(())
    }
}

fn is_file_type(e: &DirEntry, ext: &str) -> bool {
    let p = e.path();
    p.is_file() && p.extension().map_or(false, |s| s == ext)
}

fn is_music(e: &DirEntry) -> bool {
    is_file_type(e, "mp3") || is_file_type(e, "ogg")
}

fn walk_path(path: &str) -> Vec<DirEntry> {
    WalkDir::new(path)
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|e| is_music(e))
        .collect()
}
<|endoftext|>


<commit_before>
use bwapi_sys::bridge as sys;
use std::marker::PhantomData;
use std::os::raw::c_void as void;

/// `FromRaw` is a trait for entities that
/// are typically created outside of Rust code.
/// TODO Move to a proper place
pub trait FromRaw {
    /// Construct entity from raw data. Unsafe.
    /// Please be 100% sure that you pass correct pointer.
    unsafe fn from_raw(raw: *mut void) -> Self;
}

/// Iterator is a wrapper over API iterator.
/// To ensure safety it's lifetime is bound
/// to the lifetime of the referenced data.
pub struct BwIterator<'iter, T: FromRaw + 'iter> {
    raw: &'iter mut sys::Iterator,
    phantom: PhantomData<&'iter T>,
}

impl<'iter, T: FromRaw + 'iter> BwIterator<'iter, T> {
    pub unsafe fn from(raw: *mut sys::Iterator) -> BwIterator<'iter, T> {
        assert!(!raw.is_null());
        BwIterator { raw: &mut *raw, phantom: PhantomData }
    }
}

impl<'iter, T: FromRaw + 'iter> Iterator for BwIterator<'iter, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        unsafe {
            if sys::Iterator_valid(self.raw) {
                let item = sys::Iterator_get(self.raw);
                sys::Iterator_next(self.raw);
                Some(T::from_raw(item))
            } else {
                None
            }
        }
    }
}

impl<'iter, T: FromRaw + 'iter> Drop for BwIterator<'iter, T> {
    fn drop(&mut self) {
        unsafe {
            sys::Iterator_release(self.raw);
        }
    }
}
<commit_msg>Fixes lifetimes of BwIterator<commit_after>
use bwapi_sys::bridge as sys;
use std::marker::PhantomData;
use std::os::raw::c_void as void;

/// `FromRaw` is a trait for entities that
/// are typically created outside of Rust code.
/// TODO Move to a proper place
pub trait FromRaw {
    /// Construct entity from raw data. Unsafe.
    /// Please be 100% sure that you pass correct pointer.
    unsafe fn from_raw(raw: *mut void) -> Self;
}

/// Iterator is a wrapper over API iterator.
/// To ensure safety it's lifetime is bound
/// to the lifetime of the referenced data.
pub struct BwIterator<'i, 'g: 'i, T: FromRaw + 'g> {
    raw: &'i mut sys::Iterator,
    phantom: PhantomData<&'g T>,
}

impl<'i, 'g: 'i, T: FromRaw + 'g> BwIterator<'i, 'g, T> {
    pub unsafe fn from(raw: *mut sys::Iterator) -> BwIterator<'i, 'g, T> {
        assert!(!raw.is_null());
        BwIterator { raw: &mut *raw, phantom: PhantomData }
    }
}

impl<'i,'g: 'i, T: FromRaw + 'g> Iterator for BwIterator<'i, 'g, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        unsafe {
            if sys::Iterator_valid(self.raw) {
                let item = sys::Iterator_get(self.raw);
                sys::Iterator_next(self.raw);
                Some(T::from_raw(item))
            } else {
                None
            }
        }
    }
}

impl<'i, 'g: 'i, T: FromRaw + 'g> Drop for BwIterator<'i, 'g, T> {
    fn drop(&mut self) {
        unsafe {
            sys::Iterator_release(self.raw);
        }
    }
}
<|endoftext|>


<commit_before>
use ndarray::*;
use super::traits::*;
use super::exponential::Exponential;

/// Linear ODE with diagonalized matrix (exactly solvable)
pub struct Diagonal<A, D>
    where A: OdeScalar<f64> + Exponential,
          D: Dimension
{
    diag: RcArray<A, D>,
    diag_of_matrix: RcArray<A, D>,
    dt: f64,
}

impl<A, D> Diagonal<A, D>
    where A: OdeScalar<f64> + Exponential,
          D: Dimension
{
    pub fn new(diag_of_matrix: RcArray<A, D>, dt: f64) -> Self {
        let mut diag = diag_of_matrix.clone();
        for v in diag.iter_mut() {
            *v = (*v * dt).exp();
        }
        Diagonal {
            diag: diag,
            diag_of_matrix: diag_of_matrix,
            dt: dt,
        }
    }
}

impl<A, D> TimeStep for Diagonal<A, D>
    where A: OdeScalar<f64> + Exponential,
          D: Dimension
{
    fn get_dt(&self) -> f64 {
        self.dt
    }
    fn set_dt(&mut self, dt: f64) {
        Zip::from(&mut self.diag).and(&self.diag_of_matrix).apply(|a, &b| { *a = (b * dt).exp(); });
    }
}

impl<'a, A, D> TimeEvolution<A, OwnedRcRepr<A>, D> for &'a Diagonal<A, D>
    where A: OdeScalar<f64> + Exponential,
          D: Dimension
{
    fn iterate(self, mut x: RcArray<A, D>) -> RcArray<A, D> {
        for (val, d) in x.iter_mut().zip(self.diag.iter()) {
            *val = *val * *d;
        }
        x
    }
}
<commit_msg>impl ArrayViewMut interface for Diagonal<commit_after>
use ndarray::*;
use super::traits::*;
use super::exponential::Exponential;

/// Linear ODE with diagonalized matrix (exactly solvable)
pub struct Diagonal<A, D>
    where A: OdeScalar<f64> + Exponential,
          D: Dimension
{
    diag: RcArray<A, D>,
    diag_of_matrix: RcArray<A, D>,
    dt: f64,
}

impl<A, D> Diagonal<A, D>
    where A: OdeScalar<f64> + Exponential,
          D: Dimension
{
    pub fn new(diag_of_matrix: RcArray<A, D>, dt: f64) -> Self {
        let mut diag = diag_of_matrix.clone();
        for v in diag.iter_mut() {
            *v = (*v * dt).exp();
        }
        Diagonal {
            diag: diag,
            diag_of_matrix: diag_of_matrix,
            dt: dt,
        }
    }
}

impl<A, D> TimeStep for Diagonal<A, D>
    where A: OdeScalar<f64> + Exponential,
          D: Dimension
{
    fn get_dt(&self) -> f64 {
        self.dt
    }
    fn set_dt(&mut self, dt: f64) {
        Zip::from(&mut self.diag).and(&self.diag_of_matrix).apply(|a, &b| { *a = (b * dt).exp(); });
    }
}

impl<'a, A, D> TimeEvolution<A, OwnedRcRepr<A>, D> for &'a Diagonal<A, D>
    where A: OdeScalar<f64> + Exponential,
          D: Dimension
{
    fn iterate(self, mut x: RcArray<A, D>) -> RcArray<A, D> {
        for (val, d) in x.iter_mut().zip(self.diag.iter()) {
            *val = *val * *d;
        }
        x
    }
}

impl<'a, A, D> TimeEvolution<A, ViewRepr<&'a mut A>, D> for &'a Diagonal<A, D>
    where A: OdeScalar<f64> + Exponential,
          D: Dimension
{
    fn iterate(self, mut x: ArrayViewMut<A, D>) -> ArrayViewMut<A, D> {
        for (val, d) in x.iter_mut().zip(self.diag.iter()) {
            *val = *val * *d;
        }
        x
    }
}
<|endoftext|>


<commit_before>extern crate sourcemap;

use sourcemap::SourceMap;

#[test]
fn test_basic_name_mapping() {
    let input = r#"{"version":3,"file":"test.min.js","sources":["test.js"],"names":["makeAFailure","testingStuff","Error","onSuccess","data","onFailure","invoke","cb","failed","test","value"],"mappings":"AAAA,GAAIA,cAAe,WACjB,QAASC,KACP,GAAIA,GAAe,EACnB,MAAM,IAAIC,OAAMD,GAGlB,QAASE,GAAUC,GACjBH,IAGF,QAASI,GAAUD,GACjB,KAAM,IAAIF,OAAM,WAGlB,QAASI,GAAOF,GACd,GAAIG,GAAK,IACT,IAAIH,EAAKI,OAAQ,CACfD,EAAKF,MACA,CACLE,EAAKJ,EAEPI,EAAGH,GAGL,QAASK,KACP,GAAIL,IAAQI,OAAQ,KAAME,MAAO,GACjCJ,GAAOF,GAGT,MAAOK","sourcesContent":["var makeAFailure = (function() {\n  function testingStuff() {\n    var testingStuff = 42;\n    throw new Error(testingStuff);\n  }\n\n  function onSuccess(data) {\n    testingStuff();\n  }\n\n  function onFailure(data) {\n    throw new Error('failed!');\n  }\n\n  function invoke(data) {\n    var cb = null;\n    if (data.failed) {\n      cb = onFailure;\n    } else {\n      cb = onSuccess;\n    }\n    cb(data);\n  }\n\n  function test() {\n    var data = {failed: true, value: 42};\n    invoke(data);\n  }\n\n  return test;\n})();\n"]}"#.as_bytes();
    let minified_file = r#"var makeAFailure=function(){function n(){var n=42;throw new Error(n)}function r(r){n()}function e(n){throw new Error("failed!")}function i(n){var i=null;if(n.failed){i=e}else{i=r}i(n)}function u(){var n={failed:true,value:42};i(n)}return u}();"#;
    let sm = SourceMap::from_reader(input).unwrap();

    let tok = sm.lookup_token(0, 45).unwrap();
    assert_eq!(tok.get_name(), Some("testingStuff"));
    assert_eq!(tok.get_minified_name(minified_file), Some("n"));

    let tok = sm.lookup_token(0, 66).unwrap();
    assert_eq!(tok.get_name(), Some("testingStuff"));
    assert_eq!(tok.get_minified_name(minified_file), Some("n"));

    let tok = sm.lookup_token(0, 96).unwrap();
    assert_eq!(tok.get_name(), Some("onFailure"));
    assert_eq!(tok.get_minified_name(minified_file), Some("e"));

    let name = sm.get_original_function_name(0, 107, "e", minified_file);
    assert_eq!(name, Some("onFailure"));

    // a stacktrae
    let locs = &[
        (0, 107, "e", "onFailure"),
        (0, 179, "i", "invoke"),
        (0, 226, "u", "test"),
    ];

    for &(line, col, minified_name, original_name) in locs {
        let name = sm.get_original_function_name(line, col, minified_name, minified_file);
        assert_eq!(name, Some(original_name));
    }
}
<commit_msg>Added a basic unicode test<commit_after>extern crate sourcemap;

use sourcemap::SourceMap;

#[test]
fn test_basic_name_mapping() {
    let input = r#"{"version":3,"file":"test.min.js","sources":["test.js"],"names":["makeAFailure","testingStuff","Error","onSuccess","data","onFailure","invoke","cb","failed","test","value"],"mappings":"AAAA,GAAIA,cAAe,WACjB,QAASC,KACP,GAAIA,GAAe,EACnB,MAAM,IAAIC,OAAMD,GAGlB,QAASE,GAAUC,GACjBH,IAGF,QAASI,GAAUD,GACjB,KAAM,IAAIF,OAAM,WAGlB,QAASI,GAAOF,GACd,GAAIG,GAAK,IACT,IAAIH,EAAKI,OAAQ,CACfD,EAAKF,MACA,CACLE,EAAKJ,EAEPI,EAAGH,GAGL,QAASK,KACP,GAAIL,IAAQI,OAAQ,KAAME,MAAO,GACjCJ,GAAOF,GAGT,MAAOK","sourcesContent":["var makeAFailure = (function() {\n  function testingStuff() {\n    var testingStuff = 42;\n    throw new Error(testingStuff);\n  }\n\n  function onSuccess(data) {\n    testingStuff();\n  }\n\n  function onFailure(data) {\n    throw new Error('failed!');\n  }\n\n  function invoke(data) {\n    var cb = null;\n    if (data.failed) {\n      cb = onFailure;\n    } else {\n      cb = onSuccess;\n    }\n    cb(data);\n  }\n\n  function test() {\n    var data = {failed: true, value: 42};\n    invoke(data);\n  }\n\n  return test;\n})();\n"]}"#.as_bytes();
    let minified_file = r#"var makeAFailure=function(){function n(){var n=42;throw new Error(n)}function r(r){n()}function e(n){throw new Error("failed!")}function i(n){var i=null;if(n.failed){i=e}else{i=r}i(n)}function u(){var n={failed:true,value:42};i(n)}return u}();"#;
    let sm = SourceMap::from_reader(input).unwrap();

    let tok = sm.lookup_token(0, 45).unwrap();
    assert_eq!(tok.get_name(), Some("testingStuff"));
    assert_eq!(tok.get_minified_name(minified_file), Some("n"));

    let tok = sm.lookup_token(0, 66).unwrap();
    assert_eq!(tok.get_name(), Some("testingStuff"));
    assert_eq!(tok.get_minified_name(minified_file), Some("n"));

    let tok = sm.lookup_token(0, 96).unwrap();
    assert_eq!(tok.get_name(), Some("onFailure"));
    assert_eq!(tok.get_minified_name(minified_file), Some("e"));

    let name = sm.get_original_function_name(0, 107, "e", minified_file);
    assert_eq!(name, Some("onFailure"));

    // a stacktrae
    let locs = &[
        (0, 107, "e", "onFailure"),
        (0, 179, "i", "invoke"),
        (0, 226, "u", "test"),
    ];

    for &(line, col, minified_name, original_name) in locs {
        let name = sm.get_original_function_name(line, col, minified_name, minified_file);
        assert_eq!(name, Some(original_name));
    }
}

#[test]
fn test_unicode_mapping() {
    let input = r#"{"version":3,"file":"test.min.js","sources":["test.js"],"names":["makeAFailure","onSuccess","data","onFailure","Error","invoke","cb","failed","㮏","value"],"mappings":"AAAA,GAAIA,cAAe,WACjB,QAASC,GAAUC,IAEnB,QAASC,GAAUD,IACjB,WACE,KAAM,IAAIE,OAAM,eAIpB,QAASC,GAAOH,GACd,GAAII,GAAK,IACT,IAAIJ,EAAKK,OAAQ,CACfD,EAAKH,MACA,CACLG,EAAKL,EAEPK,EAAGJ,GAGI,QAASM,KAChB,GAAIN,IAAQK,OAAQ,KAAME,MAAO,GACjCJ,GAAOH,GAGT,MAAOM","sourcesContent":["var makeAFailure = (function() {\n  function onSuccess(data) {}\n\n  function onFailure(data) {\n    (function() {\n      throw new Error('failed!');\n    })();\n  }\n\n  function invoke(data) {\n    var cb = null;\n    if (data.failed) {\n      cb = onFailure;\n    } else {\n      cb = onSuccess;\n    }\n    cb(data);\n  }\n\n  /* 😍 */ function 㮏() {\n    var data = {failed: true, value: 42};\n    invoke(data);\n  }\n\n  return 㮏;\n})();\n"]}"#.as_bytes();
    let minified_file = r#"var makeAFailure=function(){function n(n){}function e(n){(function(){throw new Error("failed!")})()}function i(i){var r=null;if(i.failed){r=e}else{r=n}r(i)}function r(){var n={failed:true,value:42};i(n)}return r}();"#;
    let sm = SourceMap::from_reader(input).unwrap();

    // stacktrace
    let locs = &[
        (0, 75, "<unknown>", None),
        (0, 97, "e", Some("onFailure")),
        (0, 151, "i", Some("invoke")),
        (0, 198, "r", Some("㮏")),
    ];

    for &(line, col, minified_name, original_name_match) in locs {
        let name = sm.get_original_function_name(line, col, minified_name, minified_file);
        assert_eq!(name, original_name_match);
    }
}
<|endoftext|>


<commit_before>
use nom::{HexDisplay, IResult, Needed, ErrorKind};

struct Document {
    header: Header,
    body: Vec<Element>
}

struct Header {

}

#[derive(Debug)]
enum ElementData {
    Signed(i64),
    Unsigned(u64),
    Float(f64),
    PlainString(String),
    UTF8String(String),
    Date(u64),
    Master(Vec<Element>),
    Binary(Vec<u8>),
    Unknown(u64)
}

#[derive(Debug)]
pub struct Element {
    id: u64,
    size: u64,
    data: ElementData
}

fn vint(input: &[u8]) -> IResult<&[u8], u64> {
    if input.len() == 0 {
        return IResult::Incomplete(Needed::Size(1))
    }

    let v = input[0];
    let len = v.leading_zeros();

    if len == 8 {
        return IResult::Error(ErrorKind::Custom(1));
    }

    if input.len() <= len as usize {
        return IResult::Incomplete(Needed::Size(1));
    }

    let mut val = (v ^ (1 << (7 - len))) as u64;

    // println!("vint {:08b} {:08b} {:08b} {}", val, v, (1 << (8 - len)), len);

    for i in 0..len as usize {
        val = (val << 8) | input[i + 1] as u64;
    }

    IResult::Done(&input[len as usize + 1 ..], val)
}

// The ID are represented in the specification as their binary representation
// do not drop the marker bit.
fn vid(input: &[u8]) -> IResult<&[u8], u64> {
    if input.len() == 0 {
        return IResult::Incomplete(Needed::Size(1))
    }

    let v = input[0];
    let len = v.leading_zeros();

    if len == 8 {
        return IResult::Error(ErrorKind::Custom(1));
    }

    if input.len() <= len as usize {
        return IResult::Incomplete(Needed::Size(1));
    }

    let mut val = v as u64;

    // println!("vint {:08b} {:08b} {:08b} {}", val, v, (1 << (8 - len)), len);

    for i in 0..len as usize {
        val = (val << 8) | input[i + 1] as u64;
    }

    IResult::Done(&input[len as usize + 1 ..], val)
}

fn parse_master(input: &[u8], size: u64) -> IResult<&[u8], ElementData> {
    map!(input,
        many0!(parse_element), |elem| ElementData::Master(elem)
    )
}

fn parse_uint(input: &[u8], size: u64) -> IResult<&[u8], ElementData> {
    let mut val = 0;

    if size > 8 {
        return IResult::Error(ErrorKind::Custom(1));
    }

    for i in 0..size as usize {
        val = (val << 8) | input[i] as u64;
    }

    IResult::Done(&input[size as usize ..], ElementData::Unsigned(val))
}

use std::str;

fn parse_str(input: &[u8], size: u64) -> IResult<&[u8], ElementData> {
    do_parse!(input,
        s: take_s!(size as usize) >>
        ( ElementData::PlainString(String::from_utf8(s.to_owned()).unwrap()) )
    )
}

fn parse_element_id(input: &[u8], id: u64, size: u64) -> IResult<&[u8], ElementData> {
    // println!("id: 0x{:X} size: {}", id, size);
    if input.len() < size as usize {
        return IResult::Incomplete(Needed::Size(size as usize));
    }

    match id {
        0x1A45DFA3 => parse_master(input, size),
        0x4286 => parse_uint(input, size),
        0x42F7 => parse_uint(input, size),
        0x42F2 => parse_uint(input, size),
        0x42F3 => parse_uint(input, size),
        0x4282 => parse_str(input, size),
        0x4287 => parse_uint(input, size),
        0x4285 => parse_uint(input, size),
        _ => IResult::Done(&input[size as usize ..], ElementData::Unknown(id))
    }
}

named!(pub parse_element<Element>,
    do_parse!(
        id : vid >>
        size: vint >>
        data: call!(parse_element_id, id, size) >>
        (Element { id, size, data })
    )
);

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

    const single_stream : &'static [u8] = include_bytes!("../assets/single_stream.mkv");

    #[test]
    fn variable_integer() {
        let val01 = [0b10000000];
//        let val01 = [0b01000000, 0b1];

        match vint(&val01) {
            IResult::Done(_, v) => assert!(0 == v),
            _ => panic!()
        }
    }

    #[test]
    fn header() {
        println!("{}", single_stream[..8].to_hex(8));
        println!("{:b} {:b}", single_stream[0], single_stream[1]);
        println!("{:#?}", parse_element(single_stream));
        panic!();

    }
}
<commit_msg>make helper macros to parse EBML elements<commit_after>
use nom::{HexDisplay, IResult, Needed, ErrorKind};

struct Document {
    header: Header,
    body: Vec<Element>
}

struct Header {

}

#[derive(Debug)]
enum ElementData {
    Signed(i64),
    Unsigned(u64),
    Float(f64),
    PlainString(String),
    UTF8String(String),
    Date(u64),
    Master(Vec<Element>),
    Binary(Vec<u8>),
    Unknown(u64)
}

#[derive(Debug)]
pub struct Element {
    id: u64,
    size: u64,
    data: ElementData
}

fn vint(input: &[u8]) -> IResult<&[u8], u64> {
    if input.len() == 0 {
        return IResult::Incomplete(Needed::Size(1))
    }

    let v = input[0];
    let len = v.leading_zeros();

    if len == 8 {
        return IResult::Error(ErrorKind::Custom(1));
    }

    if input.len() <= len as usize {
        return IResult::Incomplete(Needed::Size(1));
    }

    let mut val = (v ^ (1 << (7 - len))) as u64;

    // println!("vint {:08b} {:08b} {:08b} {}", val, v, (1 << (8 - len)), len);

    for i in 0..len as usize {
        val = (val << 8) | input[i + 1] as u64;
    }

    IResult::Done(&input[len as usize + 1 ..], val)
}

// The ID are represented in the specification as their binary representation
// do not drop the marker bit.
fn vid(input: &[u8]) -> IResult<&[u8], u64> {
    if input.len() == 0 {
        return IResult::Incomplete(Needed::Size(1))
    }

    let v = input[0];
    let len = v.leading_zeros();

    if len == 8 {
        return IResult::Error(ErrorKind::Custom(1));
    }

    if input.len() <= len as usize {
        return IResult::Incomplete(Needed::Size(1));
    }

    let mut val = v as u64;

    // println!("vint {:08b} {:08b} {:08b} {}", val, v, (1 << (8 - len)), len);

    for i in 0..len as usize {
        val = (val << 8) | input[i + 1] as u64;
    }

    IResult::Done(&input[len as usize + 1 ..], val)
}

fn parse_master(input: &[u8], size: u64) -> IResult<&[u8], ElementData> {
    map!(input,
        many0!(parse_element), |elem| ElementData::Master(elem)
    )
}

fn parse_uint(input: &[u8], size: u64) -> IResult<&[u8], ElementData> {
    let mut val = 0;

    if size > 8 {
        return IResult::Error(ErrorKind::Custom(1));
    }

    for i in 0..size as usize {
        val = (val << 8) | input[i] as u64;
    }

    IResult::Done(&input[size as usize ..], ElementData::Unsigned(val))
}

fn parse_uint_data(input: &[u8], size: u64) -> IResult<&[u8], u64> {
    let mut val = 0;

    if size > 8 {
        return IResult::Error(ErrorKind::Custom(1));
    }

    for i in 0..size as usize {
        val = (val << 8) | input[i] as u64;
    }

    IResult::Done(&input[size as usize ..], val)
}

use std::str;

fn parse_str(input: &[u8], size: u64) -> IResult<&[u8], ElementData> {
    do_parse!(input,
        s: take_s!(size as usize) >>
        ( ElementData::PlainString(String::from_utf8(s.to_owned()).unwrap()) )
    )
}

fn parse_str_data(input: &[u8], size: u64) -> IResult<&[u8], String> {
    do_parse!(input,
        s: take_s!(size as usize) >>
        ( String::from_utf8(s.to_owned()).unwrap() )
    )
}

fn parse_element_id(input: &[u8], id: u64, size: u64) -> IResult<&[u8], ElementData> {
    // println!("id: 0x{:X} size: {}", id, size);
    if input.len() < size as usize {
        return IResult::Incomplete(Needed::Size(size as usize));
    }

    match id {
        0x1A45DFA3 => parse_master(input, size),
        0x4286 => parse_uint(input, size),
        0x42F7 => parse_uint(input, size),
        0x42F2 => parse_uint(input, size),
        0x42F3 => parse_uint(input, size),
        0x4282 => parse_str(input, size),
        0x4287 => parse_uint(input, size),
        0x4285 => parse_uint(input, size),
        _ => IResult::Done(&input[size as usize ..], ElementData::Unknown(id))
    }
}

named!(pub parse_element<Element>,
    do_parse!(
        id : vid >>
        size: vint >>
        data: call!(parse_element_id, id, size) >>
        (Element { id, size, data })
    )
);

#[macro_export]
macro_rules! ebml_uint (
  ($i: expr, $id:expr) => (
    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: apply!(parse_uint_data, size)
      >> (data)
    )
  )
);

#[macro_export]
macro_rules! ebml_str (
  ($i: expr, $id:expr) => (
    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: apply!(parse_str_data, size)
      >> (data)
    )
  )
);

#[macro_export]
macro_rules! ebml_master (
  ($i: expr, $id:expr, $submac:ident!( $($args:tt)* )) => (
    do_parse!($i,
               verify!(vid, |val:u64| val == $id)
      >> size: vint
      >> data: flat_map!(take!(size as usize), $submac!($($args)*))
      >> (data)
    )
  )
);

#[derive(Debug,Clone,PartialEq)]
pub struct EBMLHeader {
  pub version:               u64,
  pub read_version:          u64,
  pub max_id_length:         u64,
  pub max_size_length:       u64,
  pub doc_type:              String,
  pub doc_type_version:      u64,
  pub doc_type_read_version: u64,
}

named!(pub ebml_header<EBMLHeader>,
  ebml_master!(0x1A45DFA3,
    do_parse!(
      t: permutation!(
        ebml_uint!(0x4286), // version
        ebml_uint!(0x42F7), // read_version
        ebml_uint!(0x42F2), // max id length
        ebml_uint!(0x42F3), // max size length
        ebml_str!(0x4282),  // doctype
        ebml_uint!(0x4287), // doctype version
        ebml_uint!(0x4285)  // doctype_read version
      ) >>
      ({
        EBMLHeader {
          version:               t.0,
          read_version:          t.1,
          max_id_length:         t.2,
          max_size_length:       t.3,
          doc_type:              t.4,
          doc_type_version:      t.5,
          doc_type_read_version: t.6,

        }
      })
    )
  )
);

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

    const single_stream : &'static [u8] = include_bytes!("../assets/single_stream.mkv");

    #[test]
    fn variable_integer() {
        let val01 = [0b10000000];
//        let val01 = [0b01000000, 0b1];

        match vint(&val01) {
            IResult::Done(_, v) => assert!(0 == v),
            _ => panic!()
        }
    }

    /*
    #[test]
    fn header() {
        println!("{}", single_stream[..8].to_hex(8));
        println!("{:b} {:b}", single_stream[0], single_stream[1]);
        println!("{:#?}", parse_element(single_stream));
        panic!();
    }*/

    #[test]
    fn header() {
        println!("{}", single_stream[..8].to_hex(8));
        println!("{:b} {:b}", single_stream[0], single_stream[1]);
        println!("{:?}", ebml_header(&single_stream[..100]));
        panic!();
    }
}
<|endoftext|>


<commit_before>use imgui::{Ui,ImStr,ImString};
use lichen::parse::{StreamParser,Env};

use std::fs;
use std::path::Path;

use app::AppState;

use std::io::{BufReader};
use std::fs::File;

pub struct FileState {
    /// MAX_PATH set to 260 chars
    cd: ImString,
    idx: i32,
    files: Vec<String>,
    selected: Option<String>,
    stream: Option<StreamParser<BufReader<File>>>,
    failed: String,
}

impl Default for FileState {
    fn default() -> Self {
        let mut cd = ImString::from(im_str!("./"));
        cd.reserve(261); //arbitrary max path size

        FileState {
            cd: cd,
            idx: 1,
            files: vec![],
            selected: None,
            stream: None,
            failed: "".to_owned(),
        }
    }
}

impl FileState {
    fn update(&mut self) -> Option<Env> {
        if self.idx > 1 { // chose a file?
            self.failed = "".to_owned();

            if let Some(file) = self.files.get(self.idx as usize) {
                self.cd.clear();
                self.cd.push_str(file);
                self.idx = 1;
            }
        }
        else if self.idx < 1 { // up a directory?
            self.failed = "".to_owned();
            self.to_parent();
        }

        let cd = self.cd.to_string();
        if Path::new(&cd).is_dir() {
            if let Ok(paths) = fs::read_dir(&cd) {
                self.files = paths
                    .filter(|p| p.is_ok())
                    .map(|p| {
                        p.unwrap().path().as_path().to_str().unwrap().to_owned()
                    })
                    .collect();

                self.files.insert(0,"./".to_owned());
                self.files.insert(0,"..".to_owned());
            }
            // NOTE: we should throw a warning here if directory cannot be traversed
        }
        else {
            if !cd.is_empty() {
                self.selected = Some(cd);
            }
        }

        if self.stream.is_some() {
            let r = self.step_stream();
            if !self.failed.is_empty() {
                self.stream = None;
            }
            r
        }
        else { None }
    }

    /// Steps through the stream chunks, finally returns parsed lichen environment
    fn step_stream (&mut self) -> Option<Env> {
        let r = {
            if let Some(ref mut stream) = self.stream {
                stream.next()
            }
            else { None }
        };

        if r.is_none() { // close stream, we're probably done
            let mut env = Env::empty();
            if let Some(ref mut stream) = self.stream {
                if let Err(e) = stream.sink(&mut env) {
                    self.failed = e.to_owned();
                    return None;
                }
            }

            self.stream = None;
            self.to_parent();

            return Some(env);
        }

        None
    }

    fn to_parent(&mut self) {
        self.selected = None;
        if let Some(path) = Path::new(&self.cd.to_string()).parent() {
            self.cd.clear();
            self.cd.push_str(path.to_str().expect("ERROR: Cannot parse path into string"));
            self.idx = 1;
        }
        // NOTE: this fails if we're at the top of a relative directory listing,
        // or the root of the drive/share
    }

    pub fn render (&mut self, ui: &Ui, state: &mut AppState) {
        if !state.open_file { return }
        state.env = self.update(); // NOTE: we should check if the environment is empty
        state.open_file = !state.env.is_some(); // close file if done

        ui.window(im_str!("Select source"))
            .always_auto_resize(true)
            .movable(true)
            .show_borders(true)
            .opened(&mut state.open_file)
            .build(||{
                ui.text(im_str!("Select a source file to be parsed and evaluated.\nSource files must be parsable through the lichen crate."));
                ui.separator();
                ui.input_text(im_str!("Current Directory"), &mut self.cd)
                    .enter_returns_true(true)
                    .build();
                ui.separator();

                // NOTE: to appease the borrow checker and have the proper argument for list_box
                // we must build the list in two steps
                let paths: Vec<ImString> = self.files.iter().map(|p| {
                    im_str!("{:}", p).to_owned()
                }).collect();

                let paths: Vec<&ImStr> = paths.iter().map(|p|p.as_ref()).collect();

                ui.list_box(im_str!("Files"),
                            &mut self.idx,
                            &paths[..],
                            paths.len() as i32);

                if let Some(ref file) = self.selected {
                    ui.text(im_str!("Select File {:}?",file));

                    if ui.small_button(im_str!("open")) {
                        if let Ok(f) = File::open(file) {
                            let f = BufReader::new(f);
                            let s = StreamParser::new(f,None);
                            self.stream = Some(s);
                        }
                    }
                }

                let mut failure = "".to_owned();
                if !self.failed.is_empty() {
                    failure.push_str("Failed to parse file ");
                    failure.push_str(&self.cd.to_str());
                    failure.push_str("\nParse Error at: ");
                    failure.push_str(&self.failed);
                }

                ui.text(im_str!("{:}", failure));
            })
    }

}

<commit_msg>tweak<commit_after>use imgui::{Ui,ImStr,ImString};
use lichen::parse::{StreamParser,Env};

use std::fs;
use std::path::Path;

use app::AppState;

use std::io::{BufReader};
use std::fs::File;

pub struct FileState {
    /// MAX_PATH set to 260 chars
    cd: ImString,
    idx: i32,
    files: Vec<String>,
    selected: Option<String>,
    stream: Option<StreamParser<BufReader<File>>>,
    failed: String,
}

impl Default for FileState {
    fn default() -> Self {
        let mut cd = ImString::from(im_str!("./"));
        cd.reserve(261); //arbitrary max path size

        FileState {
            cd: cd,
            idx: 1,
            files: vec![],
            selected: None,
            stream: None,
            failed: "".to_owned(),
        }
    }
}

impl FileState {
    fn update(&mut self) -> Option<Env> {
        if self.idx > 1 { // chose a file?
            self.failed.clear();

            if let Some(file) = self.files.get(self.idx as usize) {
                self.cd.clear();
                self.cd.push_str(file);
                self.idx = 1;
            }
        }
        else if self.idx < 1 { // up a directory?
            self.failed.clear();
            self.to_parent();
        }

        let cd = self.cd.to_string();
        if Path::new(&cd).is_dir() {
            if let Ok(paths) = fs::read_dir(&cd) {
                self.files = paths
                    .filter(|p| p.is_ok())
                    .map(|p| {
                        p.unwrap().path().as_path().to_str().unwrap().to_owned()
                    })
                    .collect();

                self.files.insert(0,"./".to_owned());
                self.files.insert(0,"..".to_owned());
            }
            // NOTE: we should throw a warning here if directory cannot be traversed
        }
        else {
            if !cd.is_empty() {
                self.selected = Some(cd);
            }
        }

        if self.stream.is_some() {
            let r = self.step_stream();
            if !self.failed.is_empty() {
                self.stream = None;
            }
            r
        }
        else { None }
    }

    /// Steps through the stream chunks, finally returns parsed lichen environment
    fn step_stream (&mut self) -> Option<Env> {
        let r = {
            if let Some(ref mut stream) = self.stream {
                stream.next()
            }
            else { None }
        };

        if r.is_none() { // close stream, we're probably done
            let mut env = Env::empty();
            if let Some(ref mut stream) = self.stream {
                if let Err(e) = stream.sink(&mut env) {
                    self.failed = e.to_owned();
                    return None;
                }
            }

            self.stream = None;
            self.to_parent();

            return Some(env);
        }

        None
    }

    fn to_parent(&mut self) {
        self.selected = None;
        if let Some(path) = Path::new(&self.cd.to_string()).parent() {
            self.cd.clear();
            self.cd.push_str(path.to_str().expect("ERROR: Cannot parse path into string"));
            self.idx = 1;
        }
        // NOTE: this fails if we're at the top of a relative directory listing,
        // or the root of the drive/share
    }

    pub fn render (&mut self, ui: &Ui, state: &mut AppState) {
        if !state.open_file { return }
        state.env = self.update(); // NOTE: we should check if the environment is empty
        state.open_file = !state.env.is_some(); // close file if done

        ui.window(im_str!("Select source"))
            .always_auto_resize(true)
            .movable(true)
            .show_borders(true)
            .opened(&mut state.open_file)
            .build(||{
                ui.text(im_str!("Select a source file to be parsed and evaluated.\nSource files must be parsable through the lichen crate."));
                ui.separator();
                ui.input_text(im_str!("Current Directory"), &mut self.cd)
                    .enter_returns_true(true)
                    .build();
                ui.separator();

                // NOTE: to appease the borrow checker and have the proper argument for list_box
                // we must build the list in two steps
                let paths: Vec<ImString> = self.files.iter().map(|p| {
                    im_str!("{:}", p).to_owned()
                }).collect();

                let paths: Vec<&ImStr> = paths.iter().map(|p|p.as_ref()).collect();

                ui.list_box(im_str!("Files"),
                            &mut self.idx,
                            &paths[..],
                            paths.len() as i32);

                if let Some(ref file) = self.selected {
                    ui.text(im_str!("Select File {:}?",file));

                    if ui.small_button(im_str!("open")) {
                        if let Ok(f) = File::open(file) {
                            let f = BufReader::new(f);
                            let s = StreamParser::new(f,None);
                            self.stream = Some(s);
                        }
                    }
                }

                if !self.failed.is_empty() {
                    ui.text(im_str!("Failed to parse file {:}\nParse Error at: {:}",
                                    &self.cd.to_str(), &self.failed));
                }
            })
    }

}

<|endoftext|>


<commit_before>use crate::{
    player::Player,
    settings::Settings,
};

pub struct Game<'a> {
    pub settings: &'a Settings,
    players: [Player; 2],
    state: GameState,
    turn: u8,
}

impl<'a> Game<'a> {
    pub fn new(settings: &Settings) -> Game {
        let grid_size = [
            settings.spaces[0],
            settings.spaces[1],
        ];

        Game {
            settings: &settings,
            players: [
                Player::new(grid_size, false),
                Player::new(grid_size, true)
            ],
            state: GameState::ShipPlacement,
            turn: 0,
        }
    }

    /// Returns a reference to the currently active player.
    pub fn active_player(&self) -> &Player {
        &self.players[self.turn as usize]
    }

    /// Returns a reference to the currently inactive player.
    pub fn inactive_player(&self) -> &Player {
        &self.players[self.not_turn()]
    }

    /// Returns a mutable reference to the currently active player.
    pub fn active_player_mut(&mut self) -> &mut Player {
        &mut self.players[self.turn as usize]
    }

    /// Returns whether the game's current state is ship placement.
    pub fn is_state_placement(&self) -> bool {
        self.state == GameState::ShipPlacement
    }

    /// Returns whether the game's current state is active.
    pub fn is_state_active(&self) -> bool {
        self.state == GameState::Active
    }

    /// Returns whether the game's current state is complete.
    pub fn is_state_complete(&self) -> bool {
        self.state == GameState::Over
    }

    /// Starts the game by setting the game state to active.
    pub fn start(&mut self) {
        self.state = GameState::Active;
    }

    /// Returns as `usize` the index of the currently active player.
    pub fn turn(&self) -> usize {
        self.turn as usize
    }

    /// Returns as `usize` the index of the currently inactive player.
    pub fn not_turn(&self) -> usize {
        (self.turn + 1) as usize % 2
    }

    /// Sets the inactive player as active.
    pub fn switch_turn(&mut self) {
        self.turn = self.not_turn() as u8;
    }

    /// Returns whether it is currently a human player's turn.
    pub fn is_player_turn(&self) -> bool {
        !self.players[self.turn as usize].is_cpu
    }

    /// Returns whether a human player is currently placing ships.
    pub fn is_player_placing_ship(&self) -> bool {
        self.state == GameState::ShipPlacement && self.is_player_turn()
    }

    /// Returns whether a human player is currently selecting a space.
    pub fn is_player_selecting_space(&self) -> bool {
        self.state == GameState::Active && self.is_player_turn()
    }

    /// Returns whether the active player is CPU-controlled.
    pub fn is_active_player_cpu(&self) -> bool {
        self.players[self.turn as usize].is_cpu
    }

    /// Returns as `usize` the winner, if there is one.
    pub fn get_winner(&self) -> Option<usize> {
        match self.state {
            GameState::Over => Some(self.turn as usize),
            _ => None
        }
    }

    /// Selects a position on the opponent's grid if it is unchecked.
    pub fn select_opponent_space(&mut self, pos: &[u8; 2]) -> bool {
        let ref mut opponent = self.players[self.not_turn()];
        let selected = opponent.space(pos).is_unchecked() && opponent.select_space(pos);

        if selected && opponent.is_ship_sunk_by_pos(pos) {
            self.state = match opponent.all_ships_sunk() {
                true => GameState::Over,
                false => GameState::Active,
            };
        }

        selected
    }
}

#[derive(Clone, Copy, PartialEq)]
pub enum GameState {
    ShipPlacement,
    Active,
    Over
}

<commit_msg>Rename GameState::ShipPlacement to GameState::Placement<commit_after>use crate::{
    player::Player,
    settings::Settings,
};

pub struct Game<'a> {
    pub settings: &'a Settings,
    players: [Player; 2],
    state: GameState,
    turn: u8,
}

impl<'a> Game<'a> {
    pub fn new(settings: &Settings) -> Game {
        let grid_size = [
            settings.spaces[0],
            settings.spaces[1],
        ];

        Game {
            settings: &settings,
            players: [
                Player::new(grid_size, false),
                Player::new(grid_size, true)
            ],
            state: GameState::Placement,
            turn: 0,
        }
    }

    /// Returns a reference to the currently active player.
    pub fn active_player(&self) -> &Player {
        &self.players[self.turn as usize]
    }

    /// Returns a reference to the currently inactive player.
    pub fn inactive_player(&self) -> &Player {
        &self.players[self.not_turn()]
    }

    /// Returns a mutable reference to the currently active player.
    pub fn active_player_mut(&mut self) -> &mut Player {
        &mut self.players[self.turn as usize]
    }

    /// Returns whether the game's current state is ship placement.
    pub fn is_state_placement(&self) -> bool {
        self.state == GameState::Placement
    }

    /// Returns whether the game's current state is active.
    pub fn is_state_active(&self) -> bool {
        self.state == GameState::Active
    }

    /// Returns whether the game's current state is complete.
    pub fn is_state_complete(&self) -> bool {
        self.state == GameState::Over
    }

    /// Starts the game by setting the game state to active.
    pub fn start(&mut self) {
        self.state = GameState::Active;
    }

    /// Returns as `usize` the index of the currently active player.
    pub fn turn(&self) -> usize {
        self.turn as usize
    }

    /// Returns as `usize` the index of the currently inactive player.
    pub fn not_turn(&self) -> usize {
        (self.turn + 1) as usize % 2
    }

    /// Sets the inactive player as active.
    pub fn switch_turn(&mut self) {
        self.turn = self.not_turn() as u8;
    }

    /// Returns whether it is currently a human player's turn.
    pub fn is_player_turn(&self) -> bool {
        !self.players[self.turn as usize].is_cpu
    }

    /// Returns whether a human player is currently placing ships.
    pub fn is_player_placing_ship(&self) -> bool {
        self.state == GameState::Placement && self.is_player_turn()
    }

    /// Returns whether a human player is currently selecting a space.
    pub fn is_player_selecting_space(&self) -> bool {
        self.state == GameState::Active && self.is_player_turn()
    }

    /// Returns whether the active player is CPU-controlled.
    pub fn is_active_player_cpu(&self) -> bool {
        self.players[self.turn as usize].is_cpu
    }

    /// Returns as `usize` the winner, if there is one.
    pub fn get_winner(&self) -> Option<usize> {
        match self.state {
            GameState::Over => Some(self.turn as usize),
            _ => None
        }
    }

    /// Selects a position on the opponent's grid if it is unchecked.
    pub fn select_opponent_space(&mut self, pos: &[u8; 2]) -> bool {
        let ref mut opponent = self.players[self.not_turn()];
        let selected = opponent.space(pos).is_unchecked() && opponent.select_space(pos);

        if selected && opponent.is_ship_sunk_by_pos(pos) {
            self.state = match opponent.all_ships_sunk() {
                true => GameState::Over,
                false => GameState::Active,
            };
        }

        selected
    }
}

#[derive(Clone, Copy, PartialEq)]
pub enum GameState {
    Placement,
    Active,
    Over
}

<|endoftext|>


<commit_before>use std::io::Writer;
use std::io::Reader;
use std::io;
use std::vec;
use std::result::Ok;
use std::result::Err;

pub struct VecWriter {
    vec: ~[u8],
}

impl VecWriter {
    pub fn new() -> VecWriter {
        VecWriter {
            vec: ~[],
        }
    }
}

impl Writer for VecWriter {
    fn write(&mut self, v: &[u8]) -> io::IoResult<()> {
        self.vec.push_all(v);
        Ok(())
    }
}

pub struct VecReader {
    vec: ~[u8],
    pos: uint,
}

impl VecReader {
    pub fn new(bytes: ~[u8]) -> VecReader {
        VecReader {
            vec: bytes,
            pos: 0,
        }
    }

    fn remaining(&self) -> uint {
        self.vec.len() - self.pos
    }
}

impl Reader for VecReader {
    fn read(&mut self, bytes: &mut [u8]) -> io::IoResult<uint> {
        if self.remaining() == 0 {
            Err(io::standard_error(io::EndOfFile))
        } else {
            let n = if bytes.len() < self.remaining() { bytes.len() } else { self.remaining() };
            vec::bytes::copy_memory(bytes, self.vec.slice(self.pos, self.pos + n));
            self.pos += n;
            Ok(n)
        }
    }
}

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

    use std::io::Writer;

    #[test]
    fn test_vec_writer() {
        let mut w = VecWriter::new();
        fn foo(writer: &mut Writer) {
            writer.write("hi".as_bytes()).unwrap();
        }
        foo(&mut w as &mut Writer);
        assert_eq!(~['h' as u8, 'i' as u8], w.vec.to_owned());
    }
}
<commit_msg>follow changes in rust master<commit_after>use std::io::Writer;
use std::io::Reader;
use std::io;
use std::slice;
use std::result::Ok;
use std::result::Err;

pub struct VecWriter {
    vec: ~[u8],
}

impl VecWriter {
    pub fn new() -> VecWriter {
        VecWriter {
            vec: ~[],
        }
    }
}

impl Writer for VecWriter {
    fn write(&mut self, v: &[u8]) -> io::IoResult<()> {
        self.vec.push_all(v);
        Ok(())
    }
}

pub struct VecReader {
    vec: ~[u8],
    pos: uint,
}

impl VecReader {
    pub fn new(bytes: ~[u8]) -> VecReader {
        VecReader {
            vec: bytes,
            pos: 0,
        }
    }

    fn remaining(&self) -> uint {
        self.vec.len() - self.pos
    }
}

impl Reader for VecReader {
    fn read(&mut self, bytes: &mut [u8]) -> io::IoResult<uint> {
        if self.remaining() == 0 {
            Err(io::standard_error(io::EndOfFile))
        } else {
            let n = if bytes.len() < self.remaining() { bytes.len() } else { self.remaining() };
            slice::bytes::copy_memory(bytes, self.vec.slice(self.pos, self.pos + n));
            self.pos += n;
            Ok(n)
        }
    }
}

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

    use std::io::Writer;

    #[test]
    fn test_vec_writer() {
        let mut w = VecWriter::new();
        fn foo(writer: &mut Writer) {
            writer.write("hi".as_bytes()).unwrap();
        }
        foo(&mut w as &mut Writer);
        assert_eq!(~['h' as u8, 'i' as u8], w.vec.to_owned());
    }
}
<|endoftext|>


<commit_before>use castle::*;
use piece::*;
use position::State;
use rand::{RngCore, SeedableRng, StdRng};
use side::*;
use square;
use square::Square;

/// Zobrist represents a set of keys for Zobrist hashing
#[derive(Debug)]
pub struct Zobrist {
    pieces: [u64; 12], // rotated based on square
    castling_rights: [u64; 16],
    en_passant_file: [u64; 8],
    castles: [[u64; 2]; 2], // pre-computed based on piece-square changes
    stm: u64,
}

/// Default zobrist_keys generated with seed = 1
pub static DEFAULT_ZOBRISH_HASH: Zobrist = Zobrist {
    pieces: [
        16257666806172921645,
        12079090740189436754,
        11577349684372483860,
        8265070477432972399,
        17204147743807346879,
        10840387247671765879,
        11023604230088064055,
        15372782004648025408,
        17607845492419163657,
        4820222721347483354,
        9222096121752829227,
        10997107696558716930,
    ],

    castling_rights: [
        5901611952838449075,
        16928860654864062033,
        3006969943347880664,
        16761043879460025667,
        15332107909825879061,
        1522114280938701486,
        1327047711097840467,
        7301561155728042398,
        4479697827097181280,
        2468172810615015476,
        11492078287679521532,
        11685917599786030246,
        10403772991926020454,
        17478376828681188621,
        15580394547059712216,
        4575347809368850956,
    ],

    en_passant_file: [
        3348961424409688254,
        2427135436213657123,
        2898060206792371384,
        14683683615540271254,
        952321900370658987,
        5796203641919266782,
        9554333785051357809,
        12082317543310182802,
    ],

    castles: [
        [10993434298710260570, 16775444492128222288],
        [13399088802984349794, 13139464958289927509],
    ],

    stm: 5703255076737973876,
};

impl Zobrist {
    #[allow(dead_code)]
    fn new(seed: [u8; 32]) -> Zobrist {
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        let mut keys = Zobrist {
            pieces: [0; 12],
            castling_rights: [0; 16],
            castles: [[0; 2]; 2],
            en_passant_file: [0; 8],
            stm: 0,
        };

        for pc in 0..12 {
            keys.pieces[pc] = rng.next_u64();
        }

        for cr in 0..16 {
            keys.castling_rights[cr] = rng.next_u64();
        }

        for ep in 0..8 {
            keys.en_passant_file[ep] = rng.next_u64();
        }

        keys.stm = rng.next_u64();

        // pre-compute castles
        for &side in &[WHITE, BLACK] {
            for &castle in &[QUEEN_SIDE, KING_SIDE] {
                let mut hash = 0u64;

                let (king_from, king_to) = castle_king_squares(side, castle);
                hash ^= keys.piece_square(KING.pc(side), king_from);
                hash ^= keys.piece_square(KING.pc(side), king_to);

                let (rook_from, rook_to) = castle_rook_squares(side, castle);
                hash ^= keys.piece_square(ROOK.pc(side), rook_to);
                hash ^= keys.piece_square(ROOK.pc(side), rook_from);

                keys.castles[castle.to_usize()][side.to_usize()] = hash;
            }
        }

        keys
    }

    /// Generates the hash of the entire position
    pub fn position(&self, grid: &[Piece; 64], state: &State) -> u64 {
        let mut hash = 0u64;

        for (idx, &pc) in grid.iter().enumerate().filter(|&(_, &pc)| pc.is_some()) {
            hash ^= self.piece_square(pc, Square::new(idx as square::Internal));
        }

        hash ^= self.castling_rights[state.castling_rights.to_usize()];

        hash ^= self.ep_hash(state.ep_square);

        hash
    }

    /// Generates the difference between two states
    #[inline]
    pub fn state(&self, before: &State, after: &State) -> u64 {
        self.castling_rights[before.castling_rights.to_usize()]
            ^ self.castling_rights[after.castling_rights.to_usize()]
            ^ self.ep_hash(before.ep_square)
            ^ self.ep_hash(after.ep_square)
            ^ self.stm
    }

    #[inline]
    pub fn castle(&self, castle: Castle, stm: Side) -> u64 {
        self.castles[castle.to_usize()][stm.to_usize()]
    }

    #[inline]
    pub fn capture(&self, captured: Piece, capture_square: Square) -> u64 {
        self.piece_square(captured, capture_square)
    }

    #[inline]
    pub fn push(&self, pc_from: Piece, from: Square, pc_to: Piece, to: Square) -> u64 {
        self.piece_square(pc_from, from) ^ self.piece_square(pc_to, to)
    }

    #[inline]
    fn piece_square(&self, piece: Piece, square: Square) -> u64 {
        self.pieces[piece.to_usize()].rotate_left(square.to_u32())
    }

    #[inline]
    fn ep_hash(&self, ep_square: Option<Square>) -> u64 {
        if ep_square.is_some() {
            self.en_passant_file[ep_square.unwrap().col() as usize]
        } else {
            0
        }
    }
}

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

    #[test]
    fn test_castle() {
        let keys = Zobrist::new([
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
            25, 26, 27, 28, 29, 30, 31, 32,
        ]);

        let side = WHITE;
        let castle = QUEEN_SIDE;

        let actual_key = keys.castle(castle, side);

        let mut expected_key = 0u64;
        expected_key ^= keys.piece_square(WHITE_KING, E1);
        expected_key ^= keys.piece_square(WHITE_KING, C1);
        expected_key ^= keys.piece_square(WHITE_ROOK, A1);
        expected_key ^= keys.piece_square(WHITE_ROOK, D1);

        assert_eq!(actual_key, expected_key);
    }
}
<commit_msg>over-optimise stuff<commit_after>use castle::*;
use piece::*;
use position::State;
use rand::{rngs::StdRng, RngCore, SeedableRng};
use side::*;
use square;
use square::Square;

/// Zobrist represents a set of keys for Zobrist hashing
#[derive(Debug)]
pub struct Zobrist {
    pieces: [u64; 12], // rotated based on square
    castling_rights: [u64; 16],
    en_passant_file: [u64; 8],
    castles: [[u64; 2]; 2], // pre-computed based on piece-square changes
    stm: u64,
}

/// Default zobrist_keys generated with seed = 1
pub static DEFAULT_ZOBRISH_HASH: Zobrist = Zobrist {
    pieces: [
        16257666806172921645,
        12079090740189436754,
        11577349684372483860,
        8265070477432972399,
        17204147743807346879,
        10840387247671765879,
        11023604230088064055,
        15372782004648025408,
        17607845492419163657,
        4820222721347483354,
        9222096121752829227,
        10997107696558716930,
    ],

    castling_rights: [
        5901611952838449075,
        16928860654864062033,
        3006969943347880664,
        16761043879460025667,
        15332107909825879061,
        1522114280938701486,
        1327047711097840467,
        7301561155728042398,
        4479697827097181280,
        2468172810615015476,
        11492078287679521532,
        11685917599786030246,
        10403772991926020454,
        17478376828681188621,
        15580394547059712216,
        4575347809368850956,
    ],

    en_passant_file: [
        3348961424409688254,
        2427135436213657123,
        2898060206792371384,
        14683683615540271254,
        952321900370658987,
        5796203641919266782,
        9554333785051357809,
        12082317543310182802,
    ],

    castles: [
        [10993434298710260570, 16775444492128222288],
        [13399088802984349794, 13139464958289927509],
    ],

    stm: 5703255076737973876,
};

impl Zobrist {
    #[allow(dead_code)]
    fn new(seed: [u8; 32]) -> Zobrist {
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        let mut keys = Zobrist {
            pieces: [0; 12],
            castling_rights: [0; 16],
            castles: [[0; 2]; 2],
            en_passant_file: [0; 8],
            stm: 0,
        };

        for pc in 0..12 {
            keys.pieces[pc] = rng.next_u64();
        }

        for cr in 0..16 {
            keys.castling_rights[cr] = rng.next_u64();
        }

        for ep in 0..8 {
            keys.en_passant_file[ep] = rng.next_u64();
        }

        keys.stm = rng.next_u64();

        // pre-compute castles
        for &side in &[WHITE, BLACK] {
            for &castle in &[QUEEN_SIDE, KING_SIDE] {
                let mut hash = 0u64;

                let (king_from, king_to) = castle_king_squares(side, castle);
                hash ^= keys.piece_square(KING.pc(side), king_from);
                hash ^= keys.piece_square(KING.pc(side), king_to);

                let (rook_from, rook_to) = castle_rook_squares(side, castle);
                hash ^= keys.piece_square(ROOK.pc(side), rook_to);
                hash ^= keys.piece_square(ROOK.pc(side), rook_from);

                keys.castles[castle.to_usize()][side.to_usize()] = hash;
            }
        }

        keys
    }

    /// Generates the hash of the entire position
    pub fn position(&self, grid: &[Piece; 64], state: &State) -> u64 {
        let mut hash = 0u64;

        for (idx, &pc) in grid.iter().enumerate().filter(|&(_, &pc)| pc.is_some()) {
            hash ^= self.piece_square(pc, Square::new(idx as square::Internal));
        }

        hash ^= self.castling_rights[state.castling_rights.to_usize()];

        hash ^= self.ep_hash(state.ep_square);

        hash
    }

    /// Generates the difference between two states
    #[inline]
    pub fn state(&self, before: &State, after: &State) -> u64 {
        self.castling_rights[before.castling_rights.to_usize()]
            ^ self.castling_rights[after.castling_rights.to_usize()]
            ^ self.ep_hash(before.ep_square)
            ^ self.ep_hash(after.ep_square)
            ^ self.stm
    }

    #[inline]
    pub fn castle(&self, castle: Castle, stm: Side) -> u64 {
        return unsafe {
            *self
                .castles
                .get_unchecked(castle.to_usize())
                .get_unchecked(stm.to_usize())
        };
    }

    #[inline]
    pub fn capture(&self, captured: Piece, capture_square: Square) -> u64 {
        self.piece_square(captured, capture_square)
    }

    #[inline]
    pub fn push(&self, pc_from: Piece, from: Square, pc_to: Piece, to: Square) -> u64 {
        self.piece_square(pc_from, from) ^ self.piece_square(pc_to, to)
    }

    #[inline]
    fn piece_square(&self, piece: Piece, square: Square) -> u64 {
        return unsafe {
            (*self.pieces.get_unchecked(piece.to_usize())).rotate_left(square.to_u32())
        };
    }

    #[inline]
    fn ep_hash(&self, ep_square: Option<Square>) -> u64 {
        if ep_square.is_some() {
            return unsafe {
                *self
                    .en_passant_file
                    .get_unchecked(ep_square.unwrap().col() as usize)
            };
        } else {
            0
        }
    }
}

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

    #[test]
    fn test_castle() {
        let keys = Zobrist::new([
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
            25, 26, 27, 28, 29, 30, 31, 32,
        ]);

        let side = WHITE;
        let castle = QUEEN_SIDE;

        let actual_key = keys.castle(castle, side);

        let mut expected_key = 0u64;
        expected_key ^= keys.piece_square(WHITE_KING, E1);
        expected_key ^= keys.piece_square(WHITE_KING, C1);
        expected_key ^= keys.piece_square(WHITE_ROOK, A1);
        expected_key ^= keys.piece_square(WHITE_ROOK, D1);

        assert_eq!(actual_key, expected_key);
    }
}
<|endoftext|>


<commit_before>use std::process::Command;
use std::str;

use repo_config::*;

use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::sha1::Sha1;

use rustc_serialize::hex::ToHex;
use rustc_serialize::json::*;

#[derive(Debug)]
pub struct GithubHook {
    pub event: String,
    pub payload: String,
    pub signature: String,
    pub config_root: String
}

impl GithubHook {
    pub fn new(event: &str, payload: &str, signature: &str, config_root: &str) -> GithubHook {
        GithubHook {
            event: event.to_string(),
            payload: payload.to_string(),
            signature: signature.to_string(),
            config_root: config_root.to_string()
        }
    }

    pub fn receive(&self) {
        let json_payload = Json::from_str(&self.payload).unwrap();
        let repo_name = json_payload.find_path(&["repository", "full_name"]).unwrap().as_string().unwrap();

        info!("Received payload for {}", repo_name);

        let repo_config_filename = self.config_root.clone() + "/" + &str::replace(&repo_name, "/", "__") + ".json";
        let repo_config = RepoConfig::new(repo_config_filename);

        match repo_config.secret {
            None => {
                info!("No secret in config file, skipping validation.");
            },
            Some(secret) => {
                match self.is_valid(secret.into_bytes()) {
                    false => {
                        error!("Payload validation failed, aborting!");
                        panic!();
                    },
                    true => {
                        info!("Payload validation succeeded.");
                    }
                };
            }
        };

        let push_ref = json_payload.find("ref").unwrap().as_string().unwrap();
        for aref in &repo_config.refs {
            if aref == push_ref {
                match Command::new(repo_config.command).status() {
                    Ok(_) => {
                        info!("Command ran successfully.");
                    },
                    Err(exception) => {
                        error!("Command failed: {}", exception);
                    }
                };
                break;
            }
        }
    }

    fn is_valid(&self, secret: Vec<u8>) -> bool {
        let raw_signature = str::replace(&self.signature, "sha1=", "");
        let mut hmac = Hmac::new(Sha1::new(), &secret);

        hmac.input(&self.payload.as_bytes()[..]);
        let result = hmac.result().code().to_hex();

        raw_signature == result
    }
}
<commit_msg>Move signature existence check into is_valid()<commit_after>use std::process::Command;
use std::str;

use repo_config::*;

use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::sha1::Sha1;

use rustc_serialize::hex::ToHex;
use rustc_serialize::json::*;

#[derive(Debug)]
pub struct GithubHook {
    pub event: String,
    pub payload: String,
    pub signature: String,
    pub config_root: String
}

impl GithubHook {
    pub fn new(event: &str, payload: &str, signature: &str, config_root: &str) -> GithubHook {
        GithubHook {
            event: event.to_string(),
            payload: payload.to_string(),
            signature: signature.to_string(),
            config_root: config_root.to_string()
        }
    }

    pub fn receive(&self) {
        let json_payload = Json::from_str(&self.payload).unwrap();
        let repo_name = json_payload.find_path(&["repository", "full_name"]).unwrap().as_string().unwrap();

        info!("Received payload for {}", repo_name);

        let repo_config_filename = self.config_root.clone() + "/" + &str::replace(&repo_name, "/", "__") + ".json";
        let repo_config = RepoConfig::new(repo_config_filename);

        match self.is_valid(repo_config.secret) {
            false => {
                error!("Payload validation failed, aborting!");
                panic!();
            },
            true => {
                info!("Payload validation succeeded.");
            }
        };

        let push_ref = json_payload.find("ref").unwrap().as_string().unwrap();
        for aref in &repo_config.refs {
            if aref == push_ref {
                match Command::new(repo_config.command).status() {
                    Ok(_) => {
                        info!("Command ran successfully.");
                    },
                    Err(exception) => {
                        error!("Command failed: {}", exception);
                    }
                };
                break;
            }
        }
    }

    fn is_valid(&self, secret: Option<String>) -> bool {
        match secret {
            None => {
                info!("No secret in config file, skipping validation.");
                true
            },
            Some(secret) => {
                let mut hmac = Hmac::new(Sha1::new(), &secret.as_bytes());
                hmac.input(&self.payload.as_bytes()[..]);

                str::replace(&self.signature, "sha1=", "") == hmac.result().code().to_hex()
            }
        }
    }
}
<|endoftext|>