<commit_before>#![crate_name = "tiny-http"]
#![crate_type = "lib"]
#![license = "Apache"]
#![feature(unsafe_destructor)]

extern crate url;

use std::io::{Acceptor, IoError, IoResult, Listener, TimedOut};
use std::io::net::ip;
use std::io::net::tcp;
use std::sync;
use std::comm::Select;
use client::ClientConnection;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use response::Response;

mod chunks;
mod client;
mod common;
mod response;
mod sequential;

/// The main class of this library.
///
/// Usually your code will look like this:
///
/// ```
/// let server = httpd::Server::new();
///
/// let pool = std::sync::TaskPool<()>::new(
///     std::cmp::min(1, std::os::num_cpus() - 1), || {}
/// );
///
/// loop {
///     let rq = match server.recv() {
///         Ok(rq) => rq,
///         Err(_) => break
///     };
///
///     pool.execute(proc(_) {
///         handle_request(rq)
///     });
/// }
/// ```
#[unstable]
pub struct Server {
    connections_receiver: Receiver<IoResult<ClientConnection>>,
    connections_close: Sender<()>,
    requests_receiver: sync::Mutex<Vec<Receiver<Request>>>,
    listening_addr: ip::SocketAddr,
}

/// Represents an HTTP request made by a client.
///
/// A `Request` object is what is produced by the server, and is your what
///  your code must analyse and answer.
///
/// This object implements the `Send` trait, therefore you can spawn several threads to
///  handle multiple requests at once.
///
/// It is possible that multiple requests objects are linked to the same client, but
///  don't worry: the library automatically handles synchronization of the answers.
#[unstable]
pub struct Request {
    data_reader: Box<Reader + Send>,
    response_writer: Box<Writer + Send>,
    remote_addr: ip::SocketAddr,
    method: Method,
    path: url::Path,
    http_version: HTTPVersion,
    headers: Vec<Header>,
    body_length: uint,
}

enum ServerRecvEvent {
    NewRequest(Request),
    NewClient(ClientConnection),
    ReceiverErrord(uint),
    ServerSocketCrashed(IoError),
}

impl Server {
    /// Builds a new server on port 80 that listens to all inputs.
    #[unstable]
    pub fn new() -> IoResult<Server> {
        Server::new_with_port(80)
    }

    /// Builds a new server on a given port and that listens to all inputs.
    #[unstable]
    pub fn new_with_port(port: ip::Port) -> IoResult<Server> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: port})
    }

    /// Builds a new server on a rand port and that listens to all inputs.
    /// Returns the server and the port it was created on.
    /// This function is guaranteed not to fail because of a port already in use,
    ///  and is useful for testing purposes.
    #[unstable]
    pub fn new_with_random_port() -> IoResult<(Server, ip::Port)> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: 0})
            .map(|s| { let port = s.get_port(); (s, port) })
    }

    /// Builds a new server that listens on the specified address.
    #[unstable]
    pub fn new_with_addr(addr: &ip::SocketAddr) -> IoResult<Server> {
        // building the TcpAcceptor
        let mut listener = try!(tcp::TcpListener::bind(
            format!("{}", addr.ip).as_slice(), addr.port));
        let local_addr = try!(listener.socket_name());
        let server = try!(listener.listen());

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx_incoming, rx_incoming) = channel();
        let (tx_close, rx_close) = channel();
        spawn(proc() {
            let mut server = server;
            server.set_timeout(Some(2000));

            loop {
                match rx_close.try_recv() {
                    Ok(_) => break,
                    _ => ()
                };

                let val = match server.accept().map(|sock| ClientConnection::new(sock)) {
                    Err(ref err) if err.kind == TimedOut =>
                        continue,
                    a => a
                };

                match tx_incoming.send_opt(val) {
                    Err(_) => break,
                    _ => ()
                }
            }
        });

        // result
        Ok(Server {
            connections_receiver: rx_incoming,
            connections_close: tx_close,
            requests_receiver: sync::Mutex::new(Vec::new()),
            listening_addr: local_addr,
        })
    }

    /// Returns the port where the server is currently running on.
    #[experimental]
    pub fn get_port(&self) -> ip::Port {
        self.listening_addr.port
    }

    /// Returns the number of clients currently connected to the server.
    #[stable]
    pub fn get_num_connections(&self) -> uint {
        self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    #[stable]
    pub fn recv(&self) -> IoResult<Request> {
        loop {
            match self.recv_impl() {
                NewClient(client) => self.add_client(client),
                NewRequest(rq) => return Ok(rq),
                ReceiverErrord(id) => { self.requests_receiver.lock().remove(id); },
                ServerSocketCrashed(err) => return Err(err)
            }
        }
    }

    /// Returns either a new client or a request, plus a list of connections that are
    ///   no longer valid
    fn recv_impl(&self) -> ServerRecvEvent {
        let mut locked_receivers = self.requests_receiver.lock();

        let select = Select::new();

        // add the handle for a new connection to the select
        let mut connections_handle = select.handle(&self.connections_receiver);
        unsafe { connections_handle.add() };

        // add all the existing connections
        let mut rq_handles = Vec::new();
        for rc in locked_receivers.iter() {
            rq_handles.push(select.handle(rc));
        }
        for h in rq_handles.mut_iter() { unsafe { h.add() } }

        // getting the result
        loop {
            let handle_id = select.wait();

            // checking for connections_handle
            if handle_id == connections_handle.id() {
                match connections_handle.recv_opt() {
                    Ok(Ok(connec)) => {
                        for h in rq_handles.mut_iter() { unsafe { h.remove() } };
                        unsafe { connections_handle.remove() };
                        return NewClient(connec);
                    },
                    Ok(Err(err)) => {
                        for h in rq_handles.mut_iter() { unsafe { h.remove() } };
                        unsafe { connections_handle.remove() };
                        return ServerSocketCrashed(err)
                    },
                    _ => ()
                }
            }

            // checking the clients
            let mut result = None;
            for (id, h) in rq_handles.mut_iter().enumerate() {
                if handle_id == h.id() {
                    match h.recv_opt() {
                        Ok(rq) => result = Some(NewRequest(rq)),
                        Err(_) => result = Some(ReceiverErrord(id))
                    }
                    break
                }
            };

            match result {
                None => continue,
                Some(r) => {
                    for h in rq_handles.mut_iter() { unsafe { h.remove() } };
                    unsafe { connections_handle.remove() };
                    return r;
                }
            }
        }
    }

    /// Same as `recv()` but doesn't block.
    #[stable]
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        self.process_new_clients();

        {
            let mut locked_receivers = self.requests_receiver.lock();
            for rx in locked_receivers.iter() {
                let attempt = rx.try_recv();
                if attempt.is_ok() {       // TODO: remove the channel if it is closed
                    return Ok(Some(attempt.unwrap()));
                }
            }
        }

        Ok(None)
    }

    /// Does not block.
    fn process_new_clients(&self) {
        let mut new_clients = Vec::new();

        // we add all the elements available on connections_receiver to new_clients
        loop {
            match self.connections_receiver.try_recv() {
                Ok(client) => new_clients.push(client),
                Err(_) => break
            }
        }

        // for each new client, spawning a task that will
        // continuously try to read a Request
        for client in new_clients.move_iter().filter_map(|c| c.ok()) {
            self.add_client(client)
        }
    }

    /// Adds a new client to the list.
    fn add_client(&self, client: ClientConnection) {
        let (tx, rx) = channel();
        spawn(proc() {
            let mut client = client;
            // TODO: when the channel is being closed, immediatly notify the task
            client.advance(|rq| tx.send_opt(rq).is_ok());
        });
        self.requests_receiver.lock().push(rx);
    }
}

impl Request {
    /// Returns the method requested by the client (eg. `GET`, `POST`, etc.).
    #[stable]
    pub fn get_method<'a>(&'a self) -> &'a Method {
        &self.method
    }

    /// Returns the resource requested by the client.
    #[unstable]
    pub fn get_url<'a>(&'a self) -> &'a url::Path {
        &self.path
    }

    /// Returns a list of all headers sent by the client.
    #[stable]
    pub fn get_headers<'a>(&'a self) -> &'a [Header] {
        self.headers.as_slice()
    }

    /// Returns the length of the body in bytes.
    #[unstable]
    pub fn get_body_length(&self) -> uint {
        self.body_length
    }

    /// Returns the length of the body in bytes.
    #[stable]
    pub fn get_remote_addr<'a>(&'a self) -> &'a ip::SocketAddr {
        &self.remote_addr
    }

    /// Allows to read the body of the request.
    ///
    /// # Example
    ///
    /// ```
    /// let request = server.recv();
    ///
    /// if get_content_type(&request) == "application/json" {
    ///     let json: Json = from_str(request.as_reader().read_to_string()).unwrap();
    /// }
    /// ```
    #[unstable]
    pub fn as_reader<'a>(&'a mut self) -> &'a mut Reader {
        fn passthrough<'a>(r: &'a mut Reader) -> &'a mut Reader { r }
        passthrough(self.data_reader)
    }

    /// Turns the `Request` into a writer.
    ///
    /// The writer has a raw access to the stream to the user.
    /// This function is useful for things like CGI.
    ///
    /// Note that the destruction of the `Writer` object may trigger
    ///  some events. For exemple if a client has sent multiple requests and the requests
    ///  have been processed in parallel, the destruction of a writer will trigger
    ///  the writing of the next response.
    /// Therefore you should always destroy the `Writer` as soon as possible.
    #[stable]
    pub fn into_writer(self) -> Box<Writer + Send> {
        self.response_writer
    }

    /// Sends a response to this request.
    #[unstable]
    pub fn respond<R: Reader>(mut self, response: Response<R>) {
        fn passthrough<'a>(w: &'a mut Writer) -> &'a mut Writer { w }

        let response = response.with_http_version(self.http_version);

        match response.raw_print(passthrough(self.response_writer)) {
            Ok(_) => (),
            Err(err) => println!("error while sending answer: {}", err)     // TODO: handle better?
        }
    }
}

impl std::fmt::Show for Request {
    fn fmt(&self, formatter: &mut std::fmt::Formatter)
        -> Result<(), std::fmt::FormatError>
    {
        (format!("Request({} {} from {})",
            self.method, self.path, self.remote_addr.ip)).fmt(formatter)
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.connections_close.send_opt(()).ok();
    }
}
<commit_msg>get_port() is now get_server_addr()<commit_after>#![crate_name = "tiny-http"]
#![crate_type = "lib"]
#![license = "Apache"]
#![feature(unsafe_destructor)]

extern crate url;

use std::io::{Acceptor, IoError, IoResult, Listener, TimedOut};
use std::io::net::ip;
use std::io::net::tcp;
use std::sync;
use std::comm::Select;
use client::ClientConnection;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use response::Response;

mod chunks;
mod client;
mod common;
mod response;
mod sequential;

/// The main class of this library.
///
/// Usually your code will look like this:
///
/// ```
/// let server = httpd::Server::new();
///
/// let pool = std::sync::TaskPool<()>::new(
///     std::cmp::min(1, std::os::num_cpus() - 1), || {}
/// );
///
/// loop {
///     let rq = match server.recv() {
///         Ok(rq) => rq,
///         Err(_) => break
///     };
///
///     pool.execute(proc(_) {
///         handle_request(rq)
///     });
/// }
/// ```
#[unstable]
pub struct Server {
    connections_receiver: Receiver<IoResult<ClientConnection>>,
    connections_close: Sender<()>,
    requests_receiver: sync::Mutex<Vec<Receiver<Request>>>,
    listening_addr: ip::SocketAddr,
}

