<commit_before>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! jsonrpc server over unix sockets
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate json_ipc_server;
//! extern crate rand;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use json_ipc_server::Server;
//!
//! struct SayHello;
//! impl MethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let server = Server::new("/tmp/json-ipc-test.ipc", &Arc::new(io)).unwrap();
//!     ::std::thread::spawn(move || server.run());
//! }
//! ```

use mio::*;
use mio::unix::*;
use bytes::{Buf, ByteBuf, MutByteBuf};
use std::io;
use jsonrpc_core::IoHandler;
use std::sync::*;
use std::sync::atomic::*;
use std;
use slab;
use validator;
#[cfg(test)]
use tests;

const SERVER: Token = Token(0);
const MAX_CONCURRENT_CONNECTIONS: usize = 16;
const MAX_WRITE_LENGTH: usize = 8192;

struct SocketConnection {
    socket: UnixStream,
    buf: Option<ByteBuf>,
    mut_buf: Option<MutByteBuf>,
    token: Option<Token>,
    interest: EventSet,
}

type Slab<T> = slab::Slab<T, Token>;

impl SocketConnection {
    fn new(sock: UnixStream) -> Self {
        SocketConnection {
            socket: sock,
            buf: None,
            mut_buf: Some(ByteBuf::mut_with_capacity(4096)),
            token: None,
            interest: EventSet::hup(),
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<RpcServer>, _handler: &IoHandler) -> io::Result<()> {
        use std::io::Write;
        if let Some(buf) = self.buf.take() {
			if buf.remaining() < MAX_WRITE_LENGTH {
	            try!(self.socket.write_all(&buf.bytes()));
				self.interest.remove(EventSet::writable());
				self.interest.insert(EventSet::readable());
			}
			else {
				try!(self.socket.write_all(&buf.bytes()[0..MAX_WRITE_LENGTH]));
				self.buf = Some(ByteBuf::from_slice(&buf.bytes()[MAX_WRITE_LENGTH..]));
			}
        }

        event_loop.reregister(&self.socket, self.token.unwrap(), self.interest, PollOpt::edge() | PollOpt::oneshot())
    }

    fn readable(&mut self, event_loop: &mut EventLoop<RpcServer>, handler: &IoHandler) -> io::Result<()> {
        let mut buf = self.mut_buf.take().unwrap_or_else(|| panic!("unwrapping mutable buffer which is None"));

        match self.socket.try_read_buf(&mut buf) {
            Ok(None) => {
                self.mut_buf = Some(buf);
            }
            Ok(Some(_)) => {
                let (requests, last_index) = validator::extract_requests(buf.bytes());
                if requests.len() > 0 {
                    let mut response_bytes = Vec::new();
                    for rpc_msg in requests {
                        trace!(target: "ipc", "Request: {}", rpc_msg);
                        let response: Option<String> = handler.handle_request(&rpc_msg);
                        if let Some(response_str) = response {
                            trace!(target: "ipc", "Response: {}", &response_str);
                            response_bytes.extend(response_str.into_bytes());
                        }
                    }
                    self.buf = Some(ByteBuf::from_slice(&response_bytes[..]));

                    let mut new_buf = ByteBuf::mut_with_capacity(4096);
                    new_buf.write_slice(&buf.bytes()[last_index+1..]);
                    self.mut_buf = Some(new_buf);

                    self.interest.remove(EventSet::readable());
                    self.interest.insert(EventSet::writable());
                }
                else {
                    self.mut_buf = Some(buf);
                }
            }
            Err(e) => {
                trace!(target: "ipc", "Error receiving data: {:?}", e);
                self.interest.remove(EventSet::readable());
            }

        };

        event_loop.reregister(&self.socket, self.token.unwrap(), self.interest, PollOpt::edge() | PollOpt::oneshot())
    }
}

struct RpcServer {
    socket: UnixListener,
    connections: Slab<SocketConnection>,
    io_handler: Arc<IoHandler>,
}

pub struct Server {
    rpc_server: Arc<RwLock<RpcServer>>,
    event_loop: Arc<RwLock<EventLoop<RpcServer>>>,
    is_stopping: Arc<AtomicBool>,
    is_stopped: Arc<AtomicBool>,
    addr: String,
}

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    NotStarted,
    AlreadyStopping,
    NotStopped,
    IsStopping,
}

impl std::convert::From<std::io::Error> for Error {
    fn from(io_error: std::io::Error) -> Error {
        Error::Io(io_error)
    }
}

impl Server {
    /// New server
    pub fn new(socket_addr: &str, io_handler: &Arc<IoHandler>) -> Result<Server, Error> {
        let (server, event_loop) = try!(RpcServer::start(socket_addr, io_handler));
        Ok(Server {
            rpc_server: Arc::new(RwLock::new(server)),
            event_loop: Arc::new(RwLock::new(event_loop)),
            is_stopping: Arc::new(AtomicBool::new(false)),
            is_stopped: Arc::new(AtomicBool::new(true)),
            addr: socket_addr.to_owned(),
        })
    }

    /// Run server (in current thread)
    pub fn run(&self) {
        let mut event_loop = self.event_loop.write().unwrap();
        let mut server = self.rpc_server.write().unwrap();
        event_loop.run(&mut server).unwrap();
    }

    /// Poll server requests (for manual async scenarios)
    pub fn poll(&self) {
        let mut event_loop = self.event_loop.write().unwrap();
        let mut server = self.rpc_server.write().unwrap();

        event_loop.run_once(&mut server, Some(100)).unwrap();
    }

    /// Run server (in separate thread)
    pub fn run_async(&self) -> Result<(), Error> {
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::IsStopping) }
        if !self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStopped) }

        self.is_stopped.store(false, Ordering::Relaxed);

        let event_loop = self.event_loop.clone();
        let server = self.rpc_server.clone();
        let thread_stopping = self.is_stopping.clone();
        let thread_stopped = self.is_stopped.clone();
        std::thread::spawn(move || {
            let mut event_loop = event_loop.write().unwrap();
            let mut server = server.write().unwrap();
            while !thread_stopping.load(Ordering::Relaxed) {
                event_loop.run_once(&mut server, Some(100)).unwrap();
            }
            thread_stopped.store(true, Ordering::Relaxed);
        });
        Ok(())
    }

    pub fn stop_async(&self) -> Result<(), Error> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop(&self) -> Result<(), Error> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        while !self.is_stopped.load(Ordering::Relaxed) { std::thread::sleep(std::time::Duration::new(0, 10)); }
        Ok(())
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.stop().unwrap_or_else(|_| {}); // ignore error - can be stopped already
        ::std::fs::remove_file(&self.addr).unwrap_or_else(|_| {}); // ignoer error - server could have never been started
    }
}

impl RpcServer {

    /// start ipc rpc server (blocking)
    pub fn start(addr: &str, io_handler: &Arc<IoHandler>) -> Result<(RpcServer, EventLoop<RpcServer>), Error> {
        let mut event_loop = try!(EventLoop::new());
        ::std::fs::remove_file(addr).unwrap_or_else(|_| {} ); // ignore error (if no file)
        let socket = try!(UnixListener::bind(&addr));
        event_loop.register(&socket, SERVER, EventSet::readable(), PollOpt::edge()).unwrap();
        let server = RpcServer {
            socket: socket,
            connections: Slab::new_starting_at(Token(1), MAX_CONCURRENT_CONNECTIONS),
            io_handler: io_handler.clone(),
        };
        Ok((server, event_loop))
    }

    fn accept(&mut self, event_loop: &mut EventLoop<RpcServer>) -> io::Result<()> {
        let new_client_socket = self.socket.accept().unwrap().unwrap();
        let connection = SocketConnection::new(new_client_socket);
        if self.connections.count() >= MAX_CONCURRENT_CONNECTIONS {
            let oldest_token = self.connections.iter().nth(0)
                .expect("fatal: impossible since count > MAX_CONCURRENT_CONNECTIONS and we request first one")
                .token.unwrap().clone();
            self.connections.remove(oldest_token);
        }
        let token = self.connections.insert(connection).ok().expect("fatal: Could not add connection to slab (memory issue?)");

        self.connections[token].token = Some(token);
        event_loop.register(
            &self.connections[token].socket,
            token,
            EventSet::readable(),
            PollOpt::edge() | PollOpt::oneshot()
        ).ok().expect("fatal: could not register socket with event loop (memory issue?)");

        Ok(())
    }

    fn connection_readable(&mut self, event_loop: &mut EventLoop<RpcServer>, tok: Token) -> io::Result<()> {
        let io_handler = self.io_handler.clone();
        self.connection(tok).readable(event_loop, &io_handler)
    }

    fn connection_writable(&mut self, event_loop: &mut EventLoop<RpcServer>, tok: Token) -> io::Result<()> {
        let io_handler = self.io_handler.clone();
        self.connection(tok).writable(event_loop, &io_handler)
    }

    fn connection<'a>(&'a mut self, tok: Token) -> &'a mut SocketConnection {
        &mut self.connections[tok]
    }
}

impl Handler for RpcServer {
    type Timeout = usize;
    type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<RpcServer>, token: Token, events: EventSet) {
        if events.is_readable() {
            match token {
                SERVER => self.accept(event_loop).unwrap(),
                _ => self.connection_readable(event_loop, token).unwrap()
            };
        }

        if events.is_writable() {
            match token {
                SERVER => { },
                _ => self.connection_writable(event_loop, token).unwrap_or_else(|_| {}), // todo: disqualify connection from list on error
            };
        }
    }
}

#[test]
pub fn test_reqrep_poll() {
    let addr = tests::random_ipc_endpoint();
    let io = tests::dummy_io_handler();
    let server = Server::new(&addr, &io).unwrap();
    std::thread::spawn(move || {
        loop {
            server.poll();
        }
    });

    let request = r#"{"jsonrpc": "2.0", "method": "say_hello", "params": [42, 23], "id": 1}"#;
    let response = r#"{"jsonrpc":"2.0","result":"hello 42! you sent 23","id":1}"#;
    assert_eq!(String::from_utf8(tests::dummy_request(&addr, request.as_bytes())).unwrap(), response.to_string());

    std::thread::sleep(std::time::Duration::from_millis(500));
}

#[test]
pub fn test_file_removed() {
    let addr = tests::random_ipc_endpoint();
    let io = tests::dummy_io_handler();
    {
        let server = Server::new(&addr, &io).unwrap();
        server.run_async().unwrap();
        std::thread::sleep(std::time::Duration::from_millis(50));

        let request = r#"{"jsonrpc": "2.0", "method": "say_hello", "params": [42, 23], "id": 1}"#;
        let response = r#"{"jsonrpc":"2.0","result":"hello 42! you sent 23","id":1}"#;
        assert_eq!(String::from_utf8(tests::dummy_request(&addr, request.as_bytes())).unwrap(), response.to_string());
    }
    assert!(::std::fs::metadata(addr).is_err()); // err is file not exists
}
<commit_msg>fix issue with lurking connections<commit_after>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! jsonrpc server over unix sockets
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate json_ipc_server;
//! extern crate rand;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use json_ipc_server::Server;
//!
//! struct SayHello;
//! impl MethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let server = Server::new("/tmp/json-ipc-test.ipc", &Arc::new(io)).unwrap();
//!     ::std::thread::spawn(move || server.run());
//! }
//! ```

