<commit_before>/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::new()`.

The `new()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```rust
let server = httpd::Server::new().unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```rust
loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```rust
let server = Arc::new(server);

for _ in range(0u, 4) {
    spawn(proc() {
        loop {
            let rq = server.recv().unwrap();

            ...
        }
    })
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.get_method()` and `request.get_url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```rust
let response = httpd::Response::from_file(Path::new("image.png"));
```

All that remains to do is call `request.respond()`:

```rust
request.respond(response)
```
*/

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

extern crate encoding;
extern crate time;
extern crate url;

use std::io::{Acceptor, IoResult, Listener};
use std::io::net::ip;
use std::io::net::tcp;
use std::comm::Select;
use std::sync::Arc;
use std::sync::atomics::AtomicBool;
use client::ClientConnection;

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

mod client;
mod common;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket annd the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
#[unstable]
pub struct Server {
    // tasks where the client connections are dispatched
    tasks_pool: util::TaskPool,

    // receiver for client connections
    connections_receiver: Receiver<IoResult<ClientConnection>>,

    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // the sender linked to requests_receiver
    // cloned each time a client connection is created
    requests_sender: Sender<Request>,

    // channel to receive requests from
    requests_receiver: Receiver<Request>,

    // result of TcpListener::socket_name()
    listening_addr: ip::SocketAddr,
}

#[unstable]
pub struct IncomingRequests<'a> {
    server: &'a Server
}

/// 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 dispatch your requests to
///  worker threads.
///
/// It is possible that multiple requests objects are simultaneously linked to the same client,
///  but don't worry: tiny-http automatically handles synchronization of the answers.
///
/// If a `Request` object is destroyed without `into_writer` or `respond` being called,
///  an empty response with a 500 status code (internal server error) will automatically be
///  sent back to the client.
/// This means that if your code fails during the handling of a request, this "internal server
///  error" response will automatically be sent during the stack unwinding.
#[unstable]
pub struct Request {
    data_reader: Box<Reader + Send>,

    // if this writer is empty, then the request has been answered
    response_writer: Option<Box<Writer + Send>>,

    remote_addr: ip::SocketAddr,
    method: Method,
    path: url::Path,
    http_version: HTTPVersion,
    headers: Vec<Header>,
    body_length: uint,
}

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 "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpAcceptor
        let (server, local_addr) = {
            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());
            let server = util::ClosableTcpAcceptor::new(server, close_trigger.clone());
            (server, local_addr)
        };

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx_incoming, rx_incoming) = channel();

        let inside_close_trigger = close_trigger.clone();
        spawn(proc() {
            let mut server = server;

            loop {
                let new_client = server.accept().map(|sock| {
                    use util::ClosableTcpStream;

                    let read_closable = ClosableTcpStream::new(sock.clone(),
                        inside_close_trigger.clone(), true, false);

                    let write_closable = ClosableTcpStream::new(sock.clone(),
                        inside_close_trigger.clone(), false, true);

                    ClientConnection::new(write_closable, read_closable)
                });

                if tx_incoming.send_opt(new_client).is_err() {
                    break
                }
            }
        });

        //
        let (tx_requests, rx_requests) = channel();

        // result
        Ok(Server {
            tasks_pool: util::TaskPool::new(),
            connections_receiver: rx_incoming,
            close: close_trigger,
            requests_sender: tx_requests,
            requests_receiver: rx_requests,
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[unstable]
    pub fn incoming_requests<'a>(&'a self) -> IncomingRequests<'a> {
        IncomingRequests { server: self }
    }

    /// 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 {
        unimplemented!()
        //self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    #[stable]
    pub fn recv(&self) -> IoResult<Request> {
        let rx_requests = &self.requests_receiver;
        let rx_connecs = &self.connections_receiver;

        // TODO: the select! macro doesn't seem to be usable without moving
        //       out of self, so we use Select directly

        let select = Select::new();

        let mut request_handle = select.handle(rx_requests);
        unsafe { request_handle.add() };

        let mut connect_handle = select.handle(rx_connecs);
        unsafe { connect_handle.add() };

        loop {
            let id = select.wait();

            if id == request_handle.id() {
                let request = request_handle.recv();

                unsafe { request_handle.remove() };
                unsafe { connect_handle.remove() };

                return Ok(request)
            }

            if id == connect_handle.id() {
                let client = connect_handle.recv_opt();

                match client {
                    Ok(Ok(client)) => {
                        self.add_client(client);
                        continue
                    },
                    Ok(Err(err)) => {
                        unsafe { request_handle.remove() };
                        unsafe { connect_handle.remove() };

                        return Err(err)
                    },
                    Err(_) => {
                        use std::io;

                        unsafe { request_handle.remove() };
                        unsafe { connect_handle.remove() };

                        return Err(io::standard_error(io::Closed));
                    }
                }
            }

            unreachable!()
        }
    }

    /// Same as `recv()` but doesn't block.
    #[stable]
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        // processing all new clients
        loop {
            match self.connections_receiver.try_recv() {
                Ok(client) => self.add_client(try!(client)),
                Err(_) => break
            }
        }

        // reading the next request
        Ok(self.requests_receiver.try_recv().ok())
    }

    /// Adds a new client to the list.
    fn add_client(&self, client: ClientConnection) {
        let requests_sender = self.requests_sender.clone();

        self.tasks_pool.spawn(proc() {
            let mut client = client;
            // TODO: when the channel is being closed, immediatly notify the task
            client.advance(|rq| requests_sender.send_opt(rq).is_ok());
        });
    }
}

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 HTTP version of the request.
    #[unstable]
    pub fn get_http_version<'a>(&'a self) -> &'a HTTPVersion {
        &self.http_version
    }

    /// Returns the length of the body in bytes.
    ///
    /// Returns `None` if the length is unknown.
    #[unstable]
    pub fn get_body_length(&self) -> Option<uint> {
        Some(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(mut self) -> Box<Writer + Send> {
        self.into_writer_impl()
    }

    fn into_writer_impl(&mut self) -> Box<Writer + Send> {
        use std::mem;

        assert!(self.response_writer.is_some());

        let mut writer = None;
        mem::swap(&mut self.response_writer, &mut writer);
        writer.unwrap()
    }

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

    fn respond_impl<R: Reader>(&mut self, response: Response<R>) {
        use std::io;

        fn passthrough<'a>(w: &'a mut Writer) -> &'a mut Writer { w }
        let mut writer = self.into_writer_impl();

        let do_not_send_body = self.method.equiv(&"HEAD");

        match response.raw_print(passthrough(writer),
                                self.http_version, self.headers.as_slice(),
                                do_not_send_body)
        {
            Ok(_) => (),
            Err(ref err) if err.kind == io::Closed => (),
            Err(ref err) if err.kind == io::BrokenPipe => (),
            Err(ref err) if err.kind == io::ConnectionAborted => (),
            Err(ref err) if err.kind == io::ConnectionRefused => (),
            Err(ref err) if err.kind == io::ConnectionReset => (),
            Err(ref err) =>
                println!("error while sending answer: {}", err)     // TODO: handle better?
        };

        writer.flush().ok();
    }
}

impl<'a> Iterator<Request> for IncomingRequests<'a> {
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

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 Request {
    fn drop(&mut self) {
        if self.response_writer.is_some() {
            let response = Response::new_empty(StatusCode(500));
            self.respond_impl(response);
        }
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        use std::sync::atomics::Relaxed;
        self.close.store(true, Relaxed);
    }
}
<commit_msg>Server fulfills Share again Closes #16<commit_after>/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::new()`.

The `new()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```rust
let server = httpd::Server::new().unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```rust
loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```rust
let server = Arc::new(server);