/// Represents an HTTP request made by a client.
///
/// A `Request` object is what is produced by the server, and is your what
///  your code must analyse and answer.
///
/// This object implements the `Send` trait, therefore you can spawn several threads to
///  handle multiple requests at once.
///
/// It is possible that multiple requests objects are linked to the same client, but
///  don't worry: the library automatically handles synchronization of the answers.
#[unstable]
pub struct Request {
    data_reader: Box<Reader + Send>,
    response_writer: Box<Writer + Send>,
    remote_addr: ip::SocketAddr,
    method: Method,
    path: url::Path,
    http_version: HTTPVersion,
    headers: Vec<Header>,
    body_length: uint,
}

enum ServerRecvEvent {
    NewRequest(Request),
    NewClient(ClientConnection),
    ReceiverErrord(uint),
    ServerSocketCrashed(IoError),
}

impl Server {
    /// Builds a new server on port 80 that listens to all inputs.
    #[unstable]
    pub fn new() -> IoResult<Server> {
        Server::new_with_port(80)
    }

    /// Builds a new server on a given port and that listens to all inputs.
    #[unstable]
    pub fn new_with_port(port: ip::Port) -> IoResult<Server> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: port})
    }

    /// Builds a new server on a rand port and that listens to all inputs.
    /// Returns the server and the port it was created on.
    /// This function is guaranteed not to fail because of a port already in use,
    ///  and is useful for testing purposes.
    #[unstable]
    pub fn new_with_random_port() -> IoResult<(Server, ip::Port)> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: 0})
            .map(|s| { let port = s.get_server_addr().port; (s, port) })
    }

    /// Builds a new server that listens on the specified address.
    #[unstable]
    pub fn new_with_addr(addr: &ip::SocketAddr) -> IoResult<Server> {
        // building the TcpAcceptor
        let mut listener = try!(tcp::TcpListener::bind(
            format!("{}", addr.ip).as_slice(), addr.port));
        let local_addr = try!(listener.socket_name());
        let server = try!(listener.listen());

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx_incoming, rx_incoming) = channel();
        let (tx_close, rx_close) = channel();
        spawn(proc() {
            let mut server = server;
            server.set_timeout(Some(2000));

            loop {
                match rx_close.try_recv() {
                    Ok(_) => break,
                    _ => ()
                };

                let val = match server.accept().map(|sock| ClientConnection::new(sock)) {
                    Err(ref err) if err.kind == TimedOut =>
                        continue,
                    a => a
                };

                match tx_incoming.send_opt(val) {
                    Err(_) => break,
                    _ => ()
                }
            }
        });

        // result
        Ok(Server {
            connections_receiver: rx_incoming,
            connections_close: tx_close,
            requests_receiver: sync::Mutex::new(Vec::new()),
            listening_addr: local_addr,
        })
    }

    /// Returns the address the server is listening to.
    #[experimental]
    pub fn get_server_addr(&self) -> ip::SocketAddr {
        self.listening_addr
    }

    /// Returns the number of clients currently connected to the server.
    #[stable]
    pub fn get_num_connections(&self) -> uint {
        self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    #[stable]
    pub fn recv(&self) -> IoResult<Request> {
        loop {
            match self.recv_impl() {
                NewClient(client) => self.add_client(client),
                NewRequest(rq) => return Ok(rq),
                ReceiverErrord(id) => { self.requests_receiver.lock().remove(id); },
                ServerSocketCrashed(err) => return Err(err)
            }
        }
    }

    /// Returns either a new client or a request, plus a list of connections that are
    ///   no longer valid
    fn recv_impl(&self) -> ServerRecvEvent {
        let mut locked_receivers = self.requests_receiver.lock();

        let select = Select::new();

        // add the handle for a new connection to the select
        let mut connections_handle = select.handle(&self.connections_receiver);
        unsafe { connections_handle.add() };

        // add all the existing connections
        let mut rq_handles = Vec::new();
        for rc in locked_receivers.iter() {
            rq_handles.push(select.handle(rc));
        }
        for h in rq_handles.mut_iter() { unsafe { h.add() } }

        // getting the result
        loop {
            let handle_id = select.wait();

            // checking for connections_handle
            if handle_id == connections_handle.id() {
                match connections_handle.recv_opt() {
                    Ok(Ok(connec)) => {
                        for h in rq_handles.mut_iter() { unsafe { h.remove() } };
                        unsafe { connections_handle.remove() };
                        return NewClient(connec);
                    },
                    Ok(Err(err)) => {
                        for h in rq_handles.mut_iter() { unsafe { h.remove() } };
                        unsafe { connections_handle.remove() };
                        return ServerSocketCrashed(err)
                    },
                    _ => ()
                }
            }

            // checking the clients
            let mut result = None;
            for (id, h) in rq_handles.mut_iter().enumerate() {
                if handle_id == h.id() {
                    match h.recv_opt() {
                        Ok(rq) => result = Some(NewRequest(rq)),
                        Err(_) => result = Some(ReceiverErrord(id))
                    }
                    break
                }
            };

            match result {
                None => continue,
                Some(r) => {
                    for h in rq_handles.mut_iter() { unsafe { h.remove() } };
                    unsafe { connections_handle.remove() };
                    return r;
                }
            }
        }
    }

    /// Same as `recv()` but doesn't block.
    #[stable]
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        self.process_new_clients();

        {
            let mut locked_receivers = self.requests_receiver.lock();
            for rx in locked_receivers.iter() {
                let attempt = rx.try_recv();
                if attempt.is_ok() {       // TODO: remove the channel if it is closed
                    return Ok(Some(attempt.unwrap()));
                }
            }
        }

        Ok(None)
    }

    /// Does not block.
    fn process_new_clients(&self) {
        let mut new_clients = Vec::new();

        // we add all the elements available on connections_receiver to new_clients
        loop {
            match self.connections_receiver.try_recv() {
                Ok(client) => new_clients.push(client),
                Err(_) => break
            }
        }

        // for each new client, spawning a task that will
        // continuously try to read a Request
        for client in new_clients.move_iter().filter_map(|c| c.ok()) {
            self.add_client(client)
        }
    }

    /// Adds a new client to the list.
    fn add_client(&self, client: ClientConnection) {
        let (tx, rx) = channel();
        spawn(proc() {
            let mut client = client;
            // TODO: when the channel is being closed, immediatly notify the task
            client.advance(|rq| tx.send_opt(rq).is_ok());
        });
        self.requests_receiver.lock().push(rx);
    }
}

impl Request {
    /// Returns the method requested by the client (eg. `GET`, `POST`, etc.).
    #[stable]
    pub fn get_method<'a>(&'a self) -> &'a Method {
        &self.method
    }

    /// Returns the resource requested by the client.
    #[unstable]
    pub fn get_url<'a>(&'a self) -> &'a url::Path {
        &self.path
    }

    /// Returns a list of all headers sent by the client.
    #[stable]
    pub fn get_headers<'a>(&'a self) -> &'a [Header] {
        self.headers.as_slice()
    }

    /// Returns the length of the body in bytes.
    #[unstable]
    pub fn get_body_length(&self) -> uint {
        self.body_length
    }

    /// Returns the length of the body in bytes.
    #[stable]
    pub fn get_remote_addr<'a>(&'a self) -> &'a ip::SocketAddr {
        &self.remote_addr
    }

    /// Allows to read the body of the request.
    ///
    /// # Example
    ///
    /// ```
    /// let request = server.recv();
    ///
    /// if get_content_type(&request) == "application/json" {
    ///     let json: Json = from_str(request.as_reader().read_to_string()).unwrap();
    /// }
    /// ```
    #[unstable]
    pub fn as_reader<'a>(&'a mut self) -> &'a mut Reader {
        fn passthrough<'a>(r: &'a mut Reader) -> &'a mut Reader { r }
        passthrough(self.data_reader)
    }

    /// Turns the `Request` into a writer.
    ///
    /// The writer has a raw access to the stream to the user.
    /// This function is useful for things like CGI.
    ///
    /// Note that the destruction of the `Writer` object may trigger
    ///  some events. For exemple if a client has sent multiple requests and the requests
    ///  have been processed in parallel, the destruction of a writer will trigger
    ///  the writing of the next response.
    /// Therefore you should always destroy the `Writer` as soon as possible.
    #[stable]
    pub fn into_writer(self) -> Box<Writer + Send> {
        self.response_writer
    }

    /// Sends a response to this request.
    #[unstable]
    pub fn respond<R: Reader>(mut self, response: Response<R>) {
        fn passthrough<'a>(w: &'a mut Writer) -> &'a mut Writer { w }

        let response = response.with_http_version(self.http_version);

        match response.raw_print(passthrough(self.response_writer)) {
            Ok(_) => (),
            Err(err) => println!("error while sending answer: {}", err)     // TODO: handle better?
        }
    }
}

impl std::fmt::Show for Request {
    fn fmt(&self, formatter: &mut std::fmt::Formatter)
        -> Result<(), std::fmt::FormatError>
    {
        (format!("Request({} {} from {})",
            self.method, self.path, self.remote_addr.ip)).fmt(formatter)
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.connections_close.send_opt(()).ok();
    }
}
<|endoftext|>


<commit_before>//! A simple library for parsing an XML file into an in-memory tree structure
//!
//! Not recommended for large XML files, as it will load the entire file into memory.
//!
//! # Example
//!
//! ```no_run
//! use xmltree::Element;
//! use std::fs::File;
//!
//! let data: &'static str = r##"
//! <?xml version="1.0" encoding="utf-8" standalone="yes"?>
//! <names>
//!     <name first="bob" last="jones" />
//!     <name first="elizabeth" last="smith" />
//! </names>
//! "##;
//!
//! let mut names_element = Element::parse(data.as_bytes()).unwrap();
//!
//! println!("{:#?}", names_element);
//! {
//!     // get first `name` element
//!     let name = names_element.get_mut_child("name").expect("Can't find name element");
//!     name.attributes.insert("suffix".to_owned(), "mr".to_owned());
//! }
//! names_element.write(File::create("result.xml").unwrap());
//!
//!
//! ```
extern crate xml;

use std::collections::HashMap;
use std::io::{Read, Write};
use std::borrow::Cow;
use std::fmt;

use xml::reader::{EventReader, XmlEvent};
pub use xml::writer::{EmitterConfig, Error};
pub use xml::namespace::Namespace;

/// Represents an XML element.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Element {
    /// This elements prefix, if any
    pub prefix: Option<String>,

    /// This elements namespace, if any
    pub namespace: Option<String>,

    /// The full list of namespaces, if any
    ///
    /// The `Namespace` type is exported from the `xml-rs` crate.
    pub namespaces: Option<Namespace>,

    /// The name of the Element.  Does not include any namespace info
    pub name: String,

    /// The Element attributes
    pub attributes: HashMap<String, String>,

    /// Children
    pub children: Vec<Element>,

    /// The text data for this element
    pub text: Option<String>,
}

