<commit_before>extern crate mio;
extern crate byteorder;

#[path="../shared/frame.rs"]
pub mod frame;
use frame::{MessageFrame, ToFrame, Message};

#[path="../shared/state.rs"]
pub mod state;
use state::ClientState;

use mio::tcp::*;
use mio::TryWrite;
use mio::util::Slab;
use std::net::SocketAddr;
use std::io::{Result, Read, Error, ErrorKind};
use mio::{EventSet, EventLoop, Token, Handler, PollOpt};
use std::thread;
use std::thread::JoinHandle;
use std::sync::{Arc, RwLock};
//use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::collections::VecDeque;

const CLIENT_TOKEN: mio::Token = mio::Token(1);

/// Contains data related to the client
pub struct ClientData{
    pub token: Token,

    interest: EventSet,

    send_queue: VecDeque<MessageFrame>,
}

impl ClientData{
    fn new() -> ClientData{
        ClientData {
            send_queue: VecDeque::new(),
            token: CLIENT_TOKEN,
            interest: EventSet::readable()
        }
    }

    fn set_writable(&mut self){
        self.interest.insert(EventSet::writable());
    }

    fn set_read_only(&mut self){
        self.interest.remove(EventSet::writable());
        self.interest.insert(EventSet::readable());
    }

    fn has_messages_to_send(&self) -> bool{
        !self.send_queue.is_empty()
    }
}

/// Maintains a reference to the client, the socket, and the thread join handle
struct ClientInterface{
    socket: TcpStream,

    thread_handle: Option<JoinHandle<()>>,

    client: Arc<RwLock<ClientData>>,

    is_connected: bool
}

impl ClientInterface{
    fn new(event_loop: Arc<RwLock<EventLoop<ClientInterface>>>, socket: TcpStream, client: Arc<RwLock<ClientData>>) -> Arc<RwLock<ClientInterface>>{
        let interface = Arc::new(RwLock::new(ClientInterface{
            socket: socket,
            thread_handle: None,
            client: client,
            is_connected: true
        }));

        let thread_interface = interface.clone();
        let handle = thread::spawn(move||{
            loop{
                if let Ok(mut event_loop) = event_loop.write(){
                    if let Ok(mut client_interface) = thread_interface.write(){
                        event_loop.run_once(&mut client_interface, None);
                    }
                }

                if let Ok(client_interface) = thread_interface.read(){
                    if !client_interface.is_connected{
                        println!("The client has disconnected from the server!");
                        break;
                    }
                }
            }
        });

        if let Ok(mut interface_mut) = interface.write(){
            interface_mut.thread_handle = Some(handle);
        }

        return interface;
    }

    fn register(&mut self, event_loop: &mut EventLoop<ClientInterface>){
        if let Ok(client) = self.client.read(){
            event_loop.register(
                &self.socket,
                client.token,
                client.interest,
                PollOpt::edge() | PollOpt::oneshot()
            ).or_else(|e| {
                println!("Failed to register server! {:?}", e);
                Err(e)
            }).ok();
        }
    }

    fn reregister(&mut self, event_loop: &mut EventLoop<ClientInterface>){
        if let Ok(client) = self.client.read(){
            event_loop.reregister(&self.socket, client.token, client.interest, PollOpt::edge())
                .or_else(|e|{
                    println!("I am a sad panda, {:?}", e);
                    Err(e)
            }).ok();
        }
    }

    pub fn read(&mut self) -> Result<Message>{
        let read_socket = <TcpStream as Read>::by_ref(&mut self.socket);

        println!("Begin client read message");

        // Read the message from the socket
        let message = Message::read(read_socket);

        match message{
            Ok(message) => {
                match message{
                    Message::Text{message: ref message_text} => {
                        println!("Received message: {}", &message_text);
                    },
                    Message::Ping => {
                        println!("Received Ping!");
                    },
                    Message::ClientUpdate{ position: _, rotation: _} =>{
                        println!("PANIC! CLIENT SHOULDN'T RECEIVE A CLIENT UPDATE PACKET!");
                        return Err(Error::new(ErrorKind::Other, String::from("Client received invalid packet type!")));
                    }
                }
                return Ok(message);
            },
            Err(e) => {
                return Err(e);
            }
        }
    }

    fn set_writable(&mut self){
        if let Ok(mut client) = self.client.write(){
            client.set_writable();
        }
    }

    fn set_read_only(&mut self){
        if let Ok(mut client) = self.client.write(){
            client.set_read_only();
        }
    }

    fn has_messages_to_send(&self) -> bool{
        if let Ok(client) = self.client.read(){
            return client.has_messages_to_send();
        }
        return false;
    }

    fn set_socket_disconnected(&mut self){
        self.is_connected = false;
    }
}

impl Handler for ClientInterface{
    type Timeout = ();
    type Message = ();

    fn tick(&mut self, event_loop: &mut EventLoop<ClientInterface>) {
        println!("Begin client tick");

        if self.has_messages_to_send(){
            self.set_writable();
        }
        else{
            self.set_read_only();
        }

        if self.is_connected{
            println!("Reregistering the things");
            self.reregister(event_loop);
        }

        println!("End client tick");
    }

    fn ready(&mut self, event_loop: &mut EventLoop<ClientInterface>, token: Token, events: EventSet) {
        assert!(token != Token(0), "Token 0, y?????");

        println!("ready from {:?}!", token);

        if token == CLIENT_TOKEN{
            println!("Why is token ready for self?!?!??!");
        }

        if events.is_error(){
            println!("Client received error for token {:?}", token);
            return;
        }

        if events.is_hup(){
            println!("Oh shit, did the server ({:?}) crash or some shit?!", token);
            return;
        }

        if events.is_writable(){
            println!("TIME TO TALK MOTHERFUCKER");

            if let Ok(mut client) = self.client.write(){
                if !client.send_queue.is_empty(){
                    if let Some(message_frame) = client.send_queue.pop_front(){
                        match self.socket.try_write(message_frame.to_bytes().as_slice()){
                            Ok(Some(n)) => {
                                println!("Wrote {} bytes", n);
                            },
                            Ok(None) => {
                                println!("Nothing happened but it's okay I guess?");
                                client.send_queue.push_back(message_frame);
                            },
                            Err(e) => {
                                println!("Oh fuck me god fucking damn it fucking shit fuck: {:?}", e);
                                client.send_queue.push_back(message_frame);
                            }
                        };
                    }
                    else{
                        println!("Failed to pop message from queue!");
                    }
                }
                else{
                    println!("WTF do you mean there's no messages for me?");
                }
            }
            else{
                println!("Nothing to write...");
            }
        }

        if events.is_readable(){
            println!("OH shit, what've you got to say?");

            let received_message = self.read();

            match received_message{
                Ok(message) => {

                },
                Err(e) => {
                    println!("Error trying to read! {:?}", e);
                    if let Some(error_number) = e.raw_os_error(){
                        if error_number == 10057{
                            println!("Socket is not connected!");
                            self.set_socket_disconnected();
                        }
                    }
                }
            }
        }

        //let client_rereg = self.client.clone();
        //self.reregister(event_loop, &client_rereg);
        //self.debug.fetch_add(1, Ordering::SeqCst);
    }

    fn notify(&mut self, _: &mut EventLoop<Self>, _: Self::Message) {
        println!("Received notify!");
    }

    fn timeout(&mut self, _: &mut EventLoop<Self>, _: Self::Timeout) {
        println!("Received timeout");
    }
    fn interrupted(&mut self, _: &mut EventLoop<Self>) {
        println!("Interrupted! :O");
    }
}

pub struct Client{
    data: Arc<RwLock<ClientData>>,
    interface: Arc<RwLock<ClientInterface>>,
    event_loop: Arc<RwLock<EventLoop<ClientInterface>>>
}

impl Client{
    /// Connect to the given socket and register with a threaded event loop
    pub fn connect(address: &SocketAddr) -> Result<Client>{
        let socket = TcpStream::connect(address);
        match socket{
            Ok(socket) => {
                let event_loop = Arc::new(RwLock::new(EventLoop::new().ok().expect("Failed to create event loop!")));
                let client_data = Arc::new(RwLock::new(ClientData::new()));

                let interface_event_loop = event_loop.clone();
                let client_interface = ClientInterface::new(interface_event_loop, socket, client_data.clone());

                let mut client = Client{
                    data: client_data,
                    interface: client_interface,
                    event_loop: event_loop
                };

                client.register();

                return Ok(client);
            },
            Err(e) => {
                println!("Failed to connect! {:?}", e);
                return Err(e);
            }
        }
    }

    /// Register with the event loop
    fn register(&mut self){
        if let Ok(mut event_loop) = self.event_loop.write(){
            if let Ok(mut interface) = self.interface.write(){
                interface.register(&mut event_loop);
            }
        }
    }

    /// Register with the event loop
    fn reregister(&mut self){
        if let Ok(mut event_loop) = self.event_loop.write(){
            if let Ok(mut interface) = self.interface.write(){
                interface.reregister(&mut event_loop);
            }
        }
    }

    pub fn send_message<T: ToFrame>(&mut self, message: &T){
        if let Ok(mut data) = self.data.write(){
            data.send_queue.push_back(message.to_frame());
            data.set_writable();
        } else { return; }

        self.reregister();
    }

    pub fn read(&mut self) -> Result<Message>{
        if let Ok(mut interface) = self.interface.write(){
            return interface.read();
        }
        else{
            return Err(Error::new(ErrorKind::Other, String::from("Failed to read from client interface!")));
        }
    }

    pub fn is_connected(&self) -> bool{
        if let Ok(interface) = self.interface.read(){
            return interface.is_connected;
        }
        return false;
    }
}

#[cfg(test)]
mod test {
    use std::time::Duration;
    use std::net::SocketAddr;
    use std::thread;
    use super::Client;