for _ in range(0u, 4) {
    spawn(proc() {
        loop {
            let rq = server.recv().unwrap();

            ...
        }
    })
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.get_method()` and `request.get_url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```rust
let response = httpd::Response::from_file(Path::new("image.png"));
```

All that remains to do is call `request.respond()`:

```rust
request.respond(response)
```
*/

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

extern crate encoding;
extern crate time;
extern crate url;

use std::io::{Acceptor, IoResult, Listener};
use std::io::net::ip;
use std::io::net::tcp;
use std::comm::Select;
use std::sync::{Arc, Mutex};
use std::sync::atomics::AtomicBool;
use client::ClientConnection;

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

mod client;
mod common;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket annd the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
#[unstable]
pub struct Server {
    // tasks where the client connections are dispatched
    tasks_pool: util::TaskPool,

    // receiver for client connections
    connections_receiver: Mutex<Receiver<IoResult<ClientConnection>>>,

    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // the sender linked to requests_receiver
    // cloned each time a client connection is created
    requests_sender: Mutex<Sender<Request>>,

    // channel to receive requests from
    requests_receiver: Mutex<Receiver<Request>>,

    // result of TcpListener::socket_name()
    listening_addr: ip::SocketAddr,
}

#[unstable]
pub struct IncomingRequests<'a> {
    server: &'a Server
}

/// 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 dispatch your requests to
///  worker threads.
///
/// It is possible that multiple requests objects are simultaneously linked to the same client,
///  but don't worry: tiny-http automatically handles synchronization of the answers.
///
/// If a `Request` object is destroyed without `into_writer` or `respond` being called,
///  an empty response with a 500 status code (internal server error) will automatically be
///  sent back to the client.
/// This means that if your code fails during the handling of a request, this "internal server
///  error" response will automatically be sent during the stack unwinding.
#[unstable]
pub struct Request {
    data_reader: Box<Reader + Send>,

    // if this writer is empty, then the request has been answered
    response_writer: Option<Box<Writer + Send>>,

    remote_addr: ip::SocketAddr,
    method: Method,
    path: url::Path,
    http_version: HTTPVersion,
    headers: Vec<Header>,
    body_length: uint,
}

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 "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpAcceptor
        let (server, local_addr) = {
            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());
            let server = util::ClosableTcpAcceptor::new(server, close_trigger.clone());
            (server, local_addr)
        };

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx_incoming, rx_incoming) = channel();

        let inside_close_trigger = close_trigger.clone();
        spawn(proc() {
            let mut server = server;

            loop {
                let new_client = server.accept().map(|sock| {
                    use util::ClosableTcpStream;

                    let read_closable = ClosableTcpStream::new(sock.clone(),
                        inside_close_trigger.clone(), true, false);

                    let write_closable = ClosableTcpStream::new(sock.clone(),
                        inside_close_trigger.clone(), false, true);

                    ClientConnection::new(write_closable, read_closable)
                });

                if tx_incoming.send_opt(new_client).is_err() {
                    break
                }
            }
        });

        //
        let (tx_requests, rx_requests) = channel();

        // result
        Ok(Server {
            tasks_pool: util::TaskPool::new(),
            connections_receiver: Mutex::new(rx_incoming),
            close: close_trigger,
            requests_sender: Mutex::new(tx_requests),
            requests_receiver: Mutex::new(rx_requests),
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[unstable]
    pub fn incoming_requests<'a>(&'a self) -> IncomingRequests<'a> {
        IncomingRequests { server: self }
    }

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

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

    /// Blocks until an HTTP request has been submitted and returns it.
    #[stable]
    pub fn recv(&self) -> IoResult<Request> {
        let connections_receiver = self.connections_receiver.lock();
        let requests_receiver = self.requests_receiver.lock();

        // TODO: the select! macro doesn't seem to be usable without moving
        //       out of self, so we use Select directly

        let select = Select::new();

        let mut request_handle = select.handle(&*requests_receiver);
        unsafe { request_handle.add() };

        let mut connect_handle = select.handle(&*connections_receiver);
        unsafe { connect_handle.add() };

        loop {
            let id = select.wait();

            if id == request_handle.id() {
                let request = request_handle.recv();

                unsafe { request_handle.remove() };
                unsafe { connect_handle.remove() };

                return Ok(request)
            }

            if id == connect_handle.id() {
                let client = connect_handle.recv_opt();

                match client {
                    Ok(Ok(client)) => {
                        self.add_client(client);
                        continue
                    },
                    Ok(Err(err)) => {
                        unsafe { request_handle.remove() };
                        unsafe { connect_handle.remove() };

                        return Err(err)
                    },
                    Err(_) => {
                        use std::io;

                        unsafe { request_handle.remove() };
                        unsafe { connect_handle.remove() };

                        return Err(io::standard_error(io::Closed));
                    }
                }
            }

            unreachable!()
        }
    }

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

        // processing all new clients
        loop {
            match connections_receiver.try_recv() {
                Ok(client) => self.add_client(try!(client)),
                Err(_) => break
            }
        }

        // reading the next request
        Ok(requests_receiver.try_recv().ok())
    }

    /// Adds a new client to the list.
    fn add_client(&self, client: ClientConnection) {
        let requests_sender = self.requests_sender.lock().clone();

        self.tasks_pool.spawn(proc() {
            let mut client = client;
            // TODO: when the channel is being closed, immediatly notify the task
            client.advance(|rq| requests_sender.send_opt(rq).is_ok());
        });
    }
}

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 HTTP version of the request.
    #[unstable]
    pub fn get_http_version<'a>(&'a self) -> &'a HTTPVersion {
        &self.http_version
    }

    /// Returns the length of the body in bytes.
    ///
    /// Returns `None` if the length is unknown.
    #[unstable]
    pub fn get_body_length(&self) -> Option<uint> {
        Some(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(mut self) -> Box<Writer + Send> {
        self.into_writer_impl()
    }

    fn into_writer_impl(&mut self) -> Box<Writer + Send> {
        use std::mem;

        assert!(self.response_writer.is_some());

        let mut writer = None;
        mem::swap(&mut self.response_writer, &mut writer);
        writer.unwrap()
    }

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

    fn respond_impl<R: Reader>(&mut self, response: Response<R>) {
        use std::io;

        fn passthrough<'a>(w: &'a mut Writer) -> &'a mut Writer { w }
        let mut writer = self.into_writer_impl();

        let do_not_send_body = self.method.equiv(&"HEAD");

        match response.raw_print(passthrough(writer),
                                self.http_version, self.headers.as_slice(),
                                do_not_send_body)
        {
            Ok(_) => (),
            Err(ref err) if err.kind == io::Closed => (),
            Err(ref err) if err.kind == io::BrokenPipe => (),
            Err(ref err) if err.kind == io::ConnectionAborted => (),
            Err(ref err) if err.kind == io::ConnectionRefused => (),
            Err(ref err) if err.kind == io::ConnectionReset => (),
            Err(ref err) =>
                println!("error while sending answer: {}", err)     // TODO: handle better?
        };

        writer.flush().ok();
    }
}

