<commit_before>//! Lightweight, event-driven WebSockets for Rust.
#![deny(
    missing_copy_implementations,
    trivial_casts, trivial_numeric_casts,
    unstable_features,
    unused_import_braces)]

extern crate httparse;
extern crate mio;
extern crate sha1;
extern crate rand;
extern crate url;
extern crate slab;
extern crate bytes;
extern crate byteorder;
#[cfg(feature="ssl")] extern crate openssl;
#[macro_use] extern crate log;

mod result;
mod connection;
mod handler;
mod factory;
mod frame;
mod message;
mod handshake;
mod protocol;
mod communication;
mod io;
mod stream;

#[cfg(feature="permessage-deflate")]
pub mod deflate;

pub mod util;

pub use factory::Factory;
pub use handler::Handler;

pub use result::{Result, Error};
pub use result::Kind as ErrorKind;
pub use message::Message;
pub use communication::Sender;
pub use frame::Frame;
pub use protocol::{CloseCode, OpCode};
pub use handshake::{Handshake, Request, Response};

use std::fmt;
use std::default::Default;
use std::net::ToSocketAddrs;
use std::borrow::Borrow;

use mio::Poll;

/// A utility function for setting up a WebSocket server.
///
/// # Safety
///
/// This function blocks until the event loop finishes running. Avoid calling this method within
/// another WebSocket handler.
///
/// # Examples
///
/// ```no_run
/// use ws::listen;
///
/// listen("127.0.0.1:3012", |out| {
///     move |msg| {
///        out.send(msg)
///    }
/// }).unwrap()
/// ```
///
pub fn listen<A, F, H>(addr: A, factory: F) -> Result<()>
    where
        A: ToSocketAddrs + fmt::Debug,
        F: FnMut(Sender) -> H,
        H: Handler,
{
    let ws = try!(WebSocket::new(factory));
    try!(ws.listen(addr));
    Ok(())
}

/// A utility function for setting up a WebSocket client.
///
/// # Safety
///
/// This function blocks until the event loop finishes running. Avoid calling this method within
/// another WebSocket handler. If you need to establish a connection from inside of a handler,
/// use the `connect` method on the Sender.
///
/// # Examples
///
/// ```no_run
/// use ws::{connect, CloseCode};
///
/// connect("ws://127.0.0.1:3012", |out| {
///     out.send("Hello WebSocket").unwrap();
///
///     move |msg| {
///         println!("Got message: {}", msg);
///         out.close(CloseCode::Normal)
///     }
/// }).unwrap()
/// ```
///
pub fn connect<U, F, H>(url: U, factory: F) -> Result<()>
    where
        U: Borrow<str>,
        F: FnMut(Sender) -> H,
        H: Handler
{
    let mut ws = try!(WebSocket::new(factory));
    let parsed = try!(
        url::Url::parse(url.borrow())
            .map_err(|err| Error::new(
                ErrorKind::Internal,
                format!("Unable to parse {} as url due to {:?}", url.borrow(), err))));
    try!(ws.connect(parsed));
    try!(ws.run());
    Ok(())
}

/// WebSocket settings
#[derive(Debug, Clone, Copy)]
pub struct Settings {
    /// The maximum number of connections that this WebSocket will support.
    /// The default setting is low and should be increased when expecting more
    /// connections because this is a hard limit and no new connections beyond
    /// this limit can be made until an old connection is dropped.
    /// Default: 100
    pub max_connections: usize,
    /// The number of events anticipated per connection. The event loop queue size will
    /// be `queue_size` * `max_connections`. In order to avoid an overflow error,
    /// `queue_size` * `max_connections` must be less than or equal to `usize::max_value()`.
    /// The queue is shared between connections, which means that a connection may schedule
    /// more events than `queue_size` provided that another connection is using less than
    /// `queue_size`. However, if the queue is maxed out a Queue error will occur.
    /// Default: 5
    pub queue_size: usize,
    /// Whether to panic when unable to establish a new TCP connection.
    /// Default: false
    pub panic_on_new_connection: bool,
    /// Whether to panic when a shutdown of the WebSocket is requested.
    /// Default: false
    pub panic_on_shutdown: bool,
    /// The maximum number of fragments the connection can handle without reallocating.
    /// Default: 10
    pub fragments_capacity: usize,
    /// Whether to reallocate when `fragments_capacity` is reached. If this is false,
    /// a Capacity error will be triggered instead.
    /// Default: true
    pub fragments_grow: bool,
    /// The maximum length of outgoing frames. Messages longer than this will be fragmented.
    /// Default: 65,535
    pub fragment_size: usize,
    /// The size of the incoming buffer. A larger buffer uses more memory but will allow for fewer
    /// reallocations.
    /// Default: 2048
    pub in_buffer_capacity: usize,
    /// Whether to reallocate the incoming buffer when `in_buffer_capacity` is reached. If this is
    /// false, a Capacity error will be triggered instead.
    /// Default: true
    pub in_buffer_grow: bool,
    /// The size of the outgoing buffer. A larger buffer uses more memory but will allow for fewer
    /// reallocations.
    /// Default: 2048
    pub out_buffer_capacity: usize,
    /// Whether to reallocate the incoming buffer when `out_buffer_capacity` is reached. If this is
    /// false, a Capacity error will be triggered instead.
    /// Default: true
    pub out_buffer_grow: bool,
    /// Whether to panic when an Internal error is encountered. Internal errors should generally
    /// not occur, so this setting defaults to true as a debug measure, whereas production
    /// applications should consider setting it to false.
    /// Default: true
    pub panic_on_internal: bool,
    /// Whether to panic when a Capacity error is encountered.
    /// Default: false
    pub panic_on_capacity: bool,
    /// Whether to panic when a Protocol error is encountered.
    /// Default: false
    pub panic_on_protocol: bool,
    /// Whether to panic when an Encoding error is encountered.
    /// Default: false
    pub panic_on_encoding: bool,
    /// Whether to panic when a Queue error is encountered.
    /// Default: false
    pub panic_on_queue: bool,
    /// Whether to panic when an Io error is encountered.
    /// Default: false
    pub panic_on_io: bool,
    /// Whether to panic when a Timer error is encountered.
    /// Default: false
    pub panic_on_timeout: bool,
    /// Whether to shutdown the eventloop when an interrupt is received.
    /// Default: true
    pub shutdown_on_interrupt: bool,
    /// The WebSocket protocol requires frames sent from client endpoints to be masked as a
    /// security and sanity precaution. Enforcing this requirement, which may be removed at some
    /// point may cause incompatibilities. If you need the extra security, set this to true.
    /// Default: false
    pub masking_strict: bool,
    /// The WebSocket protocol requires clients to verify the key returned by a server to ensure
    /// that the server and all intermediaries can perform the protocol. Verifying the key will
    /// consume processing time and other resources with the benifit that we can fail the
    /// connection early. The default in WS-RS is to accept any key from the server and instead
    /// fail late if a protocol error occurs. Change this setting to enable key verification.
    /// Default: false
    pub key_strict: bool,
    /// The WebSocket protocol requires clients to perform an opening handshake using the HTTP
    /// GET method for the request. However, since only WebSockets are supported on the connection,
    /// verifying the method of handshake requests is not always necessary. To enforce the
    /// requirement that handshakes begin with a GET method, set this to true.
    /// Default: false
    pub method_strict: bool,
    /// Indicate whether server connections should use ssl encryption when accepting connections.
    /// Setting this to true means that clients should use the `wss` scheme to connect to this
    /// server. Note that using this flag will in general necessitate overriding the
    /// `Handler::upgrade_ssl_server` method in order to provide the details of the ssl context. It may be
    /// simpler for most users to use a reverse proxy such as nginx to provide server side
    /// encryption.
    ///
    /// Default: false
    pub encrypt_server: bool,
    /// Disables Nagle's algorithm.
    /// Usually tcp socket tries to accumulate packets to send them all together (every 200ms).
    /// When enabled socket will try to send packet as fast as possible.
    ///
    /// Default: false
    pub tcp_nodelay: bool
}

impl Default for Settings {

    fn default() -> Settings {
        Settings {
            max_connections: 100,
            queue_size: 5,
            panic_on_new_connection: false,
            panic_on_shutdown: false,
            fragments_capacity: 10,
            fragments_grow: true,
            fragment_size: u16::max_value() as usize,
            in_buffer_capacity: 2048,
            in_buffer_grow: true,
            out_buffer_capacity: 2048,
            out_buffer_grow: true,
            panic_on_internal: true,
            panic_on_capacity: false,
            panic_on_protocol: false,
            panic_on_encoding: false,
            panic_on_queue: false,
            panic_on_io: false,
            panic_on_timeout: false,
            shutdown_on_interrupt: true,
            masking_strict: false,
            key_strict: false,
            method_strict: false,
            encrypt_server: false,
            tcp_nodelay: false
        }
    }
}

/// The WebSocket struct. A WebSocket can support multiple incoming and outgoing connections.
pub struct WebSocket<F>
    where F: Factory
{
    poll: Poll,
    handler: io::Handler<F>,
}

impl<F> WebSocket<F>
    where F: Factory
{
    /// Create a new WebSocket using the given Factory to create handlers.
    pub fn new(factory: F) -> Result<WebSocket<F>> {
        Builder::new().build(factory)
    }

    /// Consume the WebSocket and listen for new connections on the specified address.
    ///
    /// # Safety
    ///
    /// This method will block until the event loop finishes running.
    pub fn listen<A>(mut self, addr_spec: A) -> Result<WebSocket<F>>
        where A: ToSocketAddrs + fmt::Debug
    {
        let mut result = Err(Error::new(ErrorKind::Internal, format!("Unable to listen on {:?}", addr_spec)));

        for addr in try!(addr_spec.to_socket_addrs()) {
            result = self.handler.listen(&mut self.poll, &addr).map(|_| ());
            if result.is_ok() {
                info!("Listening for new connections on {}.", addr);
                return self.run()
            }
        }

        result.map(|_| self)
    }

    /// Queue an outgoing connection on this WebSocket. This method may be called multiple times,
    /// but the actual connections will not be established until after `run` is called.
    pub fn connect(&mut self, url: url::Url) -> Result<&mut WebSocket<F>> {
        let sender = self.handler.sender();
        info!("Queuing connection to {}", url);
        try!(sender.connect(url));
        Ok(self)
    }

    /// Run the WebSocket. This will run the encapsulated event loop blocking until the WebSocket
    /// is shutdown.
    pub fn run(mut self) -> Result<WebSocket<F>> {
        try!(self.handler.run(&mut self.poll));
        Ok(self)
    }

    /// Get a Sender that can be used to send messages on all connections.
    /// Calling `send` on this Sender is equivalent to calling `broadcast`.
    /// Calling `shutdown` on this Sender will shudown the WebSocket even if no connections have
    /// been established.
    #[inline]
    pub fn broadcaster(&self) -> Sender {
        self.handler.sender()
    }
}