use mio::*;
use mio::unix::*;
use bytes::{Buf, ByteBuf, MutByteBuf};
use std::io;
use jsonrpc_core::IoHandler;
use std::sync::*;
use std::sync::atomic::*;
use std;
use slab;
use validator;
#[cfg(test)]
use tests;

const SERVER: Token = Token(0);
const MAX_CONCURRENT_CONNECTIONS: usize = 16;
const MAX_WRITE_LENGTH: usize = 8192;

struct SocketConnection {
    socket: UnixStream,
    buf: Option<ByteBuf>,
    mut_buf: Option<MutByteBuf>,
    token: Option<Token>,
    interest: EventSet,
}

type Slab<T> = slab::Slab<T, Token>;

impl SocketConnection {
    fn new(sock: UnixStream) -> Self {
        SocketConnection {
            socket: sock,
            buf: None,
            mut_buf: Some(ByteBuf::mut_with_capacity(4096)),
            token: None,
            interest: EventSet::hup(),
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<RpcServer>, _handler: &IoHandler) -> io::Result<()> {
        use std::io::Write;
        if let Some(buf) = self.buf.take() {
			if buf.remaining() < MAX_WRITE_LENGTH {
	            try!(self.socket.write_all(&buf.bytes()));
				self.interest.remove(EventSet::writable());
				self.interest.insert(EventSet::readable());
			}
			else {
				try!(self.socket.write_all(&buf.bytes()[0..MAX_WRITE_LENGTH]));
				self.buf = Some(ByteBuf::from_slice(&buf.bytes()[MAX_WRITE_LENGTH..]));
			}
        }

        event_loop.reregister(&self.socket, self.token.unwrap(), self.interest, PollOpt::edge() | PollOpt::oneshot())
    }

    fn readable(&mut self, event_loop: &mut EventLoop<RpcServer>, handler: &IoHandler) -> io::Result<()> {
        let mut buf = self.mut_buf.take().unwrap_or_else(|| panic!("unwrapping mutable buffer which is None"));

        match self.socket.try_read_buf(&mut buf) {
            Ok(None) => {
				trace!(target: "ipc", "Empty read ({:?})", self.token);
                self.mut_buf = Some(buf);
				return Ok(());
            }
            Ok(Some(_)) => {
                let (requests, last_index) = validator::extract_requests(buf.bytes());
                if requests.len() > 0 {
                    let mut response_bytes = Vec::new();
                    for rpc_msg in requests {
                        trace!(target: "ipc", "Request: {}", rpc_msg);
                        let response: Option<String> = handler.handle_request(&rpc_msg);
                        if let Some(response_str) = response {
                            trace!(target: "ipc", "Response: {}", &response_str);
                            response_bytes.extend(response_str.into_bytes());
                        }
                    }
                    self.buf = Some(ByteBuf::from_slice(&response_bytes[..]));

                    let mut new_buf = ByteBuf::mut_with_capacity(4096);
                    new_buf.write_slice(&buf.bytes()[last_index+1..]);
                    self.mut_buf = Some(new_buf);

                    self.interest.remove(EventSet::readable());
                    self.interest.insert(EventSet::writable());
                }
                else {
                    self.mut_buf = Some(buf);
                }
            }
            Err(e) => {
                trace!(target: "ipc", "Error receiving data ({:?}): {:?}", self.token, e);
                self.interest.remove(EventSet::readable());
            }

        };
        event_loop.reregister(&self.socket, self.token.unwrap(), self.interest, PollOpt::edge() | PollOpt::oneshot())
    }
}

struct RpcServer {
    socket: UnixListener,
    connections: Slab<SocketConnection>,
    io_handler: Arc<IoHandler>,
}

pub struct Server {
    rpc_server: Arc<RwLock<RpcServer>>,
    event_loop: Arc<RwLock<EventLoop<RpcServer>>>,
    is_stopping: Arc<AtomicBool>,
    is_stopped: Arc<AtomicBool>,
    addr: String,
}

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    NotStarted,
    AlreadyStopping,
    NotStopped,
    IsStopping,
}

impl std::convert::From<std::io::Error> for Error {
    fn from(io_error: std::io::Error) -> Error {
        Error::Io(io_error)
    }
}

impl Server {
    /// New server
    pub fn new(socket_addr: &str, io_handler: &Arc<IoHandler>) -> Result<Server, Error> {
        let (server, event_loop) = try!(RpcServer::start(socket_addr, io_handler));
        Ok(Server {
            rpc_server: Arc::new(RwLock::new(server)),
            event_loop: Arc::new(RwLock::new(event_loop)),
            is_stopping: Arc::new(AtomicBool::new(false)),
            is_stopped: Arc::new(AtomicBool::new(true)),
            addr: socket_addr.to_owned(),
        })
    }

    /// Run server (in current thread)
    pub fn run(&self) {
        let mut event_loop = self.event_loop.write().unwrap();
        let mut server = self.rpc_server.write().unwrap();
        event_loop.run(&mut server).unwrap();
    }

    /// Poll server requests (for manual async scenarios)
    pub fn poll(&self) {
        let mut event_loop = self.event_loop.write().unwrap();
        let mut server = self.rpc_server.write().unwrap();

        event_loop.run_once(&mut server, Some(100)).unwrap();
    }

    /// Run server (in separate thread)
    pub fn run_async(&self) -> Result<(), Error> {
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::IsStopping) }
        if !self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStopped) }

        self.is_stopped.store(false, Ordering::Relaxed);

        let event_loop = self.event_loop.clone();
        let server = self.rpc_server.clone();
        let thread_stopping = self.is_stopping.clone();
        let thread_stopped = self.is_stopped.clone();
        std::thread::spawn(move || {
            let mut event_loop = event_loop.write().unwrap();
            let mut server = server.write().unwrap();
            while !thread_stopping.load(Ordering::Relaxed) {
                event_loop.run_once(&mut server, Some(100)).unwrap();
            }
            thread_stopped.store(true, Ordering::Relaxed);
        });
        Ok(())
    }

    pub fn stop_async(&self) -> Result<(), Error> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop(&self) -> Result<(), Error> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        while !self.is_stopped.load(Ordering::Relaxed) { std::thread::sleep(std::time::Duration::new(0, 10)); }
        Ok(())
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.stop().unwrap_or_else(|_| {}); // ignore error - can be stopped already
        ::std::fs::remove_file(&self.addr).unwrap_or_else(|_| {}); // ignoer error - server could have never been started
    }
}

impl RpcServer {

    /// start ipc rpc server (blocking)
    pub fn start(addr: &str, io_handler: &Arc<IoHandler>) -> Result<(RpcServer, EventLoop<RpcServer>), Error> {
        let mut event_loop = try!(EventLoop::new());
        ::std::fs::remove_file(addr).unwrap_or_else(|_| {} ); // ignore error (if no file)
        let socket = try!(UnixListener::bind(&addr));
        event_loop.register(&socket, SERVER, EventSet::readable(), PollOpt::edge()).unwrap();
        let server = RpcServer {
            socket: socket,
            connections: Slab::new_starting_at(Token(1), MAX_CONCURRENT_CONNECTIONS),
            io_handler: io_handler.clone(),
        };
        Ok((server, event_loop))
    }

    fn accept(&mut self, event_loop: &mut EventLoop<RpcServer>) -> io::Result<()> {
        let new_client_socket = self.socket.accept().unwrap().unwrap();
        let connection = SocketConnection::new(new_client_socket);
        if self.connections.count() >= MAX_CONCURRENT_CONNECTIONS {
            let oldest_token = self.connections.iter().nth(0)
                .expect("fatal: impossible since count > MAX_CONCURRENT_CONNECTIONS and we request first one")
                .token.unwrap().clone();

            let old_connection = self.connections.remove(oldest_token).expect("There is max connections here");
			trace!(target: "ipc", "Recycled old socket {:?}", oldest_token);
			try!(event_loop.deregister(&old_connection.socket));
        }
        let token = self.connections.insert(connection).ok().expect("fatal: Could not add connection to slab (memory issue?)");

		trace!(target: "ipc", "Accepted connection with token {:?}", token);

        self.connections[token].token = Some(token);
        event_loop.register(
            &self.connections[token].socket,
            token,
            EventSet::readable(),
            PollOpt::edge() | PollOpt::oneshot()
        ).ok().expect("fatal: could not register socket with event loop (memory issue?)");

        Ok(())
    }

    fn connection_readable(&mut self, event_loop: &mut EventLoop<RpcServer>, tok: Token) -> io::Result<()> {
        let io_handler = self.io_handler.clone();
        self.connection(tok).readable(event_loop, &io_handler)
    }

    fn connection_writable(&mut self, event_loop: &mut EventLoop<RpcServer>, tok: Token) -> io::Result<()> {
        let io_handler = self.io_handler.clone();
        self.connection(tok).writable(event_loop, &io_handler)
    }

    fn connection<'a>(&'a mut self, tok: Token) -> &'a mut SocketConnection {
        &mut self.connections[tok]
    }
}

impl Handler for RpcServer {
    type Timeout = usize;
    type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<RpcServer>, token: Token, events: EventSet) {
        if events.is_readable() {
            match token {
                SERVER => self.accept(event_loop).unwrap(),
                _ => self.connection_readable(event_loop, token).unwrap()
            };
        }

        if events.is_writable() {
            match token {
                SERVER => { },
                _ => self.connection_writable(event_loop, token).unwrap_or_else(|_| {}), // todo: disqualify connection from list on error
            };
        }
    }
}

#[test]
pub fn test_reqrep_poll() {
    let addr = tests::random_ipc_endpoint();
    let io = tests::dummy_io_handler();
    let server = Server::new(&addr, &io).unwrap();
    std::thread::spawn(move || {
        loop {
            server.poll();
        }
    });

    let request = r#"{"jsonrpc": "2.0", "method": "say_hello", "params": [42, 23], "id": 1}"#;
    let response = r#"{"jsonrpc":"2.0","result":"hello 42! you sent 23","id":1}"#;
    assert_eq!(String::from_utf8(tests::dummy_request(&addr, request.as_bytes())).unwrap(), response.to_string());

    std::thread::sleep(std::time::Duration::from_millis(500));
}

#[test]
pub fn test_file_removed() {
    let addr = tests::random_ipc_endpoint();
    let io = tests::dummy_io_handler();
    {
        let server = Server::new(&addr, &io).unwrap();
        server.run_async().unwrap();
        std::thread::sleep(std::time::Duration::from_millis(50));

        let request = r#"{"jsonrpc": "2.0", "method": "say_hello", "params": [42, 23], "id": 1}"#;
        let response = r#"{"jsonrpc":"2.0","result":"hello 42! you sent 23","id":1}"#;
        assert_eq!(String::from_utf8(tests::dummy_request(&addr, request.as_bytes())).unwrap(), response.to_string());
    }
    assert!(::std::fs::metadata(addr).is_err()); // err is file not exists
}
<|endoftext|>


<commit_before>#![feature(globs,macro_rules)]
#![desc = "Omnomnom incremental byte parser"]
#![license = "MIT"]