impl<'a> Iterator<Request> for IncomingRequests<'a> {
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

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 Request {
    fn drop(&mut self) {
        if self.response_writer.is_some() {
            let response = Response::new_empty(StatusCode(500));
            self.respond_impl(response);
        }
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        use std::sync::atomics::Relaxed;
        self.close.store(true, Relaxed);
    }
}
<|endoftext|>


<commit_before>//! Derive Getters
//! ===
//!
//! Macro for autogenerating getters. Can only be used on named structs. Will generate
//! getters that will reside in a new trait so as not to pollute the struct namespace.
//!
//! # Usage
//! Add to your project Cargo.toml;
//! ```toml
//! [dependencies]
//! derive-getters = "0.0.4"
//! ```
//!
//! In lib.rs or main.rs;
//! ```
//! #[macro_use]
//! extern crate derive_getters;
//! #
//! # fn main() { }
//! ```
//!
//! # Example
//! ```
//! #[macro_use]
//! extern crate derive_getters;
//!
//! #[derive(Getters)]
//! struct Number {
//!    num: u64,
//! }
//!
//! fn main() {
//!    let number = Number { num: 655 };
//!    assert!(number.get_num() == &655);
//! }
//! ```

#[macro_use] extern crate quote;
extern crate proc_macro;
extern crate syn;

use std::convert::From;

use proc_macro::TokenStream;

use syn::{Data, Type, Ident, Fields, Field, token::Comma};
use syn::punctuated::Punctuated;

static INVALID_STRUCT: &str = "Struct must be a named struct. Not unnamed or unit.";
static INVALID_VARIANT: &str = "Variant must be a struct. Not an enum or union.";
static GETTER_PREFIX: &str = "get_";

type TraitSlots = Vec<TraitSlot>;
type TraitName = Ident;
type StructName = Ident;

/// Derive getters into a seperate trait for the named struct.
#[proc_macro_derive(Getters)]
pub fn getters(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    let (trait_tokens, struct_name, trait_name, trait_slots) = setup_getters_trait(&ast);
    let impl_tokens = setup_trait_impl(struct_name, trait_name, trait_slots);

    let mut tokens = quote::Tokens::new();
    tokens.append_all(trait_tokens.into_iter());
    tokens.append_all(impl_tokens.into_iter());

    //println!("Tokens: {}", &tokens);
    tokens.into()
}

// For building a list of methods that need to be in the trait.
struct TraitSlot {
    label: Ident,
    name: Ident,
    ty: Type,
}

impl TraitSlot {
    fn new(label: Ident, name: Ident, ty: Type) -> TraitSlot {
        TraitSlot {
            label: label,
            name: name,
            ty: ty,
        }
    }
}

fn field_to_trait_slot(field: &Field) -> TraitSlot {
    let name = field.ident.as_ref().unwrap().clone();
    let label = Ident::from(format!("{}{}", GETTER_PREFIX, &name).as_str());
    TraitSlot::new(label, name, field.ty.clone())
}

// Fetch the slots (aka fields) in a structure. If the passed in ast is not a `struct`, it
// return `None`.
fn get_slots<'a>(
    data: &'a syn::Data
) -> Result<&'a Punctuated<Field, Comma>, &'static str> {
    match data {
        &Data::Struct(ref body) => {
            match &body.fields {
                &Fields::Named(ref named) => Ok(&named.named),
                _ => Err(INVALID_STRUCT),
            }
        },
        _ => Err(INVALID_VARIANT),
    }
}

fn setup_getters_trait<'a>(
    ast: &'a syn::DeriveInput
) -> (quote::Tokens, StructName, TraitName, TraitSlots)  {
    let slots: Vec<TraitSlot> = get_slots(&ast.data)
        .unwrap_or_else(|e| panic!("Couldn't autogenerate: {}", e))
        .iter()
        .map(field_to_trait_slot)
        .collect();

    let trait_methods: Vec<quote::Tokens> = slots
        .iter()
        .map(|slot| {
            let label = slot.label.clone();
            let ty = slot.ty.clone();
            quote! {
                fn #label(&self) -> &#ty;
            }
        })
        .collect();

    let struct_name = ast.ident.clone();
    let trait_name = Ident::from(format!("{}Getters", &struct_name).as_str());

    let tokens = quote! {
        pub trait #trait_name {
            #(#trait_methods)*
        }
    };

    (tokens, struct_name, trait_name, slots)
}

fn setup_trait_impl(
    struct_name: StructName, trait_name: TraitName, slots: TraitSlots
) -> quote::Tokens {
    let trait_methods: Vec<quote::Tokens> = slots
        .into_iter()
        .map(|slot| {
            let label = slot.label.clone();
            let name = slot.name.clone();
            let ty = slot.ty.clone();
            quote! {
                fn #label(&self) -> &#ty {
                    &self.#name
                }
            }
        })
        .collect();

    quote! {
        impl #trait_name for #struct_name {
            #(#trait_methods)*
        }
    }
}
<commit_msg>WIP: Little extra doc.<commit_after>//! Derive Getters
//! ===
//!
//! Macro for autogenerating getters. Can only be used on named structs. Will generate
//! getters that will reside in a new trait so as not to pollute the struct namespace.
//!
//! # Usage
//! Add to your project Cargo.toml;
//! ```toml
//! [dependencies]
//! derive-getters = "0.0.4"
//! ```
//!
//! In lib.rs or main.rs;
//! ```
//! #[macro_use]
//! extern crate derive_getters;
//! #
//! # fn main() { }
//! ```
//!
//! # Example
//! ```
//! #[macro_use]
//! extern crate derive_getters;
//!
//! #[derive(Getters)]
//! struct Number {
//!    num: u64,
//! }
//!
//! fn main() {
//!    let number = Number { num: 655 };
//!    assert!(number.get_num() == &655);
//! }
//! ```
//!
//! A new trait, `NumberGetters` will have been generated and implemented for the `Numbers`
//! struct which contains the `get_num` method. To use the trait in other modules one must
//! define a `use` for it from the same location the struct resides.

#[macro_use] extern crate quote;
extern crate proc_macro;
extern crate syn;

use std::convert::From;

use proc_macro::TokenStream;

use syn::{Data, Type, Ident, Fields, Field, token::Comma};
use syn::punctuated::Punctuated;

static INVALID_STRUCT: &str = "Struct must be a named struct. Not unnamed or unit.";
static INVALID_VARIANT: &str = "Variant must be a struct. Not an enum or union.";
static GETTER_PREFIX: &str = "get_";

type TraitSlots = Vec<TraitSlot>;
type TraitName = Ident;
type StructName = Ident;

/// Derive getters into a seperate trait for the named struct.
#[proc_macro_derive(Getters)]
pub fn getters(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    let (trait_tokens, struct_name, trait_name, trait_slots) = setup_getters_trait(&ast);
    let impl_tokens = setup_trait_impl(struct_name, trait_name, trait_slots);

    let mut tokens = quote::Tokens::new();
    tokens.append_all(trait_tokens.into_iter());
    tokens.append_all(impl_tokens.into_iter());

    //println!("Tokens: {}", &tokens);
    tokens.into()
}

// For building a list of methods that need to be in the trait.
struct TraitSlot {
    label: Ident,
    name: Ident,
    ty: Type,
}

impl TraitSlot {
    fn new(label: Ident, name: Ident, ty: Type) -> TraitSlot {
        TraitSlot {
            label: label,
            name: name,
            ty: ty,
        }
    }
}

fn field_to_trait_slot(field: &Field) -> TraitSlot {
    let name = field.ident.as_ref().unwrap().clone();
    let label = Ident::from(format!("{}{}", GETTER_PREFIX, &name).as_str());
    TraitSlot::new(label, name, field.ty.clone())
}

// Fetch the slots (aka fields) in a structure. If the passed in ast is not a `struct`, it
// return `None`.
fn get_slots<'a>(
    data: &'a syn::Data
) -> Result<&'a Punctuated<Field, Comma>, &'static str> {
    match data {
        &Data::Struct(ref body) => {
            match &body.fields {
                &Fields::Named(ref named) => Ok(&named.named),
                _ => Err(INVALID_STRUCT),
            }
        },
        _ => Err(INVALID_VARIANT),
    }
}

fn setup_getters_trait<'a>(
    ast: &'a syn::DeriveInput
) -> (quote::Tokens, StructName, TraitName, TraitSlots)  {
    let slots: Vec<TraitSlot> = get_slots(&ast.data)
        .unwrap_or_else(|e| panic!("Couldn't autogenerate: {}", e))
        .iter()
        .map(field_to_trait_slot)
        .collect();

    let trait_methods: Vec<quote::Tokens> = slots
        .iter()
        .map(|slot| {
            let label = slot.label.clone();
            let ty = slot.ty.clone();
            quote! {
                fn #label(&self) -> &#ty;
            }
        })
        .collect();

    let struct_name = ast.ident.clone();
    let trait_name = Ident::from(format!("{}Getters", &struct_name).as_str());

    let tokens = quote! {
        pub trait #trait_name {
            #(#trait_methods)*
        }
    };

    (tokens, struct_name, trait_name, slots)
}