    #[path="../../shared/frame.rs"]
    mod frame;
    use frame::{MessageHeader, ToFrame, Message};

    #[test]
    fn connect(){
        let addr = "127.0.0.1:6969".parse().unwrap();

        if let Ok(mut client) = Client::connect(&addr){
            let message = Message::new_text_message(String::from("Hello, world!"));
            client.send_message(&message);

            thread::sleep(Duration::new(1,0));

        }

            //loop{
                // if client.debug.load(Ordering::Relaxed) > 0{
                //     break;
                // }
            //}

            //loop {}

            //println!("Done with this shit");
    }
}
<commit_msg>added received message queue to client<commit_after>extern crate mio;
extern crate byteorder;

#[path="../shared/frame.rs"]
pub mod frame;
use frame::{MessageFrame, ToFrame, Message};

#[path="../shared/state.rs"]
pub mod state;
use state::ClientState;

use mio::tcp::*;
use mio::TryWrite;
use mio::util::Slab;
use std::net::SocketAddr;
use std::io::{Result, Read, Error, ErrorKind};
use mio::{EventSet, EventLoop, Token, Handler, PollOpt};
use std::thread;
use std::thread::JoinHandle;
use std::sync::{Arc, RwLock};
//use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::collections::VecDeque;

const CLIENT_TOKEN: mio::Token = mio::Token(1);

/// Estimation of the average number of messages that will be received per tick.
/// Used as the capacity value in Vec::with_capacity(capacity: usize);
const RECEIVED_MESSAGES_PER_TICK: usize = 2;

/// Contains data related to the client
pub struct ClientData{
    pub token: Token,

    interest: EventSet,

    send_queue: VecDeque<MessageFrame>,

    // Buffer of received messages
    receive_queue: Vec<Message>
}

impl ClientData{
    fn new() -> ClientData{
        ClientData {
            send_queue: VecDeque::new(),
            token: CLIENT_TOKEN,
            interest: EventSet::readable(),
            receive_queue: Vec::with_capacity(RECEIVED_MESSAGES_PER_TICK)
        }
    }

    fn set_writable(&mut self){
        self.interest.insert(EventSet::writable());
    }

    fn set_read_only(&mut self){
        self.interest.remove(EventSet::writable());
        self.interest.insert(EventSet::readable());
    }

    fn has_messages_to_send(&self) -> bool{
        !self.send_queue.is_empty()
    }
}

/// Maintains a reference to the client, the socket, and the thread join handle
struct ClientInterface{
    socket: TcpStream,

    thread_handle: Option<JoinHandle<()>>,

    client: Arc<RwLock<ClientData>>,

    is_connected: bool,
}

impl ClientInterface{
    fn new(event_loop: Arc<RwLock<EventLoop<ClientInterface>>>, socket: TcpStream, client: Arc<RwLock<ClientData>>) -> Arc<RwLock<ClientInterface>>{
        let interface = Arc::new(RwLock::new(ClientInterface{
            socket: socket,
            thread_handle: None,
            client: client,
            is_connected: true
        }));

        let thread_interface = interface.clone();
        let handle = thread::spawn(move||{
            loop{
                if let Ok(mut event_loop) = event_loop.write(){
                    if let Ok(mut client_interface) = thread_interface.write(){
                        event_loop.run_once(&mut client_interface, None);
                    }
                }

                if let Ok(client_interface) = thread_interface.read(){
                    if !client_interface.is_connected{
                        println!("The client has disconnected from the server!");
                        break;
                    }
                }
            }
        });

        if let Ok(mut interface_mut) = interface.write(){
            interface_mut.thread_handle = Some(handle);
        }

        return interface;
    }

    fn register(&mut self, event_loop: &mut EventLoop<ClientInterface>){
        if let Ok(client) = self.client.read(){
            event_loop.register(
                &self.socket,
                client.token,
                client.interest,
                PollOpt::edge() | PollOpt::oneshot()
            ).or_else(|e| {
                println!("Failed to register server! {:?}", e);
                Err(e)
            }).ok();
        }
    }

    fn reregister(&mut self, event_loop: &mut EventLoop<ClientInterface>){
        if let Ok(client) = self.client.read(){
            event_loop.reregister(&self.socket, client.token, client.interest, PollOpt::edge())
                .or_else(|e|{
                    println!("I am a sad panda, {:?}", e);
                    Err(e)
            }).ok();
        }
    }

    pub fn read(&mut self) -> Result<Message>{
        let read_socket = <TcpStream as Read>::by_ref(&mut self.socket);

        println!("Begin client read message");

        // Read the message from the socket
        let message = Message::read(read_socket);

        match message{
            Ok(message) => {
                match message{
                    Message::Text{message: ref message_text} => {
                        println!("Received message: {}", &message_text);
                    },
                    Message::Ping => {
                        println!("Received Ping!");
                    },
                    Message::ClientUpdate{ position: _, rotation: _} =>{
                        println!("PANIC! CLIENT SHOULDN'T RECEIVE A CLIENT UPDATE PACKET!");
                        return Err(Error::new(ErrorKind::Other, String::from("Client received invalid packet type!")));
                    }
                }
                return Ok(message);
            },
            Err(e) => {
                return Err(e);
            }
        }
    }

    fn set_writable(&mut self){
        if let Ok(mut client) = self.client.write(){
            client.set_writable();
        }
    }

    fn set_read_only(&mut self){
        if let Ok(mut client) = self.client.write(){
            client.set_read_only();
        }
    }

    fn has_messages_to_send(&self) -> bool{
        if let Ok(client) = self.client.read(){
            return client.has_messages_to_send();
        }
        return false;
    }

    fn set_socket_disconnected(&mut self){
        self.is_connected = false;
    }
}

impl Handler for ClientInterface{
    type Timeout = ();
    type Message = ();

    fn tick(&mut self, event_loop: &mut EventLoop<ClientInterface>) {
        println!("Begin client tick");

        if self.has_messages_to_send(){
            self.set_writable();
        }
        else{
            self.set_read_only();
        }

        if self.is_connected{
            println!("Reregistering the things");
            self.reregister(event_loop);
        }

        println!("End client tick");
    }

    fn ready(&mut self, event_loop: &mut EventLoop<ClientInterface>, token: Token, events: EventSet) {
        assert!(token != Token(0), "Token 0, y?????");

        println!("ready from {:?}!", token);

        if token == CLIENT_TOKEN{
            println!("Why is token ready for self?!?!??!");
        }

        if events.is_error(){
            println!("Client received error for token {:?}", token);
            return;
        }

        if events.is_hup(){
            println!("Oh shit, did the server ({:?}) crash or some shit?!", token);
            return;
        }

        if events.is_writable(){
            println!("TIME TO TALK MOTHERFUCKER");

            if let Ok(mut client) = self.client.write(){
                if !client.send_queue.is_empty(){
                    if let Some(message_frame) = client.send_queue.pop_front(){
                        match self.socket.try_write(message_frame.to_bytes().as_slice()){
                            Ok(Some(n)) => {
                                println!("Wrote {} bytes", n);
                            },
                            Ok(None) => {
                                println!("Nothing happened but it's okay I guess?");
                                client.send_queue.push_back(message_frame);
                            },
                            Err(e) => {
                                println!("Oh fuck me god fucking damn it fucking shit fuck: {:?}", e);
                                client.send_queue.push_back(message_frame);
                            }
                        };
                    }
                    else{
                        println!("Failed to pop message from queue!");
                    }
                }
                else{
                    println!("WTF do you mean there's no messages for me?");
                }
            }
            else{
                println!("Nothing to write...");
            }
        }

        if events.is_readable(){
            println!("OH shit, what've you got to say?");

            let received_message = self.read();

            match received_message{
                Ok(message) => {
                    if let Ok(mut data) = self.client.write(){
                        data.receive_queue.push(message);
                    }
                },
                Err(e) => {
                    println!("Error trying to read! {:?}", e);
                    if let Some(error_number) = e.raw_os_error(){
                        if error_number == 10057{
                            println!("Socket is not connected!");
                            self.set_socket_disconnected();
                        }
                    }
                }
            }
        }

        //let client_rereg = self.client.clone();
        //self.reregister(event_loop, &client_rereg);
        //self.debug.fetch_add(1, Ordering::SeqCst);
    }

    fn notify(&mut self, _: &mut EventLoop<Self>, _: Self::Message) {
        println!("Received notify!");
    }

    fn timeout(&mut self, _: &mut EventLoop<Self>, _: Self::Timeout) {
        println!("Received timeout");
    }
    fn interrupted(&mut self, _: &mut EventLoop<Self>) {
        println!("Interrupted! :O");
    }
}

pub struct Client{
    data: Arc<RwLock<ClientData>>,
    interface: Arc<RwLock<ClientInterface>>,
    event_loop: Arc<RwLock<EventLoop<ClientInterface>>>
}

impl Client{
    /// Connect to the given socket and register with a threaded event loop
    pub fn connect(address: &SocketAddr) -> Result<Client>{
        let socket = TcpStream::connect(address);
        match socket{
            Ok(socket) => {
                let event_loop = Arc::new(RwLock::new(EventLoop::new().ok().expect("Failed to create event loop!")));
                let client_data = Arc::new(RwLock::new(ClientData::new()));

                let interface_event_loop = event_loop.clone();
                let client_interface = ClientInterface::new(interface_event_loop, socket, client_data.clone());

                let mut client = Client{
                    data: client_data,
                    interface: client_interface,
                    event_loop: event_loop
                };

                client.register();

                return Ok(client);
            },
            Err(e) => {
                println!("Failed to connect! {:?}", e);
                return Err(e);
            }
        }
    }