extern crate collections;

use std::fmt::Show;
use std::str;
use std::cmp::min;
use std::io::fs::File;
use std::io::{IoResult, IoErrorKind};
use self::Parser::*;
use self::ProducerState::*;
use std::kinds::Sized;

pub type Err = uint;
type ParserClosure<'a,I,O> = |I|:'a -> Parser<I,O>;

//type ParserClosure<'a,I,O> = |I|:'a -> Parser<'a,I,O>;
//type ParserClosure<'a,I,O> = Fn<I, Parser<'a,I,O>>;
#[deriving(Show,PartialEq,Eq)]
pub enum Parser<I,O> {
  Done(I,O),
  Error(Err),
  //Incomplete(ParserClosure<'a,I,O>)
  //Incomplete(|I|:'a -> Parser<'a,I,O>)
  //Incomplete(fn(I) -> Parser<'a,I,O>)
}

pub trait Mapper<O,N> for Sized? {
  fn map(& self, f: |O| -> Parser<O,N>) -> Parser<O,N>;
  fn mapf(& self, f: |O| -> Option<N>) -> Parser<O,N>;
}

impl<'a,R,S,T> Mapper<&'a[S], T> for Parser<R,&'a [S]> {
  fn map(&self, f: |&'a[S]| -> Parser<&'a[S],T>) -> Parser<&'a[S],T> {
    match self {
      &Error(ref e) => Error(*e),
      //&Incomplete(ref cl) => Incomplete(f), //Incomplete(|input:I| { cl(input).map(f) })
      &Done(_, ref o) => f(*o)
    }
  }

  fn mapf(&self, f: |&'a[S]| -> Option<T>) -> Parser<&'a[S],T> {
    match self {
      &Error(ref e) => Error(*e),
      //&Incomplete(ref cl) => Error(0),//Incomplete(|input: &'a I| {*cl(input).mapf(f)}),
      &Done(_, ref o) => match f(*o) {
        Some(output) => Done(*o, output),
        None         => Error(0)
      }
    }
  }
}

impl<R,T> Mapper<(), T> for Parser<R,()> {
  fn map(&self, f: |()| -> Parser<(),T>) -> Parser<(),T> {
    match self {
      &Error(ref e) => Error(*e),
      //&Incomplete(ref cl) => Incomplete(f), //Incomplete(|input:I| { cl(input).map(f) })
      &Done(_, _) => f(())
    }
  }

  fn mapf(&self, f: |()| -> Option<T>) -> Parser<(),T> {
    match self {
      &Error(ref e) => Error(*e),
      //&Incomplete(ref cl) => Error(0),//Incomplete(|input: &'a I| {*cl(input).mapf(f)}),
      &Done(_, __) => match f(()) {
        Some(output) => Done((), output),
        None         => Error(0)
      }
    }
  }
}

pub trait Ender<O> {
  fn end(&self, f: |O| -> ()) -> ();
}

impl<'a> Ender<&'a [u8]> for Parser<&'a [u8],&'a [u8]> {
  fn end(&self, f: |&'a [u8]| -> ()) -> () {
    match self {
      &Error(_) => (),
      //&Incomplete(ref cl) => Incomplete(f), //Incomplete(|input:I| { cl(input).map(f) })
      &Done(_, ref o) => {
        f(*o)
      }
    }
  }
}
impl<'a> Ender<&'a str> for Parser<&'a [u8],&'a str> {
  fn end(&self, f: |&'a str| -> ()) -> () {
    match self {
      &Error(_) => (),
      //&Incomplete(ref cl) => Incomplete(f), //Incomplete(|input:I| { cl(input).map(f) })
      &Done(_, ref o) => {
        f(*o)
      }
    }
  }
}

impl<'a> Ender<&'a [u8]> for Parser<(),&'a [u8]> {
  fn end(&self, f: |&'a [u8]| -> ()) -> () {
    match self {
      &Error(_) => (),
      //&Incomplete(ref cl) => Incomplete(f), //Incomplete(|input:I| { cl(input).map(f) })
      &Done(_, ref o) => {
        f(*o)
      }
    }
  }
}

/***/
impl<'a>  Parser<(),&'a [u8]> {
  pub fn m2<'b,'c>(&'b self, f: |&'a [u8]| -> Parser<&'c [u8],()>) -> Parser<&'c [u8], ()> {
    match self {
      &Error(ref e) => Error(*e),
      &Done(_, ref o) => f(*o)
    }
  }
  pub fn m3<'b,'c>(&'b self, f: |&'a [u8]| -> Parser<&'c [u8],&'c [u8]>) -> Parser<&'c [u8], &'c [u8]> {
    match self {
      &Error(ref e) => Error(*e),
      &Done(_, ref o) => f(*o)
    }
  }
}
impl<'a>  Parser<&'a [u8],&'a str> {
  pub fn m4<'b,'c>(&'b self, f: |&'a str| -> Parser<&'c str,()>) -> Parser<&'c str, ()> {
    match self {
      &Error(ref e) => Error(*e),
      &Done(_, ref o) => f(*o)
    }
  }
}
/***/

pub fn accline<'a>(input: &'a [u8]) -> Parser<&'a [u8], &'a [u8]> {
  match input.iter().position(|&c| c == '\n' as u8) {
    None      => Error(0),//Incomplete(accline),
    Some(pos) => Done(input.slice_from(pos), input.slice(0, pos))
  }
}

pub fn print<T: Show>(input: T) -> Parser<T, ()> {
  println!("{}", input);
  Done(input, ())
}

pub fn begin<'a>(input: &'a [u8]) -> Parser<(), &'a [u8]> {
  Done((), input)
}

#[macro_export]
macro_rules! tag(
  ($name:ident $inp:expr) => (
    fn $name(i:&[u8]) -> Parser<&[u8], &[u8]>{
      if i.len() >= $inp.len() && i.slice(0, $inp.len()) == $inp {
        Done(i.slice_from($inp.len()), i.slice(0, 0))
      } else {
        Error(0)
      }
    }
  )
)

#[deriving(Show,PartialEq,Eq)]
pub enum ProducerState<O> {
  Eof(O),
  Continue,
  Data(O),
  ProducerError(Err),
}

type ParserStarterClosure<'a,I,T,O> = |Parser<(),I>|:'a -> Parser<T,O>;

pub struct FileProducer {
  size: uint,
  file: File
}

impl FileProducer {
  pub fn new(filename: &str, buffer_size: uint) -> IoResult<FileProducer> {
    File::open(&Path::new(filename)).map(|f| { FileProducer {size: buffer_size, file: f} })
  }

  fn produce(&mut self) -> ProducerState<Vec<u8>> {
    let mut v = Vec::with_capacity(self.size);
    match self.file.push(self.size, &mut v) {
      Err(e) => {
        match e.kind {
          IoErrorKind::NoProgress => Continue,
          IoErrorKind::EndOfFile  => Eof(v),
          _          => ProducerError(0)
        }
      },
      Ok(i)  => {
        println!("read {} bytes", i);
        Data(v)
      }
    }
  }
/*}

impl Producer for FileProducer {
*/
  pub fn push<'x,'y,O>(&mut self, f: |Parser<(),&[u8]>| -> Parser<&'y[u8],O>) {
    loop {
      if self.file.eof() {
        println!("end");
        break;
      }
      let state = self.produce();
      let mut acc: Vec<u8> = Vec::new();
      match state {
        ProducerError(e)  => println!("error: {}", e),
        Continue => {},
        Data(v) => {
          let mut v2 = Vec::new();
          v2.push_all(acc.as_slice());
          v2.push_all(v.as_slice());
          let p = Done((), v2.as_slice());
          match f(p) {
          //match f(begin(v2.as_slice())) {
            Error(e)      => println!("error, stopping: {}", e),
            //Incomplete(_) => println!("incomplete, continue"),
            Done(_, _)    => {
              //println!("end, done");
              acc.clear();
            }
          }
        },
        Eof(v) => {
          println!("GOT EOF");
          let mut v3 = Vec::new();
          v3.push_all(acc.as_slice());
          v3.push_all(v.as_slice());
          let p = Done((), v3.as_slice());
          match f(p) {
          //match f(begin(v2.as_slice())) {
            Error(e)      => println!("error, stopping: {}", e),
            //Incomplete(_) => println!("incomplete, continue"),
            Done(_, _)    => {
              println!("end, done");
              acc.clear();
            }
          };
          break;
        }
      }
      //v2.clear();
    }
    println!("end push");
  }
}

pub struct MemProducer<'x> {
  buffer: &'x [u8],
  chunk_size: uint,
  length: uint,
  index: uint
}

impl<'x> MemProducer<'x> {
  pub fn new(buffer: &'x[u8], chunk_size: uint) -> MemProducer {
    MemProducer {
      buffer:     buffer,
      chunk_size: chunk_size,
      length:     buffer.len(),
      index:      0
    }
  }

  fn produce(&mut self) -> ProducerState<&'x[u8]> {
    if self.index + self.chunk_size < self.length {
      println!("self.index + {} < self.length", self.chunk_size);
      let new_index = self.index+self.chunk_size;
      let res = Data(self.buffer.slice(self.index, new_index));
      self.index = new_index;
      res
    } else if self.index < self.length {
      println!("self.index < self.length - 1");
      let res = Eof(self.buffer.slice(self.index, self.length));
      self.index = self.length;
      res
    } else {
      ProducerError(0)
    }
  }

  /*
}

impl<'x> Producer for MemProducer<'x> {
*/
  fn push<'b,O>(&mut self, f: |Parser<(),&'b[u8]>| -> Parser<&'b[u8],O>) {
    loop {
      let state = self.produce();
      match state {
        ProducerError(e)  => {println!("error: {}", e);break;},
        Continue => {println!("continue should not happen");break;},
        Data(v) => {
          let p = Done((), v);
          match f(p) {
            Error(e)      => println!("error, stopping: {}", e),
            Done(_, _)    => {
              println!("data, done");
            }
          }
        },
        Eof(v) => {
          let p = Done((), v);
          match f(p) {
            Error(e)      => println!("error, stopping: {}", e),
            Done(_, _)    => {
              println!("eof, done");
            }
          }
          break;
        }
      }
    }
  }
}

#[test]
fn map_fn() {
  Done((),()).map(print);
}

#[test]
fn map_closure() {
  Done((),()).map(|data| { println!("data: {}", data); Done(data,())});
  //assert_eq!(decoded.number, 10);
}

#[test]
fn t1() {
  let v1:Vec<u8> = vec![1,2,3];
  let v2:Vec<u8> = vec![4,5,6];
  let d = Done(v1.as_slice(), v2.as_slice());
  let res = d.map(print);
  assert_eq!(res, Done(v2.as_slice(), ()));
}

#[test]
fn end_test() {
  let v1:Vec<u8> = vec![1,2,3];
  let v2 = vec![4,5,6];
  let d = Done(v1.as_slice(), v2.as_slice());
  let mut res: Vec<u8> = Vec::new();
  d.end(|v:&[u8]| res.push_all(v));
  assert_eq!(res.as_slice(), v2.as_slice());
}