/// Utility for constructing a WebSocket from various settings.
#[derive(Debug, Clone, Copy)]
pub struct Builder {
    settings: Settings,
}

// TODO: add convenience methods for each setting
impl Builder {
    /// Create a new Builder with default settings.
    pub fn new() -> Builder {
        Builder {
            settings: Settings::default(),
        }
    }

    /// Build a WebSocket using this builder and a factory.
    /// It is possible to use the same builder to create multiple WebSockets.
    pub fn build<F>(&self, factory: F) -> Result<WebSocket<F>>
        where F: Factory
    {
        Ok(WebSocket {
            poll: try!(Poll::new()),
            handler: io::Handler::new(factory, self.settings),
        })
    }

    /// Set the WebSocket settings to use.
    pub fn with_settings(&mut self, settings: Settings) -> &mut Builder {
        self.settings = settings;
        self
    }
}
<commit_msg>add local_addr method on WebSocket<commit_after>//! Lightweight, event-driven WebSockets for Rust.
#![deny(
    missing_copy_implementations,
    trivial_casts, trivial_numeric_casts,
    unstable_features,
    unused_import_braces)]

extern crate httparse;
extern crate mio;
extern crate sha1;
extern crate rand;
extern crate url;
extern crate slab;
extern crate bytes;
extern crate byteorder;
#[cfg(feature="ssl")] extern crate openssl;
#[macro_use] extern crate log;

mod result;
mod connection;
mod handler;
mod factory;
mod frame;
mod message;
mod handshake;
mod protocol;
mod communication;
mod io;
mod stream;

#[cfg(feature="permessage-deflate")]
pub mod deflate;

pub mod util;

pub use factory::Factory;
pub use handler::Handler;

pub use result::{Result, Error};
pub use result::Kind as ErrorKind;
pub use message::Message;
pub use communication::Sender;
pub use frame::Frame;
pub use protocol::{CloseCode, OpCode};
pub use handshake::{Handshake, Request, Response};

use std::fmt;
use std::default::Default;
use std::net::{SocketAddr, ToSocketAddrs};
use std::borrow::Borrow;

use mio::Poll;

/// A utility function for setting up a WebSocket server.
///
/// # Safety
///
/// This function blocks until the event loop finishes running. Avoid calling this method within
/// another WebSocket handler.
///
/// # Examples
///
/// ```no_run
/// use ws::listen;
///
/// listen("127.0.0.1:3012", |out| {
///     move |msg| {
///        out.send(msg)
///    }
/// }).unwrap()
/// ```
///
pub fn listen<A, F, H>(addr: A, factory: F) -> Result<()>
    where
        A: ToSocketAddrs + fmt::Debug,
        F: FnMut(Sender) -> H,
        H: Handler,
{
    let ws = try!(WebSocket::new(factory));
    try!(ws.listen(addr));
    Ok(())
}

/// A utility function for setting up a WebSocket client.
///
/// # Safety
///
/// This function blocks until the event loop finishes running. Avoid calling this method within
/// another WebSocket handler. If you need to establish a connection from inside of a handler,
/// use the `connect` method on the Sender.
///
/// # Examples
///
/// ```no_run
/// use ws::{connect, CloseCode};
///
/// connect("ws://127.0.0.1:3012", |out| {
///     out.send("Hello WebSocket").unwrap();
///
///     move |msg| {
///         println!("Got message: {}", msg);
///         out.close(CloseCode::Normal)
///     }
/// }).unwrap()
/// ```
///
pub fn connect<U, F, H>(url: U, factory: F) -> Result<()>
    where
        U: Borrow<str>,
        F: FnMut(Sender) -> H,
        H: Handler
{
    let mut ws = try!(WebSocket::new(factory));
    let parsed = try!(
        url::Url::parse(url.borrow())
            .map_err(|err| Error::new(
                ErrorKind::Internal,
                format!("Unable to parse {} as url due to {:?}", url.borrow(), err))));
    try!(ws.connect(parsed));
    try!(ws.run());
    Ok(())
}

/// WebSocket settings
#[derive(Debug, Clone, Copy)]
pub struct Settings {
    /// The maximum number of connections that this WebSocket will support.
    /// The default setting is low and should be increased when expecting more
    /// connections because this is a hard limit and no new connections beyond
    /// this limit can be made until an old connection is dropped.
    /// Default: 100
    pub max_connections: usize,
    /// The number of events anticipated per connection. The event loop queue size will
    /// be `queue_size` * `max_connections`. In order to avoid an overflow error,
    /// `queue_size` * `max_connections` must be less than or equal to `usize::max_value()`.
    /// The queue is shared between connections, which means that a connection may schedule
    /// more events than `queue_size` provided that another connection is using less than
    /// `queue_size`. However, if the queue is maxed out a Queue error will occur.
    /// Default: 5
    pub queue_size: usize,
    /// Whether to panic when unable to establish a new TCP connection.
    /// Default: false
    pub panic_on_new_connection: bool,
    /// Whether to panic when a shutdown of the WebSocket is requested.
    /// Default: false
    pub panic_on_shutdown: bool,
    /// The maximum number of fragments the connection can handle without reallocating.
    /// Default: 10
    pub fragments_capacity: usize,
    /// Whether to reallocate when `fragments_capacity` is reached. If this is false,
    /// a Capacity error will be triggered instead.
    /// Default: true
    pub fragments_grow: bool,
    /// The maximum length of outgoing frames. Messages longer than this will be fragmented.
    /// Default: 65,535
    pub fragment_size: usize,
    /// The size of the incoming buffer. A larger buffer uses more memory but will allow for fewer
    /// reallocations.
    /// Default: 2048
    pub in_buffer_capacity: usize,
    /// Whether to reallocate the incoming buffer when `in_buffer_capacity` is reached. If this is
    /// false, a Capacity error will be triggered instead.
    /// Default: true
    pub in_buffer_grow: bool,
    /// The size of the outgoing buffer. A larger buffer uses more memory but will allow for fewer
    /// reallocations.
    /// Default: 2048
    pub out_buffer_capacity: usize,
    /// Whether to reallocate the incoming buffer when `out_buffer_capacity` is reached. If this is
    /// false, a Capacity error will be triggered instead.
    /// Default: true
    pub out_buffer_grow: bool,
    /// Whether to panic when an Internal error is encountered. Internal errors should generally
    /// not occur, so this setting defaults to true as a debug measure, whereas production
    /// applications should consider setting it to false.
    /// Default: true
    pub panic_on_internal: bool,
    /// Whether to panic when a Capacity error is encountered.
    /// Default: false
    pub panic_on_capacity: bool,
    /// Whether to panic when a Protocol error is encountered.
    /// Default: false
    pub panic_on_protocol: bool,
    /// Whether to panic when an Encoding error is encountered.
    /// Default: false
    pub panic_on_encoding: bool,
    /// Whether to panic when a Queue error is encountered.
    /// Default: false
    pub panic_on_queue: bool,
    /// Whether to panic when an Io error is encountered.
    /// Default: false
    pub panic_on_io: bool,
    /// Whether to panic when a Timer error is encountered.
    /// Default: false
    pub panic_on_timeout: bool,
    /// Whether to shutdown the eventloop when an interrupt is received.
    /// Default: true
    pub shutdown_on_interrupt: bool,
    /// The WebSocket protocol requires frames sent from client endpoints to be masked as a
    /// security and sanity precaution. Enforcing this requirement, which may be removed at some
    /// point may cause incompatibilities. If you need the extra security, set this to true.
    /// Default: false
    pub masking_strict: bool,
    /// The WebSocket protocol requires clients to verify the key returned by a server to ensure
    /// that the server and all intermediaries can perform the protocol. Verifying the key will
    /// consume processing time and other resources with the benifit that we can fail the
    /// connection early. The default in WS-RS is to accept any key from the server and instead
    /// fail late if a protocol error occurs. Change this setting to enable key verification.
    /// Default: false
    pub key_strict: bool,
    /// The WebSocket protocol requires clients to perform an opening handshake using the HTTP
    /// GET method for the request. However, since only WebSockets are supported on the connection,
    /// verifying the method of handshake requests is not always necessary. To enforce the
    /// requirement that handshakes begin with a GET method, set this to true.
    /// Default: false
    pub method_strict: bool,
    /// Indicate whether server connections should use ssl encryption when accepting connections.
    /// Setting this to true means that clients should use the `wss` scheme to connect to this
    /// server. Note that using this flag will in general necessitate overriding the
    /// `Handler::upgrade_ssl_server` method in order to provide the details of the ssl context. It may be
    /// simpler for most users to use a reverse proxy such as nginx to provide server side
    /// encryption.
    ///
    /// Default: false
    pub encrypt_server: bool,
    /// Disables Nagle's algorithm.
    /// Usually tcp socket tries to accumulate packets to send them all together (every 200ms).
    /// When enabled socket will try to send packet as fast as possible.
    ///
    /// Default: false
    pub tcp_nodelay: bool
}

impl Default for Settings {

    fn default() -> Settings {
        Settings {
            max_connections: 100,
            queue_size: 5,
            panic_on_new_connection: false,
            panic_on_shutdown: false,
            fragments_capacity: 10,
            fragments_grow: true,
            fragment_size: u16::max_value() as usize,
            in_buffer_capacity: 2048,
            in_buffer_grow: true,
            out_buffer_capacity: 2048,
            out_buffer_grow: true,
            panic_on_internal: true,
            panic_on_capacity: false,
            panic_on_protocol: false,
            panic_on_encoding: false,
            panic_on_queue: false,
            panic_on_io: false,
            panic_on_timeout: false,
            shutdown_on_interrupt: true,
            masking_strict: false,
            key_strict: false,
            method_strict: false,
            encrypt_server: false,
            tcp_nodelay: false
        }
    }
}

/// The WebSocket struct. A WebSocket can support multiple incoming and outgoing connections.
pub struct WebSocket<F>
    where F: Factory
{
    poll: Poll,
    handler: io::Handler<F>,
}