    /// Register with the event loop
    fn register(&mut self){
        if let Ok(mut event_loop) = self.event_loop.write(){
            if let Ok(mut interface) = self.interface.write(){
                interface.register(&mut event_loop);
            }
        }
    }

    /// Register with the event loop
    fn reregister(&mut self){
        if let Ok(mut event_loop) = self.event_loop.write(){
            if let Ok(mut interface) = self.interface.write(){
                interface.reregister(&mut event_loop);
            }
        }
    }

    pub fn send_message<T: ToFrame>(&mut self, message: &T){
        if let Ok(mut data) = self.data.write(){
            data.send_queue.push_back(message.to_frame());
            data.set_writable();
        } else { return; }

        self.reregister();
    }

    pub fn read(&mut self) -> Result<Message>{
        if let Ok(mut interface) = self.interface.write(){
            // Suddenly realizing that I just wrote some really confusing code here.
            return interface.read();
        }
        else{
            return Err(Error::new(ErrorKind::Other, String::from("Failed to read from client interface!")));
        }
    }

    pub fn is_connected(&self) -> bool{
        if let Ok(interface) = self.interface.read(){
            return interface.is_connected;
        }
        return false;
    }

    pub fn pop_received_messages(&mut self) -> Option<Vec<Message>>{
        if let Ok(mut data) = self.data.write(){
            if !data.receive_queue.is_empty(){
                return Some(std::mem::replace(&mut data.receive_queue, Vec::with_capacity(RECEIVED_MESSAGES_PER_TICK)));
            }
            else{
                return None;
            }
        }
        return None;
    }
}

#[cfg(test)]
mod test {
    use std::time::Duration;
    use std::net::SocketAddr;
    use std::thread;
    use super::Client;

    #[path="../../shared/frame.rs"]
    mod frame;
    use frame::{MessageHeader, ToFrame, Message};

    #[test]
    fn connect(){
        let addr = "127.0.0.1:6969".parse().unwrap();

        if let Ok(mut client) = Client::connect(&addr){
            let message = Message::new_text_message(String::from("Hello, world!"));
            client.send_message(&message);

            thread::sleep(Duration::new(1,0));

        }

            //loop{
                // if client.debug.load(Ordering::Relaxed) > 0{
                //     break;
                // }
            //}

            //loop {}

            //println!("Done with this shit");
    }
}
<|endoftext|>


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

use std::fmt::{Display, Formatter};

/// A simplification of Clojure's Symbol.
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct PlainSymbol(pub String);

#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct NamespacedSymbol {
    // We derive PartialOrd, which implements a lexicographic based
    // on the order of members, so put namespace first.
    pub namespace: String,
    pub name: String,
}

/// A keyword is a symbol, optionally with a namespace, that prints with a leading colon.
/// This concept is imported from Clojure, as it features in EDN and the query
/// syntax that we use.
///
/// Clojure's constraints are looser than ours, allowing empty namespaces or
/// names:
///
/// ```clojure
/// user=> (keyword "" "")
/// :/
/// user=> (keyword "foo" "")
/// :foo/
/// user=> (keyword "" "bar")
/// :/bar
/// ```
///
/// We think that's nonsense, so we only allow keywords like `:bar` and `:foo/bar`,
/// with both namespace and main parts containing no whitespace and no colon or slash:
///
/// ```rust
/// # use edn::symbols::Keyword;
/// # use edn::symbols::NamespacedKeyword;
/// let bar     = Keyword::new("bar");                         // :bar
/// let foo_bar = NamespacedKeyword::new("foo", "bar");        // :foo/bar
/// assert_eq!("bar", bar.0);
/// assert_eq!("bar", foo_bar.name);
/// assert_eq!("foo", foo_bar.namespace);
/// ```
///
/// If you're not sure whether your input is well-formed, you should use a
/// parser or a reader function first to validate. TODO: implement `read`.
///
/// Callers are expected to follow these rules:
/// http://www.clojure.org/reference/reader#_symbols
///
/// Future: fast equality (interning?) for keywords.
///
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct Keyword(pub String);

#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct NamespacedKeyword {
    // We derive PartialOrd, which implements a lexicographic order based
    // on the order of members, so put namespace first.
    pub namespace: String,
    pub name: String,
}

impl PlainSymbol {
    pub fn new<T>(name: T) -> Self where T: Into<String> {
        let n = name.into();
        assert!(!n.is_empty(), "Symbols cannot be unnamed.");

        PlainSymbol(n)
    }

    /// Return the name of the symbol without any leading '?' or '$'.
    ///
    /// ```rust
    /// # use edn::symbols::PlainSymbol;
    /// assert_eq!("foo", PlainSymbol::new("?foo").plain_name());
    /// assert_eq!("foo", PlainSymbol::new("$foo").plain_name());
    /// assert_eq!("!foo", PlainSymbol::new("!foo").plain_name());
    /// ```
    pub fn plain_name(&self) -> &str {
        if self.is_src_symbol() || self.is_var_symbol() {
            &self.0[1..]
        } else {
            &self.0
        }
    }

    #[inline]
    pub fn is_var_symbol(&self) -> bool {
        self.0.starts_with('?')
    }

    #[inline]
    pub fn is_src_symbol(&self) -> bool {
        self.0.starts_with('$')
    }
}

impl NamespacedSymbol {
    pub fn new<T>(namespace: T, name: T) -> Self where T: Into<String> {
        let n = name.into();
        let ns = namespace.into();

        assert!(!n.is_empty(), "Symbols cannot be unnamed.");
        assert!(!ns.is_empty(), "Symbols cannot have an empty non-null namespace.");

        NamespacedSymbol { name: n, namespace: ns }
    }
}

impl Keyword {
    pub fn new<T>(name: T) -> Self where T: Into<String> {
        let n = name.into();
        assert!(!n.is_empty(), "Keywords cannot be unnamed.");

        Keyword(n)
    }
}

impl NamespacedKeyword {
    /// Creates a new `NamespacedKeyword`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// let keyword = NamespacedKeyword::new("foo", "bar");
    /// assert_eq!(keyword.to_string(), ":foo/bar");
    /// ```
    pub fn new<T>(namespace: T, name: T) -> Self where T: Into<String> {
        let n = name.into();
        let ns = namespace.into();
        assert!(!n.is_empty(), "Keywords cannot be unnamed.");
        assert!(!ns.is_empty(), "Keywords cannot have an empty non-null namespace.");

        // TODO: debug asserts to ensure that neither field matches [ :/].
        NamespacedKeyword {
            name: n,
            namespace: ns,
        }
    }

    /// Whether this `NamespacedKeyword` should be interpreted in reverse order. For example,
    /// the two following snippets are identical:
    ///
    /// ```edn
    /// [?y :person/friend ?x]
    /// [?x :person/hired ?y]
    ///
    /// [?y :person/friend ?x]
    /// [?y :person/_hired ?x]
    /// ```
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// assert!(!NamespacedKeyword::new("foo", "bar").is_backward());
    /// assert!(NamespacedKeyword::new("foo", "_bar").is_backward());
    /// ```
    #[inline]
    pub fn is_backward(&self) -> bool {
        self.name.starts_with("_")
    }

    /// Whether this `NamespacedKeyword` should be interpreted in forward order.
    /// See `symbols::NamespacedKeyword::is_backward`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// assert!(NamespacedKeyword::new("foo", "bar").is_forward());
    /// assert!(!NamespacedKeyword::new("foo", "_bar").is_forward());
    /// ```
    #[inline]
    pub fn is_forward(&self) -> bool {
        !self.is_backward()
    }

    /// Returns a `NamespacedKeyword` with the same namespace and a
    /// 'backward' name. See `symbols::NamespacedKeyword::is_backward`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// let nsk = NamespacedKeyword::new("foo", "bar");
    /// assert!(!nsk.is_backward());
    /// assert_eq!(":foo/bar", nsk.to_string());
    ///
    /// let reversed = nsk.to_reversed();
    /// assert!(reversed.is_backward());
    /// assert_eq!(":foo/_bar", reversed.to_string());
    /// ```
    pub fn to_reversed(&self) -> NamespacedKeyword {
        let name = if self.is_backward() {
            self.name[1..].to_string()
        } else {
            format!("{}{}", "_", self.name)
        };

        NamespacedKeyword {
            name: name,
            namespace: self.namespace.clone(),
        }
    }
}

//
// Note that we don't currently do any escaping.
//

impl Display for PlainSymbol {
    /// Print the symbol in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::PlainSymbol;
    /// assert_eq!("baz", PlainSymbol::new("baz").to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl Display for NamespacedSymbol {
    /// Print the symbol in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedSymbol;
    /// assert_eq!("bar/baz", NamespacedSymbol::new("bar", "baz").to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, "{}/{}", self.namespace, self.name)
    }
}

impl Display for Keyword {
    /// Print the keyword in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::Keyword;
    /// assert_eq!(":baz", Keyword::new("baz").to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, ":{}", self.0)
    }
}

impl Display for NamespacedKeyword {
    /// Print the keyword in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// assert_eq!(":bar/baz", NamespacedKeyword::new("bar", "baz").to_string());
    /// assert_eq!(":bar/_baz", NamespacedKeyword::new("bar", "baz").to_reversed().to_string());
    /// assert_eq!(":bar/baz", NamespacedKeyword::new("bar", "baz").to_reversed().to_reversed().to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, ":{}/{}", self.namespace, self.name)
    }
}
<commit_msg>Don't use single-character string constants in the `is_backward` function<commit_after>// Copyright 2016 Mozilla
//
// 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.

use std::fmt::{Display, Formatter};

/// A simplification of Clojure's Symbol.
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct PlainSymbol(pub String);

#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct NamespacedSymbol {
    // We derive PartialOrd, which implements a lexicographic based
    // on the order of members, so put namespace first.
    pub namespace: String,
    pub name: String,
}