#[test]
fn mem_producer_test() {
  let mut p = MemProducer::new("abcdefgh".as_bytes(), 4);
  assert_eq!(p.produce(), Data("abcd".as_bytes()));
}

#[test]
fn mem_producer_test_2() {
  let mut p = MemProducer::new("abcdefgh".as_bytes(), 8);
  p.push(|par| par.map(print));
  let mut iterations: uint = 0;
  let mut p = MemProducer::new("abcdefghi".as_bytes(), 4);
  p.push(|par| {iterations = iterations + 1; par.map(print)});
  assert_eq!(iterations, 3);
}

#[test]
fn file_test() {
  FileProducer::new("links.txt", 20).map(|producer: FileProducer| {
    let mut p = producer;
    //p.push(|par| {println!("parsed file: {}", par); par});
    p.push(|par| par.map(print));
  });
}

#[test]
fn tag_test() {
  FileProducer::new("links.txt", 20).map(|producer: FileProducer| {
    let mut p = producer;
    tag!(f "https://".as_bytes());
    p.push(|par| par.map(f).map(print));
  });
}

/*
#[test]
fn file_chain_test() {
  FileProducer::new("links.txt", 20).map(|producer: FileProducer| {
    let mut p = producer;
    p.push(|par| par.map(accline).mapf(|v2: &[u8]| str::from_utf8(v2.as_slice())).map(print));
  });
}*/

/* FIXME: this makes rustc weep
fn pr(par: Parser<(),&[u8]>) -> Parser<&[u8], ()> {
  Error(0)
}

#[test]
fn rustc_panic_test() {
  FileProducer::new("links.txt", 20).map(|producer: FileProducer| {
    let mut p = producer;
    p.push(pr);
  });
}*/
<commit_msg>Add a macro to chain two functions but ignore<commit_after>#![feature(globs,macro_rules)]
#![desc = "Omnomnom incremental byte parser"]
#![license = "MIT"]

extern crate collections;

use std::fmt::Show;
use std::str;
use std::cmp::min;
use std::io::fs::File;
use std::io::{IoResult, IoErrorKind};
use self::Parser::*;
use self::ProducerState::*;
use std::kinds::Sized;

pub type Err = uint;
type ParserClosure<'a,I,O> = |I|:'a -> Parser<I,O>;

//type ParserClosure<'a,I,O> = |I|:'a -> Parser<'a,I,O>;
//type ParserClosure<'a,I,O> = Fn<I, Parser<'a,I,O>>;
#[deriving(Show,PartialEq,Eq)]
pub enum Parser<I,O> {
  Done(I,O),
  Error(Err),
  //Incomplete(ParserClosure<'a,I,O>)
  //Incomplete(|I|:'a -> Parser<'a,I,O>)
  //Incomplete(fn(I) -> Parser<'a,I,O>)
}

pub trait Mapper<O,N> for Sized? {
  fn map(& self, f: |O| -> Parser<O,N>) -> Parser<O,N>;
  fn mapf(& self, f: |O| -> Option<N>) -> Parser<O,N>;
}

impl<'a,R,S,T> Mapper<&'a[S], T> for Parser<R,&'a [S]> {
  fn map(&self, f: |&'a[S]| -> Parser<&'a[S],T>) -> Parser<&'a[S],T> {
    match self {
      &Error(ref e) => Error(*e),
      //&Incomplete(ref cl) => Incomplete(f), //Incomplete(|input:I| { cl(input).map(f) })
      &Done(_, ref o) => f(*o)
    }
  }

  fn mapf(&self, f: |&'a[S]| -> Option<T>) -> Parser<&'a[S],T> {
    match self {
      &Error(ref e) => Error(*e),
      //&Incomplete(ref cl) => Error(0),//Incomplete(|input: &'a I| {*cl(input).mapf(f)}),
      &Done(_, ref o) => match f(*o) {
        Some(output) => Done(*o, output),
        None         => Error(0)
      }
    }
  }
}

impl<R,T> Mapper<(), T> for Parser<R,()> {
  fn map(&self, f: |()| -> Parser<(),T>) -> Parser<(),T> {
    match self {
      &Error(ref e) => Error(*e),
      //&Incomplete(ref cl) => Incomplete(f), //Incomplete(|input:I| { cl(input).map(f) })
      &Done(_, _) => f(())
    }
  }

  fn mapf(&self, f: |()| -> Option<T>) -> Parser<(),T> {
    match self {
      &Error(ref e) => Error(*e),
      //&Incomplete(ref cl) => Error(0),//Incomplete(|input: &'a I| {*cl(input).mapf(f)}),
      &Done(_, __) => match f(()) {
        Some(output) => Done((), output),
        None         => Error(0)
      }
    }
  }
}

pub trait Ender<O> {
  fn end(&self, f: |O| -> ()) -> ();
}

impl<'a> Ender<&'a [u8]> for Parser<&'a [u8],&'a [u8]> {
  fn end(&self, f: |&'a [u8]| -> ()) -> () {
    match self {
      &Error(_) => (),
      //&Incomplete(ref cl) => Incomplete(f), //Incomplete(|input:I| { cl(input).map(f) })
      &Done(_, ref o) => {
        f(*o)
      }
    }
  }
}
impl<'a> Ender<&'a str> for Parser<&'a [u8],&'a str> {
  fn end(&self, f: |&'a str| -> ()) -> () {
    match self {
      &Error(_) => (),
      //&Incomplete(ref cl) => Incomplete(f), //Incomplete(|input:I| { cl(input).map(f) })
      &Done(_, ref o) => {
        f(*o)
      }
    }
  }
}

impl<'a> Ender<&'a [u8]> for Parser<(),&'a [u8]> {
  fn end(&self, f: |&'a [u8]| -> ()) -> () {
    match self {
      &Error(_) => (),
      //&Incomplete(ref cl) => Incomplete(f), //Incomplete(|input:I| { cl(input).map(f) })
      &Done(_, ref o) => {
        f(*o)
      }
    }
  }
}

/***/
impl<'a>  Parser<(),&'a [u8]> {
  pub fn m2<'b,'c>(&'b self, f: |&'a [u8]| -> Parser<&'c [u8],()>) -> Parser<&'c [u8], ()> {
    match self {
      &Error(ref e) => Error(*e),
      &Done(_, ref o) => f(*o)
    }
  }
  pub fn m3<'b,'c>(&'b self, f: |&'a [u8]| -> Parser<&'c [u8],&'c [u8]>) -> Parser<&'c [u8], &'c [u8]> {
    match self {
      &Error(ref e) => Error(*e),
      &Done(_, ref o) => f(*o)
    }
  }
}
impl<'a>  Parser<&'a [u8],&'a str> {
  pub fn m4<'b,'c>(&'b self, f: |&'a str| -> Parser<&'c str,()>) -> Parser<&'c str, ()> {
    match self {
      &Error(ref e) => Error(*e),
      &Done(_, ref o) => f(*o)
    }
  }
}
/***/

pub fn accline<'a>(input: &'a [u8]) -> Parser<&'a [u8], &'a [u8]> {
  match input.iter().position(|&c| c == '\n' as u8) {
    None      => Error(0),//Incomplete(accline),
    Some(pos) => Done(input.slice_from(pos), input.slice(0, pos))
  }
}

pub fn print<T: Show>(input: T) -> Parser<T, ()> {
  println!("{}", input);
  Done(input, ())
}

pub fn begin<'a>(input: &'a [u8]) -> Parser<(), &'a [u8]> {
  Done((), input)
}

#[macro_export]
macro_rules! tag(
  ($name:ident $inp:expr) => (
    fn $name(i:&[u8]) -> Parser<&[u8], &[u8]>{
      if i.len() >= $inp.len() && i.slice(0, $inp.len()) == $inp {
        Done(i.slice_from($inp.len()), i.slice(0, 0))
      } else {
        Error(0)
      }
    }
  )
)

macro_rules! c (
  ($name:ident<$i:ty,$o:ty>($f1:expr, $f2:expr)) => (
    fn $name(input:$i) -> Parser<$i, $o>{
      match $f1(input) {
        Error(e)  => Error(e),
        Done(i,_) => $f2(i)
      }
    }
  );
)

#[deriving(Show,PartialEq,Eq)]
pub enum ProducerState<O> {
  Eof(O),
  Continue,
  Data(O),
  ProducerError(Err),
}

type ParserStarterClosure<'a,I,T,O> = |Parser<(),I>|:'a -> Parser<T,O>;

pub struct FileProducer {
  size: uint,
  file: File
}

impl FileProducer {
  pub fn new(filename: &str, buffer_size: uint) -> IoResult<FileProducer> {
    File::open(&Path::new(filename)).map(|f| { FileProducer {size: buffer_size, file: f} })
  }

  fn produce(&mut self) -> ProducerState<Vec<u8>> {
    let mut v = Vec::with_capacity(self.size);
    match self.file.push(self.size, &mut v) {
      Err(e) => {
        match e.kind {
          IoErrorKind::NoProgress => Continue,
          IoErrorKind::EndOfFile  => Eof(v),
          _          => ProducerError(0)
        }
      },
      Ok(i)  => {
        println!("read {} bytes", i);
        Data(v)
      }
    }
  }
/*}

impl Producer for FileProducer {
*/
  pub fn push<'x,'y,O>(&mut self, f: |Parser<(),&[u8]>| -> Parser<&'y[u8],O>) {
    loop {
      if self.file.eof() {
        println!("end");
        break;
      }
      let state = self.produce();
      let mut acc: Vec<u8> = Vec::new();
      match state {
        ProducerError(e)  => println!("error: {}", e),
        Continue => {},
        Data(v) => {
          let mut v2 = Vec::new();
          v2.push_all(acc.as_slice());
          v2.push_all(v.as_slice());
          let p = Done((), v2.as_slice());
          match f(p) {
          //match f(begin(v2.as_slice())) {
            Error(e)      => println!("error, stopping: {}", e),
            //Incomplete(_) => println!("incomplete, continue"),
            Done(_, _)    => {
              //println!("end, done");
              acc.clear();
            }
          }
        },
        Eof(v) => {
          println!("GOT EOF");
          let mut v3 = Vec::new();
          v3.push_all(acc.as_slice());
          v3.push_all(v.as_slice());
          let p = Done((), v3.as_slice());
          match f(p) {
          //match f(begin(v2.as_slice())) {
            Error(e)      => println!("error, stopping: {}", e),
            //Incomplete(_) => println!("incomplete, continue"),
            Done(_, _)    => {
              println!("end, done");
              acc.clear();
            }
          };
          break;
        }
      }
      //v2.clear();
    }
    println!("end push");
  }
}

pub struct MemProducer<'x> {
  buffer: &'x [u8],
  chunk_size: uint,
  length: uint,
  index: uint
}

impl<'x> MemProducer<'x> {
  pub fn new(buffer: &'x[u8], chunk_size: uint) -> MemProducer {
    MemProducer {
      buffer:     buffer,
      chunk_size: chunk_size,
      length:     buffer.len(),
      index:      0
    }
  }