/// Errors that can occur parsing XML
#[derive(Debug)]
pub enum ParseError {
    /// The XML is invalid
    MalformedXml(xml::reader::Error),
    /// This library is unable to process this XML. This can occur if, for
    /// example, the XML contains processing instructions.
    CannotParse,
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ParseError::MalformedXml(ref e) => write!(f, "Malformed XML. {}", e),
            ParseError::CannotParse => write!(f, "Cannot parse"),
        }
    }
}

impl std::error::Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::MalformedXml(..) => "Malformed XML",
            ParseError::CannotParse => "Cannot parse",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            ParseError::MalformedXml(ref e) => Some(e),
            ParseError::CannotParse => None,
        }
    }
}

fn build<B: Read>(reader: &mut EventReader<B>, mut elem: Element) -> Result<Element, ParseError> {
    loop {
        match reader.next() {
            Ok(XmlEvent::EndElement { ref name }) => {
                if name.local_name == elem.name {
                    return Ok(elem);
                } else {
                    return Err(ParseError::CannotParse);
                }
            }
            Ok(XmlEvent::StartElement {
                name,
                attributes,
                namespace,
            }) => {
                let mut attr_map = HashMap::new();
                for attr in attributes {
                    attr_map.insert(attr.name.local_name, attr.value);
                }

                let new_elem = Element {
                    prefix: name.prefix,
                    namespace: name.namespace,
                    namespaces: if namespace.is_essentially_empty() {
                        None
                    } else {
                        Some(namespace)
                    },
                    name: name.local_name,
                    attributes: attr_map,
                    children: Vec::new(),
                    text: None,
                };
                elem.children.push(try!(build(reader, new_elem)));
            }
            Ok(XmlEvent::Characters(s)) => {
                elem.text = Some(s);
            }
            Ok(XmlEvent::Whitespace(..)) | Ok(XmlEvent::Comment(..)) => (),
            Ok(XmlEvent::CData(s)) => elem.text = Some(s),
            Ok(XmlEvent::StartDocument { .. })
            | Ok(XmlEvent::EndDocument)
            | Ok(XmlEvent::ProcessingInstruction { .. }) => return Err(ParseError::CannotParse),
            Err(e) => return Err(ParseError::MalformedXml(e)),
        }
    }
}

impl Element {
    /// Create a new empty element with given name
    ///
    /// All other fields are empty
    pub fn new(name: &str) -> Element {
        Element {
            name: String::from(name),
            prefix: None,
            namespace: None,
            namespaces: None,
            attributes: HashMap::new(),
            children: Vec::new(),
            text: None,
        }
    }

    /// Parses some data into an Element
    pub fn parse<R: Read>(r: R) -> Result<Element, ParseError> {
        let mut reader = EventReader::new(r);
        loop {
            match reader.next() {
                Ok(XmlEvent::StartElement {
                    name,
                    attributes,
                    namespace,
                }) => {
                    let mut attr_map = HashMap::new();
                    for attr in attributes {
                        attr_map.insert(attr.name.local_name, attr.value);
                    }

                    let root = Element {
                        prefix: name.prefix,
                        namespace: name.namespace,
                        namespaces: if namespace.is_essentially_empty() {
                            None
                        } else {
                            Some(namespace)
                        },
                        name: name.local_name,
                        attributes: attr_map,
                        children: Vec::new(),
                        text: None,
                    };
                    return build(&mut reader, root);
                }
                Ok(XmlEvent::Comment(..))
                | Ok(XmlEvent::Whitespace(..))
                | Ok(XmlEvent::StartDocument { .. }) => continue,
                Ok(XmlEvent::EndDocument)
                | Ok(XmlEvent::EndElement { .. })
                | Ok(XmlEvent::Characters(..))
                | Ok(XmlEvent::CData(..))
                | Ok(XmlEvent::ProcessingInstruction { .. }) => return Err(ParseError::CannotParse),
                Err(e) => return Err(ParseError::MalformedXml(e)),
            }
        }
    }

    fn _write<B: Write>(&self, emitter: &mut xml::writer::EventWriter<B>) -> Result<(), Error> {
        use xml::writer::events::XmlEvent;
        use xml::name::Name;
        use xml::attribute::Attribute;

        let mut name = Name::local(&self.name);
        if let Some(ref ns) = self.namespace {
            name.namespace = Some(ns);
        }
        if let Some(ref p) = self.prefix {
            name.prefix = Some(p);
        }

        let mut attributes = Vec::with_capacity(self.attributes.len());
        for (k, v) in &self.attributes {
            attributes.push(Attribute {
                name: Name::local(k),
                value: v,
            });
        }

        let empty_ns = Namespace::empty();
        let namespace = if let Some(ref ns) = self.namespaces {
            Cow::Borrowed(ns)
        } else {
            Cow::Borrowed(&empty_ns)
        };

        emitter.write(XmlEvent::StartElement {
            name: name,
            attributes: Cow::Owned(attributes),
            namespace: namespace,
        })?;
        if let Some(ref t) = self.text {
            emitter.write(XmlEvent::Characters(t))?;
        }
        for elem in &self.children {
            elem._write(emitter)?;
        }
        emitter.write(XmlEvent::EndElement { name: Some(name) })?;

        Ok(())
    }

    /// Writes out this element as the root element in an new XML document
    pub fn write<W: Write>(&self, w: W) -> Result<(), Error> {
        self.write_with_config(w, EmitterConfig::new())
    }

    /// Writes out this element as the root element in a new XML document using the provided configuration
    pub fn write_with_config<W: Write>(&self, w: W, config: EmitterConfig) -> Result<(), Error> {
        use xml::writer::EventWriter;
        use xml::writer::events::XmlEvent;
        use xml::common::XmlVersion;

        let mut emitter = EventWriter::new_with_config(w, config);
        emitter.write(XmlEvent::StartDocument {
            version: XmlVersion::Version10,
            encoding: None,
            standalone: None,
        })?;
        self._write(&mut emitter)
    }

    /// Find a child element with the given name and return a reference to it.
    pub fn get_child<K>(&self, k: K) -> Option<&Element>
    where
        String: PartialEq<K>,
    {
        self.children.iter().find(|e| e.name == k)
    }

    /// Find a child element with the given name and return a mutable reference to it.
    pub fn get_mut_child<K>(&mut self, k: K) -> Option<&mut Element>
    where
        String: PartialEq<K>,
    {
        self.children.iter_mut().find(|e| e.name == k)
    }

    /// Find a child element with the given name, remove and return it.
    pub fn take_child<K>(&mut self, k: K) -> Option<Element>
    where
        String: PartialEq<K>,
    {
        self.children
            .iter()
            .position(|e| e.name == k)
            .map(|i| self.children.remove(i))
    }
}
<commit_msg>fix warning: use of deprecated item 'try': use the  operator instead<commit_after>//! A simple library for parsing an XML file into an in-memory tree structure
//!
//! Not recommended for large XML files, as it will load the entire file into memory.
//!
//! # Example
//!
//! ```no_run
//! use xmltree::Element;
//! use std::fs::File;
//!
//! let data: &'static str = r##"
//! <?xml version="1.0" encoding="utf-8" standalone="yes"?>
//! <names>
//!     <name first="bob" last="jones" />
//!     <name first="elizabeth" last="smith" />
//! </names>
//! "##;
//!
//! let mut names_element = Element::parse(data.as_bytes()).unwrap();
//!
//! println!("{:#?}", names_element);
//! {
//!     // get first `name` element
//!     let name = names_element.get_mut_child("name").expect("Can't find name element");
//!     name.attributes.insert("suffix".to_owned(), "mr".to_owned());
//! }
//! names_element.write(File::create("result.xml").unwrap());
//!
//!
//! ```
extern crate xml;

use std::collections::HashMap;
use std::io::{Read, Write};
use std::borrow::Cow;
use std::fmt;

use xml::reader::{EventReader, XmlEvent};
pub use xml::writer::{EmitterConfig, Error};
pub use xml::namespace::Namespace;

/// Represents an XML element.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Element {
    /// This elements prefix, if any
    pub prefix: Option<String>,

    /// This elements namespace, if any
    pub namespace: Option<String>,

    /// The full list of namespaces, if any
    ///
    /// The `Namespace` type is exported from the `xml-rs` crate.
    pub namespaces: Option<Namespace>,

    /// The name of the Element.  Does not include any namespace info
    pub name: String,

    /// The Element attributes
    pub attributes: HashMap<String, String>,

    /// Children
    pub children: Vec<Element>,

    /// The text data for this element
    pub text: Option<String>,
}

/// Errors that can occur parsing XML
#[derive(Debug)]
pub enum ParseError {
    /// The XML is invalid
    MalformedXml(xml::reader::Error),
    /// This library is unable to process this XML. This can occur if, for
    /// example, the XML contains processing instructions.
    CannotParse,
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ParseError::MalformedXml(ref e) => write!(f, "Malformed XML. {}", e),
            ParseError::CannotParse => write!(f, "Cannot parse"),
        }
    }
}

impl std::error::Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::MalformedXml(..) => "Malformed XML",
            ParseError::CannotParse => "Cannot parse",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            ParseError::MalformedXml(ref e) => Some(e),
            ParseError::CannotParse => None,
        }
    }
}

fn build<B: Read>(reader: &mut EventReader<B>, mut elem: Element) -> Result<Element, ParseError> {
    loop {
        match reader.next() {
            Ok(XmlEvent::EndElement { ref name }) => {
                if name.local_name == elem.name {
                    return Ok(elem);
                } else {
                    return Err(ParseError::CannotParse);
                }
            }
            Ok(XmlEvent::StartElement {
                name,
                attributes,
                namespace,
            }) => {
                let mut attr_map = HashMap::new();
                for attr in attributes {
                    attr_map.insert(attr.name.local_name, attr.value);
                }

                let new_elem = Element {
                    prefix: name.prefix,
                    namespace: name.namespace,
                    namespaces: if namespace.is_essentially_empty() {
                        None
                    } else {
                        Some(namespace)
                    },
                    name: name.local_name,
                    attributes: attr_map,
                    children: Vec::new(),
                    text: None,
                };
                elem.children.push(build(reader, new_elem)?);
            }
            Ok(XmlEvent::Characters(s)) => {
                elem.text = Some(s);
            }
            Ok(XmlEvent::Whitespace(..)) | Ok(XmlEvent::Comment(..)) => (),
            Ok(XmlEvent::CData(s)) => elem.text = Some(s),
            Ok(XmlEvent::StartDocument { .. })
            | Ok(XmlEvent::EndDocument)
            | Ok(XmlEvent::ProcessingInstruction { .. }) => return Err(ParseError::CannotParse),
            Err(e) => return Err(ParseError::MalformedXml(e)),
        }
    }
}

impl Element {
    /// Create a new empty element with given name
    ///
    /// All other fields are empty
    pub fn new(name: &str) -> Element {
        Element {
            name: String::from(name),
            prefix: None,
            namespace: None,
            namespaces: None,
            attributes: HashMap::new(),
            children: Vec::new(),
            text: None,
        }
    }