impl<F> WebSocket<F>
    where F: Factory
{
    /// Create a new WebSocket using the given Factory to create handlers.
    pub fn new(factory: F) -> Result<WebSocket<F>> {
        Builder::new().build(factory)
    }

    /// Consume the WebSocket and listen for new connections on the specified address.
    ///
    /// # Safety
    ///
    /// This method will block until the event loop finishes running.
    pub fn listen<A>(mut self, addr_spec: A) -> Result<WebSocket<F>>
        where A: ToSocketAddrs + fmt::Debug
    {
        let mut result = Err(Error::new(ErrorKind::Internal, format!("Unable to listen on {:?}", addr_spec)));

        for addr in try!(addr_spec.to_socket_addrs()) {
            result = self.handler.listen(&mut self.poll, &addr).map(|_| ());
            let addr = self.handler.local_addr().unwrap_or(addr);
            if result.is_ok() {
                info!("Listening for new connections on {}.", addr);
                return self.run()
            }
        }

        result.map(|_| self)
    }

    /// Queue an outgoing connection on this WebSocket. This method may be called multiple times,
    /// but the actual connections will not be established until after `run` is called.
    pub fn connect(&mut self, url: url::Url) -> Result<&mut WebSocket<F>> {
        let sender = self.handler.sender();
        info!("Queuing connection to {}", url);
        try!(sender.connect(url));
        Ok(self)
    }

    /// Run the WebSocket. This will run the encapsulated event loop blocking until the WebSocket
    /// is shutdown.
    pub fn run(mut self) -> Result<WebSocket<F>> {
        try!(self.handler.run(&mut self.poll));
        Ok(self)
    }

    /// Get a Sender that can be used to send messages on all connections.
    /// Calling `send` on this Sender is equivalent to calling `broadcast`.
    /// Calling `shutdown` on this Sender will shudown the WebSocket even if no connections have
    /// been established.
    #[inline]
    pub fn broadcaster(&self) -> Sender {
        self.handler.sender()
    }

    /// Get the local socket address this socket is bound to. Will return an error
    /// if the backend returns an error. Will return a `NotFound` error if
    /// this WebSocket is not a listening socket.
    pub fn local_addr(&self) -> ::std::io::Result<SocketAddr> {
        self.handler.local_addr()
    }
}

/// Utility for constructing a WebSocket from various settings.
#[derive(Debug, Clone, Copy)]
pub struct Builder {
    settings: Settings,
}

// TODO: add convenience methods for each setting
impl Builder {
    /// Create a new Builder with default settings.
    pub fn new() -> Builder {
        Builder {
            settings: Settings::default(),
        }
    }

    /// Build a WebSocket using this builder and a factory.
    /// It is possible to use the same builder to create multiple WebSockets.
    pub fn build<F>(&self, factory: F) -> Result<WebSocket<F>>
        where F: Factory
    {
        Ok(WebSocket {
            poll: try!(Poll::new()),
            handler: io::Handler::new(factory, self.settings),
        })
    }

    /// Set the WebSocket settings to use.
    pub fn with_settings(&mut self, settings: Settings) -> &mut Builder {
        self.settings = settings;
        self
    }
}
<|endoftext|>


<commit_before>#![doc(html_playground_url = "https://play.rust-lang.org/")]
//! Frunk: generic functional programming toolbelt for Rust
//!
//! Aims to be a collection of functional programming abstractions implemented in Rust
//! in effective, useful, and idiomatic ways. Examples of things that are included in rust are:
//!
//!   1. HLists (heterogeneously-typed lists)
//!   2. LabelledGeneric, and Generic
//!   3. Coproduct
//!   4. Validated (accumulator for Result)
//!   5. Semigroup
//!   6. Monoid
//!
//! Here is a small taste of what Frunk has to offer:
//!
//! ```
//! # #[macro_use] extern crate frunk;
//! # #[macro_use] extern crate frunk_core;
//! # fn main() {
//! use frunk::prelude::*;
//! use frunk::{self, monoid, Semigroup, Generic};
//!
//! // Combining Monoids
//! let v = vec![Some(1), Some(3)];
//! assert_eq!(monoid::combine_all(&v), Some(4));
//!
//! // HLists
//! let h = hlist![1, "hi"];
//! assert_eq!(h.len(), 2);
//! let hlist_pat!(a, b) = h;
//! assert_eq!(a, 1);
//! assert_eq!(b, "hi");
//!
//! let h1 = hlist![Some(1), 3.3, 53i64, "hello".to_owned()];
//! let h2 = hlist![Some(2), 1.2, 1i64, " world".to_owned()];
//! let h3 = hlist![Some(3), 4.5, 54, "hello world".to_owned()];
//! assert_eq!(h1.combine(&h2), h3);
//!
//! // Generic and LabelledGeneric-based programming
//! // Allows Structs to play well easily with HLists
//!
//! #[derive(Generic, LabelledGeneric)]
//! struct ApiUser<'a> {
//!     FirstName: &'a str,
//!     LastName: &'a str,
//!     Age: usize,
//! }
//!
//! #[derive(Generic, LabelledGeneric)]
//! struct NewUser<'a> {
//!     first_name: &'a str,
//!     last_name: &'a str,
//!     age: usize,
//! }
//!
//! #[derive(LabelledGeneric)]
//! struct SavedUser<'a> {
//!     first_name: &'a str,
//!     last_name: &'a str,
//!     age: usize,
//! }
//!
//! // Instantiate a struct from an HList. Note that you can go the other way too.
//! let a_user: ApiUser = frunk::from_generic(hlist!["Joe", "Blow", 30]);
//!
//! // Convert using Generic
//! let n_user: NewUser = Generic::convert_from(a_user); // done
//!
//! // Convert using LabelledGeneric
//! //
//! // This will fail if the fields of the types converted to and from do not
//! // have the same names or do not line up properly :)
//! //
//! // Also note that we're using a helper method to avoid having to use universal
//! // function call syntax
//! let s_user: SavedUser = frunk::labelled_convert_from(n_user);
//!
//! assert_eq!(s_user.first_name, "Joe");
//! assert_eq!(s_user.last_name, "Blow");
//! assert_eq!(s_user.age, 30);
//!
//! // Uh-oh ! last_name and first_name have been flipped!
//! #[derive(LabelledGeneric)]
//! struct DeletedUser<'a> {
//!     last_name: &'a str,
//!     first_name: &'a str,
//!     age: usize,
//! }
//! // let d_user = <DeletedUser as LabelledGeneric>::convert_from(s_user); <-- this would fail at compile time :)
//!
//! // This will, however, work, because we make use of the Sculptor type-class
//! // to type-safely reshape the representations to align/match each other.
//! let d_user: DeletedUser = frunk::transform_from(s_user);
//! assert_eq!(d_user.first_name, "Joe");
//! # }
//! ```
//!
//! Links:
//!   1. [Source on Github](https://github.com/lloydmeta/frunk)
//!   2. [Crates.io page](https://crates.io/crates/frunk)

#[allow(unused_imports)]
#[macro_use]
extern crate frunk_core;
#[allow(unused_imports)]
#[macro_use]
extern crate frunk_derives;

pub mod semigroup;
pub mod monoid;
pub mod validated;

pub use frunk_core::*;
pub use frunk_derives::*;

// Root-level reexports so that users don't need to guess where things are located.
//
// Things to re-export:
//
// * Datatypes and free functions intended for human consumption.
//   * **Exception:** things that benefit from being namespaced,
//     like `frunk::semigroup::Any`
//
// * Traits that users ought to care enough about to `use` it **by name:**
//   * ...because users might want to `impl` it for their own types
//   * ...because it shows up in lots of `where` bounds
//   * NOT simply because it extends existing types with useful methods
//     (that's what the prelude is for!)

// NOTE: without `#[doc(no_inline)]`, rustdoc will generate two separate pages for
//       each item (one in `frunk::` and another in `frunk_core::module::`).
//       Hyperlinks will be broken for the ones in `frunk::`, so we need to prevent it.

#[doc(no_inline)]
pub use hlist::HNil;
#[doc(no_inline)]
pub use hlist::HCons;
#[doc(no_inline)]
pub use hlist::lift_from;

#[doc(no_inline)]
pub use coproduct::Coproduct;

#[doc(no_inline)]
pub use generic::Generic;
#[doc(no_inline)]
pub use generic::from_generic;
#[doc(no_inline)]
pub use generic::into_generic;
#[doc(no_inline)]
pub use generic::convert_from;

#[doc(no_inline)]
pub use labelled::LabelledGeneric;
#[doc(no_inline)]
pub use labelled::from_labelled_generic;
#[doc(no_inline)]
pub use labelled::into_labelled_generic;
#[doc(no_inline)]
pub use labelled::labelled_convert_from;
#[doc(no_inline)]
pub use labelled::transform_from;

#[doc(no_inline)]
pub use semigroup::Semigroup;

#[doc(no_inline)]
pub use monoid::Monoid;

#[doc(no_inline)]
pub use validated::Validated;

pub mod prelude {
    //! Traits that need to be imported for the complete `frunk` experience.
    //!
    //! The intent here is that `use frunk::prelude::*` is enough to provide
    //! access to any missing methods advertised in frunk's documentation.

    #[doc(no_inline)]
    pub use hlist::HList; // for LEN
    #[doc(no_inline)]
    pub use hlist::HMappable;
    #[doc(no_inline)]
    pub use hlist::HFoldRightable;
    #[doc(no_inline)]
    pub use hlist::HFoldLeftable;
    #[doc(no_inline)]
    pub use hlist::LiftFrom;
    #[doc(no_inline)]
    pub use hlist::LiftInto;

    #[doc(no_inline)]
    pub use coproduct::CoproductFoldable;