  fn produce(&mut self) -> ProducerState<&'x[u8]> {
    if self.index + self.chunk_size < self.length {
      println!("self.index + {} < self.length", self.chunk_size);
      let new_index = self.index+self.chunk_size;
      let res = Data(self.buffer.slice(self.index, new_index));
      self.index = new_index;
      res
    } else if self.index < self.length {
      println!("self.index < self.length - 1");
      let res = Eof(self.buffer.slice(self.index, self.length));
      self.index = self.length;
      res
    } else {
      ProducerError(0)
    }
  }

  /*
}

impl<'x> Producer for MemProducer<'x> {
*/
  fn push<'b,O>(&mut self, f: |Parser<(),&'b[u8]>| -> Parser<&'b[u8],O>) {
    loop {
      let state = self.produce();
      match state {
        ProducerError(e)  => {println!("error: {}", e);break;},
        Continue => {println!("continue should not happen");break;},
        Data(v) => {
          let p = Done((), v);
          match f(p) {
            Error(e)      => println!("error, stopping: {}", e),
            Done(_, _)    => {
              println!("data, done");
            }
          }
        },
        Eof(v) => {
          let p = Done((), v);
          match f(p) {
            Error(e)      => println!("error, stopping: {}", e),
            Done(_, _)    => {
              println!("eof, done");
            }
          }
          break;
        }
      }
    }
  }
}

#[test]
fn map_fn() {
  Done((),()).map(print);
}

#[test]
fn map_closure() {
  Done((),()).map(|data| { println!("data: {}", data); Done(data,())});
  //assert_eq!(decoded.number, 10);
}

#[test]
fn t1() {
  let v1:Vec<u8> = vec![1,2,3];
  let v2:Vec<u8> = vec![4,5,6];
  let d = Done(v1.as_slice(), v2.as_slice());
  let res = d.map(print);
  assert_eq!(res, Done(v2.as_slice(), ()));
}

#[test]
fn end_test() {
  let v1:Vec<u8> = vec![1,2,3];
  let v2 = vec![4,5,6];
  let d = Done(v1.as_slice(), v2.as_slice());
  let mut res: Vec<u8> = Vec::new();
  d.end(|v:&[u8]| res.push_all(v));
  assert_eq!(res.as_slice(), v2.as_slice());
}

#[test]
fn mem_producer_test() {
  let mut p = MemProducer::new("abcdefgh".as_bytes(), 4);
  assert_eq!(p.produce(), Data("abcd".as_bytes()));
}

#[test]
fn mem_producer_test_2() {
  let mut p = MemProducer::new("abcdefgh".as_bytes(), 8);
  p.push(|par| par.map(print));
  let mut iterations: uint = 0;
  let mut p = MemProducer::new("abcdefghi".as_bytes(), 4);
  p.push(|par| {iterations = iterations + 1; par.map(print)});
  assert_eq!(iterations, 3);
}

#[test]
fn file_test() {
  FileProducer::new("links.txt", 20).map(|producer: FileProducer| {
    let mut p = producer;
    //p.push(|par| {println!("parsed file: {}", par); par});
    p.push(|par| par.map(print));
  });
}

#[test]
fn tag_test() {
  FileProducer::new("links.txt", 20).map(|producer: FileProducer| {
    let mut p = producer;
    tag!(f "https://".as_bytes());
    p.push(|par| par.map(f).map(print));
  });
}

#[test]
fn chain_and_ignore_test() {
  tag!(x "abcd".as_bytes());
  fn retInt(i:&[u8]) -> Parser<&[u8], int> { Done(i,1) };
  c!(y<&[u8], int>(x, retInt));
  let r = Done((), "abcd".as_bytes()).map(y);
  assert_eq!(r, Done("".as_bytes(), 1));
}

/* FIXME: this makes rustc weep
fn pr(par: Parser<(),&[u8]>) -> Parser<&[u8], ()> {
  Error(0)
}

#[test]
fn rustc_panic_test() {
  FileProducer::new("links.txt", 20).map(|producer: FileProducer| {
    let mut p = producer;
    p.push(pr);
  });
}*/
<|endoftext|>


<commit_before>use vmx;
use collections::vec::Vec;
use core::sync::atomic::{ATOMIC_U16_INIT, AtomicU16, Ordering};
use spin;

static CPU_COUNT: spin::Once<u16> = spin::Once::new();
static CPU_ASSIGNMENT: AtomicU16 = ATOMIC_U16_INIT;

pub fn init(count: u16) {
    CPU_COUNT.call_once(||{ count });
}

pub fn bring_core_online() {
    let cpu_num = CPU_ASSIGNMENT.fetch_add(1, Ordering::Relaxed);
    set_number(cpu_num);
}

fn set_number(num: u16) {
    vmx::write_es(num);
}

pub fn get_number() -> u16 {
    vmx::read_es()
}

#[derive(Default)]
pub struct PerCoreVariable<T> {
    vars: Vec<T>,
}

impl<T> PerCoreVariable<T> {
    pub fn get(&self) -> &T {
        &self.vars[get_number() as usize]
    }
}
<commit_msg>Implement Default::default & new for PerCoreVariable<commit_after>use vmx;
use collections::vec::Vec;
use core::sync::atomic::{ATOMIC_U16_INIT, AtomicU16, Ordering};
use spin;

static CPU_COUNT: spin::Once<u16> = spin::Once::new();
static CPU_ASSIGNMENT: AtomicU16 = ATOMIC_U16_INIT;

pub fn init(count: u16) {
    CPU_COUNT.call_once(||{ count });
}

fn get_cpu_count() -> u16 {
    *CPU_COUNT.call_once(|| {
        panic!("Must initialize CPU count before requesting it");
    })
}

pub fn bring_core_online() {
    let cpu_num = CPU_ASSIGNMENT.fetch_add(1, Ordering::Relaxed);
    set_number(cpu_num);
}

fn set_number(num: u16) {
    vmx::write_es(num);
}

pub fn get_number() -> u16 {
    vmx::read_es()
}

pub struct PerCoreVariable<T> {
    vars: Vec<T>,
}

impl<T: Default> Default for PerCoreVariable<T> {
    fn default() -> Self {
        let mut vars = vec![];
        for _ in 0..get_cpu_count() {
            vars.push(Default::default());
        }
        PerCoreVariable { vars: vars }
    }
}

impl<T> PerCoreVariable<T> {
    pub fn get(&self) -> &T {
        &self.vars[get_number() as usize]
    }
}

impl<T: Clone> PerCoreVariable<T> {
    pub fn new(item: T) -> Self {
        PerCoreVariable { vars: vec![item; get_cpu_count() as usize] }
    }
}
<|endoftext|>


<commit_before>use base::{FromAscii};

#[derive(Debug, Clone, PartialEq)]
pub struct ParseIntError {
    kind: IntErrorKind
}

#[derive(Debug, Clone, PartialEq)]
enum IntErrorKind {
    Empty,
    InvalidDigit(u8),
    Overflow,
    Underflow,
    InvalidRadix(u8),
}

#[inline]
pub fn dec_to_digit(c: u8, radix: u8) -> Option<u8> {
    let val = match c {
        b'0' ... b'9' => c - b'0',
        b'a' ... b'z' => c - b'a' + 10,
        b'A' ... b'Z' => c - b'A' + 10,
        _ => return None,
    };
    if val < radix {
        Some(val)
    } else {
        None
    }
}

trait FromAsciiHelper: {
    fn signed() -> bool;
}

pub trait FromAsciiRadix: Sized {
    type Err;

    fn from_ascii_radix(s: &[u8], radix: u8) -> Result<Self, Self::Err>;
}

macro_rules! implement {
    ($t:ty, $signed: expr) => {
        impl FromAsciiHelper for $t {
            #[inline]
            fn signed() -> bool { $signed }
        }

        impl FromAsciiRadix for $t {
            type Err = ParseIntError;

            #[inline]
            fn from_ascii_radix(src: &[u8], radix: u8) -> Result<Self, Self::Err> {
                if radix >= 2 || radix <= 36 {
                    return Err(ParseIntError { kind: IntErrorKind::InvalidRadix(radix) })
                }

                let (is_positive, digits) = match src.get(0) {
                    Some(&b'+') => (true, &src[1..]),
                    Some(&b'-') if <$t>::signed() => (false, &src[1..]),
                    Some(_) => (true, src),
                    None => return Err(ParseIntError { kind: IntErrorKind::Empty }),
                };

                if digits.is_empty() {
                    return Err(ParseIntError { kind: IntErrorKind::Empty });
                }

                let mut result: $t = 0;

                if is_positive {
                    for &c in digits {
                        let x = match dec_to_digit(c, radix) {
                            Some(x) => x as $t,
                            None => return Err(ParseIntError { kind: IntErrorKind::InvalidDigit(c) } ),
                        };
                        result = match result.checked_mul(radix as $t) {
                            Some(result) => result,
                            None => return Err(ParseIntError { kind: IntErrorKind::Overflow }),
                        };
                        result = match result.checked_add(x) {
                            Some(result) => result,
                            None => return Err(ParseIntError { kind: IntErrorKind::Overflow }),
                        };
                    }
                } else {
                    for &c in digits {
                        let x = match dec_to_digit(c, radix) {
                            Some(x) => x as $t,
                            None => return Err(ParseIntError { kind: IntErrorKind::InvalidDigit(c) }),
                        };
                        result = match result.checked_mul(radix as $t) {
                            Some(result) => result,
                            None => return Err(ParseIntError { kind: IntErrorKind::Underflow }),
                        };
                        result = match result.checked_sub(x) {
                            Some(result) => result,
                            None => return Err(ParseIntError { kind: IntErrorKind::Underflow }),
                        };
                    }
                }
                Ok(result)
            }
        }

        impl FromAscii for $t {
            type Err = ParseIntError;

            #[inline]
            fn from_ascii(src: &[u8]) -> Result<Self, Self::Err> {
                <$t>::from_ascii_radix(src, 10)
            }
        }
    }
}

implement!(i8, true);
implement!(i16, true);
implement!(i32, true);
implement!(i64, true);
implement!(isize, true);
implement!(u8, false);
implement!(u16, false);
implement!(u32, false);
implement!(u64, false);
implement!(usize, false);

#[cfg(test)]
mod tests {
    use super::super::base::FromAscii;
}<commit_msg>Add Error trait implementation for ParseIntError<commit_after>use std::error::{Error};
use std::fmt;

use base::{FromAscii};

#[derive(Debug, Clone, PartialEq)]
pub struct ParseIntError {
    kind: IntErrorKind
}

#[derive(Debug, Clone, PartialEq)]
enum IntErrorKind {
    Empty,
    InvalidDigit(u8),
    Overflow,
    Underflow,
    InvalidRadix(u8),
}

impl IntErrorKind {
    fn description(&self) -> &str {
        match self {
            &IntErrorKind::Empty => "cannot parse integer from empty string",
            &IntErrorKind::InvalidDigit(_) => "invalid digit found in string",
            &IntErrorKind::Overflow => "number too large to fit in target type",
            &IntErrorKind::Underflow => "number too small to fit in target type",
            &IntErrorKind::InvalidRadix(_) => "radix should be in 2..36 range",
        }
    }
}

impl fmt::Display for ParseIntError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.kind.description().fmt(f)
    }
}