/// A keyword is a symbol, optionally with a namespace, that prints with a leading colon.
/// This concept is imported from Clojure, as it features in EDN and the query
/// syntax that we use.
///
/// Clojure's constraints are looser than ours, allowing empty namespaces or
/// names:
///
/// ```clojure
/// user=> (keyword "" "")
/// :/
/// user=> (keyword "foo" "")
/// :foo/
/// user=> (keyword "" "bar")
/// :/bar
/// ```
///
/// We think that's nonsense, so we only allow keywords like `:bar` and `:foo/bar`,
/// with both namespace and main parts containing no whitespace and no colon or slash:
///
/// ```rust
/// # use edn::symbols::Keyword;
/// # use edn::symbols::NamespacedKeyword;
/// let bar     = Keyword::new("bar");                         // :bar
/// let foo_bar = NamespacedKeyword::new("foo", "bar");        // :foo/bar
/// assert_eq!("bar", bar.0);
/// assert_eq!("bar", foo_bar.name);
/// assert_eq!("foo", foo_bar.namespace);
/// ```
///
/// If you're not sure whether your input is well-formed, you should use a
/// parser or a reader function first to validate. TODO: implement `read`.
///
/// Callers are expected to follow these rules:
/// http://www.clojure.org/reference/reader#_symbols
///
/// Future: fast equality (interning?) for keywords.
///
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct Keyword(pub String);

#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
pub struct NamespacedKeyword {
    // We derive PartialOrd, which implements a lexicographic order based
    // on the order of members, so put namespace first.
    pub namespace: String,
    pub name: String,
}

impl PlainSymbol {
    pub fn new<T>(name: T) -> Self where T: Into<String> {
        let n = name.into();
        assert!(!n.is_empty(), "Symbols cannot be unnamed.");

        PlainSymbol(n)
    }

    /// Return the name of the symbol without any leading '?' or '$'.
    ///
    /// ```rust
    /// # use edn::symbols::PlainSymbol;
    /// assert_eq!("foo", PlainSymbol::new("?foo").plain_name());
    /// assert_eq!("foo", PlainSymbol::new("$foo").plain_name());
    /// assert_eq!("!foo", PlainSymbol::new("!foo").plain_name());
    /// ```
    pub fn plain_name(&self) -> &str {
        if self.is_src_symbol() || self.is_var_symbol() {
            &self.0[1..]
        } else {
            &self.0
        }
    }

    #[inline]
    pub fn is_var_symbol(&self) -> bool {
        self.0.starts_with('?')
    }

    #[inline]
    pub fn is_src_symbol(&self) -> bool {
        self.0.starts_with('$')
    }
}

impl NamespacedSymbol {
    pub fn new<T>(namespace: T, name: T) -> Self where T: Into<String> {
        let n = name.into();
        let ns = namespace.into();

        assert!(!n.is_empty(), "Symbols cannot be unnamed.");
        assert!(!ns.is_empty(), "Symbols cannot have an empty non-null namespace.");

        NamespacedSymbol { name: n, namespace: ns }
    }
}

impl Keyword {
    pub fn new<T>(name: T) -> Self where T: Into<String> {
        let n = name.into();
        assert!(!n.is_empty(), "Keywords cannot be unnamed.");

        Keyword(n)
    }
}

impl NamespacedKeyword {
    /// Creates a new `NamespacedKeyword`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// let keyword = NamespacedKeyword::new("foo", "bar");
    /// assert_eq!(keyword.to_string(), ":foo/bar");
    /// ```
    pub fn new<T>(namespace: T, name: T) -> Self where T: Into<String> {
        let n = name.into();
        let ns = namespace.into();
        assert!(!n.is_empty(), "Keywords cannot be unnamed.");
        assert!(!ns.is_empty(), "Keywords cannot have an empty non-null namespace.");

        // TODO: debug asserts to ensure that neither field matches [ :/].
        NamespacedKeyword {
            name: n,
            namespace: ns,
        }
    }

    /// Whether this `NamespacedKeyword` should be interpreted in reverse order. For example,
    /// the two following snippets are identical:
    ///
    /// ```edn
    /// [?y :person/friend ?x]
    /// [?x :person/hired ?y]
    ///
    /// [?y :person/friend ?x]
    /// [?y :person/_hired ?x]
    /// ```
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// assert!(!NamespacedKeyword::new("foo", "bar").is_backward());
    /// assert!(NamespacedKeyword::new("foo", "_bar").is_backward());
    /// ```
    #[inline]
    pub fn is_backward(&self) -> bool {
        self.name.starts_with('_')
    }

    /// Whether this `NamespacedKeyword` should be interpreted in forward order.
    /// See `symbols::NamespacedKeyword::is_backward`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// assert!(NamespacedKeyword::new("foo", "bar").is_forward());
    /// assert!(!NamespacedKeyword::new("foo", "_bar").is_forward());
    /// ```
    #[inline]
    pub fn is_forward(&self) -> bool {
        !self.is_backward()
    }

    /// Returns a `NamespacedKeyword` with the same namespace and a
    /// 'backward' name. See `symbols::NamespacedKeyword::is_backward`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// let nsk = NamespacedKeyword::new("foo", "bar");
    /// assert!(!nsk.is_backward());
    /// assert_eq!(":foo/bar", nsk.to_string());
    ///
    /// let reversed = nsk.to_reversed();
    /// assert!(reversed.is_backward());
    /// assert_eq!(":foo/_bar", reversed.to_string());
    /// ```
    pub fn to_reversed(&self) -> NamespacedKeyword {
        let name = if self.is_backward() {
            self.name[1..].to_string()
        } else {
            format!("{}{}", "_", self.name)
        };

        NamespacedKeyword {
            name: name,
            namespace: self.namespace.clone(),
        }
    }
}

//
// Note that we don't currently do any escaping.
//

impl Display for PlainSymbol {
    /// Print the symbol in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::PlainSymbol;
    /// assert_eq!("baz", PlainSymbol::new("baz").to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl Display for NamespacedSymbol {
    /// Print the symbol in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedSymbol;
    /// assert_eq!("bar/baz", NamespacedSymbol::new("bar", "baz").to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, "{}/{}", self.namespace, self.name)
    }
}

impl Display for Keyword {
    /// Print the keyword in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::Keyword;
    /// assert_eq!(":baz", Keyword::new("baz").to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, ":{}", self.0)
    }
}

impl Display for NamespacedKeyword {
    /// Print the keyword in EDN format.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use edn::symbols::NamespacedKeyword;
    /// assert_eq!(":bar/baz", NamespacedKeyword::new("bar", "baz").to_string());
    /// assert_eq!(":bar/_baz", NamespacedKeyword::new("bar", "baz").to_reversed().to_string());
    /// assert_eq!(":bar/baz", NamespacedKeyword::new("bar", "baz").to_reversed().to_reversed().to_string());
    /// ```
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        write!(f, ":{}/{}", self.namespace, self.name)
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! Set of structs and methods that act as a sort of internal prelude.
//!
//! The elements available in this module and its children are fairly basic building blocks that
//! the other modules all glob-import to make available as a common language. A lot of
//! infrastructure code goes in here.
//!
//! # Module contents
//!
//! Since i split this into multiple files that are then "flattened" into the final module, it's
//! worth giving an inventory of what's in here, since every file has a `use common::*;` in it.
//!
//! ## Reexports
//!
//! These types are shared by some very common infrastructure, and i caught myself loading them
//! enough times that i just put them in here instead.
//!
//! * `tokio_core::reactor::Handle`
//! * `hyper::Headers`
//!
//! ## `ParamList`
//!
//! `ParamList` is a type alias for use as a collection of parameters to a given web call. It's
//! consumed in the auth module, and provides some easy wrappers to consistently handle some types.
//!
//! `add_param` is a basic function that turns its arguments into `Cow<'a, str>`, then inserts them
//! as a parameter into the given `ParamList`.
//!
//! `add_name_param` provides some special handling for the `UserID` enum, since Twitter always
//! handles user parameters the same way: either as a `"user_id"` parameter with the ID, or as a
//! `"screen_name"` parameter with the screen name. Since that's also how the `UserID` enum is laid
//! out, this just puts the right parameter into the given `ParamList`.
//!
//! `add_list_param` does the same thing, but for `ListID`. Lists get a little more complicated
//! than users, though, since there are technically *three* ways to reference a list: by its ID, by
//! the owner's ID and the list slug, or by the owner's screen name and the list slug. Again, since
//! Twitter always uses the same set of parameters when referencing a list, this deals with all of
//! that work in one place, and i can just take a `ListID` from the user and shove it directly into
//! a `ParamList`.
//!
//! `multiple_names_param` is for when a function takes an `IntoIterator<Item=UserID>` It's
//! possible to mix and match the use of the `"user_id"` and `"screen_name"` parameters on these
//! lookup functions, so this saves up all that handling and splits the iterator into two strings:
//! one for the user IDs, one for the screen names.
//!
//! ## `WebResponse` and `FutureResponse`
//!
//! These are just convenience type aliases for when i need to return rate-limit information with a
//! call. Most of the methods in this library do that, so the alias is there to make that easier.
//!
//! ## Miscellaneous functions
//!
//! `codepoints_to_bytes` is a convenience function that i use when Twitter returns text ranges in
//! terms of codepoint offsets rather than byte offsets. It takes the pair of numbers from twitter
//! and the string it refers to, and returns a pair that can be used directly to slice the given
//! string. It's also an example of how function parameters are themselves patterns, because i
//! destructure the pair right in the signature. `>_>`
//!
//! `merge_by` and its companion type `MergeBy` is a copy of the iterator adapter of the same name
//! from itertools, because i didn't want to add another dependency onto the great towering pile
//! that is my dep tree. `>_>`
//!
//! `max_opt` and `min_opt` are helper functions because i didn't realize that `Option` derived
//! `PartialOrd` and `Ord` at the time. Strictly speaking they're subtly different because
//! `std::cmp::{min,max}` require `Ord` and `min_opt` won't reach for the None if it's there,
//! unlike the derived `PartialOrd` which considers None to be less than Some.
//!
//! ## `Response`
//!
//! Also in its own module, `Response` is a public structure that contains rate-limit information
//! from Twitter, alongside some other desired output. This type is used all over the place in
//! egg-mode, because i wanted to make sure people always had rate-limit information on hand. The
//! module also contains the types and functions that all web calls go through: the ones that load
//! a web call, parse out the rate-limit headers, and call some handler to perform final processing
//! on the result.
//!
//! `ResponseIterRef`, `ResponseIterMut`, and `ResponseIter` are iterator adaptors on
//! `Response<Vec<T>>` that copy out the rate-limit information to all the elements of the
//! contained Vec, individually. There's also a `FromIterator` implementation for
//! `Response<Vec<T>>`, which takes an iterator of `Response<T>` and loads up the last set of
//! rate-limit information for the collection as a whole.
//!
//! `RawFuture` and `TwitterFuture` are the central `Future` types in egg-mode. `RawFuture` is the
//! base-line Future that handles all the steps of a web call, loading up the response into a
//! String to be handled later. `TwitterFuture` wraps `RawFuture` and allows arbitrary handling of
//! the response when it completes.
//!
//! *Most* of the futures in this library can use `TwitterFuture`, but several cannot, because it
//! uses a bare function pointer at its core. As a core design point i didn't want to use `impl
//! Trait`, nor did i want to box any function pointers or trait objects, so i instead chose to
//! create several special-purpose Futures whenever something needed to carry around extra state.
//! Those are contained within the modules that need them - `common::response` only contains
//! `RawFuture` and `TwitterFuture`.
//!
//! `make_raw_future` is only exported for `AuthFuture`, otherwise it's called by the other Future
//! constructors to get the basic load-to-String action.
//!
//! `make_future` is the general form of the `TwitterFuture` constructor, where the processing
//! function pointer is handed in directly.
//!
//! `make_parsed_future` is the most common `TwitterFuture` constructor, which just uses
//! `make_response` (which just calls `serde_json` and loads up the rate-limit headers - it's also
//! exported) as the processor.
//!
//! `rate_headers` is an infra function that takes the `Headers` and returns an empty `Response`
//! with the rate-limit info parsed out. It's only exported for a couple functions in `list` which
//! need to get that info even on an error.

use std::borrow::Cow;
use std::collections::HashMap;
use std::iter::Peekable;
use user;
use list;

pub use tokio_core::reactor::Handle;
pub use hyper::Headers;
use chrono::{self, TimeZone};
use mime;
use serde::{Deserialize, Deserializer};
use serde::de::Error;

mod response;

pub use common::response::*;

///Convenience type used to hold parameters to an API call.
pub type ParamList<'a> = HashMap<Cow<'a, str>, Cow<'a, str>>;

///Convenience function to add a key/value parameter to a `ParamList`.
pub fn add_param<'a, K, V>(list: &mut ParamList<'a>, key: K, value: V) -> Option<Cow<'a, str>>
    where K: Into<Cow<'a, str>>,
          V: Into<Cow<'a, str>>
{
    list.insert(key.into(), value.into())
}