fn setup_trait_impl(
    struct_name: StructName, trait_name: TraitName, slots: TraitSlots
) -> quote::Tokens {
    let trait_methods: Vec<quote::Tokens> = slots
        .into_iter()
        .map(|slot| {
            let label = slot.label.clone();
            let name = slot.name.clone();
            let ty = slot.ty.clone();
            quote! {
                fn #label(&self) -> &#ty {
                    &self.#name
                }
            }
        })
        .collect();

    quote! {
        impl #trait_name for #struct_name {
            #(#trait_methods)*
        }
    }
}
<|endoftext|>


<commit_before>pub struct Lock<T> {
    opt_val: Option<T>
}

impl<T> Lock<T> {
    /// Creates a Lock<T> container, which should never be directly visible
    ///
    /// Should not be called directly. Only public so that `noleak!()` can call it
    pub unsafe fn new() -> Self {
        Lock { opt_val: None }
    }
}

pub struct Acceptor<'a, T: 'a> {
    mut_lock: &'a mut Lock<T>
}

impl<'a, T: 'a> Acceptor<'a, T> {
    pub unsafe fn new(lock: &'a mut Lock<T>) -> Self {
        Acceptor { mut_lock: lock }
    }

    pub fn fill(self, t: T) -> Handle<'a, T> {
        self.mut_lock.opt_val = Some(t);
        Handle { mut_lock: self.mut_lock }
    }

    pub fn fill_from<'b>(self, handle_t: Handle<'b, T>) -> Handle<'a, T> {
        let new = handle_t.mut_lock.opt_val.take().expect("Attempting to .fill_from() an emptied Handle!");
        self.fill(new)
    }
}

pub struct Handle<'a, T: 'a> {
    mut_lock: &'a mut Lock<T>
}

impl<'a, T: 'a> std::ops::Deref for Handle<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        self.mut_lock.opt_val.as_ref().expect("Tried to deref() an emptied Handle!")
    }
}

impl <'a, T: 'a> std::ops::DerefMut for Handle<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.mut_lock.opt_val.as_mut().expect("Tried to deref_mut() an emptied Handle!")
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn it_works() {
    }
}
<commit_msg>Use Locks as the primary entrance point to creating Acceptors, including creating self-references.<commit_after>use std::marker::PhantomData;

pub struct Lock<'a, T: 'a> {
    opt_val: Option<T>,
    phantom_lock: PhantomData<&'a mut ()>
}

impl<'a, T: 'a> Lock<'a, T> {
    /// Creates a Lock<T> container, which should never be directly visible
    ///
    /// Should not be called directly. Only public so that `noleak!()` can call it
    pub fn new() -> Self {
        Lock { opt_val: None, phantom_lock: PhantomData }
    }

    pub fn lock<R, F: FnOnce(Acceptor<'a, T>) -> R>(&'a mut self, f: F) -> R {
        let acc = Acceptor::new(self);
        f(acc)
    }
}

pub struct Acceptor<'a, T: 'a> {
    mut_lock: &'a mut Lock<'a, T>
}

impl<'a, T: 'a> Acceptor<'a, T> {
    fn new(lock: &'a mut Lock<'a, T>) -> Self {
        Acceptor { mut_lock: lock }
    }

    pub fn fill(self, t: T) -> Handle<'a, T> {
        self.mut_lock.opt_val = Some(t);
        Handle { mut_lock: self.mut_lock }
    }

    pub fn fill_from<'b>(self, handle_t: Handle<'b, T>) -> Handle<'a, T> {
        let new = handle_t.mut_lock.opt_val.take().expect("Attempting to .fill_from() an emptied Handle!");
        self.fill(new)
    }
}

pub struct Handle<'a, T: 'a> {
    mut_lock: &'a mut Lock<'a, T>
}

impl<'a, T: 'a> std::ops::Deref for Handle<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        self.mut_lock.opt_val.as_ref().expect("Tried to deref() an emptied Handle!")
    }
}

impl <'a, T: 'a> std::ops::DerefMut for Handle<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.mut_lock.opt_val.as_mut().expect("Tried to deref_mut() an emptied Handle!")
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>


<commit_before>//! A simple library for reading and writing Riegl .sdc files.
//!
//! .sdc files are simple binary tables of discrete-return LiDAR data.

extern crate byteorder;

mod error;
pub mod file;
pub mod point;
mod result;

pub use file::File;
<commit_msg>Make the error module public<commit_after>//! A simple library for reading and writing Riegl .sdc files.
//!
//! .sdc files are simple binary tables of discrete-return LiDAR data.

extern crate byteorder;

pub mod error;
pub mod file;
pub mod point;
mod result;

pub use file::File;
<|endoftext|>


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

#![allow(unstable)]

use std::ascii::AsciiExt;

use tokenizer::{PeekableTokens, Token, Tokens};
use types::FromTokens;
use types::geometrycollection::GeometryCollection;
use types::linestring::LineString;
use types::point::Point;
use types::polygon::Polygon;
use types::multipoint::MultiPoint;
use types::multilinestring::MultiLineString;
use types::multipolygon::MultiPolygon;

mod tokenizer;
mod types;

pub enum Geometry {
    Point(Point),
    LineString(LineString),
    Polygon(Polygon),
    MultiPoint(MultiPoint),
    MultiLineString(MultiLineString),
    MultiPolygon(MultiPolygon),
    GeometryCollection(GeometryCollection),
}