    #[doc(no_inline)]
    pub use validated::IntoValidated;
}
<commit_msg>remove maps and folds from prelude<commit_after>#![doc(html_playground_url = "https://play.rust-lang.org/")]
//! Frunk: generic functional programming toolbelt for Rust
//!
//! Aims to be a collection of functional programming abstractions implemented in Rust
//! in effective, useful, and idiomatic ways. Examples of things that are included in rust are:
//!
//!   1. HLists (heterogeneously-typed lists)
//!   2. LabelledGeneric, and Generic
//!   3. Coproduct
//!   4. Validated (accumulator for Result)
//!   5. Semigroup
//!   6. Monoid
//!
//! Here is a small taste of what Frunk has to offer:
//!
//! ```
//! # #[macro_use] extern crate frunk;
//! # #[macro_use] extern crate frunk_core;
//! # fn main() {
//! use frunk::prelude::*;
//! use frunk::{self, monoid, Semigroup, Generic};
//!
//! // Combining Monoids
//! let v = vec![Some(1), Some(3)];
//! assert_eq!(monoid::combine_all(&v), Some(4));
//!
//! // HLists
//! let h = hlist![1, "hi"];
//! assert_eq!(h.len(), 2);
//! let hlist_pat!(a, b) = h;
//! assert_eq!(a, 1);
//! assert_eq!(b, "hi");
//!
//! let h1 = hlist![Some(1), 3.3, 53i64, "hello".to_owned()];
//! let h2 = hlist![Some(2), 1.2, 1i64, " world".to_owned()];
//! let h3 = hlist![Some(3), 4.5, 54, "hello world".to_owned()];
//! assert_eq!(h1.combine(&h2), h3);
//!
//! // Generic and LabelledGeneric-based programming
//! // Allows Structs to play well easily with HLists
//!
//! #[derive(Generic, LabelledGeneric)]
//! struct ApiUser<'a> {
//!     FirstName: &'a str,
//!     LastName: &'a str,
//!     Age: usize,
//! }
//!
//! #[derive(Generic, LabelledGeneric)]
//! struct NewUser<'a> {
//!     first_name: &'a str,
//!     last_name: &'a str,
//!     age: usize,
//! }
//!
//! #[derive(LabelledGeneric)]
//! struct SavedUser<'a> {
//!     first_name: &'a str,
//!     last_name: &'a str,
//!     age: usize,
//! }
//!
//! // Instantiate a struct from an HList. Note that you can go the other way too.
//! let a_user: ApiUser = frunk::from_generic(hlist!["Joe", "Blow", 30]);
//!
//! // Convert using Generic
//! let n_user: NewUser = Generic::convert_from(a_user); // done
//!
//! // Convert using LabelledGeneric
//! //
//! // This will fail if the fields of the types converted to and from do not
//! // have the same names or do not line up properly :)
//! //
//! // Also note that we're using a helper method to avoid having to use universal
//! // function call syntax
//! let s_user: SavedUser = frunk::labelled_convert_from(n_user);
//!
//! assert_eq!(s_user.first_name, "Joe");
//! assert_eq!(s_user.last_name, "Blow");
//! assert_eq!(s_user.age, 30);
//!
//! // Uh-oh ! last_name and first_name have been flipped!
//! #[derive(LabelledGeneric)]
//! struct DeletedUser<'a> {
//!     last_name: &'a str,
//!     first_name: &'a str,
//!     age: usize,
//! }
//! // let d_user = <DeletedUser as LabelledGeneric>::convert_from(s_user); <-- this would fail at compile time :)
//!
//! // This will, however, work, because we make use of the Sculptor type-class
//! // to type-safely reshape the representations to align/match each other.
//! let d_user: DeletedUser = frunk::transform_from(s_user);
//! assert_eq!(d_user.first_name, "Joe");
//! # }
//! ```
//!
//! Links:
//!   1. [Source on Github](https://github.com/lloydmeta/frunk)
//!   2. [Crates.io page](https://crates.io/crates/frunk)

#[allow(unused_imports)]
#[macro_use]
extern crate frunk_core;
#[allow(unused_imports)]
#[macro_use]
extern crate frunk_derives;

pub mod semigroup;
pub mod monoid;
pub mod validated;

pub use frunk_core::*;
pub use frunk_derives::*;

// Root-level reexports so that users don't need to guess where things are located.
//
// Things to re-export:
//
// * Datatypes and free functions intended for human consumption.
//   * **Exception:** things that benefit from being namespaced,
//     like `frunk::semigroup::Any`
//
// * Traits that users ought to care enough about to `use` it **by name:**
//   * ...because users might want to `impl` it for their own types
//   * ...because it shows up in lots of `where` bounds
//   * NOT simply because it extends existing types with useful methods
//     (that's what the prelude is for!)

// NOTE: without `#[doc(no_inline)]`, rustdoc will generate two separate pages for
//       each item (one in `frunk::` and another in `frunk_core::module::`).
//       Hyperlinks will be broken for the ones in `frunk::`, so we need to prevent it.

#[doc(no_inline)]
pub use hlist::HNil;
#[doc(no_inline)]
pub use hlist::HCons;
#[doc(no_inline)]
pub use hlist::lift_from;

#[doc(no_inline)]
pub use coproduct::Coproduct;

#[doc(no_inline)]
pub use generic::Generic;
#[doc(no_inline)]
pub use generic::from_generic;
#[doc(no_inline)]
pub use generic::into_generic;
#[doc(no_inline)]
pub use generic::convert_from;

#[doc(no_inline)]
pub use labelled::LabelledGeneric;
#[doc(no_inline)]
pub use labelled::from_labelled_generic;
#[doc(no_inline)]
pub use labelled::into_labelled_generic;
#[doc(no_inline)]
pub use labelled::labelled_convert_from;
#[doc(no_inline)]
pub use labelled::transform_from;

#[doc(no_inline)]
pub use semigroup::Semigroup;

#[doc(no_inline)]
pub use monoid::Monoid;

#[doc(no_inline)]
pub use validated::Validated;

pub mod prelude {
    //! Traits that need to be imported for the complete `frunk` experience.
    //!
    //! The intent here is that `use frunk::prelude::*` is enough to provide
    //! access to any missing methods advertised in frunk's documentation.

    #[doc(no_inline)]
    pub use hlist::HList; // for LEN
    #[doc(no_inline)]
    pub use hlist::LiftFrom;
    #[doc(no_inline)]
    pub use hlist::LiftInto;

    #[doc(no_inline)]
    pub use validated::IntoValidated;
}
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://jordanbray.github.io/chess/")]
//! This is a rust chess move generator

/// Manage side-to-move information.
pub mod color;
/// Enumerate the piece types (colorless)
pub mod piece;
/// Manage a structure for a square
pub mod square;
/// Manage a structure for a chess move with an optional promotion
pub mod chess_move;
/// Use bitboards to manage piece locations
pub mod bitboard;
/// Keep track of castle rights information, and generate some information related to castling
pub mod castle_rights;
/// Manage an entire chess board
pub mod board;
/// Magic bitboards are the heart of any good chess algorithm.  This module manages lookup tables
/// for move generation.
pub mod magic;
/// Note: You must call construct::construct() before using this library.
pub mod construct;
/// Handle a chess rank, or row.
pub mod rank;
/// Handle a chess file, or column.
pub mod file;
/// Incremental updating hashing algorithm for chess boards.
pub mod zobrist;
/// Cache a particular value for use later, using a u64 as the key.
pub mod cache_table;

extern crate rand;
#[macro_use]
extern crate lazy_static;

<commit_msg>Reorder some documentation stuff.<commit_after>#![doc(html_root_url = "https://jordanbray.github.io/chess/")]
//! This is a rust chess move generator

/// Manage an entire chess board
pub mod board;
/// Manage side-to-move information.
pub mod color;
/// Enumerate the piece types (colorless)
pub mod piece;
/// Manage a structure for a square
pub mod square;
/// Manage a structure for a chess move with an optional promotion
pub mod chess_move;
/// Use bitboards to manage piece locations
pub mod bitboard;
/// Keep track of castle rights information, and generate some information related to castling
pub mod castle_rights;
/// Magic bitboards are the heart of any good chess algorithm.  This module manages lookup tables
/// for move generation.
pub mod magic;
/// Note: You must call construct::construct() before using this library.
pub mod construct;
/// Handle a chess rank, or row.
pub mod rank;
/// Handle a chess file, or column.
pub mod file;
/// Incremental updating hashing algorithm for chess boards.
pub mod zobrist;
/// Cache a particular value for use later, using a u64 as the key.
pub mod cache_table;

extern crate rand;
#[macro_use]
extern crate lazy_static;

<|endoftext|>


<commit_before>//! This library implements basic processing of JavaScript sourcemaps.
//!
//! ## Installation
//!
//! The crate is called sourcemap and you can depend on it via cargo:
//!
//! ```toml
//! [dependencies]
//! sourcemap = "*"
//! ```
//!
//! If you want to use the git version:
//!
//! ```toml
//! [dependencies.sourcemap]
//! git = "https://github.com/mitsuhiko/rust-sourcemap.git"
//! ```
//!
//! ## Basic Operation
//!
//! This crate can load JavaScript sourcemaps from JSON files.  It uses
//! `serde` for parsing of the JSON data.  Due to the nature of sourcemaps
//! the entirety of the file must be loaded into memory which can be quite
//! memory intensive.
//!
//! Usage:
//!
//! ```rust
//! use sourcemap::SourceMap;
//! let input: &[_] = b"{
//!     \"version\":3,
//!     \"sources\":[\"coolstuff.js\"],
//!     \"names\":[\"x\",\"alert\"],
//!     \"mappings\":\"AAAA,GAAIA,GAAI,EACR,IAAIA,GAAK,EAAG,CACVC,MAAM\"
//! }";
//! let sm = SourceMap::from_reader(input).unwrap();
//! let token = sm.lookup_token(0, 0).unwrap(); // line-number and column
//! println!("token: {}", token);
//! ```
extern crate base64;
extern crate serde;
extern crate serde_json;

mod macros;

pub use types::{RawToken, Token, TokenIter, SourceMap, SourceMapIndex,
                SourceMapSection, SourceMapSectionIter};
pub use errors::{Result, Error};
pub use decoder::{decode, decode_data_url, DecodedMap};
pub use detector::{SourceMapRef, locate_sourcemap_reference};

mod errors;
mod types;
mod jsontypes;
mod decoder;
mod detector;

#[doc(hidden)]
pub mod internals {
    pub use super::decoder::StripHeaderReader;
}
<commit_msg>Fixed bad attribute<commit_after>//! This library implements basic processing of JavaScript sourcemaps.
//!
//! ## Installation
//!
//! The crate is called sourcemap and you can depend on it via cargo:
//!
//! ```toml
//! [dependencies]
//! sourcemap = "*"
//! ```
//!
//! If you want to use the git version:
//!
//! ```toml
//! [dependencies.sourcemap]
//! git = "https://github.com/mitsuhiko/rust-sourcemap.git"
//! ```
//!
//! ## Basic Operation
//!
//! This crate can load JavaScript sourcemaps from JSON files.  It uses
//! `serde` for parsing of the JSON data.  Due to the nature of sourcemaps
//! the entirety of the file must be loaded into memory which can be quite
//! memory intensive.
//!
//! Usage:
//!
//! ```rust
//! use sourcemap::SourceMap;
//! let input: &[_] = b"{
//!     \"version\":3,
//!     \"sources\":[\"coolstuff.js\"],
//!     \"names\":[\"x\",\"alert\"],
//!     \"mappings\":\"AAAA,GAAIA,GAAI,EACR,IAAIA,GAAK,EAAG,CACVC,MAAM\"
//! }";
//! let sm = SourceMap::from_reader(input).unwrap();
//! let token = sm.lookup_token(0, 0).unwrap(); // line-number and column
//! println!("token: {}", token);
//! ```
#![cfg_attr(feature="serde_macros", feature(custom_derive, plugin))]
#![cfg_attr(feature="serde_macros", plugin(serde_macros))]

extern crate base64;
extern crate serde;
extern crate serde_json;

mod macros;

pub use types::{RawToken, Token, TokenIter, SourceMap, SourceMapIndex,
                SourceMapSection, SourceMapSectionIter};
pub use errors::{Result, Error};
pub use decoder::{decode, decode_data_url, DecodedMap};
pub use detector::{SourceMapRef, locate_sourcemap_reference};

mod errors;
mod types;
mod jsontypes;
mod decoder;
mod detector;

#[doc(hidden)]
pub mod internals {
    pub use super::decoder::StripHeaderReader;
}
<|endoftext|>


<commit_before>#![warn(missing_docs)]