pub fn add_name_param<'a>(list: &mut ParamList<'a>, id: &user::UserID<'a>) -> Option<Cow<'a, str>> {
    match *id {
        user::UserID::ID(id) => add_param(list, "user_id", id.to_string()),
        user::UserID::ScreenName(name) => add_param(list, "screen_name", name),
    }
}

pub fn add_list_param<'a>(params: &mut ParamList<'a>, list: &list::ListID<'a>) {
    match *list {
        list::ListID::Slug(ref owner, name) => {
            match *owner {
                user::UserID::ID(id) => {
                    add_param(params, "owner_id", id.to_string());
                },
                user::UserID::ScreenName(name) => {
                    add_param(params, "owner_screen_name", name);
                },
            }
            add_param(params, "slug", name);
        },
        list::ListID::ID(id) => {
            add_param(params, "list_id", id.to_string());
        }
    }
}

pub fn multiple_names_param<'a, T, I>(accts: I) -> (String, String)
    where T: Into<user::UserID<'a>>, I: IntoIterator<Item=T>
{
    let mut ids = Vec::new();
    let mut names = Vec::new();

    for x in accts {
        match x.into() {
            user::UserID::ID(id) => ids.push(id.to_string()),
            user::UserID::ScreenName(name) => names.push(name),
        }
    }

    (ids.join(","), names.join(","))
}

///Type alias for responses from Twitter.
pub type WebResponse<T> = Result<Response<T>, ::error::Error>;

///Type alias for futures that resolve to responses from Twitter.
///
///See the page for [`TwitterFuture`][] for details on how to use this type. `FutureResponse` is a
///convenience alias that is only there so i don't have to write `Response<T>` all the time.
///
///[`TwitterFuture`]: struct.TwitterFuture.html
pub type FutureResponse<T> = TwitterFuture<Response<T>>;

pub fn codepoints_to_bytes(&mut (ref mut start, ref mut end): &mut (usize, usize), text: &str) {
    let mut byte_start = *start;
    let mut byte_end = *end;
    for (ch_offset, (by_offset, _)) in text.char_indices().enumerate() {
        if ch_offset == *start {
            byte_start = by_offset;
        } else if ch_offset == *end {
            byte_end = by_offset;
        }
    }
    *start = byte_start;
    if text.chars().count() == *end {
        *end = text.len()
    } else {
        *end = byte_end
    }
}

///A clone of MergeBy from Itertools.
pub struct MergeBy<Iter, Fun>
    where Iter: Iterator
{
    left: Peekable<Iter>,
    right: Peekable<Iter>,
    comp: Fun,
    fused: Option<bool>,
}

impl<Iter, Fun> Iterator for MergeBy<Iter, Fun>
    where Iter: Iterator,
          Fun: FnMut(&Iter::Item, &Iter::Item) -> bool
{
    type Item = Iter::Item;

    fn next(&mut self) -> Option<Self::Item> {
        let is_left = match self.fused {
            Some(lt) => lt,
            None => match (self.left.peek(), self.right.peek()) {
                (Some(a), Some(b)) => (self.comp)(a, b),
                (Some(_), None) => {
                    self.fused = Some(true);
                    true
                },
                (None, Some(_)) => {
                    self.fused = Some(false);
                    false
                },
                (None, None) => return None,
            },
        };

        if is_left {
            self.left.next()
        } else {
            self.right.next()
        }
    }
}

pub fn merge_by<Iter, Fun>(left: Iter, right: Iter, comp: Fun) -> MergeBy<Iter::IntoIter, Fun>
    where Iter: IntoIterator,
          Fun: FnMut(&Iter::Item, &Iter::Item) -> bool
{
    MergeBy {
        left: left.into_iter().peekable(),
        right: right.into_iter().peekable(),
        comp: comp,
        fused: None,
    }
}

pub fn max_opt<T: PartialOrd>(left: Option<T>, right: Option<T>) -> Option<T> {
    match (left, right) {
        (Some(left), Some(right)) => {
            if left >= right {
                Some(left)
            } else {
                Some(right)
            }
        },
        (left, None) => left,
        (None, right) => right,
    }
}

pub fn min_opt<T: PartialOrd>(left: Option<T>, right: Option<T>) -> Option<T> {
    match (left, right) {
        (Some(left), Some(right)) => {
            if left <= right {
                Some(left)
            } else {
                Some(right)
            }
        },
        (left, None) => left,
        (None, right) => right,
    }
}

pub fn deserialize_datetime<'de, D>(ser: D) -> Result<chrono::DateTime<chrono::Utc>, D::Error> where D: Deserializer<'de> {
    let s = String::deserialize(ser)?;
    let date = (chrono::Utc).datetime_from_str(&s, "%a %b %d %T %z %Y").map_err(|e| D::Error::custom(e))?;
    Ok(date)
}

pub fn deserialize_mime<'de, D>(ser: D) -> Result<mime::Mime, D::Error> where D: Deserializer<'de> {
    let str = String::deserialize(ser)?;
    str.parse().map_err(|e| D::Error::custom(e))
}