    /// Parses some data into an Element
    pub fn parse<R: Read>(r: R) -> Result<Element, ParseError> {
        let mut reader = EventReader::new(r);
        loop {
            match reader.next() {
                Ok(XmlEvent::StartElement {
                    name,
                    attributes,
                    namespace,
                }) => {
                    let mut attr_map = HashMap::new();
                    for attr in attributes {
                        attr_map.insert(attr.name.local_name, attr.value);
                    }

                    let root = Element {
                        prefix: name.prefix,
                        namespace: name.namespace,
                        namespaces: if namespace.is_essentially_empty() {
                            None
                        } else {
                            Some(namespace)
                        },
                        name: name.local_name,
                        attributes: attr_map,
                        children: Vec::new(),
                        text: None,
                    };
                    return build(&mut reader, root);
                }
                Ok(XmlEvent::Comment(..))
                | Ok(XmlEvent::Whitespace(..))
                | Ok(XmlEvent::StartDocument { .. }) => continue,
                Ok(XmlEvent::EndDocument)
                | Ok(XmlEvent::EndElement { .. })
                | Ok(XmlEvent::Characters(..))
                | Ok(XmlEvent::CData(..))
                | Ok(XmlEvent::ProcessingInstruction { .. }) => return Err(ParseError::CannotParse),
                Err(e) => return Err(ParseError::MalformedXml(e)),
            }
        }
    }

    fn _write<B: Write>(&self, emitter: &mut xml::writer::EventWriter<B>) -> Result<(), Error> {
        use xml::writer::events::XmlEvent;
        use xml::name::Name;
        use xml::attribute::Attribute;

        let mut name = Name::local(&self.name);
        if let Some(ref ns) = self.namespace {
            name.namespace = Some(ns);
        }
        if let Some(ref p) = self.prefix {
            name.prefix = Some(p);
        }

        let mut attributes = Vec::with_capacity(self.attributes.len());
        for (k, v) in &self.attributes {
            attributes.push(Attribute {
                name: Name::local(k),
                value: v,
            });
        }

        let empty_ns = Namespace::empty();
        let namespace = if let Some(ref ns) = self.namespaces {
            Cow::Borrowed(ns)
        } else {
            Cow::Borrowed(&empty_ns)
        };

        emitter.write(XmlEvent::StartElement {
            name: name,
            attributes: Cow::Owned(attributes),
            namespace: namespace,
        })?;
        if let Some(ref t) = self.text {
            emitter.write(XmlEvent::Characters(t))?;
        }
        for elem in &self.children {
            elem._write(emitter)?;
        }
        emitter.write(XmlEvent::EndElement { name: Some(name) })?;

        Ok(())
    }

    /// Writes out this element as the root element in an new XML document
    pub fn write<W: Write>(&self, w: W) -> Result<(), Error> {
        self.write_with_config(w, EmitterConfig::new())
    }

    /// Writes out this element as the root element in a new XML document using the provided configuration
    pub fn write_with_config<W: Write>(&self, w: W, config: EmitterConfig) -> Result<(), Error> {
        use xml::writer::EventWriter;
        use xml::writer::events::XmlEvent;
        use xml::common::XmlVersion;

        let mut emitter = EventWriter::new_with_config(w, config);
        emitter.write(XmlEvent::StartDocument {
            version: XmlVersion::Version10,
            encoding: None,
            standalone: None,
        })?;
        self._write(&mut emitter)
    }

    /// Find a child element with the given name and return a reference to it.
    pub fn get_child<K>(&self, k: K) -> Option<&Element>
    where
        String: PartialEq<K>,
    {
        self.children.iter().find(|e| e.name == k)
    }

    /// Find a child element with the given name and return a mutable reference to it.
    pub fn get_mut_child<K>(&mut self, k: K) -> Option<&mut Element>
    where
        String: PartialEq<K>,
    {
        self.children.iter_mut().find(|e| e.name == k)
    }

    /// Find a child element with the given name, remove and return it.
    pub fn take_child<K>(&mut self, k: K) -> Option<Element>
    where
        String: PartialEq<K>,
    {
        self.children
            .iter()
            .position(|e| e.name == k)
            .map(|i| self.children.remove(i))
    }
}
<|endoftext|>


<commit_before>#![feature(conservative_impl_trait)]
#![feature(const_fn)]

extern crate gl;
pub extern crate glfw;
extern crate image;
pub extern crate luminance;
extern crate nalgebra;
#[cfg(feature = "hot-resource")]
extern crate notify;
extern crate num;
extern crate openal;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[cfg(feature = "hot-resource")]
extern crate time;
extern crate vorbis;
extern crate wavefront_obj;

#[macro_use]
pub mod report;

#[macro_use]
pub mod resource;
#[macro_use]
pub mod scene;

pub mod anim;
pub mod app;
pub mod bootstrap;
pub mod camera;
pub mod compositor;
pub mod color;
pub mod device;
pub mod extra;
pub mod gui;
pub mod id;
pub mod linear;
pub mod model;
pub mod object;
pub mod projection;
pub mod renderer;
pub mod shader;
pub mod spline;
pub mod texture;
pub mod transform;

pub use anim::Cont;
pub use app::App;
pub use bootstrap::{LuminanceBackend, Keyboard, Mouse, MouseMove, Scroll, WindowDim, bootstrap};
pub use camera::{Camera, Freefly};
pub use color::{Color, ColorAlpha};
pub use compositor::{Compositor, Screen};
pub use device::Device;
pub use id::Id;
pub use linear::{Matrix4};
pub use model::{Model, ModelError, Part};
pub use object::Object;
pub use projection::{Projectable, perspective};
pub use renderer::Renderer;
pub use resource::{Load, LoadError, Reload};
pub use shader::{Program, ShaderError, new_program};
pub use scene::Scene;
pub use spline::{Interpolate, Interpolation, Key, Sampler, Spline, SplineIterator, Time};
pub use texture::{TextureImage, load_rgba_texture, save_rgba_texture};
pub use transform::{Axis, Orientation, Position, Translation, Transformable, X_AXIS, Y_AXIS, Z_AXIS,
                   Scale, translation_matrix};
<commit_msg>Better export list for textures.<commit_after>#![feature(conservative_impl_trait)]
#![feature(const_fn)]

extern crate gl;
pub extern crate glfw;
extern crate image;
pub extern crate luminance;
extern crate nalgebra;
#[cfg(feature = "hot-resource")]
extern crate notify;
extern crate num;
extern crate openal;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[cfg(feature = "hot-resource")]
extern crate time;
extern crate vorbis;
extern crate wavefront_obj;

#[macro_use]
pub mod report;

#[macro_use]
pub mod resource;
#[macro_use]
pub mod scene;

pub mod anim;
pub mod app;
pub mod bootstrap;
pub mod camera;
pub mod compositor;
pub mod color;
pub mod device;
pub mod extra;
pub mod gui;
pub mod id;
pub mod linear;
pub mod model;
pub mod object;
pub mod projection;
pub mod renderer;
pub mod shader;
pub mod spline;
pub mod texture;
pub mod transform;

pub use anim::Cont;
pub use app::App;
pub use bootstrap::{LuminanceBackend, Keyboard, Mouse, MouseMove, Scroll, WindowDim, bootstrap};
pub use camera::{Camera, Freefly};
pub use color::{Color, ColorAlpha};
pub use compositor::{Compositor, Screen};
pub use device::Device;
pub use id::Id;
pub use linear::{Matrix4};
pub use model::{Model, ModelError, Part};
pub use object::Object;
pub use projection::{Projectable, perspective};
pub use renderer::Renderer;
pub use resource::{Load, LoadError, Reload};
pub use shader::{Program, ShaderError, new_program};
pub use scene::Scene;
pub use spline::{Interpolate, Interpolation, Key, Sampler, Spline, SplineIterator, Time};
pub use texture::{RGBA32F, Texture, TextureImage, load_rgba_texture, save_rgba_texture};
pub use transform::{Axis, Orientation, Position, Translation, Transformable, X_AXIS, Y_AXIS, Z_AXIS,
                   Scale, translation_matrix};
<|endoftext|>


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

use std::default::Default;
use std::cmp::Ordering;
use std::cell::Cell;
use std::hash::{Writer, Hash};
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::RingBuf;
use std::collections::BitvSet;
use std::collections::BinaryHeap;
use std::collections::hash_map::Entry::{
    Occupied,
    Vacant,
};
use std::fmt;
use std::ops::{Add, Deref};

pub use scored::MinScored;
pub use digraph::DiGraph;
pub use graph::Graph;
pub use ograph::OGraph;
use ograph::{
    EdgeType,
};

pub use self::EdgeDirection::{Outgoing, Incoming};

mod scored;
pub mod digraph;
pub mod graph;
pub mod ograph;

pub mod unionfind;

// Index into the NodeIndex and EdgeIndex arrays
/// Edge direction
#[derive(Copy, Clone, Show, PartialEq)]
pub enum EdgeDirection {
    /// A **Outgoing** edge is an outward edge *from* the current node.
    Outgoing = 0,
    /// An **Incoming** edge is an inbound edge *to* the current node.
    Incoming = 1
}