//! A `Pinboard` is a shared, mutable, eventually consistent, lock-free data-structure.  This
//! allows multiple threads to communicate in a decoupled way by publishing data to the pinboard
//! which other threads can then read in an eventually consistent way.
//!
//! This is not a silver bullet though, there are various limitations of `Pinboard` that trade off
//! the nice behaviour described above.
//!
//! * Eventual consistency:
//!     * Writes from one thread are not guaranteed to be seen by reads from another thread
//!     * Writes from one thread can overwrite writes from another thread
//! * No in-place mutation:
//!     * The only write primitive completely overwrites the data on the `Pinboard`
//! * Requires `Clone`:
//!     * All reads return a clone of the data, decoupling the lifetime of the read value from the
//!     data stored in the global reference.

extern crate crossbeam;

use crossbeam::epoch::{Atomic, Owned, pin};
use std::sync::atomic::Ordering::*;

use std::ops::Deref;

/// An instance of a `Pinboard`, holds a shared, mutable, eventually-consistent reference to a `T`.
pub struct Pinboard<T: Clone>(Atomic<T>);

impl<T: Clone> Pinboard<T> {
    /// Create a new `Pinboard` instance holding the given value.
    pub fn new(t: T) -> Pinboard<T> {
        let t = Owned::new(t);
        let p = Pinboard::default();
        p.0.store(Some(t), Release);
        p
    }