#[cfg(test)]
pub (crate) mod tests {
    use super::*;
    use std::fs::File;
    use std::io::Read;

    pub(crate) fn load_file(path: &str) -> String {
        let mut file = File::open(path).unwrap();
        let mut content = String::new();
        file.read_to_string(&mut content).unwrap();
        content
    }

    #[test]
    fn test_codepoints_to_bytes() {
        let unicode = "frônt Iñtërnâtiônàližætiøn ënd";
        // suppose we want to slice out the middle word.
        // 30 codepoints of which we want the middle 20;
        let mut range = (6, 26);
        codepoints_to_bytes(&mut range, unicode);
        assert_eq!(&unicode[range.0..range.1], "Iñtërnâtiônàližætiøn");

        let mut range = (6, 30);
        codepoints_to_bytes(&mut range, unicode);
        assert_eq!(&unicode[range.0..range.1], "Iñtërnâtiônàližætiøn ënd");
    }
}
<commit_msg>add docs to common about new functions<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! Set of structs and methods that act as a sort of internal prelude.
//!
//! The elements available in this module and its children are fairly basic building blocks that
//! the other modules all glob-import to make available as a common language. A lot of
//! infrastructure code goes in here.
//!
//! # Module contents
//!
//! Since i split this into multiple files that are then "flattened" into the final module, it's
//! worth giving an inventory of what's in here, since every file has a `use common::*;` in it.
//!
//! ## Reexports
//!
//! These types are shared by some very common infrastructure, and i caught myself loading them
//! enough times that i just put them in here instead.
//!
//! * `tokio_core::reactor::Handle`
//! * `hyper::Headers`
//!
//! ## `ParamList`
//!
//! `ParamList` is a type alias for use as a collection of parameters to a given web call. It's
//! consumed in the auth module, and provides some easy wrappers to consistently handle some types.
//!
//! `add_param` is a basic function that turns its arguments into `Cow<'a, str>`, then inserts them
//! as a parameter into the given `ParamList`.
//!
//! `add_name_param` provides some special handling for the `UserID` enum, since Twitter always
//! handles user parameters the same way: either as a `"user_id"` parameter with the ID, or as a
//! `"screen_name"` parameter with the screen name. Since that's also how the `UserID` enum is laid
//! out, this just puts the right parameter into the given `ParamList`.
//!
//! `add_list_param` does the same thing, but for `ListID`. Lists get a little more complicated
//! than users, though, since there are technically *three* ways to reference a list: by its ID, by
//! the owner's ID and the list slug, or by the owner's screen name and the list slug. Again, since
//! Twitter always uses the same set of parameters when referencing a list, this deals with all of
//! that work in one place, and i can just take a `ListID` from the user and shove it directly into
//! a `ParamList`.
//!
//! `multiple_names_param` is for when a function takes an `IntoIterator<Item=UserID>` It's
//! possible to mix and match the use of the `"user_id"` and `"screen_name"` parameters on these
//! lookup functions, so this saves up all that handling and splits the iterator into two strings:
//! one for the user IDs, one for the screen names.
//!
//! ## `WebResponse` and `FutureResponse`
//!
//! These are just convenience type aliases for when i need to return rate-limit information with a
//! call. Most of the methods in this library do that, so the alias is there to make that easier.
//!
//! ## Miscellaneous functions
//!
//! `codepoints_to_bytes` is a convenience function that i use when Twitter returns text ranges in
//! terms of codepoint offsets rather than byte offsets. It takes the pair of numbers from twitter
//! and the string it refers to, and returns a pair that can be used directly to slice the given
//! string. It's also an example of how function parameters are themselves patterns, because i
//! destructure the pair right in the signature. `>_>`
//!
//! `deserialize_datetime` and `deserialize_mime` are glue functions to read these specific items
//! out in a `Deserialize` implementation. Twitter always gives timestamps in the same format, so
//! having that function here saves us from having to write the format out everywhere.
//!
//! `merge_by` and its companion type `MergeBy` is a copy of the iterator adapter of the same name
//! from itertools, because i didn't want to add another dependency onto the great towering pile
//! that is my dep tree. `>_>`
//!
//! `max_opt` and `min_opt` are helper functions because i didn't realize that `Option` derived
//! `PartialOrd` and `Ord` at the time. Strictly speaking they're subtly different because
//! `std::cmp::{min,max}` require `Ord` and `min_opt` won't reach for the None if it's there,
//! unlike the derived `PartialOrd` which considers None to be less than Some.
//!
//! ## `Response`
//!
//! Also in its own module, `Response` is a public structure that contains rate-limit information
//! from Twitter, alongside some other desired output. This type is used all over the place in
//! egg-mode, because i wanted to make sure people always had rate-limit information on hand. The
//! module also contains the types and functions that all web calls go through: the ones that load
//! a web call, parse out the rate-limit headers, and call some handler to perform final processing
//! on the result.
//!
//! `ResponseIterRef`, `ResponseIterMut`, and `ResponseIter` are iterator adaptors on
//! `Response<Vec<T>>` that copy out the rate-limit information to all the elements of the
//! contained Vec, individually. There's also a `FromIterator` implementation for
//! `Response<Vec<T>>`, which takes an iterator of `Response<T>` and loads up the last set of
//! rate-limit information for the collection as a whole.
//!
//! `RawFuture` and `TwitterFuture` are the central `Future` types in egg-mode. `RawFuture` is the
//! base-line Future that handles all the steps of a web call, loading up the response into a
//! String to be handled later. `TwitterFuture` wraps `RawFuture` and allows arbitrary handling of
//! the response when it completes.
//!
//! *Most* of the futures in this library can use `TwitterFuture`, but several cannot, because it
//! uses a bare function pointer at its core. As a core design point i didn't want to use `impl
//! Trait`, nor did i want to box any function pointers or trait objects, so i instead chose to
//! create several special-purpose Futures whenever something needed to carry around extra state.
//! Those are contained within the modules that need them - `common::response` only contains
//! `RawFuture` and `TwitterFuture`.
//!
//! `make_raw_future` is only exported for `AuthFuture`, otherwise it's called by the other Future
//! constructors to get the basic load-to-String action.
//!
//! `make_future` is the general form of the `TwitterFuture` constructor, where the processing
//! function pointer is handed in directly.
//!
//! `make_parsed_future` is the most common `TwitterFuture` constructor, which just uses
//! `make_response` (which just calls `serde_json` and loads up the rate-limit headers - it's also
//! exported) as the processor.
//!
//! `rate_headers` is an infra function that takes the `Headers` and returns an empty `Response`
//! with the rate-limit info parsed out. It's only exported for a couple functions in `list` which
//! need to get that info even on an error.

use std::borrow::Cow;
use std::collections::HashMap;
use std::iter::Peekable;
use user;
use list;

pub use tokio_core::reactor::Handle;
pub use hyper::Headers;
use chrono::{self, TimeZone};
use mime;
use serde::{Deserialize, Deserializer};
use serde::de::Error;

mod response;

pub use common::response::*;

///Convenience type used to hold parameters to an API call.
pub type ParamList<'a> = HashMap<Cow<'a, str>, Cow<'a, str>>;

///Convenience function to add a key/value parameter to a `ParamList`.
pub fn add_param<'a, K, V>(list: &mut ParamList<'a>, key: K, value: V) -> Option<Cow<'a, str>>
    where K: Into<Cow<'a, str>>,
          V: Into<Cow<'a, str>>
{
    list.insert(key.into(), value.into())
}

pub fn add_name_param<'a>(list: &mut ParamList<'a>, id: &user::UserID<'a>) -> Option<Cow<'a, str>> {
    match *id {
        user::UserID::ID(id) => add_param(list, "user_id", id.to_string()),
        user::UserID::ScreenName(name) => add_param(list, "screen_name", name),
    }
}

pub fn add_list_param<'a>(params: &mut ParamList<'a>, list: &list::ListID<'a>) {
    match *list {
        list::ListID::Slug(ref owner, name) => {
            match *owner {
                user::UserID::ID(id) => {
                    add_param(params, "owner_id", id.to_string());
                },
                user::UserID::ScreenName(name) => {
                    add_param(params, "owner_screen_name", name);
                },
            }
            add_param(params, "slug", name);
        },
        list::ListID::ID(id) => {
            add_param(params, "list_id", id.to_string());
        }
    }
}

pub fn multiple_names_param<'a, T, I>(accts: I) -> (String, String)
    where T: Into<user::UserID<'a>>, I: IntoIterator<Item=T>
{
    let mut ids = Vec::new();
    let mut names = Vec::new();

    for x in accts {
        match x.into() {
            user::UserID::ID(id) => ids.push(id.to_string()),
            user::UserID::ScreenName(name) => names.push(name),
        }
    }

    (ids.join(","), names.join(","))
}

///Type alias for responses from Twitter.
pub type WebResponse<T> = Result<Response<T>, ::error::Error>;

///Type alias for futures that resolve to responses from Twitter.
///
///See the page for [`TwitterFuture`][] for details on how to use this type. `FutureResponse` is a
///convenience alias that is only there so i don't have to write `Response<T>` all the time.
///
///[`TwitterFuture`]: struct.TwitterFuture.html
pub type FutureResponse<T> = TwitterFuture<Response<T>>;

pub fn codepoints_to_bytes(&mut (ref mut start, ref mut end): &mut (usize, usize), text: &str) {
    let mut byte_start = *start;
    let mut byte_end = *end;
    for (ch_offset, (by_offset, _)) in text.char_indices().enumerate() {
        if ch_offset == *start {
            byte_start = by_offset;
        } else if ch_offset == *end {
            byte_end = by_offset;
        }
    }
    *start = byte_start;
    if text.chars().count() == *end {
        *end = text.len()
    } else {
        *end = byte_end
    }
}

///A clone of MergeBy from Itertools.
pub struct MergeBy<Iter, Fun>
    where Iter: Iterator
{
    left: Peekable<Iter>,
    right: Peekable<Iter>,
    comp: Fun,
    fused: Option<bool>,
}

impl<Iter, Fun> Iterator for MergeBy<Iter, Fun>
    where Iter: Iterator,
          Fun: FnMut(&Iter::Item, &Iter::Item) -> bool
{
    type Item = Iter::Item;

    fn next(&mut self) -> Option<Self::Item> {
        let is_left = match self.fused {
            Some(lt) => lt,
            None => match (self.left.peek(), self.right.peek()) {
                (Some(a), Some(b)) => (self.comp)(a, b),
                (Some(_), None) => {
                    self.fused = Some(true);
                    true
                },
                (None, Some(_)) => {
                    self.fused = Some(false);
                    false
                },
                (None, None) => return None,
            },
        };

        if is_left {
            self.left.next()
        } else {
            self.right.next()
        }
    }
}

pub fn merge_by<Iter, Fun>(left: Iter, right: Iter, comp: Fun) -> MergeBy<Iter::IntoIter, Fun>
    where Iter: IntoIterator,
          Fun: FnMut(&Iter::Item, &Iter::Item) -> bool
{
    MergeBy {
        left: left.into_iter().peekable(),
        right: right.into_iter().peekable(),
        comp: comp,
        fused: None,
    }
}