/// A reference that is hashed and compared by its pointer value.
pub struct Ptr<'b, T: 'b>(pub &'b T);

impl<'b, T> Copy for Ptr<'b, T> {}
impl<'b, T> Clone for Ptr<'b, T>
{
    fn clone(&self) -> Self { *self }
}

fn ptreq<T>(a: &T, b: &T) -> bool {
    a as *const _ == b as *const _
}

impl<'b, T> PartialEq for Ptr<'b, T>
{
    /// Ptr compares by pointer equality, i.e if they point to the same value
    fn eq(&self, other: &Ptr<'b, T>) -> bool {
        ptreq(self.0, other.0)
    }
}

impl<'b, T> PartialOrd for Ptr<'b, T>
{
    fn partial_cmp(&self, other: &Ptr<'b, T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<'b, T> Ord for Ptr<'b, T>
{
    /// Ptr is ordered by pointer value, i.e. an arbitrary but stable and total order.
    fn cmp(&self, other: &Ptr<'b, T>) -> Ordering {
        let a = self.0 as *const _;
        let b = other.0 as *const _;
        a.cmp(&b)
    }
}

impl<'b, T> Deref for Ptr<'b, T> {
    type Target = T;
    fn deref<'a>(&'a self) -> &'a T {
        self.0
    }
}

impl<'b, T> Eq for Ptr<'b, T> {}

impl<'b, T, S: Writer> Hash<S> for Ptr<'b, T>
{
    fn hash(&self, st: &mut S)
    {
        let ptr = (self.0) as *const _;
        ptr.hash(st)
    }
}

impl<'b, T: fmt::Show> fmt::Show for Ptr<'b, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

pub fn dijkstra<'a,
                Graph, N, K,
                F, Edges>(graph: &'a Graph, start: N, mut edges: F) -> HashMap<N, K>
where
    N: Copy + Clone + Eq + Hash + fmt::Show,
    K: Default + Add<Output=K> + Copy + PartialOrd + fmt::Show,
    F: FnMut(&'a Graph, N) -> Edges,
    Edges: Iterator<Item=(N, K)>,
{
    let mut visited = HashSet::new();
    let mut scores = HashMap::new();
    let mut predecessor = HashMap::new();
    let mut visit_next = BinaryHeap::new();
    let zero_score: K = Default::default();
    scores.insert(start, zero_score);
    visit_next.push(MinScored(zero_score, start));
    while let Some(MinScored(node_score, node)) = visit_next.pop() {
        if visited.contains(&node) {
            continue
        }
        println!("Visiting {} with score={}", node, node_score);
        for (next, edge) in edges(graph, node) {
            if visited.contains(&next) {
                continue
            }
            let mut next_score = node_score + edge;
            match scores.entry(&next) {
                Occupied(ent) => if next_score < *ent.get() {
                    *ent.into_mut() = next_score;
                    predecessor.insert(next, node);
                } else {
                    next_score = *ent.get();
                },
                Vacant(ent) => {
                    ent.insert(next_score);
                    predecessor.insert(next, node);
                }
            }
            visit_next.push(MinScored(next_score, next));
        }
        visited.insert(node);
    }
    println!("{}", predecessor);
    scores
}

#[derive(Show)]
pub struct Node<T>(pub T);

pub struct NodeCell<T: Copy>(pub Cell<T>);

impl<T: Copy> Deref for NodeCell<T> {
    type Target = Cell<T>;
    #[inline]
    fn deref(&self) -> &Cell<T> {
        &self.0
    }
}

impl<T: Copy + fmt::Show> fmt::Show for NodeCell<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Node({})", self.0.get())
    }
}

/// A graph trait for accessing the neighbors iterator **I**.
pub trait GraphNeighbors<'a, N> {
    type Iter: Iterator<Item=N>;
    fn neighbors(&'a self, n: N) -> Self::Iter;
}

impl<'a, N: 'a, E> GraphNeighbors<'a, N> for Graph<N, E>
where N: Copy + Clone + PartialOrd + Hash + Eq
{
    type Iter = graph::Neighbors<'a, N>;
    fn neighbors(&'a self, n: N) -> graph::Neighbors<'a, N>
    {
        Graph::neighbors(self, n)
    }
}

impl<'a, N: 'a, E: 'a> GraphNeighbors<'a, N> for DiGraph<N, E>
where N: Copy + Clone + Hash + Eq
{
    type Iter = digraph::Neighbors<'a, N, E>;
    fn neighbors(&'a self, n: N) -> digraph::Neighbors<'a, N, E>
    {
        DiGraph::neighbors(self, n)
    }
}

impl<'a, N, E, ETy: EdgeType> GraphNeighbors<'a, ograph::NodeIndex> for OGraph<N, E, ETy>
{
    type Iter = ograph::Neighbors<'a, E>;
    fn neighbors(&'a self, n: ograph::NodeIndex) -> ograph::Neighbors<'a, E>
    {
        OGraph::neighbors(self, n)
    }
}

/// Wrapper type for walking the graph as if it is undirected
pub struct Undirected<G>(pub G);
/// Wrapper type for walking edges the other way
pub struct Reversed<G>(pub G);

impl<'a, 'b, N, E> GraphNeighbors<'a, ograph::NodeIndex> for Undirected<&'b OGraph<N, E>>
{
    type Iter = ograph::Neighbors<'a, E>;
    fn neighbors(&'a self, n: ograph::NodeIndex) -> ograph::Neighbors<'a, E>
    {
        OGraph::neighbors_both(self.0, n)
    }
}

impl<'a, 'b, N, E, ETy: EdgeType> GraphNeighbors<'a, ograph::NodeIndex> for Reversed<&'b OGraph<N, E, ETy>>
{
    type Iter = ograph::Neighbors<'a, E>;
    fn neighbors(&'a self, n: ograph::NodeIndex) -> ograph::Neighbors<'a, E>
    {
        OGraph::neighbors_directed(self.0, n, EdgeDirection::Incoming)
    }
}

pub trait VisitMap<N> {
    fn visit(&mut self, N) -> bool;
    fn contains(&self, &N) -> bool;
}

impl VisitMap<ograph::NodeIndex> for BitvSet {
    fn visit(&mut self, x: ograph::NodeIndex) -> bool {
        self.insert(x.0)
    }
    fn contains(&self, x: &ograph::NodeIndex) -> bool {
        self.contains(&x.0)
    }
}

impl<N: Eq + Hash> VisitMap<N> for HashSet<N> {
    fn visit(&mut self, x: N) -> bool {
        self.insert(x)
    }
    fn contains(&self, x: &N) -> bool {
        self.contains(x)
    }
}

/// Trait for Graph that knows which datastructure is the best for its visitor map
pub trait Visitable<N> {
    type Map: VisitMap<N>;
    fn visit_map(&self) -> Self::Map;
}

impl<N, E, ETy> Visitable<ograph::NodeIndex> for OGraph<N, E, ETy> where
    ETy: ograph::EdgeType,
{
    type Map = BitvSet;
    fn visit_map(&self) -> BitvSet { BitvSet::with_capacity(self.node_count()) }
}

impl<N, E> Visitable<N> for DiGraph<N, E>
    where N: Copy + Clone + Eq + Hash
{
    type Map = HashSet<N>;
    fn visit_map(&self) -> HashSet<N> { HashSet::with_capacity(self.node_count()) }
}

impl<N, E> Visitable<N> for Graph<N, E>
    where N: Copy + Clone + Ord + Eq + Hash
{
    type Map = HashSet<N>;
    fn visit_map(&self) -> HashSet<N> { HashSet::with_capacity(self.node_count()) }
}

impl<'a, N, V: Visitable<N>> Visitable<N> for Undirected<&'a V>
{
    type Map = <V as Visitable<N>>::Map;
    fn visit_map(&self) -> <V as Visitable<N>>::Map {
        self.0.visit_map()
    }
}

impl<'a, N, V: Visitable<N>> Visitable<N> for Reversed<&'a V>
{
    type Map = <V as Visitable<N>>::Map;
    fn visit_map(&self) -> <V as Visitable<N>>::Map {
        self.0.visit_map()
    }
}

/// A breadth first traversal of a graph.
#[derive(Clone)]
pub struct BreadthFirst<'a, G, N> where
    G: 'a,
    N: Eq + Hash,
{
    pub graph: &'a G,
    pub stack: RingBuf<N>,
    pub visited: HashSet<N>,
}

impl<'a, G, N> BreadthFirst<'a, G, N> where
    G: 'a + GraphNeighbors<'a, N>,
    N: Copy + Eq + Hash,
{
    pub fn new(graph: &'a G, start: N) -> BreadthFirst<'a, G, N>
    {
        let mut rb = RingBuf::new();
        rb.push_back(start);
        BreadthFirst{
            graph: graph,
            stack: rb,
            visited: HashSet::new(),
        }
    }
}

impl<'a, G, N> Iterator for BreadthFirst<'a, G, N> where
    G: 'a + GraphNeighbors<'a, N>,
    N: Copy + Eq + Hash,
    <G as GraphNeighbors<'a, N>>::Iter: Iterator<Item=N>,
{
    type Item = N;
    fn next(&mut self) -> Option<N>
    {
        while let Some(node) = self.stack.pop_front() {
            if !self.visited.insert(node) {
                continue;
            }

            for succ in self.graph.neighbors(node) {
                if !self.visited.contains(&succ) {
                    self.stack.push_back(succ);
                }
            }

            return Some(node);
        }
        None
    }
}

/// A depth first traversal of a graph.
#[derive(Clone)]
pub struct DepthFirst<'a, G, N> where
    G: 'a,
    N: Eq + Hash,
{
    pub graph: &'a G,
    pub stack: Vec<N>,
    pub visited: HashSet<N>,
}

impl<'a, G, N> DepthFirst<'a, G, N> where
    G: 'a + GraphNeighbors<'a, N>,
    N: Copy + Eq + Hash,
{
    pub fn new(graph: &'a G, start: N) -> DepthFirst<'a, G, N>
    {
        DepthFirst{
            graph: graph,
            stack: vec![start],
            visited: HashSet::new(),
        }
    }
}

impl<'a, G, N> Iterator for DepthFirst<'a, G, N> where
    G: 'a + GraphNeighbors<'a, N>,
    N: Copy + Eq + Hash,
    <G as GraphNeighbors<'a, N>>::Iter: Iterator<Item=N>,
{
    type Item = N;
    fn next(&mut self) -> Option<N>
    {
        while let Some(node) = self.stack.pop() {
            if !self.visited.insert(node) {
                continue;
            }

            for succ in self.graph.neighbors(node) {
                if !self.visited.contains(&succ) {
                    self.stack.push(succ);
                }
            }

            return Some(node);
        }
        None
    }
}

pub fn depth_first_search<'a, G, N, F>(graph: &'a G, start: N, mut f: F) -> bool where
    G: 'a + GraphNeighbors<'a, N> + Visitable<N>,
    N: Clone,
    <G as GraphNeighbors<'a, N>>::Iter: Iterator<Item=N>,
    <G as Visitable<N>>::Map: VisitMap<N>,
    F: FnMut(N) -> bool,
{
    let mut stack = Vec::new();
    let mut visited = graph.visit_map();

    stack.push(start);
    while let Some(node) = stack.pop() {
        if !visited.visit(node.clone()) {
            continue;
        }

        for succ in graph.neighbors(node.clone()) {
            if !visited.contains(&succ) {
                stack.push(succ);
            }
        }

        if !f(node) {
            return false
        }
    }
    true
}

/// Run a DFS over an **OGraph**, passing a mutable ref to the graph to the
/// iteration function on each step.
///
/// **Note:** The algorithm will not behave correctly if nodes are removed
/// during iteration. It will not necessarily visit added nodes or edges.
pub fn depth_first_search_mut<'a, N, E, ETy, F>(graph: &'a mut OGraph<N, E, ETy>,
                                                start: ograph::NodeIndex,
                                                mut f: F) -> bool where
    ETy: ograph::EdgeType,
    F: FnMut(&mut OGraph<N, E, ETy>, ograph::NodeIndex) -> bool,
{
    let mut stack = Vec::new();
    let mut visited = graph.visit_map();

    stack.push(start);
    while let Some(node) = stack.pop() {
        if !visited.visit(node) {
            continue;
        }

        for succ in graph.neighbors(node) {
            if !visited.contains(&succ.0) {
                stack.push(succ);
            }
        }

        if !f(graph, node) {
            return false
        }
    }
    true
}

<commit_msg>Use Visitable in dijkstra<commit_after>#![feature(slicing_syntax)]
extern crate test;

use std::default::Default;
use std::cmp::Ordering;
use std::cell::Cell;
use std::hash::{Writer, Hash};
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::RingBuf;
use std::collections::BitvSet;
use std::collections::BinaryHeap;
use std::collections::hash_map::Entry::{
    Occupied,
    Vacant,
};
use std::fmt;
use std::ops::{Add, Deref};

pub use scored::MinScored;
pub use digraph::DiGraph;
pub use graph::Graph;
pub use ograph::OGraph;
use ograph::{
    EdgeType,
};

pub use self::EdgeDirection::{Outgoing, Incoming};

mod scored;
pub mod digraph;
pub mod graph;
pub mod ograph;

pub mod unionfind;

// Index into the NodeIndex and EdgeIndex arrays
/// Edge direction
#[derive(Copy, Clone, Show, PartialEq)]
pub enum EdgeDirection {
    /// A **Outgoing** edge is an outward edge *from* the current node.
    Outgoing = 0,
    /// An **Incoming** edge is an inbound edge *to* the current node.
    Incoming = 1
}

/// A reference that is hashed and compared by its pointer value.
pub struct Ptr<'b, T: 'b>(pub &'b T);

impl<'b, T> Copy for Ptr<'b, T> {}
impl<'b, T> Clone for Ptr<'b, T>
{
    fn clone(&self) -> Self { *self }
}

fn ptreq<T>(a: &T, b: &T) -> bool {
    a as *const _ == b as *const _
}

impl<'b, T> PartialEq for Ptr<'b, T>
{
    /// Ptr compares by pointer equality, i.e if they point to the same value
    fn eq(&self, other: &Ptr<'b, T>) -> bool {
        ptreq(self.0, other.0)
    }
}

impl<'b, T> PartialOrd for Ptr<'b, T>
{
    fn partial_cmp(&self, other: &Ptr<'b, T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<'b, T> Ord for Ptr<'b, T>
{
    /// Ptr is ordered by pointer value, i.e. an arbitrary but stable and total order.
    fn cmp(&self, other: &Ptr<'b, T>) -> Ordering {
        let a = self.0 as *const _;
        let b = other.0 as *const _;
        a.cmp(&b)
    }
}

impl<'b, T> Deref for Ptr<'b, T> {
    type Target = T;
    fn deref<'a>(&'a self) -> &'a T {
        self.0
    }
}

impl<'b, T> Eq for Ptr<'b, T> {}

impl<'b, T, S: Writer> Hash<S> for Ptr<'b, T>
{
    fn hash(&self, st: &mut S)
    {
        let ptr = (self.0) as *const _;
        ptr.hash(st)
    }
}

impl<'b, T: fmt::Show> fmt::Show for Ptr<'b, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

pub fn dijkstra<'a,
                Graph, N, K,
                F, Edges>(graph: &'a Graph, start: N, mut edges: F) -> HashMap<N, K>
where
    Graph: Visitable<N>,
    N: Copy + Clone + Eq + Hash + fmt::Show,
    K: Default + Add<Output=K> + Copy + PartialOrd + fmt::Show,
    F: FnMut(&'a Graph, N) -> Edges,
    Edges: Iterator<Item=(N, K)>,
    <Graph as Visitable<N>>::Map: VisitMap<N>,
{
    let mut visited = graph.visit_map();
    let mut scores = HashMap::new();
    let mut predecessor = HashMap::new();
    let mut visit_next = BinaryHeap::new();
    let zero_score: K = Default::default();
    scores.insert(start, zero_score);
    visit_next.push(MinScored(zero_score, start));
    while let Some(MinScored(node_score, node)) = visit_next.pop() {
        if visited.contains(&node) {
            continue
        }
        println!("Visiting {} with score={}", node, node_score);
        for (next, edge) in edges(graph, node) {
            if visited.contains(&next) {
                continue
            }
            let mut next_score = node_score + edge;
            match scores.entry(&next) {
                Occupied(ent) => if next_score < *ent.get() {
                    *ent.into_mut() = next_score;
                    predecessor.insert(next, node);
                } else {
                    next_score = *ent.get();
                },
                Vacant(ent) => {
                    ent.insert(next_score);
                    predecessor.insert(next, node);
                }
            }
            visit_next.push(MinScored(next_score, next));
        }
        visited.visit(node);
    }
    println!("{}", predecessor);
    scores
}

#[derive(Show)]
pub struct Node<T>(pub T);

pub struct NodeCell<T: Copy>(pub Cell<T>);

impl<T: Copy> Deref for NodeCell<T> {
    type Target = Cell<T>;
    #[inline]
    fn deref(&self) -> &Cell<T> {
        &self.0
    }
}

impl<T: Copy + fmt::Show> fmt::Show for NodeCell<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Node({})", self.0.get())
    }
}

/// A graph trait for accessing the neighbors iterator **I**.
pub trait GraphNeighbors<'a, N> {
    type Iter: Iterator<Item=N>;
    fn neighbors(&'a self, n: N) -> Self::Iter;
}

impl<'a, N: 'a, E> GraphNeighbors<'a, N> for Graph<N, E>
where N: Copy + Clone + PartialOrd + Hash + Eq
{
    type Iter = graph::Neighbors<'a, N>;
    fn neighbors(&'a self, n: N) -> graph::Neighbors<'a, N>
    {
        Graph::neighbors(self, n)
    }
}

impl<'a, N: 'a, E: 'a> GraphNeighbors<'a, N> for DiGraph<N, E>
where N: Copy + Clone + Hash + Eq
{
    type Iter = digraph::Neighbors<'a, N, E>;
    fn neighbors(&'a self, n: N) -> digraph::Neighbors<'a, N, E>
    {
        DiGraph::neighbors(self, n)
    }
}

impl<'a, N, E, ETy: EdgeType> GraphNeighbors<'a, ograph::NodeIndex> for OGraph<N, E, ETy>
{
    type Iter = ograph::Neighbors<'a, E>;
    fn neighbors(&'a self, n: ograph::NodeIndex) -> ograph::Neighbors<'a, E>
    {
        OGraph::neighbors(self, n)
    }
}

/// Wrapper type for walking the graph as if it is undirected
pub struct Undirected<G>(pub G);
/// Wrapper type for walking edges the other way
pub struct Reversed<G>(pub G);

impl<'a, 'b, N, E> GraphNeighbors<'a, ograph::NodeIndex> for Undirected<&'b OGraph<N, E>>
{
    type Iter = ograph::Neighbors<'a, E>;
    fn neighbors(&'a self, n: ograph::NodeIndex) -> ograph::Neighbors<'a, E>
    {
        OGraph::neighbors_both(self.0, n)
    }
}

impl<'a, 'b, N, E, ETy: EdgeType> GraphNeighbors<'a, ograph::NodeIndex> for Reversed<&'b OGraph<N, E, ETy>>
{
    type Iter = ograph::Neighbors<'a, E>;
    fn neighbors(&'a self, n: ograph::NodeIndex) -> ograph::Neighbors<'a, E>
    {
        OGraph::neighbors_directed(self.0, n, EdgeDirection::Incoming)
    }
}

pub trait VisitMap<N> {
    fn visit(&mut self, N) -> bool;
    fn contains(&self, &N) -> bool;
}

impl VisitMap<ograph::NodeIndex> for BitvSet {
    fn visit(&mut self, x: ograph::NodeIndex) -> bool {
        self.insert(x.0)
    }
    fn contains(&self, x: &ograph::NodeIndex) -> bool {
        self.contains(&x.0)
    }
}

impl<N: Eq + Hash> VisitMap<N> for HashSet<N> {
    fn visit(&mut self, x: N) -> bool {
        self.insert(x)
    }
    fn contains(&self, x: &N) -> bool {
        self.contains(x)
    }
}

/// Trait for Graph that knows which datastructure is the best for its visitor map
pub trait Visitable<N> {
    type Map: VisitMap<N>;
    fn visit_map(&self) -> Self::Map;
}

impl<N, E, ETy> Visitable<ograph::NodeIndex> for OGraph<N, E, ETy> where
    ETy: ograph::EdgeType,
{
    type Map = BitvSet;
    fn visit_map(&self) -> BitvSet { BitvSet::with_capacity(self.node_count()) }
}

impl<N, E> Visitable<N> for DiGraph<N, E>
    where N: Copy + Clone + Eq + Hash
{
    type Map = HashSet<N>;
    fn visit_map(&self) -> HashSet<N> { HashSet::with_capacity(self.node_count()) }
}

impl<N, E> Visitable<N> for Graph<N, E>
    where N: Copy + Clone + Ord + Eq + Hash
{
    type Map = HashSet<N>;
    fn visit_map(&self) -> HashSet<N> { HashSet::with_capacity(self.node_count()) }
}

impl<'a, N, V: Visitable<N>> Visitable<N> for Undirected<&'a V>
{
    type Map = <V as Visitable<N>>::Map;
    fn visit_map(&self) -> <V as Visitable<N>>::Map {
        self.0.visit_map()
    }
}

impl<'a, N, V: Visitable<N>> Visitable<N> for Reversed<&'a V>
{
    type Map = <V as Visitable<N>>::Map;
    fn visit_map(&self) -> <V as Visitable<N>>::Map {
        self.0.visit_map()
    }
}

/// A breadth first traversal of a graph.
#[derive(Clone)]
pub struct BreadthFirst<'a, G, N> where
    G: 'a,
    N: Eq + Hash,
{
    pub graph: &'a G,
    pub stack: RingBuf<N>,
    pub visited: HashSet<N>,
}

impl<'a, G, N> BreadthFirst<'a, G, N> where
    G: 'a + GraphNeighbors<'a, N>,
    N: Copy + Eq + Hash,
{
    pub fn new(graph: &'a G, start: N) -> BreadthFirst<'a, G, N>
    {
        let mut rb = RingBuf::new();
        rb.push_back(start);
        BreadthFirst{
            graph: graph,
            stack: rb,
            visited: HashSet::new(),
        }
    }
}

impl<'a, G, N> Iterator for BreadthFirst<'a, G, N> where
    G: 'a + GraphNeighbors<'a, N>,
    N: Copy + Eq + Hash,
    <G as GraphNeighbors<'a, N>>::Iter: Iterator<Item=N>,
{
    type Item = N;
    fn next(&mut self) -> Option<N>
    {
        while let Some(node) = self.stack.pop_front() {
            if !self.visited.insert(node) {
                continue;
            }

            for succ in self.graph.neighbors(node) {
                if !self.visited.contains(&succ) {
                    self.stack.push_back(succ);
                }
            }

            return Some(node);
        }
        None
    }
}

/// A depth first traversal of a graph.
#[derive(Clone)]
pub struct DepthFirst<'a, G, N> where
    G: 'a,
    N: Eq + Hash,
{
    pub graph: &'a G,
    pub stack: Vec<N>,
    pub visited: HashSet<N>,
}

impl<'a, G, N> DepthFirst<'a, G, N> where
    G: 'a + GraphNeighbors<'a, N>,
    N: Copy + Eq + Hash,
{
    pub fn new(graph: &'a G, start: N) -> DepthFirst<'a, G, N>
    {
        DepthFirst{
            graph: graph,
            stack: vec![start],
            visited: HashSet::new(),
        }
    }
}

impl<'a, G, N> Iterator for DepthFirst<'a, G, N> where
    G: 'a + GraphNeighbors<'a, N>,
    N: Copy + Eq + Hash,
    <G as GraphNeighbors<'a, N>>::Iter: Iterator<Item=N>,
{
    type Item = N;
    fn next(&mut self) -> Option<N>
    {
        while let Some(node) = self.stack.pop() {
            if !self.visited.insert(node) {
                continue;
            }

            for succ in self.graph.neighbors(node) {
                if !self.visited.contains(&succ) {
                    self.stack.push(succ);
                }
            }

            return Some(node);
        }
        None
    }
}

pub fn depth_first_search<'a, G, N, F>(graph: &'a G, start: N, mut f: F) -> bool where
    G: 'a + GraphNeighbors<'a, N> + Visitable<N>,
    N: Clone,
    <G as GraphNeighbors<'a, N>>::Iter: Iterator<Item=N>,
    <G as Visitable<N>>::Map: VisitMap<N>,
    F: FnMut(N) -> bool,
{
    let mut stack = Vec::new();
    let mut visited = graph.visit_map();

    stack.push(start);
    while let Some(node) = stack.pop() {
        if !visited.visit(node.clone()) {
            continue;
        }

        for succ in graph.neighbors(node.clone()) {
            if !visited.contains(&succ) {
                stack.push(succ);
            }
        }

        if !f(node) {
            return false
        }
    }
    true
}

/// Run a DFS over an **OGraph**, passing a mutable ref to the graph to the
/// iteration function on each step.
///
/// **Note:** The algorithm will not behave correctly if nodes are removed
/// during iteration. It will not necessarily visit added nodes or edges.
pub fn depth_first_search_mut<'a, N, E, ETy, F>(graph: &'a mut OGraph<N, E, ETy>,
                                                start: ograph::NodeIndex,
                                                mut f: F) -> bool where
    ETy: ograph::EdgeType,
    F: FnMut(&mut OGraph<N, E, ETy>, ograph::NodeIndex) -> bool,
{
    let mut stack = Vec::new();
    let mut visited = graph.visit_map();

    stack.push(start);
    while let Some(node) = stack.pop() {
        if !visited.visit(node) {
            continue;
        }

        for succ in graph.neighbors(node) {
            if !visited.contains(&succ.0) {
                stack.push(succ);
            }
        }

        if !f(graph, node) {
            return false
        }
    }
    true
}

<|endoftext|>


<commit_before>// Copyright 2019 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interface to the operating system's random number generator.
//!
//! # Supported targets
//!
//! | Target            | Target Triple      | Implementation
//! | ----------------- | ------------------ | --------------
//! | Linux, Android    | `*‑linux‑*`        | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random` |
//! | Windows           | `*‑pc‑windows‑*`   | [`RtlGenRandom`][3] |
//! | [Windows UWP][22] | `*‑uwp‑windows‑*`  | [`BCryptGenRandom`][23] |
//! | macOS             | `*‑apple‑darwin`   | [`getentropy()`][19] if available, otherwise [`/dev/random`][20] (identical to `/dev/urandom`)
//! | iOS               | `*‑apple‑ios`      | [`SecRandomCopyBytes`][4]
//! | FreeBSD           | `*‑freebsd`        | [`getrandom()`][21] if available, otherwise [`kern.arandom`][5]
//! | OpenBSD           | `*‑openbsd`        | [`getentropy`][6]
//! | NetBSD            | `*‑netbsd`         | [`kern.arandom`][7]
//! | Dragonfly BSD     | `*‑dragonfly`      | [`/dev/random`][8]
//! | Solaris, illumos  | `*‑solaris`, `*‑illumos` | [`getrandom()`][9] if available, otherwise [`/dev/random`][10]
//! | Fuchsia OS        | `*‑fuchsia`        | [`cprng_draw`][11]
//! | Redox             | `*‑redox`          | [`rand:`][12]
//! | Haiku             | `*‑haiku`          | `/dev/random` (identical to `/dev/urandom`)
//! | SGX               | `x86_64‑*‑sgx`     | [RDRAND][18]
//! | VxWorks           | `*‑wrs‑vxworks‑*`  | `randABytes` after checking entropy pool initialization with `randSecure`
//! | Emscripten        | `*‑emscripten`     | `/dev/random` (identical to `/dev/urandom`)
//! | WASI              | `wasm32‑wasi`      | [`__wasi_random_get`][17]
//! | Web Browser       | `wasm32‑*‑unknown` | [`Crypto.getRandomValues()`][14], see [WebAssembly support][16]
//! | Node.js           | `wasm32‑*‑unknown` | [`crypto.randomBytes`][15], see [WebAssembly support][16]
//!
//! There is no blanket implementation on `unix` targets that reads from
//! `/dev/urandom`. This ensures all supported targets are using the recommended
//! interface and respect maximum buffer sizes.
//!
//! Pull Requests that add support for new targets to `getrandom` are always welcome.
//!
//! ## Unsupported targets
//!
//! By default, `getrandom` will not compile on unsupported targets, but certain
//! features allow a user to select a "fallback" implementation if no supported
//! implementation exists.
//!
//! All of the below mechanisms only affect unsupported
//! targets. Supported targets will _always_ use their supported implementations.
//! This prevents a crate from overriding a secure source of randomness
//! (either accidentally or intentionally).
//!
//! ### RDRAND on x86
//!
//! *If the `"rdrand"` Cargo feature is enabled*, `getrandom` will fallback to using
//! the [`RDRAND`][18] instruction to get randomness on `no_std` `x86`/`x86_64`
//! targets. This feature has no effect on other CPU architectures.
//!
//! ### WebAssembly support
//!
//! This crate fully supports the
//! [`wasm32-wasi`](https://github.com/CraneStation/wasi) and
//! [`wasm32-unknown-emscripten`](https://www.hellorust.com/setup/emscripten/)
//! targets. However, the `wasm32-unknown-unknown` target is not automatically
//! supported since, from the target name alone, we cannot deduce which
//! JavaScript interface is in use (or if JavaScript is available at all).
//!
//! Instead, *if the `"js"` Cargo feature is enabled*, this crate will assume
//! that you are building for an environment containing JavaScript, and will
//! call the appropriate methods. Both web browser (main window and Web Workers)
//! and Node.js environments are supported, invoking the methods
//! [described above](#supported-targets) using the
//! [wasm-bindgen](https://github.com/rust-lang/rust-bindgen) toolchain.
//!
//! This feature has no effect on targets other than `wasm32-unknown-unknown`.
//!
//! ### Custom implementations
//!
//! The [`register_custom_getrandom!`] macro allows a user to mark their own
//! function as the backing implementation for [`getrandom`]. See the macro's
//! documentation for more information about writing and registering your own
//! custom implementations.
//!
//! Note that registering a custom implementation only has an effect on targets
//! that would otherwise not compile. Any supported targets (including those
//! using `"rdrand"` and `"js"` Cargo features) continue using their normal
//! implementations even if a function is registered.
//!
//! ### Indirect Dependencies
//!
//! If `getrandom` is not a direct dependency of your crate, you can still
//! enable any of the above fallback behaviors by enabling the relevant
//! feature in your root crate's `Cargo.toml`:
//! ```toml
//! [dependencies]
//! getrandom = { version = "0.2", features = ["js"] }
//! ```
//!
//! ## Early boot
//!
//! Sometimes, early in the boot process, the OS has not collected enough
//! entropy to securely seed its RNG. This is especially common on virtual
//! machines, where standard "random" events are hard to come by.
//!
//! Some operating system interfaces always block until the RNG is securely
//! seeded. This can take anywhere from a few seconds to more than a minute.
//! A few (Linux, NetBSD and Solaris) offer a choice between blocking and
//! getting an error; in these cases, we always choose to block.
//!
//! On Linux (when the `getrandom` system call is not available), reading from
//! `/dev/urandom` never blocks, even when the OS hasn't collected enough
//! entropy yet. To avoid returning low-entropy bytes, we first poll
//! `/dev/random` and only switch to `/dev/urandom` once this has succeeded.
//!
//! ## Error handling
//!
//! We always choose failure over returning insecure "random" bytes. In general,
//! on supported platforms, failure is highly unlikely, though not impossible.
//! If an error does occur, then it is likely that it will occur on every call to
//! `getrandom`, hence after the first successful call one can be reasonably
//! confident that no errors will occur.
//!
//! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html
//! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html
//! [3]: https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-rtlgenrandom
//! [4]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc
//! [5]: https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4
//! [6]: https://man.openbsd.org/getentropy.2
//! [7]: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7+NetBSD-8.0
//! [8]: https://leaf.dragonflybsd.org/cgi/web-man?command=random&section=4
//! [9]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html
//! [10]: https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html
//! [11]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw
//! [12]: https://github.com/redox-os/randd/blob/master/src/main.rs
//! [14]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
//! [15]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback
//! [16]: #webassembly-support
//! [17]: https://github.com/WebAssembly/WASI/blob/master/design/WASI-core.md#__wasi_random_get
//! [18]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
//! [19]: https://www.unix.com/man-page/mojave/2/getentropy/
//! [20]: https://www.unix.com/man-page/mojave/4/random/
//! [21]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable
//! [22]: https://docs.microsoft.com/en-us/windows/uwp/
//! [23]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom

#![doc(
    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
    html_favicon_url = "https://www.rust-lang.org/favicon.ico",
    html_root_url = "https://rust-random.github.io/rand/"
)]
#![no_std]
#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]

#[macro_use]
extern crate cfg_if;

mod error;
mod util;
// To prevent a breaking change when targets are added, we always export the
// register_custom_getrandom macro, so old Custom RNG crates continue to build.
#[cfg(feature = "custom")]
mod custom;
#[cfg(feature = "std")]
mod error_impls;

pub use crate::error::Error;

// System-specific implementations.
//
// These should all provide getrandom_inner with the same signature as getrandom.
cfg_if! {
    if #[cfg(any(target_os = "dragonfly", target_os = "emscripten",
                 target_os = "haiku",     target_os = "redox"))] {
        mod util_libc;
        #[path = "use_file.rs"] mod imp;
    } else if #[cfg(any(target_os = "android", target_os = "linux"))] {
        mod util_libc;
        mod use_file;
        #[path = "linux_android.rs"] mod imp;
    } else if #[cfg(any(target_os = "illumos", target_os = "solaris"))] {
        mod util_libc;
        mod use_file;
        #[path = "solaris_illumos.rs"] mod imp;
    } else if #[cfg(any(target_os = "freebsd", target_os = "netbsd"))] {
        mod util_libc;
        #[path = "bsd_arandom.rs"] mod imp;
    } else if #[cfg(target_os = "fuchsia")] {
        #[path = "fuchsia.rs"] mod imp;
    } else if #[cfg(target_os = "ios")] {
        #[path = "ios.rs"] mod imp;
    } else if #[cfg(target_os = "macos")] {
        mod util_libc;
        mod use_file;
        #[path = "macos.rs"] mod imp;
    } else if #[cfg(target_os = "openbsd")] {
        mod util_libc;
        #[path = "openbsd.rs"] mod imp;
    } else if #[cfg(target_os = "wasi")] {
        #[path = "wasi.rs"] mod imp;
    } else if #[cfg(target_os = "vxworks")] {
        mod util_libc;
        #[path = "vxworks.rs"] mod imp;
    } else if #[cfg(all(windows, target_vendor = "uwp"))] {
        #[path = "windows_uwp.rs"] mod imp;
    } else if #[cfg(windows)] {
        #[path = "windows.rs"] mod imp;
    } else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] {
        #[path = "rdrand.rs"] mod imp;
    } else if #[cfg(all(feature = "rdrand",
                        any(target_arch = "x86_64", target_arch = "x86")))] {
        #[path = "rdrand.rs"] mod imp;
    } else if #[cfg(all(feature = "js",
                        target_arch = "wasm32", target_os = "unknown"))] {
        #[path = "js.rs"] mod imp;
    } else if #[cfg(feature = "custom")] {
        use custom as imp;
    } else {
        compile_error!("target is not supported, for more information see: \
                        https://docs.rs/getrandom/#unsupported-targets");
    }
}