    /// Update the value stored in the `Pinboard`.
    pub fn set(&self, t: T) {
        let guard = pin();
        let t = Owned::new(t);
        if let Some(t) = self.0.swap(Some(t), Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Clear out the `Pinboard` so its no longer holding any data.
    pub fn clear(&self) {
        let guard = pin();
        if let Some(t) = self.0.swap(None, Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    pub fn read(&self) -> Option<T> {
        let guard = pin();
        let t = self.0.load(Acquire, &guard);
        t.map(|t| -> &T { t.deref() }).cloned()
    }
}

impl<T: Clone> Default for Pinboard<T> {
    fn default() -> Pinboard<T> {
        Pinboard(Atomic::null())
    }
}

impl<T: Clone> Drop for Pinboard<T> {
    fn drop(&mut self) {
        // Make sure any stored data is marked for deletion
        self.clear();
    }
}

impl<T: Clone> From<Option<T>> for Pinboard<T> {
    fn from(src: Option<T>) -> Pinboard<T> {
        src.map(Pinboard::new).unwrap_or_default()
    }
}

/// An wrapper around a `Pinboard` which provides the guarantee it is never empty.
pub struct NonEmptyPinboard<T: Clone>(Pinboard<T>);

impl<T: Clone> NonEmptyPinboard<T> {
    /// Create a new `NonEmptyPinboard` instance holding the given value.
    pub fn new(t: T) -> NonEmptyPinboard<T> {
        NonEmptyPinboard(Pinboard::new(t))
    }

    /// Update the value stored in the `NonEmptyPinboard`.
    #[inline]
    pub fn set(&self, t: T) {
        self.0.set(t)
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    #[inline]
    pub fn read(&self) -> T {
        // Unwrap the option returned by the inner `Pinboard`. This will never panic, because it's
        // impossible for this `Pinboard` to be empty (though it's not possible to prove this to the
        // compiler).
        match self.0.read() {
            Some(t) => t,
            None => unreachable!("Inner pointer was unexpectedly null"),
        }
    }
}

macro_rules! debuggable {
    ($struct:ident, $trait:ident) => {
        impl<T: Clone> ::std::fmt::$trait for $struct<T> where T: ::std::fmt::$trait {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
                write!(f, "{}(", stringify!($struct))?;
                ::std::fmt::$trait::fmt(&self.read(), f)?;
                write!(f, ")")
            }
        }
    }
}

debuggable!(Pinboard, Debug);
debuggable!(NonEmptyPinboard, Debug);
debuggable!(NonEmptyPinboard, Binary);
debuggable!(NonEmptyPinboard, Display);
debuggable!(NonEmptyPinboard, LowerExp);
debuggable!(NonEmptyPinboard, LowerHex);
debuggable!(NonEmptyPinboard, Octal);
debuggable!(NonEmptyPinboard, Pointer);
debuggable!(NonEmptyPinboard, UpperExp);
debuggable!(NonEmptyPinboard, UpperHex);

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

    fn consume<T: Clone + Display>(t: &Pinboard<T>) {
        loop {
            match t.read() {
                Some(_) => {}
                None => break,
            }
            std::thread::sleep(std::time::Duration::from_millis(1));
        }
    }

    fn produce(t: &Pinboard<u32>) {
        for i in 1..100 {
            t.set(i);
            std::thread::sleep(std::time::Duration::from_millis(2));
        }
        t.clear();
    }

    fn check_debug<T: ::std::fmt::Debug>(_: T) {}

    #[test]
    fn it_works() {
        let t = Pinboard::<u32>::default();
        assert_eq!(None, t.read());
        t.set(3);
        assert_eq!(Some(3), t.read());
        t.clear();
        assert_eq!(None, t.read());
    }

    #[test]
    fn single_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn multi_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn single_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn multi_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn non_empty_pinboard() {
        let t = NonEmptyPinboard::<u32>::new(3);
        assert_eq!(3, t.read());
        t.set(4);
        assert_eq!(4, t.read());
    }

    #[test]
    fn debuggable() {
        let t = Pinboard::<i32>::new(3);
        check_debug(t);
        let t = NonEmptyPinboard::<i32>::new(2);
        check_debug(t);
    }
}
<commit_msg>[patch] Use AqcRel for swaps<commit_after>#![warn(missing_docs)]

//! A `Pinboard` is a shared, mutable, eventually consistent, lock-free data-structure.  This
//! allows multiple threads to communicate in a decoupled way by publishing data to the pinboard
//! which other threads can then read in an eventually consistent way.
//!
//! This is not a silver bullet though, there are various limitations of `Pinboard` that trade off
//! the nice behaviour described above.
//!
//! * Eventual consistency:
//!     * Writes from one thread are not guaranteed to be seen by reads from another thread
//!     * Writes from one thread can overwrite writes from another thread
//! * No in-place mutation:
//!     * The only write primitive completely overwrites the data on the `Pinboard`
//! * Requires `Clone`:
//!     * All reads return a clone of the data, decoupling the lifetime of the read value from the
//!     data stored in the global reference.

extern crate crossbeam;

use crossbeam::epoch::{Atomic, Owned, pin};
use std::sync::atomic::Ordering::*;

use std::ops::Deref;

/// An instance of a `Pinboard`, holds a shared, mutable, eventually-consistent reference to a `T`.
pub struct Pinboard<T: Clone>(Atomic<T>);

impl<T: Clone> Pinboard<T> {
    /// Create a new `Pinboard` instance holding the given value.
    pub fn new(t: T) -> Pinboard<T> {
        let t = Owned::new(t);
        let p = Pinboard::default();
        p.0.store(Some(t), Release);
        p
    }

    /// Update the value stored in the `Pinboard`.
    pub fn set(&self, t: T) {
        let guard = pin();
        let t = Owned::new(t);
        if let Some(t) = self.0.swap(Some(t), AcqRel, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Clear out the `Pinboard` so its no longer holding any data.
    pub fn clear(&self) {
        let guard = pin();
        if let Some(t) = self.0.swap(None, AcqRel, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    pub fn read(&self) -> Option<T> {
        let guard = pin();
        let t = self.0.load(Acquire, &guard);
        t.map(|t| -> &T { t.deref() }).cloned()
    }
}

impl<T: Clone> Default for Pinboard<T> {
    fn default() -> Pinboard<T> {
        Pinboard(Atomic::null())
    }
}

impl<T: Clone> Drop for Pinboard<T> {
    fn drop(&mut self) {
        // Make sure any stored data is marked for deletion
        self.clear();
    }
}

impl<T: Clone> From<Option<T>> for Pinboard<T> {
    fn from(src: Option<T>) -> Pinboard<T> {
        src.map(Pinboard::new).unwrap_or_default()
    }
}

/// An wrapper around a `Pinboard` which provides the guarantee it is never empty.
pub struct NonEmptyPinboard<T: Clone>(Pinboard<T>);

impl<T: Clone> NonEmptyPinboard<T> {
    /// Create a new `NonEmptyPinboard` instance holding the given value.
    pub fn new(t: T) -> NonEmptyPinboard<T> {
        NonEmptyPinboard(Pinboard::new(t))
    }

    /// Update the value stored in the `NonEmptyPinboard`.
    #[inline]
    pub fn set(&self, t: T) {
        self.0.set(t)
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    #[inline]
    pub fn read(&self) -> T {
        // Unwrap the option returned by the inner `Pinboard`. This will never panic, because it's
        // impossible for this `Pinboard` to be empty (though it's not possible to prove this to the
        // compiler).
        match self.0.read() {
            Some(t) => t,
            None => unreachable!("Inner pointer was unexpectedly null"),
        }
    }
}

macro_rules! debuggable {
    ($struct:ident, $trait:ident) => {
        impl<T: Clone> ::std::fmt::$trait for $struct<T> where T: ::std::fmt::$trait {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
                write!(f, "{}(", stringify!($struct))?;
                ::std::fmt::$trait::fmt(&self.read(), f)?;
                write!(f, ")")
            }
        }
    }
}

debuggable!(Pinboard, Debug);
debuggable!(NonEmptyPinboard, Debug);
debuggable!(NonEmptyPinboard, Binary);
debuggable!(NonEmptyPinboard, Display);
debuggable!(NonEmptyPinboard, LowerExp);
debuggable!(NonEmptyPinboard, LowerHex);
debuggable!(NonEmptyPinboard, Octal);
debuggable!(NonEmptyPinboard, Pointer);
debuggable!(NonEmptyPinboard, UpperExp);
debuggable!(NonEmptyPinboard, UpperHex);

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

    fn consume<T: Clone + Display>(t: &Pinboard<T>) {
        loop {
            match t.read() {
                Some(_) => {}
                None => break,
            }
            std::thread::sleep(std::time::Duration::from_millis(1));
        }
    }

    fn produce(t: &Pinboard<u32>) {
        for i in 1..100 {
            t.set(i);
            std::thread::sleep(std::time::Duration::from_millis(2));
        }
        t.clear();
    }

    fn check_debug<T: ::std::fmt::Debug>(_: T) {}

    #[test]
    fn it_works() {
        let t = Pinboard::<u32>::default();
        assert_eq!(None, t.read());
        t.set(3);
        assert_eq!(Some(3), t.read());
        t.clear();
        assert_eq!(None, t.read());
    }

    #[test]
    fn single_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn multi_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn single_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn multi_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn non_empty_pinboard() {
        let t = NonEmptyPinboard::<u32>::new(3);
        assert_eq!(3, t.read());
        t.set(4);
        assert_eq!(4, t.read());
    }

    #[test]
    fn debuggable() {
        let t = Pinboard::<i32>::new(3);
        check_debug(t);
        let t = NonEmptyPinboard::<i32>::new(2);
        check_debug(t);
    }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

//! WebSocketStream crate

#![feature(libc, net, std_misc, os, collections, core)]

extern crate libc;

use std::mem;
use std::net::TcpStream;
use std::os;
use std::os::unix::prelude::AsRawFd;

use self::libc::consts::os::posix88;
use self::libc::{size_t, c_void, c_int, ssize_t};

use util::*;
pub mod util;

extern "system" {
    fn read(fd: c_int, buffer: *mut c_void, count: size_t) -> ssize_t;
    fn write(fd: c_int, buffer: *const c_void, cout: size_t) -> ssize_t;
}

pub type NewResult = Result<WebSocketStream, SetFdError>;
pub type ReadResult = Result<(OpCode, Vec<u8>), ReadError>;
pub type WriteResult = Result<u64, WriteError>;

type SysReadResult = Result<Vec<u8>, ReadError>;
type SysWriteResult = Result<u64, WriteError>;
type PayloadKeyResult = Result<u8, ReadError>;
type PayloadLenResult = Result<u64, ReadError>;

/// Represents a non-blocking RFC-6455 Protocol stream
pub struct WebSocketStream {
    stream: TcpStream
}

impl WebSocketStream {

    /// Creates a new WebSocket
    pub fn new(stream: TcpStream) -> NewResult {
        // Set fd as non-blocking
        let fd = stream.as_raw_fd();
        let mut response;
        unsafe {
            response = libc::fcntl(
                fd,
                libc::consts::os::posix01::F_SETFL,
                libc::consts::os::extra::O_NONBLOCK);
        }

        if response < 0 {
            let errno = os::errno();
            return match errno {
                posix88::EACCES     => Err(SetFdError::EACCES),
                posix88::EAGAIN     => Err(SetFdError::EAGAIN),
                posix88::EBADF      => Err(SetFdError::EBADF),
                posix88::EDEADLK    => Err(SetFdError::EDEADLK),
                posix88::EFAULT     => Err(SetFdError::EFAULT),
                posix88::EINTR      => Err(SetFdError::EINTR),
                posix88::EINVAL     => Err(SetFdError::EINVAL),
                posix88::EMFILE     => Err(SetFdError::EMFILE),
                posix88::ENOLCK     => Err(SetFdError::ENOLCK),
                posix88::EPERM      => Err(SetFdError::EPERM),
                _ => panic!("Unknown errno from fcntl: {}", errno)
            };
        }

        Ok(WebSocketStream {
            stream: stream
        })
    }

    /// Attempts to read data from the socket.
    ///
    /// If data is available, it waits until a complete message has
    /// been received.
    /// It will return immediately if no data is available, or data is present,
    /// but a complete message is not yet available.  The previously read
    /// sections of that message will be discarded.  Non-blocking, ftw!
    pub fn read(&mut self) -> ReadResult {
        match self.check_for_data() {
            Ok(buf) => {
                if buf.len() > 0 {
                    // Ensure opcode is valid
                    let op_code = buf[0] & OP_CODE_UN_MASK;
                    let valid_op = match op_code {
                        OP_CONTINUATION => true,
                        OP_TEXT         => true,
                        OP_BINARY       => true,
                        OP_CLOSE        => true,
                        OP_PING         => true,
                        OP_PONG         => true,
                        _ => false
                    };
                    if !valid_op {
                        return Err(ReadError::OpCode);
                    }

                    // Assign OpCode
                    let op = match op_code {
                        OP_CONTINUATION => OpCode::Continuation,
                        OP_TEXT         => OpCode::Text,
                        OP_BINARY       => OpCode::Binary,
                        OP_CLOSE        => OpCode::Close,
                        OP_PING         => OpCode::Ping,
                        OP_PONG         => OpCode::Pong,
                        _ => unimplemented!()
                    };

                    // Get payload
                    match self.read_payload() {
                        Ok(payload) => Ok((op, payload)),
                        Err(e) => Err(e)
                    }
                } else {
                    Err(ReadError::NoData)
                }
            }
            Err(e) => Err(e)
        }
    }

    fn check_for_data(&mut self) -> SysReadResult {
        self.read_num_bytes(1)
    }

    fn read_payload(&mut self) -> SysReadResult {
        match self.read_payload_key() {
            Ok(key) => {
                match self.read_payload_len(key) {
                    Ok(len) => {
                        match self.read_masking_key() {
                            Ok(mask) => {
                                match self.read_num_bytes(len as usize) {
                                    Ok(buf) => {
                                        if buf.len() < 1 {
                                            return Err(ReadError::DataStop);
                                        }

                                        let mut payload = Vec::<u8>::
                                            with_capacity(buf.len());
                                        for x in 0..buf.len() {
                                            payload.push(buf[x] ^ mask[x % 4]);
                                        }
                                        Ok(payload)
                                    }
                                    Err(e) => Err(e)
                                }
                            }
                            Err(e) => Err(e)
                        }
                    }
                    Err(e) => Err(e)
                }
            }
            Err(e) => Err(e)
        }
    }

    fn read_payload_key(&mut self) -> PayloadKeyResult {
        match self.read_num_bytes(1) {
            Ok(key_buf) => {
                if key_buf.len() > 0 {
                    Ok(key_buf[0] & PAYLOAD_KEY_UN_MASK)
                } else {
                    Err(ReadError::DataStop)
                }
            }
            Err(e) => Err(e)
        }
    }

    fn read_payload_len(&mut self, key: u8) -> PayloadLenResult {
        match key {
            126 => {
                match self.read_num_bytes(2) {
                    Ok(buf) => {
                        let mut len = 0u16;
                        len = len | buf[0] as u16;
                        len = (len << 8) ^ buf[1] as u16;
                        Ok(len as u64)
                    }
                    Err(e) => Err(e)
                }
            }
            127 => {
                match self.read_num_bytes(8) {
                    Ok(buf) => {
                        let mut len = 0u64;
                        len = len | buf[0] as u64;
                        len = (len << 8) ^ buf[1] as u64;
                        len = (len << 8) ^ buf[2] as u64;
                        len = (len << 8) ^ buf[3] as u64;
                        len = (len << 8) ^ buf[4] as u64;
                        len = (len << 8) ^ buf[5] as u64;
                        len = (len << 8) ^ buf[6] as u64;
                        len = (len << 8) ^ buf[7] as u64;
                        Ok(len)
                    }
                    Err(e) => Err(e)
                }
            }
            _ => Ok(key as u64)
        }
    }

    fn read_masking_key(&mut self) -> SysReadResult {
        match self.read_num_bytes(4) {
            Ok(mask_buf) => {
                if mask_buf.len() > 0 {
                    Ok(mask_buf)
                } else {
                    Err(ReadError::DataStop)
                }
            }
            Err(e) => Err(e)
        }
    }

    fn read_num_bytes(&mut self, count: usize) -> SysReadResult {
        let mut temp_count = count;
        let mut total_read: usize = 0;
        let mut final_buffer: Vec<u8> = Vec::with_capacity(count);

        let mut num_reads_missed = 0u8;
        while total_read < count {
            let mut num_read;
            let mut buffer = [0u8; 512];
            let fd = self.stream.as_raw_fd();

            unsafe {
                let buf_ptr = buffer.as_mut_ptr();
                let void_buf_ptr: *mut c_void = mem::transmute(buf_ptr);
                num_read = read(fd, void_buf_ptr, temp_count as size_t);
            }

            if num_read > 0 {
                for x in 0..num_read {
                    final_buffer.push(buffer[x as usize]);
                }

                total_read += num_read as usize;
                temp_count -= num_read as usize;
            } else if num_read < 0 {
                let errno = os::errno();
                return match errno {
                    posix88::EBADF      => Err(ReadError::EBADF),
                    posix88::EFAULT     => Err(ReadError::EFAULT),
                    posix88::EINTR      => Err(ReadError::EINTR),
                    posix88::EINVAL     => Err(ReadError::EINVAL),
                    posix88::EIO        => Err(ReadError::EIO),
                    posix88::EISDIR     => Err(ReadError::EISDIR),
                    _ => Ok(Vec::<u8>::new()),
                };
            } else { // Zero data read

                // If this is our first attempt and we've read nothing, there
                // is nothing to read, and we're done with this call
                if total_read == 0 {
                    return Ok(Vec::<u8>::new());
                }

                // Have we read all we need to?
                if total_read == count {
                    break;
                }

                // We'll give it 5 more read attempts. If nothing by then,
                // We should assume the client has forced disconnect and not
                // sent use a Close Op (Not a very nice client...)
                num_reads_missed += 1;
                if num_reads_missed > 4 {
                    return Ok(Vec::<u8>::new());
                }
            }
        }
        Ok(final_buffer)
    }

    /// Attempts to write data to the socket
    pub fn write(&mut self, op: OpCode, payload: &mut Vec<u8>) -> WriteResult {
        let mut out_buf: Vec<u8> = Vec::with_capacity(payload.len() + 9);

        self.set_op_code(&op, &mut out_buf);
        self.set_payload_info(payload.len(), &mut out_buf);
        out_buf.append(payload);

        self.write_bytes(&out_buf)
    }

    fn set_op_code(&self, op: &OpCode, buf: &mut Vec<u8>) {
        let op_code = match *op {
            OpCode::Continuation    => OP_CONTINUATION,
            OpCode::Text            => OP_TEXT,
            OpCode::Binary          => OP_BINARY,
            OpCode::Close           => OP_CLOSE,
            OpCode::Ping            => OP_PING,
            OpCode::Pong            => OP_PONG
        };
        buf.push(op_code | OP_CODE_MASK);
    }

    fn set_payload_info(&self, len: usize, buf: &mut Vec<u8>) {
        if len <= 125 {
            buf.push(len as u8);
        } else if len <= 65535 {
            let mut len_buf = [0u8; 2];
            len_buf[0] = (len as u16 & 0b1111_1111u16 << 8) as u8;
            len_buf[1] = (len as u16 & 0b1111_1111 as u16) as u8;

            buf.push(126u8); // 16 bit prelude
            buf.push(len_buf[0]);
            buf.push(len_buf[1]);
        } else {
            let mut len_buf = [0u8; 8];
            len_buf[0] = (len as u64 & 0b1111_1111u64 << 56) as u8;
            len_buf[1] = (len as u64 & 0b1111_1111u64 << 48) as u8;
            len_buf[2] = (len as u64 & 0b1111_1111u64 << 40) as u8;
            len_buf[3] = (len as u64 & 0b1111_1111u64 << 32) as u8;
            len_buf[4] = (len as u64 & 0b1111_1111u64 << 24) as u8;
            len_buf[5] = (len as u64 & 0b1111_1111u64 << 16) as u8;
            len_buf[6] = (len as u64 & 0b1111_1111u64 << 8) as u8;
            len_buf[7] = (len as u64 & 0b1111_1111u64) as u8;

            buf.push(127u8); // 64 bit prelude
            buf.push(len_buf[0]);
            buf.push(len_buf[1]);
            buf.push(len_buf[2]);
            buf.push(len_buf[3]);
            buf.push(len_buf[4]);
            buf.push(len_buf[5]);
            buf.push(len_buf[6]);
            buf.push(len_buf[7]);
        }
    }

    fn write_bytes(&mut self, buf: &Vec<u8>) -> SysWriteResult {
        let buffer = buf.as_slice();
        let fd = self.stream.as_raw_fd();
        let count = buf.len() as size_t;

        let mut num_written;
        unsafe {
            let buff_ptr = buffer.as_ptr();
            let void_buff_ptr: *const c_void = mem::transmute(buff_ptr);
            num_written = write(fd, void_buff_ptr, count);
        }

        if num_written < 0 {
            let errno = os::errno();
            return match errno {
                posix88::EAGAIN     => Err(WriteError::EAGAIN),
                posix88::EBADF      => Err(WriteError::EBADF),
                posix88::EFAULT     => Err(WriteError::EFAULT),
                posix88::EFBIG      => Err(WriteError::EFBIG),
                posix88::EINTR      => Err(WriteError::EINTR),
                posix88::EINVAL     => Err(WriteError::EINVAL),
                posix88::EIO        => Err(WriteError::EIO),
                posix88::ENOSPC     => Err(WriteError::ENOSPC),
                posix88::EPIPE      => Err(WriteError::EPIPE),
                _ => panic!("Unknown errno: {}", errno),
            }
        }
        Ok(num_written as u64)
    }
}

impl Clone for WebSocketStream {
    fn clone(&self) -> WebSocketStream {
        WebSocketStream {
            stream: self.stream.try_clone().unwrap()
        }
    }
}
<commit_msg>Update lib.rs<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

//! WebSocketStream crate

#![feature(libc, net, std_misc, os, collections, core)]

extern crate libc;

use std::mem;
use std::net::TcpStream;
use std::os;
use std::os::unix::prelude::AsRawFd;

use self::libc::consts::os::posix88;
use self::libc::{size_t, c_void, c_int, ssize_t};

use util::*;
pub mod util;

extern "system" {
    fn read(fd: c_int, buffer: *mut c_void, count: size_t) -> ssize_t;
    fn write(fd: c_int, buffer: *const c_void, cout: size_t) -> ssize_t;
}

pub type NewResult = Result<WebSocketStream, SetFdError>;
pub type ReadResult = Result<(OpCode, Vec<u8>), ReadError>;
pub type WriteResult = Result<u64, WriteError>;

type SysReadResult = Result<Vec<u8>, ReadError>;
type SysWriteResult = Result<u64, WriteError>;
type PayloadKeyResult = Result<u8, ReadError>;
type PayloadLenResult = Result<u64, ReadError>;

/// Represents a non-blocking RFC-6455 Protocol stream
pub struct WebSocketStream {
    stream: TcpStream
}

impl WebSocketStream {

    /// Creates a new WebSocket
    pub fn new(stream: TcpStream) -> NewResult {
        // Set fd as non-blocking
        let fd = stream.as_raw_fd();
        let mut response;
        unsafe {
            response = libc::fcntl(
                fd,
                libc::consts::os::posix01::F_SETFL,
                libc::consts::os::extra::O_NONBLOCK);
        }

        if response < 0 {
            let errno = os::errno();
            return match errno {
                posix88::EACCES     => Err(SetFdError::EACCES),
                posix88::EAGAIN     => Err(SetFdError::EAGAIN),
                posix88::EBADF      => Err(SetFdError::EBADF),
                posix88::EDEADLK    => Err(SetFdError::EDEADLK),
                posix88::EFAULT     => Err(SetFdError::EFAULT),
                posix88::EINTR      => Err(SetFdError::EINTR),
                posix88::EINVAL     => Err(SetFdError::EINVAL),
                posix88::EMFILE     => Err(SetFdError::EMFILE),
                posix88::ENOLCK     => Err(SetFdError::ENOLCK),
                posix88::EPERM      => Err(SetFdError::EPERM),
                _ => panic!("Unknown errno from fcntl: {}", errno)
            };
        }

        Ok(WebSocketStream {
            stream: stream
        })
    }

    /// Attempts to read data from the socket.
    ///
    /// If data is available, it waits until a complete message has
    /// been received.
    /// It will return immediately if no data is available, or data is present,
    /// but a complete message is not yet available.  The previously read
    /// sections of that message will be discarded.  Non-blocking, ftw!
    pub fn read(&mut self) -> ReadResult {
        match self.check_for_data() {
            Ok(buf) => {
                if buf.len() > 0 {
                    // Ensure opcode is valid
                    let op_code = buf[0] & OP_CODE_UN_MASK;
                    let valid_op = match op_code {
                        OP_CONTINUATION => true,
                        OP_TEXT         => true,
                        OP_BINARY       => true,
                        OP_CLOSE        => true,
                        OP_PING         => true,
                        OP_PONG         => true,
                        _ => false
                    };
                    if !valid_op {
                        return Err(ReadError::OpCode);
                    }

                    // Assign OpCode
                    let op = match op_code {
                        OP_CONTINUATION => OpCode::Continuation,
                        OP_TEXT         => OpCode::Text,
                        OP_BINARY       => OpCode::Binary,
                        OP_CLOSE        => OpCode::Close,
                        OP_PING         => OpCode::Ping,
                        OP_PONG         => OpCode::Pong,
                        _ => unimplemented!()
                    };

                    // Get payload
                    match self.read_payload() {
                        Ok(payload) => Ok((op, payload)),
                        Err(e) => Err(e)
                    }
                } else {
                    Err(ReadError::NoData)
                }
            }
            Err(e) => Err(e)
        }
    }

    fn check_for_data(&mut self) -> SysReadResult {
        self.read_num_bytes(1)
    }

    fn read_payload(&mut self) -> SysReadResult {
        match self.read_payload_key() {
            Ok(key) => {
                match self.read_payload_len(key) {
                    Ok(len) => {
                        match self.read_masking_key() {
                            Ok(mask) => {
                                match self.read_num_bytes(len as usize) {
                                    Ok(buf) => {
                                        if buf.len() < 1 {
                                            return Err(ReadError::DataStop);
                                        }

                                        let mut payload = Vec::<u8>::
                                            with_capacity(buf.len());
                                        for x in 0..buf.len() {
                                            payload.push(buf[x] ^ mask[x % 4]);
                                        }
                                        Ok(payload)
                                    }
                                    Err(e) => Err(e)
                                }
                            }
                            Err(e) => Err(e)
                        }
                    }
                    Err(e) => Err(e)
                }
            }
            Err(e) => Err(e)
        }
    }

    fn read_payload_key(&mut self) -> PayloadKeyResult {
        match self.read_num_bytes(1) {
            Ok(key_buf) => {
                if key_buf.len() > 0 {
                    Ok(key_buf[0] & PAYLOAD_KEY_UN_MASK)
                } else {
                    Err(ReadError::DataStop)
                }
            }
            Err(e) => Err(e)
        }
    }

    fn read_payload_len(&mut self, key: u8) -> PayloadLenResult {
        match key {
            126 => {
                match self.read_num_bytes(2) {
                    Ok(buf) => {
                        let mut len = 0u16;
                        len = len | buf[0] as u16;
                        len = (len << 8) ^ buf[1] as u16;
                        Ok(len as u64)
                    }
                    Err(e) => Err(e)
                }
            }
            127 => {
                match self.read_num_bytes(8) {
                    Ok(buf) => {
                        let mut len = 0u64;
                        len = len | buf[0] as u64;
                        len = (len << 8) ^ buf[1] as u64;
                        len = (len << 8) ^ buf[2] as u64;
                        len = (len << 8) ^ buf[3] as u64;
                        len = (len << 8) ^ buf[4] as u64;
                        len = (len << 8) ^ buf[5] as u64;
                        len = (len << 8) ^ buf[6] as u64;
                        len = (len << 8) ^ buf[7] as u64;
                        Ok(len)
                    }
                    Err(e) => Err(e)
                }
            }
            _ => Ok(key as u64)
        }
    }

    fn read_masking_key(&mut self) -> SysReadResult {
        match self.read_num_bytes(4) {
            Ok(mask_buf) => {
                if mask_buf.len() > 0 {
                    Ok(mask_buf)
                } else {
                    Err(ReadError::DataStop)
                }
            }
            Err(e) => Err(e)
        }
    }

    fn read_num_bytes(&mut self, count: usize) -> SysReadResult {
        let mut temp_count = count;
        let mut total_read: usize = 0;
        let mut final_buffer: Vec<u8> = Vec::with_capacity(count);

        let mut num_reads_missed = 0u8;
        while total_read < count {
            let mut num_read;
            let mut buffer = [0u8; 512];
            let fd = self.stream.as_raw_fd();

            unsafe {
                let buf_ptr = buffer.as_mut_ptr();
                let void_buf_ptr: *mut c_void = mem::transmute(buf_ptr);
                num_read = read(fd, void_buf_ptr, temp_count as size_t);
            }

            if num_read > 0 {
                for x in 0..num_read {
                    final_buffer.push(buffer[x as usize]);
                }

                total_read += num_read as usize;
                temp_count -= num_read as usize;
            } else if num_read < 0 {
                let errno = os::errno();
                return match errno {
                    posix88::EBADF      => Err(ReadError::EBADF),
                    posix88::EFAULT     => Err(ReadError::EFAULT),
                    posix88::EINTR      => Err(ReadError::EINTR),
                    posix88::EINVAL     => Err(ReadError::EINVAL),
                    posix88::EIO        => Err(ReadError::EIO),
                    posix88::EISDIR     => Err(ReadError::EISDIR),
                    _ => Ok(Vec::<u8>::new()),
                };
            } else { // Zero data read

                // If this is our first attempt and we've read nothing, there
                // is nothing to read, and we're done with this call
                if total_read == 0 {
                    return Ok(Vec::<u8>::new());
                }

                // Have we read all we need to?
                if total_read == count {
                    break;
                }

                // We'll give it 10 more read attempts. If nothing by then,
                // We should assume the client has forced disconnect and not
                // sent use a Close Op (Not a very nice client...)
                num_reads_missed += 1;
                if num_reads_missed > 9 {
                    return Ok(Vec::<u8>::new());
                }
            }
        }
        Ok(final_buffer)
    }

    /// Attempts to write data to the socket
    pub fn write(&mut self, op: OpCode, payload: &mut Vec<u8>) -> WriteResult {
        let mut out_buf: Vec<u8> = Vec::with_capacity(payload.len() + 9);

        self.set_op_code(&op, &mut out_buf);
        self.set_payload_info(payload.len(), &mut out_buf);
        out_buf.append(payload);

        self.write_bytes(&out_buf)
    }

    fn set_op_code(&self, op: &OpCode, buf: &mut Vec<u8>) {
        let op_code = match *op {
            OpCode::Continuation    => OP_CONTINUATION,
            OpCode::Text            => OP_TEXT,
            OpCode::Binary          => OP_BINARY,
            OpCode::Close           => OP_CLOSE,
            OpCode::Ping            => OP_PING,
            OpCode::Pong            => OP_PONG
        };
        buf.push(op_code | OP_CODE_MASK);
    }

    fn set_payload_info(&self, len: usize, buf: &mut Vec<u8>) {
        if len <= 125 {
            buf.push(len as u8);
        } else if len <= 65535 {
            let mut len_buf = [0u8; 2];
            len_buf[0] = (len as u16 & 0b1111_1111u16 << 8) as u8;
            len_buf[1] = (len as u16 & 0b1111_1111 as u16) as u8;

            buf.push(126u8); // 16 bit prelude
            buf.push(len_buf[0]);
            buf.push(len_buf[1]);
        } else {
            let mut len_buf = [0u8; 8];
            len_buf[0] = (len as u64 & 0b1111_1111u64 << 56) as u8;
            len_buf[1] = (len as u64 & 0b1111_1111u64 << 48) as u8;
            len_buf[2] = (len as u64 & 0b1111_1111u64 << 40) as u8;
            len_buf[3] = (len as u64 & 0b1111_1111u64 << 32) as u8;
            len_buf[4] = (len as u64 & 0b1111_1111u64 << 24) as u8;
            len_buf[5] = (len as u64 & 0b1111_1111u64 << 16) as u8;
            len_buf[6] = (len as u64 & 0b1111_1111u64 << 8) as u8;
            len_buf[7] = (len as u64 & 0b1111_1111u64) as u8;

            buf.push(127u8); // 64 bit prelude
            buf.push(len_buf[0]);
            buf.push(len_buf[1]);
            buf.push(len_buf[2]);
            buf.push(len_buf[3]);
            buf.push(len_buf[4]);
            buf.push(len_buf[5]);
            buf.push(len_buf[6]);
            buf.push(len_buf[7]);
        }
    }

    fn write_bytes(&mut self, buf: &Vec<u8>) -> SysWriteResult {
        let buffer = buf.as_slice();
        let fd = self.stream.as_raw_fd();
        let count = buf.len() as size_t;

        let mut num_written;
        unsafe {
            let buff_ptr = buffer.as_ptr();
            let void_buff_ptr: *const c_void = mem::transmute(buff_ptr);
            num_written = write(fd, void_buff_ptr, count);
        }

        if num_written < 0 {
            let errno = os::errno();
            return match errno {
                posix88::EAGAIN     => Err(WriteError::EAGAIN),
                posix88::EBADF      => Err(WriteError::EBADF),
                posix88::EFAULT     => Err(WriteError::EFAULT),
                posix88::EFBIG      => Err(WriteError::EFBIG),
                posix88::EINTR      => Err(WriteError::EINTR),
                posix88::EINVAL     => Err(WriteError::EINVAL),
                posix88::EIO        => Err(WriteError::EIO),
                posix88::ENOSPC     => Err(WriteError::ENOSPC),
                posix88::EPIPE      => Err(WriteError::EPIPE),
                _ => panic!("Unknown errno: {}", errno),
            }
        }
        Ok(num_written as u64)
    }
}

impl Clone for WebSocketStream {
    fn clone(&self) -> WebSocketStream {
        WebSocketStream {
            stream: self.stream.try_clone().unwrap()
        }
    }
}
<|endoftext|>


<commit_before>//! Use this library to open a path or URL using the program configured on the system.
//!
//! # Usage
//!
//! The following should open the given URL in a web browser
//!
//! ```test_harness,no_run
//! extern crate open;
//!
//! # #[test]
//! # fn doit() {
//! open::that("http://rust-lang.org").unwrap();
//! # }
//! ```
//!
//! # Notes
//!
//! As an operating system program is used, chances are that the open operation fails.
//! Therefore, you are advised to at least check the result with `.is_err()` and
//! behave accordingly, e.g. by letting the user know what you tried to open, and failed.
//!
//! ```
//! # fn doit() {
//! match open::that("http://rust-lang.org") {
//!     Ok(exit_status) => {
//!         if exit_status.success() {
//!             println!("Look at your browser!");
//!         } else {
//!             if let Some(code) = exit_status.code() {
//!                 println!("Command returned non-zero exit status {}!", code);
//!             } else {
//!                 println!("Command returned with unknown exit status!");
//!             }
//!         }
//!     }
//!     Err(why) => println!("Failure to execute command: {}", why),
//! }
//! # }
//! ```
#[cfg(windows)]
extern crate winapi;

#[cfg(not(target_os = "windows"))]
use std::process::{Command, Stdio};

use std::ffi::OsStr;
use std::io;
use std::process::ExitStatus;
use std::thread;

#[cfg(not(any(target_os = "windows", target_os = "macos")))]
pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
    let path_ref = path.as_ref();
    let mut last_err: io::Error = io::Error::from_raw_os_error(0);
    for program in &["xdg-open", "gnome-open", "kde-open", "wslview"] {
        match Command::new(program)
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .arg(path_ref)
            .spawn()
        {
            Ok(mut child) => return child.wait(),
            Err(err) => {
                last_err = err;
                continue;
            }
        }
    }
    Err(last_err)
}

#[cfg(target_os = "windows")]
pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
    use std::os::windows::ffi::OsStrExt;
    use std::os::windows::process::ExitStatusExt;
    use std::ptr;
    use winapi::ctypes::c_int;
    use winapi::um::shellapi::ShellExecuteW;

    const SW_SHOW: c_int = 5;

    let path = windows::convert_path(path.as_ref())?;
    let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
    let result = unsafe {
        ShellExecuteW(
            ptr::null_mut(),
            operation.as_ptr(),
            path.as_ptr(),
            ptr::null(),
            ptr::null(),
            SW_SHOW,
        )
    };
    if result as c_int > 32 {
        Ok(ExitStatus::from_raw(0))
    } else {
        Err(io::Error::last_os_error())
    }
}

#[cfg(target_os = "macos")]
pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
    Command::new("open")
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .arg(path.as_ref())
        .spawn()?
        .wait()
}

/// Convenience function for opening the passed path in a new thread.
pub fn that_in_background<T: AsRef<OsStr> + Sized>(
    path: T,
) -> thread::JoinHandle<io::Result<ExitStatus>> {
    let path = path.as_ref().to_os_string();
    thread::spawn(|| that(path))
}

#[cfg(windows)]
mod windows {
    use std::ffi::OsStr;
    use std::io;
    use std::os::windows::ffi::OsStrExt;

    pub fn convert_path(path: &OsStr) -> io::Result<Vec<u16>> {
        let mut maybe_result: Vec<_> = path.encode_wide().collect();
        if maybe_result.iter().any(|&u| u == 0) {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                "path contains NUL byte(s)",
            ));
        }
        maybe_result.push(0);
        Ok(maybe_result)
    }
}
<commit_msg>Improve documentation<commit_after>//! Use this library to open a path or URL using the program configured on the system.
//!
//! # Usage
//!
//! The following should open the given URL in a web browser
//!
//! ```test_harness,no_run
//! extern crate open;
//!
//! # #[test]
//! # fn doit() {
//! open::that("http://rust-lang.org").unwrap();
//! # }
//! ```
//!
//! # Notes
//!
//! As an operating system program is used, chances are that the open operation fails.
//! Therefore, you are advised to at least check the result with `.is_err()` and
//! behave accordingly, e.g. by letting the user know what you tried to open, and failed.
//!
//! ```
//! # fn doit() {
//! match open::that("http://rust-lang.org") {
//!     Ok(exit_status) => {
//!         if exit_status.success() {
//!             println!("Look at your browser!");
//!         } else {
//!             if let Some(code) = exit_status.code() {
//!                 println!("Command returned non-zero exit status {}!", code);
//!             } else {
//!                 println!("Command returned with unknown exit status!");
//!             }
//!         }
//!     }
//!     Err(why) => println!("Failure to execute command: {}", why),
//! }
//! # }
//! ```
#[cfg(windows)]
extern crate winapi;

#[cfg(not(target_os = "windows"))]
use std::process::{Command, Stdio};

use std::ffi::OsStr;
use std::io;
use std::process::ExitStatus;
use std::thread;

#[cfg(not(any(target_os = "windows", target_os = "macos")))]
pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
    let path_ref = path.as_ref();
    let mut last_err: io::Error = io::Error::from_raw_os_error(0);
    for program in &["xdg-open", "gnome-open", "kde-open", "wslview"] {
        match Command::new(program)
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .arg(path_ref)
            .spawn()
        {
            Ok(mut child) => return child.wait(),
            Err(err) => {
                last_err = err;
                continue;
            }
        }
    }
    Err(last_err)
}

#[cfg(target_os = "windows")]
pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
    use std::os::windows::ffi::OsStrExt;
    use std::os::windows::process::ExitStatusExt;
    use std::ptr;
    use winapi::ctypes::c_int;
    use winapi::um::shellapi::ShellExecuteW;