pub fn max_opt<T: PartialOrd>(left: Option<T>, right: Option<T>) -> Option<T> {
    match (left, right) {
        (Some(left), Some(right)) => {
            if left >= right {
                Some(left)
            } else {
                Some(right)
            }
        },
        (left, None) => left,
        (None, right) => right,
    }
}

pub fn min_opt<T: PartialOrd>(left: Option<T>, right: Option<T>) -> Option<T> {
    match (left, right) {
        (Some(left), Some(right)) => {
            if left <= right {
                Some(left)
            } else {
                Some(right)
            }
        },
        (left, None) => left,
        (None, right) => right,
    }
}

pub fn deserialize_datetime<'de, D>(ser: D) -> Result<chrono::DateTime<chrono::Utc>, D::Error> where D: Deserializer<'de> {
    let s = String::deserialize(ser)?;
    let date = (chrono::Utc).datetime_from_str(&s, "%a %b %d %T %z %Y").map_err(|e| D::Error::custom(e))?;
    Ok(date)
}

pub fn deserialize_mime<'de, D>(ser: D) -> Result<mime::Mime, D::Error> where D: Deserializer<'de> {
    let str = String::deserialize(ser)?;
    str.parse().map_err(|e| D::Error::custom(e))
}

#[cfg(test)]
pub (crate) mod tests {
    use super::*;
    use std::fs::File;
    use std::io::Read;

    pub(crate) fn load_file(path: &str) -> String {
        let mut file = File::open(path).unwrap();
        let mut content = String::new();
        file.read_to_string(&mut content).unwrap();
        content
    }

    #[test]
    fn test_codepoints_to_bytes() {
        let unicode = "frônt Iñtërnâtiônàližætiøn ënd";
        // suppose we want to slice out the middle word.
        // 30 codepoints of which we want the middle 20;
        let mut range = (6, 26);
        codepoints_to_bytes(&mut range, unicode);
        assert_eq!(&unicode[range.0..range.1], "Iñtërnâtiônàližætiøn");

        let mut range = (6, 30);
        codepoints_to_bytes(&mut range, unicode);
        assert_eq!(&unicode[range.0..range.1], "Iñtërnâtiônàližætiøn ënd");
    }
}
<|endoftext|>


<commit_before>//! Contains Value and ValueRef structs and its conversion traits.

use std::convert::From;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

impl Value {
    /// Returns true if the `Value` is a Null. Returns false otherwise.
    pub fn is_nil(&self) -> bool {
        if let Value::Nil = *self {
            true
        } else {
            false
        }
    }

    /// If the `Value` is a Boolean, returns the associated bool.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    ///
    /// assert_eq!(Some(true), Value::Boolean(true).as_bool());
    /// assert_eq!(None, Value::Nil.as_bool());
    /// ```
    pub fn as_bool(&self) -> Option<bool> {
        if let Value::Boolean(val) = *self {
            Some(val)
        } else {
            None
        }
    }

    /// If the `Value` is an integer, return or cast it to a i64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42i64), Value::Integer(Integer::I64(42)).as_i64());
    /// assert_eq!(Some(42i64), Value::Integer(Integer::U64(42)).as_i64());
    ///
    /// assert_eq!(None, Value::Float(Float::F64(42.0)).as_i64());
    /// ```
    pub fn as_i64(&self) -> Option<i64> {
        match *self {
            Value::Integer(Integer::I64(n)) => Some(n),
            Value::Integer(Integer::U64(n)) if n <= i64::max_value() as u64 => Some(n as i64),
            _ => None,
        }
    }

    /// If the `Value` is an integer, return or cast it to a u64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42u64), Value::Integer(Integer::I64(42)).as_u64());
    /// assert_eq!(Some(42u64), Value::Integer(Integer::U64(42)).as_u64());
    ///
    /// assert_eq!(None, Value::Integer(Integer::I64(-42)).as_u64());
    /// assert_eq!(None, Value::Float(Float::F64(42.0)).as_u64());
    /// ```
    pub fn as_u64(&self) -> Option<u64> {
        match *self {
            Value::Integer(Integer::I64(n)) if 0 <= n => Some(n as u64),
            Value::Integer(Integer::U64(n)) => Some(n),
            _ => None,
        }
    }

    /// If the `Value` is a number, return or cast it to a f64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42.0), Value::Integer(Integer::I64(42)).as_f64());
    /// assert_eq!(Some(42.0), Value::Integer(Integer::U64(42)).as_f64());
    /// assert_eq!(Some(42.0), Value::Float(Float::F32(42.0f32)).as_f64());
    /// assert_eq!(Some(42.0), Value::Float(Float::F64(42.0f64)).as_f64());
    ///
    /// assert_eq!(Some(2147483647.0), Value::Integer(Integer::I64(i32::max_value() as i64)).as_f64());
    ///
    /// assert_eq!(None, Value::Nil.as_f64());
    ///
    /// assert_eq!(None, Value::Integer(Integer::I64(i32::max_value() as i64 + 1)).as_f64());
    /// ```
    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            Value::Integer(Integer::I64(n)) if (i32::min_value() as i64 <= n) && (n <= i32::max_value() as i64) => {
                Some(From::from(n as i32))
            }
            Value::Integer(Integer::U64(n)) if n <= u32::max_value() as u64 => {
                Some(From::from(n as u32))
            }
            Value::Float(Float::F32(n)) => Some(From::from(n)),
            Value::Float(Float::F64(n)) => Some(n),
            _ => None,
        }
    }

    /// If the `Value` is a String, returns the associated str.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    ///
    /// assert_eq!(Some("le message"), Value::String("le message".into()).as_str());
    /// assert_eq!(None, Value::Boolean(true).as_str());
    /// ```
    pub fn as_str(&self) -> Option<&str> {
        if let Value::String(ref val) = *self {
            Some(val)
        } else {
            None
        }
    }
}

impl From<bool> for Value {
    fn from(v: bool) -> Value {
        Value::Boolean(v)
    }
}