/// Fill `dest` with random bytes from the system's preferred random number
/// source.
///
/// This function returns an error on any failure, including partial reads. We
/// make no guarantees regarding the contents of `dest` on error. If `dest` is
/// empty, `getrandom` immediately returns success, making no calls to the
/// underlying operating system.
///
/// Blocking is possible, at least during early boot; see module documentation.
///
/// In general, `getrandom` will be fast enough for interactive usage, though
/// significantly slower than a user-space CSPRNG; for the latter consider
/// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
    if dest.is_empty() {
        return Ok(());
    }
    imp::getrandom_inner(dest)
}

#[cfg(test)]
mod test_common;
#[cfg(test)]
mod test_rdrand;
<commit_msg>Fix clippy warning (#187)<commit_after>// Copyright 2019 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interface to the operating system's random number generator.
//!
//! # Supported targets
//!
//! | Target            | Target Triple      | Implementation
//! | ----------------- | ------------------ | --------------
//! | Linux, Android    | `*‑linux‑*`        | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random` |
//! | Windows           | `*‑pc‑windows‑*`   | [`RtlGenRandom`][3] |
//! | [Windows UWP][22] | `*‑uwp‑windows‑*`  | [`BCryptGenRandom`][23] |
//! | macOS             | `*‑apple‑darwin`   | [`getentropy()`][19] if available, otherwise [`/dev/random`][20] (identical to `/dev/urandom`)
//! | iOS               | `*‑apple‑ios`      | [`SecRandomCopyBytes`][4]
//! | FreeBSD           | `*‑freebsd`        | [`getrandom()`][21] if available, otherwise [`kern.arandom`][5]
//! | OpenBSD           | `*‑openbsd`        | [`getentropy`][6]
//! | NetBSD            | `*‑netbsd`         | [`kern.arandom`][7]
//! | Dragonfly BSD     | `*‑dragonfly`      | [`/dev/random`][8]
//! | Solaris, illumos  | `*‑solaris`, `*‑illumos` | [`getrandom()`][9] if available, otherwise [`/dev/random`][10]
//! | Fuchsia OS        | `*‑fuchsia`        | [`cprng_draw`][11]
//! | Redox             | `*‑redox`          | [`rand:`][12]
//! | Haiku             | `*‑haiku`          | `/dev/random` (identical to `/dev/urandom`)
//! | SGX               | `x86_64‑*‑sgx`     | [RDRAND][18]
//! | VxWorks           | `*‑wrs‑vxworks‑*`  | `randABytes` after checking entropy pool initialization with `randSecure`
//! | Emscripten        | `*‑emscripten`     | `/dev/random` (identical to `/dev/urandom`)
//! | WASI              | `wasm32‑wasi`      | [`__wasi_random_get`][17]
//! | Web Browser       | `wasm32‑*‑unknown` | [`Crypto.getRandomValues()`][14], see [WebAssembly support][16]
//! | Node.js           | `wasm32‑*‑unknown` | [`crypto.randomBytes`][15], see [WebAssembly support][16]
//!
//! There is no blanket implementation on `unix` targets that reads from
//! `/dev/urandom`. This ensures all supported targets are using the recommended
//! interface and respect maximum buffer sizes.
//!
//! Pull Requests that add support for new targets to `getrandom` are always welcome.
//!
//! ## Unsupported targets
//!
//! By default, `getrandom` will not compile on unsupported targets, but certain
//! features allow a user to select a "fallback" implementation if no supported
//! implementation exists.
//!
//! All of the below mechanisms only affect unsupported
//! targets. Supported targets will _always_ use their supported implementations.
//! This prevents a crate from overriding a secure source of randomness
//! (either accidentally or intentionally).
//!
//! ### RDRAND on x86
//!
//! *If the `"rdrand"` Cargo feature is enabled*, `getrandom` will fallback to using
//! the [`RDRAND`][18] instruction to get randomness on `no_std` `x86`/`x86_64`
//! targets. This feature has no effect on other CPU architectures.
//!
//! ### WebAssembly support
//!
//! This crate fully supports the
//! [`wasm32-wasi`](https://github.com/CraneStation/wasi) and
//! [`wasm32-unknown-emscripten`](https://www.hellorust.com/setup/emscripten/)
//! targets. However, the `wasm32-unknown-unknown` target is not automatically
//! supported since, from the target name alone, we cannot deduce which
//! JavaScript interface is in use (or if JavaScript is available at all).
//!
//! Instead, *if the `"js"` Cargo feature is enabled*, this crate will assume
//! that you are building for an environment containing JavaScript, and will
//! call the appropriate methods. Both web browser (main window and Web Workers)
//! and Node.js environments are supported, invoking the methods
//! [described above](#supported-targets) using the
//! [wasm-bindgen](https://github.com/rust-lang/rust-bindgen) toolchain.
//!
//! This feature has no effect on targets other than `wasm32-unknown-unknown`.
//!
//! ### Custom implementations
//!
//! The [`register_custom_getrandom!`] macro allows a user to mark their own
//! function as the backing implementation for [`getrandom`]. See the macro's
//! documentation for more information about writing and registering your own
//! custom implementations.
//!
//! Note that registering a custom implementation only has an effect on targets
//! that would otherwise not compile. Any supported targets (including those
//! using `"rdrand"` and `"js"` Cargo features) continue using their normal
//! implementations even if a function is registered.
//!
//! ### Indirect Dependencies
//!
//! If `getrandom` is not a direct dependency of your crate, you can still
//! enable any of the above fallback behaviors by enabling the relevant
//! feature in your root crate's `Cargo.toml`:
//! ```toml
//! [dependencies]
//! getrandom = { version = "0.2", features = ["js"] }
//! ```
//!
//! ## Early boot
//!
//! Sometimes, early in the boot process, the OS has not collected enough
//! entropy to securely seed its RNG. This is especially common on virtual
//! machines, where standard "random" events are hard to come by.
//!
//! Some operating system interfaces always block until the RNG is securely
//! seeded. This can take anywhere from a few seconds to more than a minute.
//! A few (Linux, NetBSD and Solaris) offer a choice between blocking and
//! getting an error; in these cases, we always choose to block.
//!
//! On Linux (when the `getrandom` system call is not available), reading from
//! `/dev/urandom` never blocks, even when the OS hasn't collected enough
//! entropy yet. To avoid returning low-entropy bytes, we first poll
//! `/dev/random` and only switch to `/dev/urandom` once this has succeeded.
//!
//! ## Error handling
//!
//! We always choose failure over returning insecure "random" bytes. In general,
//! on supported platforms, failure is highly unlikely, though not impossible.
//! If an error does occur, then it is likely that it will occur on every call to
//! `getrandom`, hence after the first successful call one can be reasonably
//! confident that no errors will occur.
//!
//! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html
//! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html
//! [3]: https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-rtlgenrandom
//! [4]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc
//! [5]: https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4
//! [6]: https://man.openbsd.org/getentropy.2
//! [7]: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7+NetBSD-8.0
//! [8]: https://leaf.dragonflybsd.org/cgi/web-man?command=random&section=4
//! [9]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html
//! [10]: https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html
//! [11]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw
//! [12]: https://github.com/redox-os/randd/blob/master/src/main.rs
//! [14]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
//! [15]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback
//! [16]: #webassembly-support
//! [17]: https://github.com/WebAssembly/WASI/blob/master/design/WASI-core.md#__wasi_random_get
//! [18]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
//! [19]: https://www.unix.com/man-page/mojave/2/getentropy/
//! [20]: https://www.unix.com/man-page/mojave/4/random/
//! [21]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable
//! [22]: https://docs.microsoft.com/en-us/windows/uwp/
//! [23]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom

#![doc(
    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
    html_favicon_url = "https://www.rust-lang.org/favicon.ico",
    html_root_url = "https://rust-random.github.io/rand/"
)]
#![no_std]
#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]
// `matches!` macro was added only in Rust 1.42, which is bigger than our MSRV
#![allow(clippy::match_like_matches_macro)]