impl Geometry {
    fn from_word_and_tokens(word: &str, tokens: &mut PeekableTokens)-> Result<Self, &'static str> {
        match word {
            "POINT" => {
                let x = <Point as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "LINESTRING" => {
                let x = <LineString as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "POLYGON" => {
                let x = <Polygon as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "MULTIPOINT" => {
                let x = <MultiPoint as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "MULTILINESTRING" => {
                let x = <MultiLineString as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "MULTIPOLYGON" => {
                let x = <MultiPolygon as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "GEOMETRYCOLLECTION" => {
                let x = <GeometryCollection as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            _ => Err("Invalid type encountered"),
        }
    }
}

pub struct Wkt {
    items: Vec<Geometry>
}

impl Wkt {
    fn new() -> Self {
        Wkt {items: vec![]}
    }

    fn add_item(&mut self, item: Geometry) {
        self.items.push(item);
    }

    fn from_str(wkt_str: &str) -> Result<Self, &'static str> {
        let tokens = Tokens::from_str(wkt_str);
        Wkt::from_tokens(tokens)
    }

    fn from_tokens(tokens: Tokens) -> Result<Self, &'static str> {
        let mut wkt = Wkt::new();
        let mut tokens = tokens.peekable();
        let word = match tokens.next() {
            Some(Token::Word(word)) => {
                if !word.is_ascii() {
                    return Err("Encountered non-ascii word");
                }
                word.to_ascii_uppercase()
            },
            None => return Ok(wkt),
            _ => return Err("Invalid WKT format"),
        };
        match Geometry::from_word_and_tokens(word.as_slice(), &mut tokens) {
            Ok(item) => wkt.add_item(item),
            Err(s) => return Err(s),
        }
        Ok(wkt)
    }
}

#[cfg(test)]
mod tests {
    use super::{Wkt, Geometry};
    use super::types::multipolygon::MultiPolygon;
    use super::types::point::Point;

    #[test]
    fn empty_string() {
        let wkt = Wkt::from_str("").ok().unwrap();
        assert_eq!(0, wkt.items.len());
    }

    #[test]
    fn empty_items() {
        let mut wkt = Wkt::from_str("POINT EMPTY").ok().unwrap();
        assert_eq!(1, wkt.items.len());
        match wkt.items.pop().unwrap() {
            Geometry::Point(Point(None)) => (),
            _ => unreachable!(),
        };

        let mut wkt = Wkt::from_str("MULTIPOLYGON EMPTY").ok().unwrap();
        assert_eq!(1, wkt.items.len());
        match wkt.items.pop().unwrap() {
            Geometry::MultiPolygon(MultiPolygon(polygons)) =>
                assert_eq!(polygons.len(), 0),
            _ => unreachable!(),
        };
    }
}
<commit_msg>Publicize all geometry structs<commit_after>// Copyright 2014-2015 The GeoRust Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![allow(unstable)]

use std::ascii::AsciiExt;

use tokenizer::{PeekableTokens, Token, Tokens};
use types::FromTokens;
pub use types::coord::Coord;
pub use types::geometrycollection::GeometryCollection;
pub use types::linestring::LineString;
pub use types::point::Point;
pub use types::polygon::Polygon;
pub use types::multipoint::MultiPoint;
pub use types::multilinestring::MultiLineString;
pub use types::multipolygon::MultiPolygon;

mod tokenizer;
mod types;

pub enum Geometry {
    Point(Point),
    LineString(LineString),
    Polygon(Polygon),
    MultiPoint(MultiPoint),
    MultiLineString(MultiLineString),
    MultiPolygon(MultiPolygon),
    GeometryCollection(GeometryCollection),
}

impl Geometry {
    fn from_word_and_tokens(word: &str, tokens: &mut PeekableTokens)-> Result<Self, &'static str> {
        match word {
            "POINT" => {
                let x = <Point as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "LINESTRING" => {
                let x = <LineString as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "POLYGON" => {
                let x = <Polygon as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "MULTIPOINT" => {
                let x = <MultiPoint as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "MULTILINESTRING" => {
                let x = <MultiLineString as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "MULTIPOLYGON" => {
                let x = <MultiPolygon as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            "GEOMETRYCOLLECTION" => {
                let x = <GeometryCollection as FromTokens>::from_tokens_with_parens(tokens);
                x.map(|y| y.as_item())
            },
            _ => Err("Invalid type encountered"),
        }
    }
}

pub struct Wkt {
    items: Vec<Geometry>
}

impl Wkt {
    fn new() -> Self {
        Wkt {items: vec![]}
    }

    fn add_item(&mut self, item: Geometry) {
        self.items.push(item);
    }

    fn from_str(wkt_str: &str) -> Result<Self, &'static str> {
        let tokens = Tokens::from_str(wkt_str);
        Wkt::from_tokens(tokens)
    }

    fn from_tokens(tokens: Tokens) -> Result<Self, &'static str> {
        let mut wkt = Wkt::new();
        let mut tokens = tokens.peekable();
        let word = match tokens.next() {
            Some(Token::Word(word)) => {
                if !word.is_ascii() {
                    return Err("Encountered non-ascii word");
                }
                word.to_ascii_uppercase()
            },
            None => return Ok(wkt),
            _ => return Err("Invalid WKT format"),
        };
        match Geometry::from_word_and_tokens(word.as_slice(), &mut tokens) {
            Ok(item) => wkt.add_item(item),
            Err(s) => return Err(s),
        }
        Ok(wkt)
    }
}

#[cfg(test)]
mod tests {
    use super::{Wkt, Geometry};
    use super::types::multipolygon::MultiPolygon;
    use super::types::point::Point;

    #[test]
    fn empty_string() {
        let wkt = Wkt::from_str("").ok().unwrap();
        assert_eq!(0, wkt.items.len());
    }

    #[test]
    fn empty_items() {
        let mut wkt = Wkt::from_str("POINT EMPTY").ok().unwrap();
        assert_eq!(1, wkt.items.len());
        match wkt.items.pop().unwrap() {
            Geometry::Point(Point(None)) => (),
            _ => unreachable!(),
        };

        let mut wkt = Wkt::from_str("MULTIPOLYGON EMPTY").ok().unwrap();
        assert_eq!(1, wkt.items.len());
        match wkt.items.pop().unwrap() {
            Geometry::MultiPolygon(MultiPolygon(polygons)) =>
                assert_eq!(polygons.len(), 0),
            _ => unreachable!(),
        };
    }
}
<|endoftext|>


<commit_before>/*!
```
extern crate hertz;

fn main() {
    let sample_rate = 44100;
    let window_size = 4096;
    let power_spectrum_size = window_size / 2;
    let filter_count = 100;

    for (row, col, value) in enumerate_mel_scaling_matrix(
        sample_rate as f64,
        window_size,
        power_spectrum_size,
        filter_count,
    ) {

    }
}
```
*/

use std::ops::{Add, Sub, Mul, Div, IndexMut};

#[macro_use]
extern crate nalgebra;
use nalgebra::ApproxEq;

extern crate num;
use num::{Float, Zero, NumCast, ToPrimitive};

extern crate hertz;
extern crate apodize;

extern crate itertools;
use itertools::linspace;

macro_rules! from {
    ($expr:expr, $src:ty, $dst:ty) => {
        <$dst as std::convert::From<$src>>::from($expr)
    }
}

#[inline]
pub fn hertz_from_mel<T>(mel: T) -> T
    where T: std::convert::From<f32> + Float + Div<T, Output=T> + Sub<T, Output=T>
{
    from!(700., f32, T) *
        (from!(10., f32, T).powf(
            mel / from!(2595., f32, T)) - from!(1., f32, T))
}

#[inline]
pub fn mel_from_hertz<T>(hertz: T) -> T
    where T: std::convert::From<f32> + Float + Mul<T, Output=T> + Add<T, Output=T>
{
    from!(2595., f32, T) *
        (from!(1., f32, T) + hertz / from!(700., f32, T)).log10()
}

macro_rules! test_mel {
    ($float:ty) => {{
        assert_approx_eq_eps!(
            549.64 as $float, mel_from_hertz(440 as $float), 0.01);
        assert_approx_eq_eps!(
            440 as $float, hertz_from_mel(549.64 as $float), 0.01);

        let mel: $float = 0.;
        assert_approx_eq!(mel, mel_from_hertz(hertz_from_mel(mel)));
        let mel: $float = 100.;
        assert_approx_eq_eps!(
            mel, mel_from_hertz(hertz_from_mel(mel)), 0.0001);
        let mel: $float = 3000.;
        assert_approx_eq_eps!(
            mel, mel_from_hertz(hertz_from_mel(mel)), 0.0001);

        let hertz: $float = 0.;
        assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
        let hertz: $float = 1000.;
        assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
        let hertz: $float = 44100. / 2.;
        assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
    }}
}

#[test]
fn test_mel_f32() {
    test_mel!(f32);
}

#[test]
fn test_mel_f64() {
    test_mel!(f64);
}

/// col index changes fastest
struct MelScalingMatrixEnumerator<T, WindowIter> {
    // parameters

    /// equivalent to col count
    input_size: usize,
    /// equivalent to row count
    output_size: usize,

    mel_from_hertz: fn(T) -> T,
    hertz_from_mel: fn(T) -> T,

    window_function: fn(usize) -> WindowIter,

    // state

    row_index: usize,
    col_index: usize,

    start_mels_iter: itertools::Linspace<T>,
    end_mels_iter: itertools::Linspace<T>,

    // this gets set anew for every row
    window_size: usize,
    window_iter: WindowIter
}

impl<T, WindowIter> MelScalingMatrixEnumerator<T, WindowIter>
    where T: Zero
{
    #[inline]
    pub fn is_done(&self) -> bool {
        self.is_at_end_of_row() && self.is_at_end_of_col()
    }

    #[inline]
    pub fn is_at_end_of_col(&self) -> bool {
        self.output_size <= self.row_index
    }

    #[inline]
    pub fn is_at_end_of_row(&self) -> bool {
        self.input_size <= self.col_index
    }

    #[inline]
    pub fn index(&self) -> usize {
        self.row_index * self.input_size + self.col_index
    }

    #[inline]
    pub fn remaining(&self) -> usize {
        // TODO is this off by one ?
        self.len() - self.index()
    }
}

impl<T, WindowIter> Iterator for MelScalingMatrixEnumerator<T, WindowIter>
    where T: Zero
{
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        if self.is_done() {
            return None;
        }
        Some(T::zero())
        //     Some(value) => {
        //         if self.is_at_end_of_row() {
        //             self.col_index = 0;
        //             self.row_index += 1;
        //         } else {
        //             self.col_index += 1;
        //         }
        //         value
        //     },
        // }
    }

        // // iterate row in outer loop (slow)
        // // iterate col in inner loop (fast)
        // // fill matrix with zeros
        // for i_row in 0..output_size {
        //     for i_col in 0..input_size {
        //         matrix[(i_row, i_col)] = T::zero();
        //     }
        // }
        //
        //
        // for (i_mel, (start_mel, end_mel)) in start_mels_iter
        //     .zip(end_mels_iter)
        //     .enumerate()
        // {
        //     let start_hertz = hertz_from_mel(start_mel) as usize;
        //     let end_hertz = hertz_from_mel(end_mel) as usize;
        //     assert!(start_hertz < end_hertz);
        //     let window_size = end_hertz - start_hertz;
        //     assert!(0 < window_size);
        //     let window_iter = window_function(window_size);
        //     for (ifreq, factor) in window_iter.enumerate() {
        //         matrix[(imel, ifreq)] = factor / window_size;
        //     }
        // }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let remaining = self.remaining();
        (remaining, Some(remaining))
    }
}

impl<T, WindowIter> ExactSizeIterator for MelScalingMatrixEnumerator<T, WindowIter>
    where T: Zero
{
    #[inline]
    fn len(&self) -> usize {
        self.input_size * self.output_size
    }
}

// TODO better name
pub fn mel_scaling_matrix_indexes<T> (
    mels: Range<T>,
) -> Range<usize>
{
    let start_hertz = hertz_from_mel(mels.start);
    let end_hertz = hertz_from_mel(mels.end);
    assert!(start_hertz < end_hertz);

    // divide by max_hertz
    // multiply with output_size

    let start_index = <usize as NumCast>::from()
        .expect("type `usize` can't represent a certain value of type of `T`.
                choose a `T` that can represent fewer numbers.");
    let end_index = <usize as NumCast>::from()
        .expect("type `usize` can't represent a certain value of type of `T`.
                choose a `T` that can represent fewer numbers.");

    start_index..end_index
}

/// (or many vectors at once in form of a matrix)
/// to transform that vector into mel space.
/// efficiently
/// rows are mel
/// cols are freq
/// TODO get frequency index pair for nth mel
/// TODO enumerate scaling vector
/// TODO which dimension first
pub fn enumerate_mel_scaling_matrix_base<T, WindowIter>(
    // TODO more descriptive argument names
    min_hertz: T,
    max_hertz: T,
    // TODO shape
    input_size: usize,
    output_size: usize,
    mel_from_hertz: fn(T) -> T,
    hertz_from_mel: fn(T) -> T,
    window_function: fn(usize) -> WindowIter
) -> MelScalingMatrixEnumerator<T, WindowIter>
    where WindowIter: Iterator<Item=T>,
          T: std::cmp::PartialOrd + Float + ToPrimitive + FromPrimitive
          usize: itertools::misc::ToFloat<T>
{
    assert!(min_freq < max_freq);
    assert!(output_size < input_size);
    assert!(0 < output_size);
    assert!(0 < input_size);

    let min_mel = mel_from_hertz(min_hertz);
    let max_mel = mel_from_hertz(max_hertz);

    let mut start_mels_iter = linspace(min_mel, max_mel, output_size);
    let mut end_mels_iter = linspace(max_mel, max_mel, output_size);
    end_mels_iter.next();

    let first_window_start_mel = start_mels_iter.next().unwrap();
    let first_window_end_mel= end_mels_iter.next().unwrap();
    assert!(first_window_start_mel < first_window_end_mel);
    let first_indexes = mel_scaling_matrix_indexes(
        first_window_start_mel..first_window_end_mel);

    let first_window_size = first_window_end_hertz - first_window_start_hertz;

    let first_window_iter = window_function(first_window_size);

    MelScalingMatrixEnumerator::<T, WindowIter> {
        // parameters
        input_size: input_size,
        output_size: output_size,
        window_function: window_function,

        // state
        row_index: 0,
        col_index: 0,
        start_mels_iter: start_mels_iter,
        end_mels_iter: end_mels_iter,
        window_size: first_window_size,
        window_iter: first_window_iter,
    }
}

/// one filter per row
pub fn enumerate_mel_scaling_matrix<T, T1, T2>(
    sample_rate: T1,
    window_size: T2,
    input_size: usize,
    output_size: usize,
) -> MelScalingMatrixEnumerator<T, apodize::TriangularWindowIter>
    where T: NumCast,
          T1: ToPrimitive,
          T2: ToPrimitive,
{
    let cast_sample_rate = <T as NumCast>::from(sample_rate)
        .expect("type `T` can't represent a certain value of type of `T1`.
                choose a `T1` that can represent fewer numbers
                or `T` that can represent more numbers.");
    let cast_window_size = <T as NumCast>::from(window_size)
        .expect("type `T` can't represent a certain value of type of `T2`.
                choose a `T2` that can represent fewer numbers
                or `T` that can represent more numbers.");
    enumerate_mel_scaling_matrix_base(
        hertz::rayleigh(cast_sample_rate, cast_window_size),
        hertz::nyquist(cast_sample_rate),
        input_size,
        output_size,
        mel_from_hertz,
        hertz_from_mel,
        apodize::triangular_iter
    )
}

// TODO test that identity matrix with
// output_size = input_size
// and conversion functions = identity

// TODO test in a small scale that scaling matrixes are correct
// then test it in emir directly and check correctness visually
<commit_msg>remove complexity of generics and make it compile<commit_after>/*!
```
extern crate hertz;

fn main() {
    let sample_rate = 44100;
    let window_size = 4096;
    let power_spectrum_size = window_size / 2;
    let filter_count = 100;

    for (row, col, value) in enumerate_mel_scaling_matrix(
        sample_rate as f64,
        window_size,
        power_spectrum_size,
        filter_count,
    ) {

    }
}
```
*/

use std::ops::{Add, Sub, Mul, Div, IndexMut, Range};
use std::cmp::{PartialOrd};

#[macro_use]
extern crate nalgebra;
use nalgebra::ApproxEq;

extern crate num;
use num::{Float, Zero, NumCast, ToPrimitive, FromPrimitive};

extern crate hertz;
extern crate apodize;

extern crate itertools;
use itertools::linspace;

macro_rules! f64_from_usize {
    ($val:expr) => {
        <f64>::from_usize($val)
            .expect("type `f64` can't represent a specific value of type `usize` on this architecture.");
    }
}

macro_rules! usize_from_f64 {
    ($val:expr) => {
        <usize>::from_f64($val)
            .expect("type `usize` can't represent a specific value of type `f64` on this architecture.");
    }
}

#[inline]
pub fn hertz_from_mel(mel: f64) -> f64 {
    700. * ((10.).powf(mel / 2595.) - 1.)
}

#[inline]
pub fn mel_from_hertz(hertz: f64) -> f64 {
    2595. * (1. + hertz / 700.).log10()
}

#[test]
fn test_mel() {
    assert_approx_eq_eps!(
        549.64, mel_from_hertz(440.), 0.01);
    assert_approx_eq_eps!(
        440., hertz_from_mel(549.64), 0.01);

    let mel = 0.;
    assert_approx_eq!(mel, mel_from_hertz(hertz_from_mel(mel)));
    let mel = 100.;
    assert_approx_eq_eps!(
        mel, mel_from_hertz(hertz_from_mel(mel)), 0.0001);
    let mel = 3000.;
    assert_approx_eq_eps!(
        mel, mel_from_hertz(hertz_from_mel(mel)), 0.0001);

    let hertz = 0.;
    assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
    let hertz = 1000.;
    assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
    let hertz = 44100. / 2.;
    assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
}

/// col index changes fastest
pub struct MelScalingMatrixEnumerator<WindowIter> {
    // parameters

    /// equivalent to col count
    input_size: usize,
    /// equivalent to row count
    output_size: usize,

    mel_from_hertz: fn(f64) -> f64,
    hertz_from_mel: fn(f64) -> f64,

    window_function: fn(usize) -> WindowIter,

    // state

    row_index: usize,
    col_index: usize,

    start_mels_iter: itertools::Linspace<f64>,
    end_mels_iter: itertools::Linspace<f64>,

    // this gets set anew for every row
    window_start: usize,
    window_size: usize,
    window_iter: WindowIter
}

impl<WindowIter> MelScalingMatrixEnumerator<WindowIter>
    where WindowIter: Iterator<Item=f64>
{
    #[inline]
    pub fn is_done(&self) -> bool {
        self.is_at_end_of_row() && self.is_at_end_of_col()
    }

    #[inline]
    pub fn is_at_end_of_col(&self) -> bool {
        self.output_size <= self.row_index
    }

    #[inline]
    pub fn is_at_end_of_row(&self) -> bool {
        self.input_size <= self.col_index
    }

    #[inline]
    pub fn index(&self) -> usize {
        self.row_index * self.input_size + self.col_index
    }

    #[inline]
    pub fn remaining(&self) -> usize {
        // TODO is this off by one ?
        self.len() - self.index()
    }
}

impl<WindowIter> Iterator for MelScalingMatrixEnumerator<WindowIter>
    where WindowIter: Iterator<Item=f64>
{
    type Item = f64;

    #[inline]
    fn next(&mut self) -> Option<f64> {
        if self.is_done() {
            return None;
        }
        if self.is_at_end_of_row() {
            self.col_index = 0;
            self.row_index += 1;
            // TODO new window iterator...
            return Some(0.);
        }

        self.col_index += 1;
        Some(0.)
    }

        // // iterate row in outer loop (slow)
        // // iterate col in inner loop (fast)
        // // fill matrix with zeros
        // for i_row in 0..output_size {
        //     for i_col in 0..input_size {
        //         matrix[(i_row, i_col)] = T::zero();
        //     }
        // }
        //
        //
        // for (i_mel, (start_mel, end_mel)) in start_mels_iter
        //     .zip(end_mels_iter)
        //     .enumerate()
        // {
        //     let start_hertz = hertz_from_mel(start_mel) as usize;
        //     let end_hertz = hertz_from_mel(end_mel) as usize;
        //     assert!(start_hertz < end_hertz);
        //     let window_size = end_hertz - start_hertz;
        //     assert!(0 < window_size);
        //     let window_iter = window_function(window_size);
        //     for (ifreq, factor) in window_iter.enumerate() {
        //         matrix[(imel, ifreq)] = factor / window_size;
        //     }
        // }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let remaining = self.remaining();
        (remaining, Some(remaining))
    }
}

impl<WindowIter> ExactSizeIterator for MelScalingMatrixEnumerator<WindowIter>
    where WindowIter: Iterator<Item=f64>
{
    #[inline]
    fn len(&self) -> usize {
        self.input_size * self.output_size
    }
}

/// (or many vectors at once in form of a matrix)
/// to transform that vector into mel space.
/// efficiently
/// rows are mel
/// cols are freq
/// TODO get frequency index pair for nth mel
/// TODO enumerate scaling vector
/// TODO which dimension first
pub fn enumerate_mel_scaling_matrix_base<WindowIter>(
    // TODO more descriptive argument names
    min_hertz: f64,
    max_hertz: f64,
    // TODO shape
    input_size: usize,
    output_size: usize,
    mel_from_hertz: fn(f64) -> f64,
    hertz_from_mel: fn(f64) -> f64,
    window_function: fn(usize) -> WindowIter
) -> MelScalingMatrixEnumerator<WindowIter>
    where WindowIter: Iterator<Item=f64>
{
    assert!(min_hertz < max_hertz);
    assert!(output_size < input_size);
    assert!(0 < output_size);
    assert!(0 < input_size);

    let min_mel = mel_from_hertz(min_hertz);
    let max_mel = mel_from_hertz(max_hertz);

    let mut start_mels_iter = linspace(min_mel, max_mel, output_size);
    let mut end_mels_iter = linspace(max_mel, max_mel, output_size);
    end_mels_iter.next();

    let start_mel = start_mels_iter.next().unwrap();
    let end_mel = end_mels_iter.next().unwrap();

    let start_hertz = hertz_from_mel(start_mel);
    let end_hertz = hertz_from_mel(end_mel);

    // TODO maybe round or floor or ceil here
    let start_index = usize_from_f64!(
        start_hertz / max_hertz * f64_from_usize!(output_size));

    let end_index = usize_from_f64!(
        end_hertz / max_hertz * f64_from_usize!(output_size));

    let window_size = end_index - start_index;

    let window_iter = window_function(window_size);

    MelScalingMatrixEnumerator::<WindowIter> {
        // parameters
        input_size: input_size,
        output_size: output_size,
        window_function: window_function,
        hertz_from_mel: hertz_from_mel,
        mel_from_hertz: mel_from_hertz,

        // state
        row_index: 0,
        col_index: 0,

        start_mels_iter: start_mels_iter,
        end_mels_iter: end_mels_iter,

        window_start: start_index,
        window_size: window_size,
        window_iter: window_iter,
    }
}

/// one filter per row
pub fn enumerate_mel_scaling_matrix(
    sample_rate: usize,
    window_size: usize,
    input_size: usize,
    output_size: usize,
) -> MelScalingMatrixEnumerator<apodize::TriangularWindowIter>
{
    enumerate_mel_scaling_matrix_base(
        hertz::rayleigh(
            f64_from_usize!(sample_rate),
            f64_from_usize!(window_size)),
        hertz::nyquist(f64_from_usize!(sample_rate)),
        input_size,
        output_size,
        mel_from_hertz,
        hertz_from_mel,
        apodize::triangular_iter
    )
}

// TODO test that identity matrix with
// output_size = input_size
// and conversion functions = identity

// TODO test in a small scale that scaling matrixes are correct
// then test it in emir directly and check correctness visually
<|endoftext|>


<commit_before>extern crate libc;
extern crate nix;

use std::io;
use std::io::{Write, Read, Error, ErrorKind};
use nix::errno::Errno;
use nix::Error::Sys;
use nix::sys::termios;
use nix::sys::termios::{BRKINT, ICRNL, INPCK, ISTRIP, IXON, OPOST, CS8, ECHO, ICANON, IEXTEN, ISIG, VMIN, VTIME};

static MAX_LINE: i32 = 4096;
static UNSUPPORTED_TERM: [&'static str; 3] = ["dumb","cons25","emacs"];

enum KEYPRESS{
    NULL        = 0,     // NULL
    CTRLA       = 1,     // C-a
    CTRLB       = 2,     // C-b
    CTRLC       = 3,     // C-c
    CTRLD       = 4,     // C-d
    CTRLE       = 5,     // C-e
    CTRLF       = 6,     // C-f
    CTRLH       = 8,     // C-h
    TAB         = 9,     // Tab
    CTRLK       = 11,    // C-k
    CTRLL       = 12,    // C-l
    ENTER       = 13,    // Enter
    CTRLN       = 14,    // C-n
    CTRLP       = 16,    // C-p
    CTRLT       = 20,    // C-t
    CTRLU       = 21,    // C-u
    CTRLW       = 23,    // C-w
    ESC         = 27,    // Esc
    BACKSPACE   = 127    // Backspace
}

fn is_a_tty() -> bool {
    let isatty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
    isatty
}

fn is_unsupported_term() -> bool {
    let term = std::env::var("TERM").ok().unwrap();
    let mut unsupported = false;
    for iter in &UNSUPPORTED_TERM {
        unsupported = term == *iter
    }
    unsupported
}

fn enable_raw_mode() -> Result<termios::Termios, nix::Error> {
    if !is_a_tty() {
        Err(Sys(Errno::ENOTTY))
    } else {
        let original_term = try!(termios::tcgetattr(libc::STDIN_FILENO));
        let mut raw = original_term;
        raw.c_iflag = raw.c_iflag   & !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
        raw.c_oflag = raw.c_oflag   & !(OPOST);
        raw.c_cflag = raw.c_cflag   | (CS8);
        raw.c_lflag = raw.c_lflag   & !(ECHO | ICANON | IEXTEN | ISIG);
        raw.c_cc[VMIN] = 1;
        raw.c_cc[VTIME] = 0;
        try!(termios::tcsetattr(libc::STDIN_FILENO, termios::TCSAFLUSH, &raw));
        Ok(original_term)
    }
}

fn disable_raw_mode(original_termios: termios::Termios) -> Result<(), nix::Error> {
    try!(termios::tcsetattr(libc::STDIN_FILENO, termios::TCSAFLUSH, &original_termios));
    Ok(())
}

fn readline_edit() -> Result<String, io::Error> {
    let mut buffer = Vec::new();
    let mut input: [u8; 1] = [0];
    let numread = io::stdin().read(&mut input).unwrap();
    buffer.push(input[0]);
    println!("{}",input[0]);
    Ok(String::from_utf8(buffer).unwrap())
}

fn readline_raw() -> Result<String, io::Error> {
    if is_a_tty() {
        let original_termios = match enable_raw_mode() {
            Err(Sys(Errno::ENOTTY)) => return Err(Error::new(ErrorKind::Other, "Not a TTY")),
            Err(Sys(Errno::EBADF))  => return Err(Error::new(ErrorKind::Other, "Not a file descriptor")),
            Err(..)                 => return Err(Error::new(ErrorKind::Other, "Unknown Error")),
            Ok(term)                => term
        };

        let user_input = readline_edit();

        match disable_raw_mode(original_termios) {
            Err(..) => return Err(Error::new(ErrorKind::Other, "Failed to revert to original termios")),
            Ok(..)  => ()
        }

        user_input
    } else {

        let mut line = String::new();
        match io::stdin().read_line(&mut line) {
            Ok(_) => Ok(line),
            Err(e) => Err(e),
        }
    }
}

pub fn readline(prompt: &'static str) -> Result<String, io::Error> {
    // Write prompt and flush it to stdout
    let mut stdout = io::stdout();
    try!(stdout.write(prompt.as_bytes()));
    try!(stdout.flush());

    if is_unsupported_term() {
        let mut line = String::new();
        match io::stdin().read_line(&mut line) {
            Ok(_) => Ok(line),
            Err(e) => Err(e),
        }
    } else {
        readline_raw()
    }
}
<commit_msg>Removed the KEYPRESS enum because Rust doesn't support the FromPrimitive trait anymore<commit_after>extern crate libc;
extern crate nix;

use std::io;
use std::io::{Write, Read, Error, ErrorKind};
use nix::errno::Errno;
use nix::Error::Sys;
use nix::sys::termios;
use nix::sys::termios::{BRKINT, ICRNL, INPCK, ISTRIP, IXON, OPOST, CS8, ECHO, ICANON, IEXTEN, ISIG, VMIN, VTIME};

static MAX_LINE: i32 = 4096;
static UNSUPPORTED_TERM: [&'static str; 3] = ["dumb","cons25","emacs"];

const    NULL     : u8   = 0;     // NULL
const    CTRLA    : u8   = 1;     // C-a
const    CTRLB    : u8   = 2;     // C-b
const    CTRLC    : u8   = 3;     // C-c
const    CTRLD    : u8   = 4;     // C-d
const    CTRLE    : u8   = 5;     // C-e
const    CTRLF    : u8   = 6;     // C-f
const    CTRLH    : u8   = 8;     // C-h
const    TAB      : u8   = 9;     // Tab
const    CTRLK    : u8   = 11;    // C-k
const    CTRLL    : u8   = 12;    // C-l
const    ENTER    : u8   = 13;    // Enter
const    CTRLN    : u8   = 14;    // C-n
const    CTRLP    : u8   = 16;    // C-p
const    CTRLT    : u8   = 20;    // C-t
const    CTRLU    : u8   = 21;    // C-u
const    CTRLW    : u8   = 23;    // C-w
const    ESC      : u8   = 27;    // Esc
const    BACKSPACE: u8   = 127;   // Backspace

fn is_a_tty() -> bool {
    let isatty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
    isatty
}

fn is_unsupported_term() -> bool {
    let term = std::env::var("TERM").ok().unwrap();
    let mut unsupported = false;
    for iter in &UNSUPPORTED_TERM {
        unsupported = term == *iter
    }
    unsupported
}

fn enable_raw_mode() -> Result<termios::Termios, nix::Error> {
    if !is_a_tty() {
        Err(Sys(Errno::ENOTTY))
    } else {
        let original_term = try!(termios::tcgetattr(libc::STDIN_FILENO));
        let mut raw = original_term;
        raw.c_iflag = raw.c_iflag   & !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
        raw.c_oflag = raw.c_oflag   & !(OPOST);
        raw.c_cflag = raw.c_cflag   | (CS8);
        raw.c_lflag = raw.c_lflag   & !(ECHO | ICANON | IEXTEN | ISIG);
        raw.c_cc[VMIN] = 1;
        raw.c_cc[VTIME] = 0;
        try!(termios::tcsetattr(libc::STDIN_FILENO, termios::TCSAFLUSH, &raw));
        Ok(original_term)
    }
}

fn disable_raw_mode(original_termios: termios::Termios) -> Result<(), nix::Error> {
    try!(termios::tcsetattr(libc::STDIN_FILENO, termios::TCSAFLUSH, &original_termios));
    Ok(())
}

fn readline_edit() -> Result<String, io::Error> {
    let mut buffer = Vec::new();
    let mut input: [u8; 1] = [0];
    loop {
        let numread = io::stdin().read(&mut input).unwrap();
        match input[0] {
            ENTER  => break,
            _      => { print!("{}", input[0]); io::stdout().flush(); }
        }
        buffer.push(input[0]);
    }
    Ok(String::from_utf8(buffer).unwrap())
}

fn readline_raw() -> Result<String, io::Error> {
    if is_a_tty() {
        let original_termios = match enable_raw_mode() {
            Err(Sys(Errno::ENOTTY)) => return Err(Error::new(ErrorKind::Other, "Not a TTY")),
            Err(Sys(Errno::EBADF))  => return Err(Error::new(ErrorKind::Other, "Not a file descriptor")),
            Err(..)                 => return Err(Error::new(ErrorKind::Other, "Unknown Error")),
            Ok(term)                => term
        };

        let user_input = readline_edit();

        match disable_raw_mode(original_termios) {
            Err(..) => return Err(Error::new(ErrorKind::Other, "Failed to revert to original termios")),
            Ok(..)  => ()
        }

        user_input
    } else {

        let mut line = String::new();
        match io::stdin().read_line(&mut line) {
            Ok(_) => Ok(line),
            Err(e) => Err(e),
        }
    }
}

pub fn readline(prompt: &'static str) -> Result<String, io::Error> {
    // Write prompt and flush it to stdout
    let mut stdout = io::stdout();
    try!(stdout.write(prompt.as_bytes()));
    try!(stdout.flush());

    if is_unsupported_term() {
        let mut line = String::new();
        match io::stdin().read_line(&mut line) {
            Ok(_) => Ok(line),
            Err(e) => Err(e),
        }
    } else {
        readline_raw()
    }
}
<|endoftext|>