impl From<u8> for Value {
    fn from(v: u8) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u16> for Value {
    fn from(v: u16) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u32> for Value {
    fn from(v: u32) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u64> for Value {
    fn from(v: u64) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<usize> for Value {
    fn from(v: usize) -> Value {
        Value::Integer(Integer::U64(v as u64))
    }
}

impl From<i8> for Value {
    fn from(v: i8) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i16> for Value {
    fn from(v: i16) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i32> for Value {
    fn from(v: i32) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i64> for Value {
    fn from(v: i64) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<isize> for Value {
    fn from(v: isize) -> Value {
        Value::Integer(Integer::I64(v as i64))
    }
}

impl From<f32> for Value {
    fn from(v: f32) -> Value {
        Value::Float(Float::F32(v))
    }
}

impl From<f64> for Value {
    fn from(v: f64) -> Value {
        Value::Float(Float::F64(v))
    }
}

/// Implements human-readable value formatting.
impl ::std::fmt::Display for Value {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Value::Nil => write!(f, "nil"),
            Value::Boolean(val) => write!(f, "{}", val),
            Value::Integer(Integer::U64(val)) => write!(f, "{}", val),
            Value::Integer(Integer::I64(val)) => write!(f, "{}", val),
            Value::Float(Float::F32(val)) => write!(f, "{}", val),
            Value::Float(Float::F64(val)) => write!(f, "{}", val),
            Value::String(ref val) => write!(f, "\"{}\"", val),
            Value::Binary(ref val) => write!(f, "{:?}", val),
            Value::Array(ref vec) => {
                // TODO: This can be slower than naive implementation. Need benchmarks for more
                // information.
                let res = vec.iter()
                    .map(|val| format!("{}", val))
                    .collect::<Vec<String>>()
                    .join(", ");

                write!(f, "[{}]", res)
            }
            Value::Map(ref vec) => {
                try!(write!(f, "{{"));

                match vec.iter().take(1).next() {
                    Some(&(ref k, ref v)) => {
                        try!(write!(f, "{}: {}", k, v));
                    }
                    None => {
                        try!(write!(f, ""));
                    }
                }

                for &(ref k, ref v) in vec.iter().skip(1) {
                    try!(write!(f, ", {}: {}", k, v));
                }

                write!(f, "}}")
            }
            Value::Ext(ty, ref data) => {
                write!(f, "[{}, {:?}]", ty, data)
            }
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(&'a str),
    /// Binary extending Raw type represents a byte array.
    Binary(&'a [u8]),
    /// Array represents a sequence of objects.
    Array(Vec<ValueRef<'a>>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, &'a [u8]),
}

impl<'a> ValueRef<'a> {
    /// Converts the current non-owning value to an owned Value.
    ///
    /// This is achieved by deep copying all underlying structures and borrowed buffers.
    ///
    /// # Panics
    ///
    /// Panics in unable to allocate memory to keep all internal structures and buffers.
    ///
    /// # Examples
    /// ```
    /// use rmp::{Value, ValueRef};
    /// use rmp::value::Integer;
    ///
    /// let val = ValueRef::Array(vec![
    ///    ValueRef::Nil,
    ///    ValueRef::Integer(Integer::U64(42)),
    ///    ValueRef::Array(vec![
    ///        ValueRef::String("le message"),
    ///    ])
    /// ]);
    ///
    /// let expected = Value::Array(vec![
    ///     Value::Nil,
    ///     Value::Integer(Integer::U64(42)),
    ///     Value::Array(vec![
    ///         Value::String("le message".to_string())
    ///     ])
    /// ]);
    ///
    /// assert_eq!(expected, val.to_owned());
    /// ```
    pub fn to_owned(&self) -> Value {
        match self {
            &ValueRef::Nil => Value::Nil,
            &ValueRef::Boolean(val) => Value::Boolean(val),
            &ValueRef::Integer(val) => Value::Integer(val),
            &ValueRef::Float(val) => Value::Float(val),
            &ValueRef::String(val) => Value::String(val.to_owned()),
            &ValueRef::Binary(val) => Value::Binary(val.to_vec()),
            &ValueRef::Array(ref val) => {
                Value::Array(val.iter().map(|v| v.to_owned()).collect())
            }
            &ValueRef::Map(ref val) => {
                Value::Map(val.iter().map(|&(ref k, ref v)| (k.to_owned(), v.to_owned())).collect())
            }
            &ValueRef::Ext(ty, buf) => Value::Ext(ty, buf.to_vec()),
        }
    }
}

// For some weird reasons I can't implement it manually.
// It gives: conflicting implementations for trait `collections::borrow::ToOwned`
// impl<'a> ToOwned for ValueRef<'a> {
//     type Owned = Value;
// }
<commit_msg>feat: add array extract method to value<commit_after>//! Contains Value and ValueRef structs and its conversion traits.

use std::convert::From;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

impl Value {
    /// Returns true if the `Value` is a Null. Returns false otherwise.
    pub fn is_nil(&self) -> bool {
        if let Value::Nil = *self {
            true
        } else {
            false
        }
    }

    /// If the `Value` is a Boolean, returns the associated bool.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    ///
    /// assert_eq!(Some(true), Value::Boolean(true).as_bool());
    /// assert_eq!(None, Value::Nil.as_bool());
    /// ```
    pub fn as_bool(&self) -> Option<bool> {
        if let Value::Boolean(val) = *self {
            Some(val)
        } else {
            None
        }
    }

    /// If the `Value` is an integer, return or cast it to a i64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42i64), Value::Integer(Integer::I64(42)).as_i64());
    /// assert_eq!(Some(42i64), Value::Integer(Integer::U64(42)).as_i64());
    ///
    /// assert_eq!(None, Value::Float(Float::F64(42.0)).as_i64());
    /// ```
    pub fn as_i64(&self) -> Option<i64> {
        match *self {
            Value::Integer(Integer::I64(n)) => Some(n),
            Value::Integer(Integer::U64(n)) if n <= i64::max_value() as u64 => Some(n as i64),
            _ => None,
        }
    }

    /// If the `Value` is an integer, return or cast it to a u64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42u64), Value::Integer(Integer::I64(42)).as_u64());
    /// assert_eq!(Some(42u64), Value::Integer(Integer::U64(42)).as_u64());
    ///
    /// assert_eq!(None, Value::Integer(Integer::I64(-42)).as_u64());
    /// assert_eq!(None, Value::Float(Float::F64(42.0)).as_u64());
    /// ```
    pub fn as_u64(&self) -> Option<u64> {
        match *self {
            Value::Integer(Integer::I64(n)) if 0 <= n => Some(n as u64),
            Value::Integer(Integer::U64(n)) => Some(n),
            _ => None,
        }
    }

    /// If the `Value` is a number, return or cast it to a f64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42.0), Value::Integer(Integer::I64(42)).as_f64());
    /// assert_eq!(Some(42.0), Value::Integer(Integer::U64(42)).as_f64());
    /// assert_eq!(Some(42.0), Value::Float(Float::F32(42.0f32)).as_f64());
    /// assert_eq!(Some(42.0), Value::Float(Float::F64(42.0f64)).as_f64());
    ///
    /// assert_eq!(Some(2147483647.0), Value::Integer(Integer::I64(i32::max_value() as i64)).as_f64());
    ///
    /// assert_eq!(None, Value::Nil.as_f64());
    ///
    /// assert_eq!(None, Value::Integer(Integer::I64(i32::max_value() as i64 + 1)).as_f64());
    /// ```
    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            Value::Integer(Integer::I64(n)) if (i32::min_value() as i64 <= n) && (n <= i32::max_value() as i64) => {
                Some(From::from(n as i32))
            }
            Value::Integer(Integer::U64(n)) if n <= u32::max_value() as u64 => {
                Some(From::from(n as u32))
            }
            Value::Float(Float::F32(n)) => Some(From::from(n)),
            Value::Float(Float::F64(n)) => Some(n),
            _ => None,
        }
    }

    /// If the `Value` is a String, returns the associated str.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    ///
    /// assert_eq!(Some("le message"), Value::String("le message".into()).as_str());
    ///
    /// assert_eq!(None, Value::Boolean(true).as_str());
    /// ```
    pub fn as_str(&self) -> Option<&str> {
        if let Value::String(ref val) = *self {
            Some(val)
        } else {
            None
        }
    }

    /// If the `Value` is an Array, returns the associated vector.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    ///
    /// let val = Value::Array(vec![Value::Nil, Value::Boolean(true)]);
    ///
    /// assert_eq!(Some(&vec![Value::Nil, Value::Boolean(true)]), val.as_array());
    ///
    /// assert_eq!(None, Value::Nil.as_array());
    /// ```
    pub fn as_array(&self) -> Option<&Vec<Value>> {
        if let Value::Array(ref array) = *self {
            Some(&*array)
        } else {
            None
        }
    }
}

impl From<bool> for Value {
    fn from(v: bool) -> Value {
        Value::Boolean(v)
    }
}

impl From<u8> for Value {
    fn from(v: u8) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u16> for Value {
    fn from(v: u16) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u32> for Value {
    fn from(v: u32) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u64> for Value {
    fn from(v: u64) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<usize> for Value {
    fn from(v: usize) -> Value {
        Value::Integer(Integer::U64(v as u64))
    }
}

impl From<i8> for Value {
    fn from(v: i8) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i16> for Value {
    fn from(v: i16) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i32> for Value {
    fn from(v: i32) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i64> for Value {
    fn from(v: i64) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<isize> for Value {
    fn from(v: isize) -> Value {
        Value::Integer(Integer::I64(v as i64))
    }
}

impl From<f32> for Value {
    fn from(v: f32) -> Value {
        Value::Float(Float::F32(v))
    }
}

impl From<f64> for Value {
    fn from(v: f64) -> Value {
        Value::Float(Float::F64(v))
    }
}

/// Implements human-readable value formatting.
impl ::std::fmt::Display for Value {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Value::Nil => write!(f, "nil"),
            Value::Boolean(val) => write!(f, "{}", val),
            Value::Integer(Integer::U64(val)) => write!(f, "{}", val),
            Value::Integer(Integer::I64(val)) => write!(f, "{}", val),
            Value::Float(Float::F32(val)) => write!(f, "{}", val),
            Value::Float(Float::F64(val)) => write!(f, "{}", val),
            Value::String(ref val) => write!(f, "\"{}\"", val),
            Value::Binary(ref val) => write!(f, "{:?}", val),
            Value::Array(ref vec) => {
                // TODO: This can be slower than naive implementation. Need benchmarks for more
                // information.
                let res = vec.iter()
                    .map(|val| format!("{}", val))
                    .collect::<Vec<String>>()
                    .join(", ");

                write!(f, "[{}]", res)
            }
            Value::Map(ref vec) => {
                try!(write!(f, "{{"));

                match vec.iter().take(1).next() {
                    Some(&(ref k, ref v)) => {
                        try!(write!(f, "{}: {}", k, v));
                    }
                    None => {
                        try!(write!(f, ""));
                    }
                }

                for &(ref k, ref v) in vec.iter().skip(1) {
                    try!(write!(f, ", {}: {}", k, v));
                }

                write!(f, "}}")
            }
            Value::Ext(ty, ref data) => {
                write!(f, "[{}, {:?}]", ty, data)
            }
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(&'a str),
    /// Binary extending Raw type represents a byte array.
    Binary(&'a [u8]),
    /// Array represents a sequence of objects.
    Array(Vec<ValueRef<'a>>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, &'a [u8]),
}

impl<'a> ValueRef<'a> {
    /// Converts the current non-owning value to an owned Value.
    ///
    /// This is achieved by deep copying all underlying structures and borrowed buffers.
    ///
    /// # Panics
    ///
    /// Panics in unable to allocate memory to keep all internal structures and buffers.
    ///
    /// # Examples
    /// ```
    /// use rmp::{Value, ValueRef};
    /// use rmp::value::Integer;
    ///
    /// let val = ValueRef::Array(vec![
    ///    ValueRef::Nil,
    ///    ValueRef::Integer(Integer::U64(42)),
    ///    ValueRef::Array(vec![
    ///        ValueRef::String("le message"),
    ///    ])
    /// ]);
    ///
    /// let expected = Value::Array(vec![
    ///     Value::Nil,
    ///     Value::Integer(Integer::U64(42)),
    ///     Value::Array(vec![
    ///         Value::String("le message".to_string())
    ///     ])
    /// ]);
    ///
    /// assert_eq!(expected, val.to_owned());
    /// ```
    pub fn to_owned(&self) -> Value {
        match self {
            &ValueRef::Nil => Value::Nil,
            &ValueRef::Boolean(val) => Value::Boolean(val),
            &ValueRef::Integer(val) => Value::Integer(val),
            &ValueRef::Float(val) => Value::Float(val),
            &ValueRef::String(val) => Value::String(val.to_owned()),
            &ValueRef::Binary(val) => Value::Binary(val.to_vec()),
            &ValueRef::Array(ref val) => {
                Value::Array(val.iter().map(|v| v.to_owned()).collect())
            }
            &ValueRef::Map(ref val) => {
                Value::Map(val.iter().map(|&(ref k, ref v)| (k.to_owned(), v.to_owned())).collect())
            }
            &ValueRef::Ext(ty, buf) => Value::Ext(ty, buf.to_vec()),
        }
    }
}

// For some weird reasons I can't implement it manually.
// It gives: conflicting implementations for trait `collections::borrow::ToOwned`
// impl<'a> ToOwned for ValueRef<'a> {
//     type Owned = Value;
// }
<|endoftext|>