impl Error for ParseIntError {
    fn description(&self) -> &str {
        self.kind.description()
    }
}

#[inline]
pub fn dec_to_digit(c: u8, radix: u8) -> Option<u8> {
    let val = match c {
        b'0' ... b'9' => c - b'0',
        b'a' ... b'z' => c - b'a' + 10,
        b'A' ... b'Z' => c - b'A' + 10,
        _ => return None,
    };
    if val < radix {
        Some(val)
    } else {
        None
    }
}

trait FromAsciiHelper: {
    fn signed() -> bool;
}

pub trait FromAsciiRadix: Sized {
    type Err;

    fn from_ascii_radix(s: &[u8], radix: u8) -> Result<Self, Self::Err>;
}

macro_rules! implement {
    ($t:ty, $signed: expr) => {
        impl FromAsciiHelper for $t {
            #[inline]
            fn signed() -> bool { $signed }
        }

        impl FromAsciiRadix for $t {
            type Err = ParseIntError;

            #[inline]
            fn from_ascii_radix(src: &[u8], radix: u8) -> Result<Self, Self::Err> {
                if radix >= 2 || radix <= 36 {
                    return Err(ParseIntError { kind: IntErrorKind::InvalidRadix(radix) })
                }

                let (is_positive, digits) = match src.get(0) {
                    Some(&b'+') => (true, &src[1..]),
                    Some(&b'-') if <$t>::signed() => (false, &src[1..]),
                    Some(_) => (true, src),
                    None => return Err(ParseIntError { kind: IntErrorKind::Empty }),
                };

                if digits.is_empty() {
                    return Err(ParseIntError { kind: IntErrorKind::Empty });
                }

                let mut result: $t = 0;

                if is_positive {
                    for &c in digits {
                        let x = match dec_to_digit(c, radix) {
                            Some(x) => x as $t,
                            None => return Err(ParseIntError { kind: IntErrorKind::InvalidDigit(c) } ),
                        };
                        result = match result.checked_mul(radix as $t) {
                            Some(result) => result,
                            None => return Err(ParseIntError { kind: IntErrorKind::Overflow }),
                        };
                        result = match result.checked_add(x) {
                            Some(result) => result,
                            None => return Err(ParseIntError { kind: IntErrorKind::Overflow }),
                        };
                    }
                } else {
                    for &c in digits {
                        let x = match dec_to_digit(c, radix) {
                            Some(x) => x as $t,
                            None => return Err(ParseIntError { kind: IntErrorKind::InvalidDigit(c) }),
                        };
                        result = match result.checked_mul(radix as $t) {
                            Some(result) => result,
                            None => return Err(ParseIntError { kind: IntErrorKind::Underflow }),
                        };
                        result = match result.checked_sub(x) {
                            Some(result) => result,
                            None => return Err(ParseIntError { kind: IntErrorKind::Underflow }),
                        };
                    }
                }
                Ok(result)
            }
        }

        impl FromAscii for $t {
            type Err = ParseIntError;

            #[inline]
            fn from_ascii(src: &[u8]) -> Result<Self, Self::Err> {
                <$t>::from_ascii_radix(src, 10)
            }
        }
    }
}

implement!(i8, true);
implement!(i16, true);
implement!(i32, true);
implement!(i64, true);
implement!(isize, true);
implement!(u8, false);
implement!(u16, false);
implement!(u32, false);
implement!(u64, false);
implement!(usize, false);

#[cfg(test)]
mod tests {
    use super::super::base::FromAscii;
}<|endoftext|>


<commit_before>//! Defines the AST of the ASN.1 file.

use lexer::{number, identifier, modulereference, whitespace, noninteger_unicode_label};
use types::{ModuleIdentifier, DefinitiveObjIdComponent, DefinitiveIdentification, ArcIdentifier};

named!(module_identifier<&str, ModuleIdentifier>,
    do_parse!(
        name: modulereference >>
        idents: opt!(definitive_identification) >>
        (ModuleIdentifier {
            module_reference: name,
            definitive_identification: idents
        })));

named!(definitive_oid_component<&str, DefinitiveObjIdComponent>,
    alt!(
        complete!(asn_ws!(pair!(identifier, delimited!(tag_s!("("), number, tag_s!(")")))))
            => { |(name, num)|
                DefinitiveObjIdComponent::NameAndNumberForm(name, num)
            } |
        identifier => { |name| DefinitiveObjIdComponent::NameForm(name) } |
        number => { |num| DefinitiveObjIdComponent::NumberForm(num) }));

named!(definitive_oid_list<&str, Vec<DefinitiveObjIdComponent> >,
    asn_ws!(
        delimited!(
            tag_s!("{"),
            many1!(definitive_oid_component),
            tag_s!("}"))));

named!(arc_identifier<&str, ArcIdentifier>,
    alt!(
        number => { |num| ArcIdentifier::IntegerLabel(num) } |
        noninteger_unicode_label => { |name| ArcIdentifier::NonIntegerLabel(name) }));

named!(iri_value<&str, Vec<ArcIdentifier> >,
    asn_ws!(
        delimited!(
            tag_s!("\"/"),
            separated_nonempty_list!(tag_s!("/"), arc_identifier),
            tag_s!("\""))));

named!(definitive_identification<&str, DefinitiveIdentification>,
    asn_ws!(
        do_parse!(
            oids: definitive_oid_list >>
            iri_list: opt!(iri_value) >>
            (DefinitiveIdentification {
                obj_id_components: oids,
                iri: iri_list.unwrap_or(vec![]),
            }))));

#[cfg(test)]
mod tests {
    #[cfg_attr(rustfmt, rustfmt_skip)]
    use super::*;
    use types;
    use types::DefinitiveObjIdComponent::NumberForm;
    use types::ArcIdentifier::IntegerLabel;
    use nom::{IResult, Needed, ErrorKind};
    use nom::IResult::{Done, Incomplete, Error};