    const SW_SHOW: c_int = 5;

    let path = windows::convert_path(path.as_ref())?;
    let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
    let result = unsafe {
        ShellExecuteW(
            ptr::null_mut(),
            operation.as_ptr(),
            path.as_ptr(),
            ptr::null(),
            ptr::null(),
            SW_SHOW,
        )
    };
    if result as c_int > 32 {
        Ok(ExitStatus::from_raw(0))
    } else {
        Err(io::Error::last_os_error())
    }
}

#[cfg(target_os = "macos")]
pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
    Command::new("open")
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .arg(path.as_ref())
        .spawn()?
        .wait()
}

/// Convenience function for opening the passed path in a new thread.
/// See documentation of `that(...)` for more details.
pub fn that_in_background<T: AsRef<OsStr> + Sized>(
    path: T,
) -> thread::JoinHandle<io::Result<ExitStatus>> {
    let path = path.as_ref().to_os_string();
    thread::spawn(|| that(path))
}

#[cfg(windows)]
mod windows {
    use std::ffi::OsStr;
    use std::io;
    use std::os::windows::ffi::OsStrExt;

    pub fn convert_path(path: &OsStr) -> io::Result<Vec<u16>> {
        let mut maybe_result: Vec<_> = path.encode_wide().collect();
        if maybe_result.iter().any(|&u| u == 0) {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                "path contains NUL byte(s)",
            ));
        }
        maybe_result.push(0);
        Ok(maybe_result)
    }
}
<|endoftext|>