#[macro_use]
extern crate cfg_if;

mod error;
mod util;
// To prevent a breaking change when targets are added, we always export the
// register_custom_getrandom macro, so old Custom RNG crates continue to build.
#[cfg(feature = "custom")]
mod custom;
#[cfg(feature = "std")]
mod error_impls;

pub use crate::error::Error;

// System-specific implementations.
//
// These should all provide getrandom_inner with the same signature as getrandom.
cfg_if! {
    if #[cfg(any(target_os = "dragonfly", target_os = "emscripten",
                 target_os = "haiku",     target_os = "redox"))] {
        mod util_libc;
        #[path = "use_file.rs"] mod imp;
    } else if #[cfg(any(target_os = "android", target_os = "linux"))] {
        mod util_libc;
        mod use_file;
        #[path = "linux_android.rs"] mod imp;
    } else if #[cfg(any(target_os = "illumos", target_os = "solaris"))] {
        mod util_libc;
        mod use_file;
        #[path = "solaris_illumos.rs"] mod imp;
    } else if #[cfg(any(target_os = "freebsd", target_os = "netbsd"))] {
        mod util_libc;
        #[path = "bsd_arandom.rs"] mod imp;
    } else if #[cfg(target_os = "fuchsia")] {
        #[path = "fuchsia.rs"] mod imp;
    } else if #[cfg(target_os = "ios")] {
        #[path = "ios.rs"] mod imp;
    } else if #[cfg(target_os = "macos")] {
        mod util_libc;
        mod use_file;
        #[path = "macos.rs"] mod imp;
    } else if #[cfg(target_os = "openbsd")] {
        mod util_libc;
        #[path = "openbsd.rs"] mod imp;
    } else if #[cfg(target_os = "wasi")] {
        #[path = "wasi.rs"] mod imp;
    } else if #[cfg(target_os = "vxworks")] {
        mod util_libc;
        #[path = "vxworks.rs"] mod imp;
    } else if #[cfg(all(windows, target_vendor = "uwp"))] {
        #[path = "windows_uwp.rs"] mod imp;
    } else if #[cfg(windows)] {
        #[path = "windows.rs"] mod imp;
    } else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] {
        #[path = "rdrand.rs"] mod imp;
    } else if #[cfg(all(feature = "rdrand",
                        any(target_arch = "x86_64", target_arch = "x86")))] {
        #[path = "rdrand.rs"] mod imp;
    } else if #[cfg(all(feature = "js",
                        target_arch = "wasm32", target_os = "unknown"))] {
        #[path = "js.rs"] mod imp;
    } else if #[cfg(feature = "custom")] {
        use custom as imp;
    } else {
        compile_error!("target is not supported, for more information see: \
                        https://docs.rs/getrandom/#unsupported-targets");
    }
}

/// Fill `dest` with random bytes from the system's preferred random number
/// source.
///
/// This function returns an error on any failure, including partial reads. We
/// make no guarantees regarding the contents of `dest` on error. If `dest` is
/// empty, `getrandom` immediately returns success, making no calls to the
/// underlying operating system.
///
/// Blocking is possible, at least during early boot; see module documentation.
///
/// In general, `getrandom` will be fast enough for interactive usage, though
/// significantly slower than a user-space CSPRNG; for the latter consider
/// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
    if dest.is_empty() {
        return Ok(());
    }
    imp::getrandom_inner(dest)
}

#[cfg(test)]
mod test_common;
#[cfg(test)]
mod test_rdrand;
<|endoftext|>