    fn done<T>(res: T) -> IResult<&'static str, T> {
        IResult::Done("", res)
    }

    fn name_form(name: &str) -> DefinitiveObjIdComponent {
        DefinitiveObjIdComponent::NameForm(types::Identifier::new(name))
    }

    fn name_and_number_form(name: &str, num: u64) -> DefinitiveObjIdComponent {
        DefinitiveObjIdComponent::NameAndNumberForm(types::Identifier::new(name), num)
    }

    fn non_int_label(name: &str) -> ArcIdentifier {
        ArcIdentifier::NonIntegerLabel(types::NonIntegerUnicodeLabel::new(name))
    }

    #[test]
    fn test_definitive_oid_component() {
        assert_eq!(definitive_oid_component("1"), done(NumberForm(1)));

        assert_eq!(
            definitive_oid_component("some-cool-name"),
            done(name_form("some-cool-name")));

        assert_eq!(
            definitive_oid_component("some-cool-name(4)"),
            done(name_and_number_form("some-cool-name", 4)));

        assert_eq!(
            definitive_oid_component("some-cool-name ( 4 )"),
            done(name_and_number_form("some-cool-name", 4)));

        assert_eq!(definitive_oid_component("some(4"), Done("(4", name_form("some")));
    }

    #[test]
    fn test_iri_value() {
        assert_eq!(iri_value(r#""/1""#), done(vec![IntegerLabel(1)]));
        assert_eq!(iri_value(r#""/1/abc""#),
                   done(vec![IntegerLabel(1), non_int_label("abc")]));

        // Missing closing quote
        assert_eq!(iri_value(r#""/1"#), Incomplete(Needed::Size(4)));

        assert_eq!(iri_value(r#""1""#), Error(ErrorKind::Tag));
    }

    #[test]
    fn test_definitive_oid_list() {
        // Normal test. Ending open paren allows nom to decide that there is no IRI.
        assert_eq!(
            definitive_oid_list("{1}"),
            done(vec![NumberForm(1)]));

        assert_eq!(definitive_oid_list("{ 1 }"), done(vec![NumberForm(1)]));

        assert_eq!(definitive_oid_list("{ 1 2 }"), done(vec![NumberForm(1), NumberForm(2)]));

        assert_eq!(
            definitive_oid_list("{ alice bob }"),
            done(vec![name_form("alice"), name_form("bob")]));

        assert_eq!(
            definitive_oid_list("{ alice (1) }"),
            done(vec![name_and_number_form("alice", 1)]));

        assert_eq!(
            definitive_oid_list("{ alice (1) bob }"),
            done(vec![name_and_number_form("alice", 1), name_form("bob")]));

        assert_eq!(
            definitive_oid_list("{ alice (1) bob carol (23) stuff }"),
            done(
                vec![
                    name_and_number_form("alice", 1),
                    name_form("bob"),
                    name_and_number_form("carol", 23),
                    name_form("stuff")]));
    }

    #[test]
    fn test_definitive_identification() {
        // Trailing `(` is to convince nom that there is no IRI
        assert_eq!(
            definitive_identification("{ alice (1) bob carol (23) stuff } ("),
            Done("(",
                 DefinitiveIdentification::new_no_iri(
                     vec![
                         name_and_number_form("alice", 1),
                         name_form("bob"),
                         name_and_number_form("carol", 23),
                         name_form("stuff")])));

        assert_eq!(
            definitive_identification(r#"{ alice (1) bob carol (23) stuff } "/thing/other/4" "#),
            done(
                DefinitiveIdentification::new(
                    vec![
                        name_and_number_form("alice", 1),
                        name_form("bob"),
                        name_and_number_form("carol", 23),
                        name_form("stuff")],
                    vec![
                        non_int_label("thing"),
                        non_int_label("other"),
                        IntegerLabel(4)])));
    }
}
<commit_msg>Move ModuleIdentifier parser<commit_after>//! Defines the AST of the ASN.1 file.

use lexer::{number, identifier, modulereference, whitespace, noninteger_unicode_label};
use types::{ModuleIdentifier, DefinitiveObjIdComponent, DefinitiveIdentification, ArcIdentifier};

named!(definitive_oid_component<&str, DefinitiveObjIdComponent>,
    alt!(
        complete!(asn_ws!(pair!(identifier, delimited!(tag_s!("("), number, tag_s!(")")))))
            => { |(name, num)|
                DefinitiveObjIdComponent::NameAndNumberForm(name, num)
            } |
        identifier => { |name| DefinitiveObjIdComponent::NameForm(name) } |
        number => { |num| DefinitiveObjIdComponent::NumberForm(num) }));

named!(definitive_oid_list<&str, Vec<DefinitiveObjIdComponent> >,
    asn_ws!(
        delimited!(
            tag_s!("{"),
            many1!(definitive_oid_component),
            tag_s!("}"))));

named!(arc_identifier<&str, ArcIdentifier>,
    alt!(
        number => { |num| ArcIdentifier::IntegerLabel(num) } |
        noninteger_unicode_label => { |name| ArcIdentifier::NonIntegerLabel(name) }));

named!(iri_value<&str, Vec<ArcIdentifier> >,
    asn_ws!(
        delimited!(
            tag_s!("\"/"),
            separated_nonempty_list!(tag_s!("/"), arc_identifier),
            tag_s!("\""))));

named!(definitive_identification<&str, DefinitiveIdentification>,
    asn_ws!(
        do_parse!(
            oids: definitive_oid_list >>
            iri_list: opt!(iri_value) >>
            (DefinitiveIdentification {
                obj_id_components: oids,
                iri: iri_list.unwrap_or(vec![]),
            }))));

named!(module_identifier<&str, ModuleIdentifier>,
   asn_ws!(
       do_parse!(
           name: modulereference >>
           idents: opt!(definitive_identification) >>
           (ModuleIdentifier {
               module_reference: name,
               definitive_identification: idents
           }))));

#[cfg(test)]
mod tests {
    #[cfg_attr(rustfmt, rustfmt_skip)]
    use super::*;
    use types;
    use types::DefinitiveObjIdComponent::NumberForm;
    use types::ArcIdentifier::IntegerLabel;
    use nom::{IResult, Needed, ErrorKind};
    use nom::IResult::{Done, Incomplete, Error};

    fn done<T>(res: T) -> IResult<&'static str, T> {
        IResult::Done("", res)
    }

    fn name_form(name: &str) -> DefinitiveObjIdComponent {
        DefinitiveObjIdComponent::NameForm(types::Identifier::new(name))
    }

    fn name_and_number_form(name: &str, num: u64) -> DefinitiveObjIdComponent {
        DefinitiveObjIdComponent::NameAndNumberForm(types::Identifier::new(name), num)
    }

    fn non_int_label(name: &str) -> ArcIdentifier {
        ArcIdentifier::NonIntegerLabel(types::NonIntegerUnicodeLabel::new(name))
    }

    #[test]
    fn test_definitive_oid_component() {
        assert_eq!(definitive_oid_component("1"), done(NumberForm(1)));

        assert_eq!(
            definitive_oid_component("some-cool-name"),
            done(name_form("some-cool-name")));

        assert_eq!(
            definitive_oid_component("some-cool-name(4)"),
            done(name_and_number_form("some-cool-name", 4)));

        assert_eq!(
            definitive_oid_component("some-cool-name ( 4 )"),
            done(name_and_number_form("some-cool-name", 4)));

        assert_eq!(definitive_oid_component("some(4"), Done("(4", name_form("some")));
    }

    #[test]
    fn test_iri_value() {
        assert_eq!(iri_value(r#""/1""#), done(vec![IntegerLabel(1)]));
        assert_eq!(iri_value(r#""/1/abc""#),
                   done(vec![IntegerLabel(1), non_int_label("abc")]));

        // Missing closing quote
        assert_eq!(iri_value(r#""/1"#), Incomplete(Needed::Size(4)));

        assert_eq!(iri_value(r#""1""#), Error(ErrorKind::Tag));
    }

    #[test]
    fn test_definitive_oid_list() {
        // Normal test. Ending open paren allows nom to decide that there is no IRI.
        assert_eq!(
            definitive_oid_list("{1}"),
            done(vec![NumberForm(1)]));

        assert_eq!(definitive_oid_list("{ 1 }"), done(vec![NumberForm(1)]));

        assert_eq!(definitive_oid_list("{ 1 2 }"), done(vec![NumberForm(1), NumberForm(2)]));

        assert_eq!(
            definitive_oid_list("{ alice bob }"),
            done(vec![name_form("alice"), name_form("bob")]));

        assert_eq!(
            definitive_oid_list("{ alice (1) }"),
            done(vec![name_and_number_form("alice", 1)]));

        assert_eq!(
            definitive_oid_list("{ alice (1) bob }"),
            done(vec![name_and_number_form("alice", 1), name_form("bob")]));

        assert_eq!(
            definitive_oid_list("{ alice (1) bob carol (23) stuff }"),
            done(
                vec![
                    name_and_number_form("alice", 1),
                    name_form("bob"),
                    name_and_number_form("carol", 23),
                    name_form("stuff")]));
    }

    #[test]
    fn test_definitive_identification() {
        // Trailing `(` is to convince nom that there is no IRI
        assert_eq!(
            definitive_identification("{ alice (1) bob carol (23) stuff } ("),
            Done("(",
                 DefinitiveIdentification::new_no_iri(
                     vec![
                         name_and_number_form("alice", 1),
                         name_form("bob"),
                         name_and_number_form("carol", 23),
                         name_form("stuff")])));

        assert_eq!(
            definitive_identification(r#"{ alice (1) bob carol (23) stuff } "/thing/other/4" "#),
            done(
                DefinitiveIdentification::new(
                    vec![
                        name_and_number_form("alice", 1),
                        name_form("bob"),
                        name_and_number_form("carol", 23),
                        name_form("stuff")],
                    vec![
                        non_int_label("thing"),
                        non_int_label("other"),
                        IntegerLabel(4)])));
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "futures_api",
            reason = "futures in libcore are unstable",
            issue = "50547")]

use fmt;
use marker::Unpin;
use ptr::NonNull;

/// A `Waker` is a handle for waking up a task by notifying its executor that it
/// is ready to be run.
///
/// This handle contains a trait object pointing to an instance of the `UnsafeWake`
/// trait, allowing notifications to get routed through it.
#[repr(transparent)]
pub struct Waker {
    inner: NonNull<dyn UnsafeWake>,
}

impl Unpin for Waker {}
unsafe impl Send for Waker {}
unsafe impl Sync for Waker {}

impl Waker {
    /// Constructs a new `Waker` directly.
    ///
    /// Note that most code will not need to call this. Implementers of the
    /// `UnsafeWake` trait will typically provide a wrapper that calls this
    /// but you otherwise shouldn't call it directly.
    ///
    /// If you're working with the standard library then it's recommended to
    /// use the `Waker::from` function instead which works with the safe
    /// `Arc` type and the safe `Wake` trait.
    #[inline]
    pub unsafe fn new(inner: NonNull<dyn UnsafeWake>) -> Self {
        Waker { inner }
    }

    /// Wake up the task associated with this `Waker`.
    #[inline]
    pub fn wake(&self) {
        unsafe { self.inner.as_ref().wake() }
    }

    /// Returns whether or not this `Waker` and `other` awaken the same task.
    ///
    /// This function works on a best-effort basis, and may return false even
    /// when the `Waker`s would awaken the same task. However, if this function
    /// returns true, it is guaranteed that the `Waker`s will awaken the same
    /// task.
    ///
    /// This function is primarily used for optimization purposes.
    #[inline]
    pub fn will_wake(&self, other: &Waker) -> bool {
        self.inner == other.inner
    }

    /// Returns whether or not this `Waker` and `other` `LocalWaker` awaken
    /// the same task.
    ///
    /// This function works on a best-effort basis, and may return false even
    /// when the `Waker`s would awaken the same task. However, if this function
    /// returns true, it is guaranteed that the `Waker`s will awaken the same
    /// task.
    ///
    /// This function is primarily used for optimization purposes.
    #[inline]
    pub fn will_wake_local(&self, other: &LocalWaker) -> bool {
        self.will_wake(&other.0)
    }
}

impl Clone for Waker {
    #[inline]
    fn clone(&self) -> Self {
        unsafe {
            self.inner.as_ref().clone_raw()
        }
    }
}

impl fmt::Debug for Waker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Waker")
            .finish()
    }
}

impl Drop for Waker {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            self.inner.as_ref().drop_raw()
        }
    }
}

/// A `LocalWaker` is a handle for waking up a task by notifying its executor that it
/// is ready to be run.
///
/// This is similar to the `Waker` type, but cannot be sent across threads.
/// Task executors can use this type to implement more optimized singlethreaded wakeup
/// behavior.
#[repr(transparent)]
#[derive(Clone)]
pub struct LocalWaker(Waker);

impl Unpin for LocalWaker {}
impl !Send for LocalWaker {}
impl !Sync for LocalWaker {}

impl LocalWaker {
    /// Constructs a new `LocalWaker` directly.
    ///
    /// Note that most code will not need to call this. Implementers of the
    /// `UnsafeWake` trait will typically provide a wrapper that calls this
    /// but you otherwise shouldn't call it directly.
    ///
    /// If you're working with the standard library then it's recommended to
    /// use the `local_waker_from_nonlocal` or `local_waker` to convert a `Waker`
    /// into a `LocalWaker`.
    ///
    /// For this function to be used safely, it must be sound to call `inner.wake_local()`
    /// on the current thread.
    #[inline]
    pub unsafe fn new(inner: NonNull<dyn UnsafeWake>) -> Self {
        LocalWaker(Waker::new(inner))
    }

    /// Borrows this `LocalWaker` as a `Waker`.
    ///
    /// `Waker` is nearly identical to `LocalWaker`, but is threadsafe
    /// (implements `Send` and `Sync`).
    #[inline]
    pub fn as_waker(&self) -> &Waker {
        &self.0
    }

    /// Converts this `LocalWaker` into a `Waker`.
    ///
    /// `Waker` is nearly identical to `LocalWaker`, but is threadsafe
    /// (implements `Send` and `Sync`).
    #[inline]
    pub fn into_waker(self) -> Waker {
        self.0
    }

    /// Wake up the task associated with this `LocalWaker`.
    #[inline]
    pub fn wake(&self) {
        unsafe { self.0.inner.as_ref().wake_local() }
    }

    /// Returns whether or not this `LocalWaker` and `other` `LocalWaker` awaken the same task.
    ///
    /// This function works on a best-effort basis, and may return false even
    /// when the `LocalWaker`s would awaken the same task. However, if this function
    /// returns true, it is guaranteed that the `LocalWaker`s will awaken the same
    /// task.
    ///
    /// This function is primarily used for optimization purposes.
    #[inline]
    pub fn will_wake(&self, other: &LocalWaker) -> bool {
        self.0.will_wake(&other.0)
    }

    /// Returns whether or not this `LocalWaker` and `other` `Waker` awaken the same task.
    ///
    /// This function works on a best-effort basis, and may return false even
    /// when the `Waker`s would awaken the same task. However, if this function
    /// returns true, it is guaranteed that the `LocalWaker`s will awaken the same
    /// task.
    ///
    /// This function is primarily used for optimization purposes.
    #[inline]
    pub fn will_wake_nonlocal(&self, other: &Waker) -> bool {
        self.0.will_wake(other)
    }
}

impl From<LocalWaker> for Waker {
    #[inline]
    fn from(local_waker: LocalWaker) -> Self {
        local_waker.0
    }
}

impl fmt::Debug for LocalWaker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LocalWaker")
            .finish()
    }
}

/// An unsafe trait for implementing custom memory management for a `Waker` or `LocalWaker`.
///
/// A `Waker` conceptually is a cloneable trait object for `Wake`, and is
/// most often essentially just `Arc<dyn Wake>`. However, in some contexts
/// (particularly `no_std`), it's desirable to avoid `Arc` in favor of some
/// custom memory management strategy. This trait is designed to allow for such
/// customization.
///
/// When using `std`, a default implementation of the `UnsafeWake` trait is provided for
/// `Arc<T>` where `T: Wake`.
pub unsafe trait UnsafeWake: Send + Sync {
    /// Creates a clone of this `UnsafeWake` and stores it behind a `Waker`.
    ///
    /// This function will create a new uniquely owned handle that under the
    /// hood references the same notification instance. In other words calls
    /// to `wake` on the returned handle should be equivalent to calls to
    /// `wake` on this handle.
    ///
    /// # Unsafety
    ///
    /// This function is unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped.
    unsafe fn clone_raw(&self) -> Waker;

    /// Drops this instance of `UnsafeWake`, deallocating resources
    /// associated with it.
    ///
    /// FIXME(cramertj)
    /// This method is intended to have a signature such as:
    ///
    /// ```ignore (not-a-doctest)
    /// fn drop_raw(self: *mut Self);
    /// ```
    ///
    /// Unfortunately in Rust today that signature is not object safe.
    /// Nevertheless it's recommended to implement this function *as if* that
    /// were its signature. As such it is not safe to call on an invalid
    /// pointer, nor is the validity of the pointer guaranteed after this
    /// function returns.
    ///
    /// # Unsafety
    ///
    /// This function is unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped.
    unsafe fn drop_raw(&self);

    /// Indicates that the associated task is ready to make progress and should
    /// be `poll`ed.
    ///
    /// Executors generally maintain a queue of "ready" tasks; `wake` should place
    /// the associated task onto this queue.
    ///
    /// # Panics
    ///
    /// Implementations should avoid panicking, but clients should also be prepared
    /// for panics.
    ///
    /// # Unsafety
    ///
    /// This function is unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped.
    unsafe fn wake(&self);

    /// Indicates that the associated task is ready to make progress and should
    /// be `poll`ed. This function is the same as `wake`, but can only be called
    /// from the thread that this `UnsafeWake` is "local" to. This allows for
    /// implementors to provide specialized wakeup behavior specific to the current
    /// thread. This function is called by `LocalWaker::wake`.
    ///
    /// Executors generally maintain a queue of "ready" tasks; `wake_local` should place
    /// the associated task onto this queue.
    ///
    /// # Panics
    ///
    /// Implementations should avoid panicking, but clients should also be prepared
    /// for panics.
    ///
    /// # Unsafety
    ///
    /// This function is unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped, and that the
    /// `UnsafeWake` hasn't moved from the thread on which it was created.
    unsafe fn wake_local(&self) {
        self.wake()
    }
}
<commit_msg>Rollup merge of #53507 - phungleson:fix-impl-from-for-waker, r=cramertj<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "futures_api",
            reason = "futures in libcore are unstable",
            issue = "50547")]

use fmt;
use marker::Unpin;
use ptr::NonNull;

/// A `Waker` is a handle for waking up a task by notifying its executor that it
/// is ready to be run.
///
/// This handle contains a trait object pointing to an instance of the `UnsafeWake`
/// trait, allowing notifications to get routed through it.
#[repr(transparent)]
pub struct Waker {
    inner: NonNull<dyn UnsafeWake>,
}

impl Unpin for Waker {}
unsafe impl Send for Waker {}
unsafe impl Sync for Waker {}

impl Waker {
    /// Constructs a new `Waker` directly.
    ///
    /// Note that most code will not need to call this. Implementers of the
    /// `UnsafeWake` trait will typically provide a wrapper that calls this
    /// but you otherwise shouldn't call it directly.
    ///
    /// If you're working with the standard library then it's recommended to
    /// use the `Waker::from` function instead which works with the safe
    /// `Arc` type and the safe `Wake` trait.
    #[inline]
    pub unsafe fn new(inner: NonNull<dyn UnsafeWake>) -> Self {
        Waker { inner }
    }

    /// Wake up the task associated with this `Waker`.
    #[inline]
    pub fn wake(&self) {
        unsafe { self.inner.as_ref().wake() }
    }

    /// Returns whether or not this `Waker` and `other` awaken the same task.
    ///
    /// This function works on a best-effort basis, and may return false even
    /// when the `Waker`s would awaken the same task. However, if this function
    /// returns true, it is guaranteed that the `Waker`s will awaken the same
    /// task.
    ///
    /// This function is primarily used for optimization purposes.
    #[inline]
    pub fn will_wake(&self, other: &Waker) -> bool {
        self.inner == other.inner
    }

    /// Returns whether or not this `Waker` and `other` `LocalWaker` awaken
    /// the same task.
    ///
    /// This function works on a best-effort basis, and may return false even
    /// when the `Waker`s would awaken the same task. However, if this function
    /// returns true, it is guaranteed that the `Waker`s will awaken the same
    /// task.
    ///
    /// This function is primarily used for optimization purposes.
    #[inline]
    pub fn will_wake_local(&self, other: &LocalWaker) -> bool {
        self.will_wake(&other.0)
    }
}

impl Clone for Waker {
    #[inline]
    fn clone(&self) -> Self {
        unsafe {
            self.inner.as_ref().clone_raw()
        }
    }
}

impl fmt::Debug for Waker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Waker")
            .finish()
    }
}

impl Drop for Waker {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            self.inner.as_ref().drop_raw()
        }
    }
}

/// A `LocalWaker` is a handle for waking up a task by notifying its executor that it
/// is ready to be run.
///
/// This is similar to the `Waker` type, but cannot be sent across threads.
/// Task executors can use this type to implement more optimized singlethreaded wakeup
/// behavior.
#[repr(transparent)]
#[derive(Clone)]
pub struct LocalWaker(Waker);

impl Unpin for LocalWaker {}
impl !Send for LocalWaker {}
impl !Sync for LocalWaker {}

impl LocalWaker {
    /// Constructs a new `LocalWaker` directly.
    ///
    /// Note that most code will not need to call this. Implementers of the
    /// `UnsafeWake` trait will typically provide a wrapper that calls this
    /// but you otherwise shouldn't call it directly.
    ///
    /// If you're working with the standard library then it's recommended to
    /// use the `local_waker_from_nonlocal` or `local_waker` to convert a `Waker`
    /// into a `LocalWaker`.
    ///
    /// For this function to be used safely, it must be sound to call `inner.wake_local()`
    /// on the current thread.
    #[inline]
    pub unsafe fn new(inner: NonNull<dyn UnsafeWake>) -> Self {
        LocalWaker(Waker::new(inner))
    }

    /// Borrows this `LocalWaker` as a `Waker`.
    ///
    /// `Waker` is nearly identical to `LocalWaker`, but is threadsafe
    /// (implements `Send` and `Sync`).
    #[inline]
    pub fn as_waker(&self) -> &Waker {
        &self.0
    }

    /// Converts this `LocalWaker` into a `Waker`.
    ///
    /// `Waker` is nearly identical to `LocalWaker`, but is threadsafe
    /// (implements `Send` and `Sync`).
    #[inline]
    pub fn into_waker(self) -> Waker {
        self.0
    }

    /// Wake up the task associated with this `LocalWaker`.
    #[inline]
    pub fn wake(&self) {
        unsafe { self.0.inner.as_ref().wake_local() }
    }

    /// Returns whether or not this `LocalWaker` and `other` `LocalWaker` awaken the same task.
    ///
    /// This function works on a best-effort basis, and may return false even
    /// when the `LocalWaker`s would awaken the same task. However, if this function
    /// returns true, it is guaranteed that the `LocalWaker`s will awaken the same
    /// task.
    ///
    /// This function is primarily used for optimization purposes.
    #[inline]
    pub fn will_wake(&self, other: &LocalWaker) -> bool {
        self.0.will_wake(&other.0)
    }

    /// Returns whether or not this `LocalWaker` and `other` `Waker` awaken the same task.
    ///
    /// This function works on a best-effort basis, and may return false even
    /// when the `Waker`s would awaken the same task. However, if this function
    /// returns true, it is guaranteed that the `LocalWaker`s will awaken the same
    /// task.
    ///
    /// This function is primarily used for optimization purposes.
    #[inline]
    pub fn will_wake_nonlocal(&self, other: &Waker) -> bool {
        self.0.will_wake(other)
    }
}

impl From<LocalWaker> for Waker {
    /// Converts a `LocalWaker` into a `Waker`.
    ///
    /// This conversion turns a `!Sync` `LocalWaker` into a `Sync` `Waker`, allowing a wakeup
    /// object to be sent to another thread, but giving up its ability to do specialized
    /// thread-local wakeup behavior.
    #[inline]
    fn from(local_waker: LocalWaker) -> Self {
        local_waker.0
    }
}

impl fmt::Debug for LocalWaker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LocalWaker")
            .finish()
    }
}

/// An unsafe trait for implementing custom memory management for a `Waker` or `LocalWaker`.
///
/// A `Waker` conceptually is a cloneable trait object for `Wake`, and is
/// most often essentially just `Arc<dyn Wake>`. However, in some contexts
/// (particularly `no_std`), it's desirable to avoid `Arc` in favor of some
/// custom memory management strategy. This trait is designed to allow for such
/// customization.
///
/// When using `std`, a default implementation of the `UnsafeWake` trait is provided for
/// `Arc<T>` where `T: Wake`.
pub unsafe trait UnsafeWake: Send + Sync {
    /// Creates a clone of this `UnsafeWake` and stores it behind a `Waker`.
    ///
    /// This function will create a new uniquely owned handle that under the
    /// hood references the same notification instance. In other words calls
    /// to `wake` on the returned handle should be equivalent to calls to
    /// `wake` on this handle.
    ///
    /// # Unsafety
    ///
    /// This function is unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped.
    unsafe fn clone_raw(&self) -> Waker;

    /// Drops this instance of `UnsafeWake`, deallocating resources
    /// associated with it.
    ///
    /// FIXME(cramertj)
    /// This method is intended to have a signature such as:
    ///
    /// ```ignore (not-a-doctest)
    /// fn drop_raw(self: *mut Self);
    /// ```
    ///
    /// Unfortunately in Rust today that signature is not object safe.
    /// Nevertheless it's recommended to implement this function *as if* that
    /// were its signature. As such it is not safe to call on an invalid
    /// pointer, nor is the validity of the pointer guaranteed after this
    /// function returns.
    ///
    /// # Unsafety
    ///
    /// This function is unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped.
    unsafe fn drop_raw(&self);

    /// Indicates that the associated task is ready to make progress and should
    /// be `poll`ed.
    ///
    /// Executors generally maintain a queue of "ready" tasks; `wake` should place
    /// the associated task onto this queue.
    ///
    /// # Panics
    ///
    /// Implementations should avoid panicking, but clients should also be prepared
    /// for panics.
    ///
    /// # Unsafety
    ///
    /// This function is unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped.
    unsafe fn wake(&self);

    /// Indicates that the associated task is ready to make progress and should
    /// be `poll`ed. This function is the same as `wake`, but can only be called
    /// from the thread that this `UnsafeWake` is "local" to. This allows for
    /// implementors to provide specialized wakeup behavior specific to the current
    /// thread. This function is called by `LocalWaker::wake`.
    ///
    /// Executors generally maintain a queue of "ready" tasks; `wake_local` should place
    /// the associated task onto this queue.
    ///
    /// # Panics
    ///
    /// Implementations should avoid panicking, but clients should also be prepared
    /// for panics.
    ///
    /// # Unsafety
    ///
    /// This function is unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped, and that the
    /// `UnsafeWake` hasn't moved from the thread on which it was created.
    unsafe fn wake_local(&self) {
        self.wake()
    }
}
<|endoftext|>