<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_tcp_server;
//! extern crate rand;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use json_tcp_server::Server;
//! use std::net::SocketAddr;
//! use std::str::FromStr;
//!
//! 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(&SocketAddr::from_str("0.0.0.0:9993").unwrap(), &Arc::new(io)).unwrap();
//!     ::std::thread::spawn(move || server.run());
//! }
//! ```

extern crate jsonrpc_core;
#[macro_use] extern crate log;
#[macro_use] extern crate lazy_static;
extern crate env_logger;
extern crate slab;
extern crate mio;
extern crate bytes;

#[cfg(test)]
extern crate rand;

mod validator;
#[cfg(test)]
pub mod tests;

use mio::*;
use mio::tcp::*;
use bytes::{Buf, ByteBuf, MutByteBuf};
use std::io;
use jsonrpc_core::IoHandler;
use std::sync::*;
use std::sync::atomic::*;
use std::collections::VecDeque;
use std::env;
use log::LogLevelFilter;
use env_logger::LogBuilder;
use std::net::SocketAddr;

lazy_static! {
	static ref LOG_DUMMY: bool = {
		let mut builder = LogBuilder::new();
		builder.filter(None, LogLevelFilter::Info);

		if let Ok(log) = env::var("RUST_LOG") {
			builder.parse(&log);
		}

		if let Ok(_) = builder.init() {
			println!("logger initialized");
		}
		true
	};
}

/// Intialize log with default settings
pub fn init_log() {
    let _ = *LOG_DUMMY;
}

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

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

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

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

    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);
            }
            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: TcpListener,
    connections: Slab<SocketConnection>,
    io_handler: Arc<IoHandler>,
	tokens: VecDeque<Token>,
}

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

#[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: &SocketAddr, 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.clone(),
        })
    }

    /// 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(())
    }
}

// listener (RpcServer.socket) is never used except initializer, but have to be stored inside RpcServer and is not `Sync`
unsafe impl Sync for RpcServer { }

impl Drop for Server {
    fn drop(&mut self) {
        self.stop().unwrap_or_else(|_| {}); // ignore error - can be stopped already
    }
}

impl RpcServer {
    /// start ipc rpc server (blocking)
    pub fn start(addr: &SocketAddr, io_handler: &Arc<IoHandler>) -> Result<(RpcServer, EventLoop<RpcServer>), Error> {
        let mut event_loop = try!(EventLoop::new());
        let socket = try!(TcpListener::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(),
			tokens: VecDeque::new(),
        };
        Ok((server, event_loop))
    }

    fn accept(&mut self, event_loop: &mut EventLoop<RpcServer>) -> io::Result<()> {
        let (stream, addr) = self.socket.accept().unwrap().unwrap();
        let connection = SocketConnection::new(stream, addr.clone());
        if self.connections.count() >= MAX_CONCURRENT_CONNECTIONS {
            // max connections
            return Ok(());
        }
        let token = self.connections.insert(connection).ok().expect("fatal: Could not add connection to slab (memory issue?)");
		self.tokens.push_back(token);

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

        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]
    }

    fn drop_connection(&mut self, tok: Token) {
        trace!(target: "ipc", "Dropping connection {:?}", tok);
        self.connections.remove(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_hup() {
            match token {
                SERVER => { trace!(target: "ipc", "Server hup"); },
                other_token => {
                    self.drop_connection(other_token)
                }
            }
        }

        if events.is_writable() {
            match token {
                SERVER => { },
                _ => self.connection_writable(event_loop, token).unwrap_or_else(|_| {}), // todo: disqualify connection from list on error
            };
        }
    }
}
<commit_msg>mark unused (so far) fields<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_tcp_server;
//! extern crate rand;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use json_tcp_server::Server;
//! use std::net::SocketAddr;
//! use std::str::FromStr;
//!
//! 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(&SocketAddr::from_str("0.0.0.0:9993").unwrap(), &Arc::new(io)).unwrap();
//!     ::std::thread::spawn(move || server.run());
//! }
//! ```

extern crate jsonrpc_core;
#[macro_use] extern crate log;
#[macro_use] extern crate lazy_static;
extern crate env_logger;
extern crate slab;
extern crate mio;
extern crate bytes;

#[cfg(test)]
extern crate rand;

mod validator;
#[cfg(test)]
pub mod tests;

use mio::*;
use mio::tcp::*;
use bytes::{Buf, ByteBuf, MutByteBuf};
use std::io;
use jsonrpc_core::IoHandler;
use std::sync::*;
use std::sync::atomic::*;
use std::collections::VecDeque;
use std::env;
use log::LogLevelFilter;
use env_logger::LogBuilder;
use std::net::SocketAddr;

lazy_static! {
	static ref LOG_DUMMY: bool = {
		let mut builder = LogBuilder::new();
		builder.filter(None, LogLevelFilter::Info);

		if let Ok(log) = env::var("RUST_LOG") {
			builder.parse(&log);
		}

		if let Ok(_) = builder.init() {
			println!("logger initialized");
		}
		true
	};
}

/// Intialize log with default settings
pub fn init_log() {
    let _ = *LOG_DUMMY;
}

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

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

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

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

    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);
            }
            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: TcpListener,
    connections: Slab<SocketConnection>,
    io_handler: Arc<IoHandler>,
	tokens: VecDeque<Token>,
}

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

#[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: &SocketAddr, 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.clone(),
        })
    }

    /// 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(())
    }
}

// listener (RpcServer.socket) is never used except initializer, but have to be stored inside RpcServer and is not `Sync`
unsafe impl Sync for RpcServer { }

impl Drop for Server {
    fn drop(&mut self) {
        self.stop().unwrap_or_else(|_| {}); // ignore error - can be stopped already
    }
}

impl RpcServer {
    /// start ipc rpc server (blocking)
    pub fn start(addr: &SocketAddr, io_handler: &Arc<IoHandler>) -> Result<(RpcServer, EventLoop<RpcServer>), Error> {
        let mut event_loop = try!(EventLoop::new());
        let socket = try!(TcpListener::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(),
			tokens: VecDeque::new(),
        };
        Ok((server, event_loop))
    }

    fn accept(&mut self, event_loop: &mut EventLoop<RpcServer>) -> io::Result<()> {
        let (stream, addr) = self.socket.accept().unwrap().unwrap();
        let connection = SocketConnection::new(stream, addr.clone());
        if self.connections.count() >= MAX_CONCURRENT_CONNECTIONS {
            // max connections
            return Ok(());
        }
        let token = self.connections.insert(connection).ok().expect("fatal: Could not add connection to slab (memory issue?)");
		self.tokens.push_back(token);

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

        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]
    }

    fn drop_connection(&mut self, tok: Token) {
        trace!(target: "ipc", "Dropping connection {:?}", tok);
        self.connections.remove(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_hup() {
            match token {
                SERVER => { trace!(target: "ipc", "Server hup"); },
                other_token => {
                    self.drop_connection(other_token)
                }
            }
        }

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


<commit_before>//! Providing the features between "full" and "derive" of syn.
//!
//! This crate provides the following two unique data structures.
//!
//! * [`syn_mid::ItemFn`] -- A function whose body is not parsed.
//!
//!   ```text
//!   fn process(n: usize) -> Result<()> { ... }
//!   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^     ^
//!   ```
//!
//! * [`syn_mid::Block`] -- A block whose body is not parsed.
//!
//!   ```text
//!   { ... }
//!   ^     ^
//!   ```
//!
//! Other data structures are the same as data structures of [syn]. These are defined in this crate
//! because they cannot be used in [syn] without "full" feature.
//!
//! ## Optional features
//!
//! syn-mid in the default features aims to provide the features between "full"
//! and "derive" of [syn].
//!
//! * **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
//!   types.
//!
//! [`syn_mid::ItemFn`]: struct.ItemFn.html
//! [`syn_mid::Block`]: struct.Block.html
//! [syn]: https://github.com/dtolnay/syn
//!

#![doc(html_root_url = "https://docs.rs/syn-mid/0.2.0")]
#![deny(unsafe_code)]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        renamed_and_removed_lints,
        redundant_field_names, // Rust 1.17+ => remove
        const_static_lifetime, // Rust 1.17+ => remove
        deprecated_cfg_attr, // Rust 1.30+ => remove
        map_clone,
        large_enum_variant
    )
)]

// Many of the code contained in this crate are copies from https://github.com/dtolnay/syn.

extern crate proc_macro2;
extern crate quote;
#[allow(unused_imports)]
#[macro_use]
extern crate syn;

#[macro_use]
mod macros;

mod arg;
mod pat;
mod path;
mod print;

pub use self::arg::*;
pub use self::pat::*;

use proc_macro2::TokenStream;
use syn::punctuated::Punctuated;
use syn::{token, Abi, Attribute, Generics, Ident, ReturnType, Visibility};

ast_struct! {
    /// A braced block containing Rust statements.
    pub struct Block {
        pub brace_token: token::Brace,
        /// Statements in a block
        pub stmts: TokenStream,
    }
}

ast_struct! {
    /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
    /// }`.
    pub struct ItemFn {
        pub attrs: Vec<Attribute>,
        pub vis: Visibility,
        pub constness: Option<Token![const]>,
        pub unsafety: Option<Token![unsafe]>,
        pub asyncness: Option<Token![async]>,
        pub abi: Option<Abi>,
        pub ident: Ident,
        pub fn_token: Token![fn],
        pub generics: Generics,
        pub paren_token: token::Paren,
        pub inputs: Punctuated<FnArg, Token![,]>,
        pub variadic: Option<Token![...]>,
        pub output: ReturnType,
        pub block: Block,
    }
}

mod parsing {
    use syn::parse::{Parse, ParseStream, Result};
    use syn::{Abi, Attribute, Generics, Ident, ReturnType, Visibility, WhereClause};

    use super::{Block, FnArg, ItemFn};

    impl Parse for ItemFn {
        fn parse(input: ParseStream) -> Result<Self> {
            let outer_attrs = input.call(Attribute::parse_outer)?;
            let vis: Visibility = input.parse()?;
            let constness: Option<Token![const]> = input.parse()?;
            let unsafety: Option<Token![unsafe]> = input.parse()?;
            let asyncness: Option<Token![async]> = input.parse()?;
            let abi: Option<Abi> = input.parse()?;
            let fn_token: Token![fn] = input.parse()?;
            let ident: Ident = input.parse()?;
            let generics: Generics = input.parse()?;

            let content;
            let paren_token = parenthesized!(content in input);
            let inputs = content.parse_terminated(FnArg::parse)?;

            let output: ReturnType = input.parse()?;
            let where_clause: Option<WhereClause> = input.parse()?;

            let content;
            let brace_token = braced!(content in input);
            let stmts = content.parse()?;

            Ok(ItemFn {
                attrs: outer_attrs,
                vis: vis,
                constness: constness,
                unsafety: unsafety,
                asyncness: asyncness,
                abi: abi,
                ident: ident,
                fn_token: fn_token,
                paren_token: paren_token,
                inputs: inputs,
                output: output,
                variadic: None,
                generics: Generics {
                    where_clause: where_clause,
                    ..generics
                },
                block: Block {
                    brace_token: brace_token,
                    stmts: stmts,
                },
            })
        }
    }
}

mod printing {
    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};

    use super::*;

    impl ToTokens for Block {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.stmts.clone());
            });
        }
    }

    impl ToTokens for ItemFn {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            self.constness.to_tokens(tokens);
            self.unsafety.to_tokens(tokens);
            self.asyncness.to_tokens(tokens);
            self.abi.to_tokens(tokens);
            self.fn_token.to_tokens(tokens);
            self.ident.to_tokens(tokens);
            self.generics.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                self.inputs.to_tokens(tokens);
                if self.variadic.is_some() && !self.inputs.empty_or_trailing() {
                    <Token![,]>::default().to_tokens(tokens);
                }
                self.variadic.to_tokens(tokens);
            });
            self.output.to_tokens(tokens);
            self.generics.where_clause.to_tokens(tokens);
            self.block.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.block.stmts.clone());
            });
        }
    }
}
<commit_msg>Remove variadic field from ItemFn<commit_after>//! Providing the features between "full" and "derive" of syn.
//!
//! This crate provides the following two unique data structures.
//!
//! * [`syn_mid::ItemFn`] -- A function whose body is not parsed.
//!
//!   ```text
//!   fn process(n: usize) -> Result<()> { ... }
//!   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^     ^
//!   ```
//!
//! * [`syn_mid::Block`] -- A block whose body is not parsed.
//!
//!   ```text
//!   { ... }
//!   ^     ^
//!   ```
//!
//! Other data structures are the same as data structures of [syn]. These are defined in this crate
//! because they cannot be used in [syn] without "full" feature.
//!
//! ## Optional features
//!
//! syn-mid in the default features aims to provide the features between "full"
//! and "derive" of [syn].
//!
//! * **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
//!   types.
//!
//! [`syn_mid::ItemFn`]: struct.ItemFn.html
//! [`syn_mid::Block`]: struct.Block.html
//! [syn]: https://github.com/dtolnay/syn
//!

#![doc(html_root_url = "https://docs.rs/syn-mid/0.2.0")]
#![deny(unsafe_code)]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        renamed_and_removed_lints,
        redundant_field_names, // Rust 1.17+ => remove
        const_static_lifetime, // Rust 1.17+ => remove
        deprecated_cfg_attr, // Rust 1.30+ => remove
        map_clone,
        large_enum_variant
    )
)]

// Many of the code contained in this crate are copies from https://github.com/dtolnay/syn.

extern crate proc_macro2;
extern crate quote;
#[allow(unused_imports)]
#[macro_use]
extern crate syn;

#[macro_use]
mod macros;

mod arg;
mod pat;
mod path;
mod print;

pub use self::arg::*;
pub use self::pat::*;

use proc_macro2::TokenStream;
use syn::punctuated::Punctuated;
use syn::{token, Abi, Attribute, Generics, Ident, ReturnType, Visibility};

ast_struct! {
    /// A braced block containing Rust statements.
    pub struct Block {
        pub brace_token: token::Brace,
        /// Statements in a block
        pub stmts: TokenStream,
    }
}

ast_struct! {
    /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
    /// }`.
    pub struct ItemFn {
        pub attrs: Vec<Attribute>,
        pub vis: Visibility,
        pub constness: Option<Token![const]>,
        pub unsafety: Option<Token![unsafe]>,
        pub asyncness: Option<Token![async]>,
        pub abi: Option<Abi>,
        pub ident: Ident,
        pub fn_token: Token![fn],
        pub generics: Generics,
        pub paren_token: token::Paren,
        pub inputs: Punctuated<FnArg, Token![,]>,
        pub output: ReturnType,
        pub block: Block,
    }
}

mod parsing {
    use syn::parse::{Parse, ParseStream, Result};
    use syn::{Abi, Attribute, Generics, Ident, ReturnType, Visibility, WhereClause};

    use super::{Block, FnArg, ItemFn};

    impl Parse for ItemFn {
        fn parse(input: ParseStream) -> Result<Self> {
            let outer_attrs = input.call(Attribute::parse_outer)?;
            let vis: Visibility = input.parse()?;
            let constness: Option<Token![const]> = input.parse()?;
            let unsafety: Option<Token![unsafe]> = input.parse()?;
            let asyncness: Option<Token![async]> = input.parse()?;
            let abi: Option<Abi> = input.parse()?;
            let fn_token: Token![fn] = input.parse()?;
            let ident: Ident = input.parse()?;
            let generics: Generics = input.parse()?;

            let content;
            let paren_token = parenthesized!(content in input);
            let inputs = content.parse_terminated(FnArg::parse)?;

            let output: ReturnType = input.parse()?;
            let where_clause: Option<WhereClause> = input.parse()?;

            let content;
            let brace_token = braced!(content in input);
            let stmts = content.parse()?;

            Ok(ItemFn {
                attrs: outer_attrs,
                vis: vis,
                constness: constness,
                unsafety: unsafety,
                asyncness: asyncness,
                abi: abi,
                ident: ident,
                fn_token: fn_token,
                paren_token: paren_token,
                inputs: inputs,
                output: output,
                generics: Generics {
                    where_clause: where_clause,
                    ..generics
                },
                block: Block {
                    brace_token: brace_token,
                    stmts: stmts,
                },
            })
        }
    }
}

mod printing {
    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};

    use super::*;

    impl ToTokens for Block {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.stmts.clone());
            });
        }
    }

    impl ToTokens for ItemFn {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            self.constness.to_tokens(tokens);
            self.unsafety.to_tokens(tokens);
            self.asyncness.to_tokens(tokens);
            self.abi.to_tokens(tokens);
            self.fn_token.to_tokens(tokens);
            self.ident.to_tokens(tokens);
            self.generics.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                self.inputs.to_tokens(tokens);
            });
            self.output.to_tokens(tokens);
            self.generics.where_clause.to_tokens(tokens);
            self.block.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.block.stmts.clone());
            });
        }
    }
}
<|endoftext|>


<commit_before>//! This crate is a Rust port of Google's high-performance [SwissTable] hash
//! map, adapted to make it a drop-in replacement for Rust's standard `HashMap`
//! and `HashSet` types.
//!
//! The original C++ version of [SwissTable] can be found [here], and this
//! [CppCon talk] gives an overview of how the algorithm works.
//!
//! [SwissTable]: https://abseil.io/blog/20180927-swisstables
//! [here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h
//! [CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4

#![no_std]
#![cfg_attr(
    feature = "nightly",
    feature(
        alloc_layout_extra,
        allocator_api,
        ptr_offset_from,
        test,
        core_intrinsics,
        dropck_eyepatch,
        cfg_doctest,
    )
)]
#![allow(
    clippy::doc_markdown,
    clippy::module_name_repetitions,
    clippy::must_use_candidate
)]
#![warn(missing_docs)]
#![warn(rust_2018_idioms)]

#[cfg(test)]
#[macro_use]
extern crate std;

#[cfg(has_extern_crate_alloc)]
#[cfg_attr(test, macro_use)]
extern crate alloc;
#[cfg(not(has_extern_crate_alloc))]
extern crate std as alloc;

#[cfg(feature = "nightly")]
#[cfg(doctest)]
doc_comment::doctest!("../README.md");

#[macro_use]
mod macros;

#[cfg(feature = "raw")]
/// Experimental and unsafe `RawTable` API. This module is only available if the
/// `raw` feature is enabled.
pub mod raw {
    // The RawTable API is still experimental and is not properly documented yet.
    #[allow(missing_docs)]
    #[path = "mod.rs"]
    mod inner;
    pub use inner::*;

    #[cfg(feature = "rayon")]
    pub mod rayon {
        pub use crate::external_trait_impls::rayon::raw::*;
    }
}
#[cfg(not(feature = "raw"))]
mod raw;

mod external_trait_impls;
mod map;
#[cfg(feature = "rustc-internal-api")]
mod rustc_entry;
mod scopeguard;
mod set;

pub mod hash_map {
    //! A hash map implemented with quadratic probing and SIMD lookup.
    pub use crate::map::*;

    #[cfg(feature = "rustc-internal-api")]
    pub use crate::rustc_entry::*;

    #[cfg(feature = "rayon")]
    /// [rayon]-based parallel iterator types for hash maps.
    /// You will rarely need to interact with it directly unless you have need
    /// to name one of the iterator types.
    ///
    /// [rayon]: https://docs.rs/rayon/1.0/rayon
    pub mod rayon {
        pub use crate::external_trait_impls::rayon::map::*;
    }
}
pub mod hash_set {
    //! A hash set implemented as a `HashMap` where the value is `()`.
    pub use crate::set::*;

    #[cfg(feature = "rayon")]
    /// [rayon]-based parallel iterator types for hash sets.
    /// You will rarely need to interact with it directly unless you have need
    /// to name one of the iterator types.
    ///
    /// [rayon]: https://docs.rs/rayon/1.0/rayon
    pub mod rayon {
        pub use crate::external_trait_impls::rayon::set::*;
    }
}

pub use crate::map::HashMap;
pub use crate::set::HashSet;

/// Augments `AllocErr` with a `CapacityOverflow` variant.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum CollectionAllocErr {
    /// Error due to the computed capacity exceeding the collection's maximum
    /// (usually `isize::MAX` bytes).
    CapacityOverflow,
    /// Error due to the allocator.
    AllocErr {
        /// The layout of the allocation request that failed.
        layout: alloc::alloc::Layout,
    },
}
<commit_msg>Remove `#[cfg_doctest]` which is now stable.<commit_after>//! This crate is a Rust port of Google's high-performance [SwissTable] hash
//! map, adapted to make it a drop-in replacement for Rust's standard `HashMap`
//! and `HashSet` types.
//!
//! The original C++ version of [SwissTable] can be found [here], and this
//! [CppCon talk] gives an overview of how the algorithm works.
//!
//! [SwissTable]: https://abseil.io/blog/20180927-swisstables
//! [here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h
//! [CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4

#![no_std]
#![cfg_attr(
    feature = "nightly",
    feature(
        alloc_layout_extra,
        allocator_api,
        ptr_offset_from,
        test,
        core_intrinsics,
        dropck_eyepatch,
    )
)]
#![allow(
    clippy::doc_markdown,
    clippy::module_name_repetitions,
    clippy::must_use_candidate
)]
#![warn(missing_docs)]
#![warn(rust_2018_idioms)]

#[cfg(test)]
#[macro_use]
extern crate std;

#[cfg(has_extern_crate_alloc)]
#[cfg_attr(test, macro_use)]
extern crate alloc;
#[cfg(not(has_extern_crate_alloc))]
extern crate std as alloc;

#[cfg(feature = "nightly")]
#[cfg(doctest)]
doc_comment::doctest!("../README.md");

#[macro_use]
mod macros;

#[cfg(feature = "raw")]
/// Experimental and unsafe `RawTable` API. This module is only available if the
/// `raw` feature is enabled.
pub mod raw {
    // The RawTable API is still experimental and is not properly documented yet.
    #[allow(missing_docs)]
    #[path = "mod.rs"]
    mod inner;
    pub use inner::*;

    #[cfg(feature = "rayon")]
    pub mod rayon {
        pub use crate::external_trait_impls::rayon::raw::*;
    }
}
#[cfg(not(feature = "raw"))]
mod raw;

mod external_trait_impls;
mod map;
#[cfg(feature = "rustc-internal-api")]
mod rustc_entry;
mod scopeguard;
mod set;

pub mod hash_map {
    //! A hash map implemented with quadratic probing and SIMD lookup.
    pub use crate::map::*;

    #[cfg(feature = "rustc-internal-api")]
    pub use crate::rustc_entry::*;

    #[cfg(feature = "rayon")]
    /// [rayon]-based parallel iterator types for hash maps.
    /// You will rarely need to interact with it directly unless you have need
    /// to name one of the iterator types.
    ///
    /// [rayon]: https://docs.rs/rayon/1.0/rayon
    pub mod rayon {
        pub use crate::external_trait_impls::rayon::map::*;
    }
}
pub mod hash_set {
    //! A hash set implemented as a `HashMap` where the value is `()`.
    pub use crate::set::*;

    #[cfg(feature = "rayon")]
    /// [rayon]-based parallel iterator types for hash sets.
    /// You will rarely need to interact with it directly unless you have need
    /// to name one of the iterator types.
    ///
    /// [rayon]: https://docs.rs/rayon/1.0/rayon
    pub mod rayon {
        pub use crate::external_trait_impls::rayon::set::*;
    }
}

pub use crate::map::HashMap;
pub use crate::set::HashSet;

/// Augments `AllocErr` with a `CapacityOverflow` variant.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum CollectionAllocErr {
    /// Error due to the computed capacity exceeding the collection's maximum
    /// (usually `isize::MAX` bytes).
    CapacityOverflow,
    /// Error due to the allocator.
    AllocErr {
        /// The layout of the allocation request that failed.
        layout: alloc::alloc::Layout,
    },
}
<|endoftext|>


<commit_before>#![crate_name = "markdown"]

#![feature(fs)]
#![feature(io)]
#![feature(plugin)]
#![plugin(regex_macros)]
extern crate regex_macros;
extern crate regex;

use std::fs::File;
use std::path::Path;
use std::io::{Read, Error};

mod parser;
mod html;
mod normalizer;

pub fn to_html(text : &str) -> String{
    let normalized = normalizer::normalize(&text);
    let result = parser::parse(&normalized);
    html::to_html(&result)
}

pub fn file_to_html(path : &Path) -> Result<String, Error>{
    let mut file = match File::open(path) {
        Ok(file) => file,
        Err(e) => return Err(e)
    };

    let mut text = String::new();
    match file.read_to_string(&mut text) {
        Ok(_) => (),
        Err(e) => return Err(e)
    };

    let normalized = normalizer::normalize(&text);
    let result = parser::parse(&normalized);
    Ok(html::to_html(&result))
}

<commit_msg>Add missing test crate<commit_after>#![crate_name = "markdown"]

#![feature(plugin)]
#![feature(test)]
#![plugin(regex_macros)]
extern crate regex;
extern crate test;

use std::fs::File;
use std::path::Path;
use std::io::{Read, Error};

mod parser;
mod html;
mod normalizer;

pub fn to_html(text : &str) -> String{
    let normalized = normalizer::normalize(&text);
    let result = parser::parse(&normalized);
    html::to_html(&result)
}

pub fn file_to_html(path : &Path) -> Result<String, Error>{
    let mut file = match File::open(path) {
        Ok(file) => file,
        Err(e) => return Err(e)
    };

    let mut text = String::new();
    match file.read_to_string(&mut text) {
        Ok(_) => (),
        Err(e) => return Err(e)
    };

    let normalized = normalizer::normalize(&text);
    let result = parser::parse(&normalized);
    Ok(html::to_html(&result))
}

<|endoftext|>


<commit_before>#![feature(asm)]
#![crate_id="sha"]

use std::slice::bytes::copy_memory;

static MAGIC_VALUES_SHA256: [u32, ..8] = [
    0x6a09e667,
    0xbb67ae85,
    0x3c6ef372,
    0xa54ff53a,
    0x510e527f,
    0x9b05688c,
    0x1f83d9ab,
    0x5be0cd19
];

static ROUND_CONSTANTS: [u32, ..64] = [
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];

pub struct Sha256<'a> {
    state: &'a [u32],
    position: uint,
    buffer: Vec<u8>
}

impl<'a> Sha256<'a> {
    pub fn new() -> Sha256<'a> {
        let mut buffer = Vec::with_capacity(64);
        unsafe { buffer.set_len(64); }
        Sha256 {
            state: MAGIC_VALUES_SHA256.clone(),
            buffer: buffer,
            position: 0,
        }
    }

    //
    // Adds the message to the buffer and hashes when the
    // buffer is full
    // TODO: refactor
    //
    pub fn update(&mut self, message: &[u8]) {

        let mut position: uint = 0;

        if self.position > 0 {
            let space = 64 - self.position;
            if space > message.len() {
                {
                    let destination = self.buffer.mut_slice_from(self.position);
                    copy_memory(destination, message);
                }
                self.position += message.len();
                return;
            } else if space == message.len() {
                {
                    let destination = self.buffer.mut_slice_from(self.position);
                    copy_memory(destination, message);
                }
                self.hash();
                return;
            } else {
                {
                    let destination = self.buffer.mut_slice_from(self.position);
                    let source = message.slice_to(space);
                    copy_memory(destination, source);
                }
                self.hash();
                position += space;
            }
        }

        while position < message.len() {
            let end = position + 64;
            if end <= message.len() {
                {
                    let destination = self.buffer.as_mut_slice();
                    let source = message.slice(position, end);
                    copy_memory(destination, source);
                }
                self.hash();
                position = end;

            // final iteration
            } else {
                {
                    let destination = self.buffer.as_mut_slice();
                    let source = message.slice_from(position);
                    copy_memory(destination, source);
                }
                self.position = message.len() - position;
                break;
            }
        }

    }

    #[cfg(target_arch = "x86_64")]
    fn hash(chunk: &Vec<u8>, state: &Vec<u32>) {

        let mut schedule: Vec<u32> = Vec::with_capacity(64);

        unsafe {
            schedule.set_len(64);

        }
        let mut ptr = schedule.as_mut_ptr();
        unsafe {
            asm!(
                // Move chunk into schedule array
                "
                movq ($1), %rax
                movq 8($1), %rcx
                movq %rax, ($0)
                movq %rcx, 8($0)

                movq 16($1), %rax
                movq 24($1), %rcx
                movq %rax, 16($0)
                movq %rcx, 24($0)

                movq 32($1), %rax
                movq 40($1), %rcx
                movq %rax, 32($0)
                movq %rcx, 40($0)

                movq 48($1), %rax
                movq 56($1), %rcx
                movq %rax, 48($0)
                movq %rcx, 56($0)
                "
                :"+r"(ptr)
                :"r"(chunk.as_ptr())
                : "rax", "rcx"
            );

        }

        println!("{}", schedule[0]);
        println!("{}", schedule[1]);
        println!("{}", schedule[2]);
        println!("{}", schedule[3]);
        println!("{}", schedule[4]);
        println!("{}", schedule[5]);
    }

    #[cfg(target_arch = "x86")]
    fn hash(chunk: &Vec<u8>, state: &Vec<u32>) {

        let mut schedule: Vec<u32> = Vec::with_capacity(64);

        unsafe {
            schedule.set_len(64);

        }
        let mut ptr = schedule.as_mut_ptr();
        unsafe {
            asm!(
                // Move chunk into schedule array
                "
                movl ($1), %eax
                movl 4($1), %ecx
                movl %eax, ($0)
                movl %ecx, 4($0)

                movl 8($1), %eax
                movl 12($1), %ecx
                movl %eax, 8($0)
                movl %ecx, 12($0)

                movl 16($1), %eax
                movl 20($1), %ecx
                movl %eax, 16($0)
                movl %ecx, 20($0)

                movl 24($1), %eax
                movl 28($1), %ecx
                movl %eax, 24($0)
                movl %ecx, 28($0)

                movl 32($1), %eax
                movl 36($1), %ecx
                movl %eax, 32($0)
                movl %ecx, 36($0)

                movl 40($1), %eax
                movl 44($1), %ecx
                movl %eax, 40($0)
                movl %ecx, 44($0)

                movl 48($1), %eax
                movl 52($1), %ecx
                movl %eax, 48($0)
                movl %ecx, 52($0)

                movl 56($1), %eax
                movl 60($1), %ecx
                movl %eax, 56($0)
                movl %ecx, 60($0)
                "
                :"+r"(ptr)
                :"r"(chunk.as_ptr())
                : "eax", "ecx"
            );

        }
    }
}

#[cfg(test)]
mod test {
    #![feature(phase)]

    use super::Sha256;
    use std::string::String;

    macro_rules! rotate_right_32 (
        ($value:expr, $shift:expr) => (
            ($value >> $shift) | ($value << (32 - $shift))
        )
    )

    #[test]
    fn test_sha256() {
        let mut hasher = Sha256::new();
        let message = String::from_str("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ");

        hasher.update(message.as_bytes());

        assert!(hasher.position == 63 && message.len() == 63);
        hasher.update("a".as_bytes());
        assert!(hasher.position == 0);
    }

    #[test]
    fn test_right_rotate() {
        let five: u32 = 5;

        let shifted: u32 = 2147483650;

        assert_eq!(shifted, rotate_right_32!(five, 1));

    }
}

<commit_msg>printf driven development<commit_after>#![feature(asm)]
#![crate_id="sha"]

use std::slice::bytes::copy_memory;

static MAGIC_VALUES_SHA256: [u32, ..8] = [
    0x6a09e667,
    0xbb67ae85,
    0x3c6ef372,
    0xa54ff53a,
    0x510e527f,
    0x9b05688c,
    0x1f83d9ab,
    0x5be0cd19
];

static ROUND_CONSTANTS: [u32, ..64] = [
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];

pub struct Sha256<'a> {
    state: &'a [u32],
    position: uint,
    buffer: Vec<u8>
}

impl<'a> Sha256<'a> {
    pub fn new() -> Sha256<'a> {
        let mut buffer = Vec::with_capacity(64);
        unsafe { buffer.set_len(64); }
        Sha256 {
            state: MAGIC_VALUES_SHA256.clone(),
            buffer: buffer,
            position: 0,
        }
    }

    //
    // Adds the message to the buffer and hashes when the
    // buffer is full
    // TODO: refactor
    //
    pub fn update(&mut self, message: &[u8]) {

        let mut position: uint = 0;

        if self.position > 0 {
            let space = 64 - self.position;
            if space > message.len() {
                {
                    let destination = self.buffer.mut_slice_from(self.position);
                    copy_memory(destination, message);
                }
                self.position += message.len();
                return;
            } else if space == message.len() {
                {
                    let destination = self.buffer.mut_slice_from(self.position);
                    copy_memory(destination, message);
                }
                self.hash();
                return;
            } else {
                {
                    let destination = self.buffer.mut_slice_from(self.position);
                    let source = message.slice_to(space);
                    copy_memory(destination, source);
                }
                self.hash();
                position += space;
            }
        }

        while position < message.len() {
            let end = position + 64;
            if end <= message.len() {
                {
                    let destination = self.buffer.as_mut_slice();
                    let source = message.slice(position, end);
                    copy_memory(destination, source);
                }
                self.hash();
                position = end;

            // final iteration
            } else {
                {
                    let destination = self.buffer.as_mut_slice();
                    let source = message.slice_from(position);
                    copy_memory(destination, source);
                }
                self.position = message.len() - position;
                break;
            }
        }

    }

    #[cfg(target_arch = "x86_64")]
    fn hash(chunk: &Vec<u8>, state: &Vec<u32>) {

        let mut schedule: Vec<u32> = Vec::with_capacity(64);

        unsafe {
            schedule.set_len(64);

        }
        let mut ptr = schedule.as_mut_ptr();
        unsafe {
            asm!(
                // Move chunk into schedule array
                "
                movq ($1), %rax
                movq 8($1), %rcx
                movq %rax, ($0)
                movq %rcx, 8($0)

                movq 16($1), %rax
                movq 24($1), %rcx
                movq %rax, 16($0)
                movq %rcx, 24($0)

                movq 32($1), %rax
                movq 40($1), %rcx
                movq %rax, 32($0)
                movq %rcx, 40($0)

                movq 48($1), %rax
                movq 56($1), %rcx
                movq %rax, 48($0)
                movq %rcx, 56($0)
                "
                :"+r"(ptr)
                :"r"(chunk.as_ptr())
                : "rax", "rcx"
            );

        }

    }

    #[cfg(target_arch = "x86")]
    fn hash(chunk: &Vec<u8>, state: &Vec<u32>) {

        let mut schedule: Vec<u32> = Vec::with_capacity(64);

        unsafe {
            schedule.set_len(64);

        }
        let mut ptr = schedule.as_mut_ptr();
        unsafe {
            asm!(
                // Move chunk into schedule array
                "
                movl ($1), %eax
                movl 4($1), %ecx
                movl %eax, ($0)
                movl %ecx, 4($0)

                movl 8($1), %eax
                movl 12($1), %ecx
                movl %eax, 8($0)
                movl %ecx, 12($0)

                movl 16($1), %eax
                movl 20($1), %ecx
                movl %eax, 16($0)
                movl %ecx, 20($0)

                movl 24($1), %eax
                movl 28($1), %ecx
                movl %eax, 24($0)
                movl %ecx, 28($0)

                movl 32($1), %eax
                movl 36($1), %ecx
                movl %eax, 32($0)
                movl %ecx, 36($0)

                movl 40($1), %eax
                movl 44($1), %ecx
                movl %eax, 40($0)
                movl %ecx, 44($0)

                movl 48($1), %eax
                movl 52($1), %ecx
                movl %eax, 48($0)
                movl %ecx, 52($0)

                movl 56($1), %eax
                movl 60($1), %ecx
                movl %eax, 56($0)
                movl %ecx, 60($0)
                "
                :"+r"(ptr)
                :"r"(chunk.as_ptr())
                : "eax", "ecx"
            );

        }
    }
}

#[cfg(test)]
mod test {
    #![feature(phase)]

    use super::Sha256;
    use std::string::String;

    macro_rules! rotate_right_32 (
        ($value:expr, $shift:expr) => (
            ($value >> $shift) | ($value << (32 - $shift))
        )
    )

    #[test]
    fn test_sha256() {
        let mut hasher = Sha256::new();
        let message = String::from_str("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ");

        hasher.update(message.as_bytes());

        assert!(hasher.position == 63 && message.len() == 63);
        hasher.update("a".as_bytes());
        assert!(hasher.position == 0);
    }

    #[test]
    fn test_right_rotate() {
        let five: u32 = 5;

        let shifted: u32 = 2147483650;

        assert_eq!(shifted, rotate_right_32!(five, 1));

    }
}

<|endoftext|>


<commit_before>extern crate rand;

pub mod macaroni {
    use rand;
    use std::collections::HashMap;
    use std::io;
    use std::rc::Rc;

    const DIGITS: &'static [u8] = b"0123456789";
    const EPSILON: f64 = 0.000001;
    const PRECISION: i32 = 10;

    #[derive(Clone)]
    enum Val {
        Num(f64),
        Arr(Vec<Val>)
    }

    #[derive(Clone)]
    struct Variable {
        val: Val,
        var: Option<String>
    }

    impl Variable {
        fn by_name(name: String) -> Variable {
            Variable { val: Val::Num(0f64), var: Some(name) } // TODO
        }
        fn new_num(n: f64) -> Variable {
            Variable { val: Val::Num(n), var: None }
        }
        fn new_arr(a: Vec<Val>) -> Variable {
            Variable { val: Val::Arr(a), var: None }
        }
    }

    #[derive(Clone)]
    enum Token {
        Var(Variable),
        Op { func: Rc<Fn(&[Variable]) -> Option<Variable>>, arity: usize },
        Label(String),
        Goto(String)
    }

    pub struct Macaroni {
        vars: Vec<Variable>
    }

    impl Macaroni {
        pub fn new() -> Macaroni {
            Macaroni { vars: Vec::<Variable>::new() }
        }

        pub fn run(&self, code: String) {
            self.run_tokens(&Macaroni::tokenize(code));
        }

        fn tokenize(code: String) -> Vec<Token> {
            let mut tokens = Vec::<String>::new();
            let mut token = String::new();
            for ch in code.chars() {
                if token.starts_with("\"") {
                    token.push(ch);
                    if ch == '"' {
                        tokens.push(token);
                        token = String::new();
                    }
                } else { match ch {
                    'a'...'z' | 'A'...'Z' | '0'...'9' | '_' | '-' => {
                        token.push(ch);
                    },
                    ' ' | '\n' | '\t' => {
                        if !token.is_empty() {
                            tokens.push(token);
                            token = String::new();
                        }
                    },
                    '"' | '/' | '\\' => {
                        if token.is_empty() {
                            token.push(ch);
                        } else {
                            panic!("unexpected {}", token);
                        }
                    },
                    _ => { panic!("unrecognized char {}", ch); }
                } }
            }
            if !token.is_empty() { tokens.push(token); }
            tokens.iter().map(|t|
                if t.chars().all(|ch| ch.is_digit(10) || ch == '-') {
                    Token::Var(Variable::new_num(t.parse::<f64>().unwrap()))
                } else { match t.chars().next().unwrap() {
                    '"' => {
                        Token::Var(Variable::new_arr(Macaroni::string_to_arr(
                            &t[1..t.len() - 1].to_string())))
                    },
                    '/' => {
                        Token::Label(t[1..t.len()].to_string())
                    },
                    '\\' => {
                        Token::Goto(t[1..t.len()].to_string())
                    },
                    _ => { match &t[..] {
                        "add" => Token::Op {
                            func: Rc::new(Macaroni::add), arity: 2
                        },
                        "multiply" => Token::Op {
                            func: Rc::new(Macaroni::multiply), arity: 2
                        },
                        "floor" => Token::Op {
                            func: Rc::new(Macaroni::floor), arity: 1
                        },
                        "pow" => Token::Op {
                            func: Rc::new(Macaroni::pow), arity: 2
                        },
                        "tobase" => Token::Op {
                            func: Rc::new(Macaroni::tobase), arity: 2
                        },
                        "wrap" => Token::Op {
                            func: Rc::new(Macaroni::wrap), arity: 1
                        },
                        "print" => Token::Op {
                            func: Rc::new(Macaroni::print), arity: 1
                        },
                        "read" => Token::Op {
                            func: Rc::new(Macaroni::read), arity: 0
                        },
                        "rand" => Token::Op {
                            func: Rc::new(Macaroni::rand), arity: 0
                        },
                        _ => Token::Var(Variable::by_name(t.clone()))
                    } }
                } }).collect::<Vec<Token>>()
        }

        fn run_tokens(&self, program: &[Token]) {
            let mut label_addrs: HashMap<String, usize> = HashMap::new();
            let mut i: usize = 0;
            while let Some(t) = program.get(i) {
                match t {
                    &Token::Op { .. } => {
                        self.execute_op(&program, &mut i);
                    },
                    &Token::Label(ref label) => {
                        label_addrs.entry(label.clone()).or_insert(i);
                        i += 1;
                    },
                    &Token::Goto(ref label) => {
                        i = label_addrs.entry(label.clone())
                                       .or_insert_with(|| self.find_label(program, label, i).expect(
                                            &format!("{:#08x}: is a GOTO to label {:?}, which does not exist", i, label)[..]))
                                       .clone();
                    },
                    _ => {
                        i += 1;
                    }
                }
            }
        }

        fn execute_op(&self, program: &[Token], i: &mut usize) -> Option<Variable> {
            let (func, arity) = match program.get(i.clone()) {
                Some(&Token::Op { ref func, arity }) => (func, arity),
                Some(_) => panic!(format!("Macaroni::execute_op() called on {:#08x}, but instruction is not OP", i)),
                None => panic!(format!("Macaroni::execute_op() called on out-of-bounds index {:#08x}", i))
            };
            *i += 1;
            let mut args: Vec<Variable> = Vec::with_capacity(arity);
            while args.len() < arity {
                match program.get(i.clone()) {
                    Some(&Token::Var(ref v)) => {
                        args.push(v.clone());
                        *i += 1;
                    },
                    Some(&Token::Op { .. }) => {
                        match self.execute_op(program, i) {
                            Some(v) => args.push(v),
                            None => panic!(format!("nested OP ending before {:#08x} returned nothing", i))
                        }
                    }
                    Some(_) => panic!(format!("{:#08x} is not valid as an OP argument; it should be a VAR or an OP", i)),
                    None => panic!(format!("{:#08x}: expected OP argument (VAR or OP); found end of program", i))
                }
            }
            func(&args[..])
        }

        /// Searches the program for the specified label. Returns the position
        /// of the label in the program, or `None` if it was not found.
        ///
        /// `index` merely specifies a starting point. The entire `program`
        /// is always searched, starting at `index` and wrapping around
        /// if necessary.
        ///
        /// # Examples
        ///
        /// ```
        /// use Token::*;
        ///
        /// let print_func = Box::new(|s| println!("{}", s));
        /// let program = vec![Label(String::from("loop")), Op({ func: print, arity: 1 }), Variable(String::from("Hello, world!")), Goto(String::from("loop"))];
        /// assert_eq!(find_label(program, String::from("loop"), 0), Some(0));
        /// assert_eq!(find_label(program, String::from("cleanup"), 0), None);
        /// ```
        fn find_label(&self, program: &[Token], desired_label: &str, index: usize) -> Option<usize> {
            let enumerated = program.iter().enumerate();
            for (i, token) in enumerated.clone()
                                        .skip(index)
                                        .chain(enumerated.take(index)) {
                if let Token::Label(ref label) = *token {
                    if label == desired_label {
                        return Some(i);
                    }
                }
            }
            None
        }

        fn add(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("add called with Arr")
            } + match args[1].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("add called with Arr")
            }))
        }

        fn multiply(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("multiply called with Arr")
            } * match args[1].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("multiply called with Arr")
            }))
        }

        fn floor(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("floor called with Arr")
            }.floor()))
        }

        fn pow(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("pow called with Arr")
            }.powf(match args[1].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("pow called with Arr")
            })))
        }

        fn tobase(args: &[Variable]) -> Option<Variable> {
            match args[0].val { Val::Num(n) => {
                match args[1].val { Val::Num(m) => {
                    let (base, mut ipart, mut fpart) =
                        (m as i64, n.floor() as i64, n - n.floor());
                    let neg = ipart < 0;

                    // convert integer part
                    let mut nb = String::new();
                    while ipart != 0 {
                        nb.insert(0, DIGITS[(ipart % base) as usize] as char);
                        ipart /= base;
                    }

                    // handle negatives and zero (we must do this
                    // before converting float part)
                    if neg { nb.insert(0, '-'); }
                    if nb.is_empty() { nb.push('0'); }

                    // convert float part
                    if fpart > EPSILON {
                        nb.push('.');
                        for _ in 0..PRECISION {
                            if fpart <= EPSILON { break; }
                            fpart *= base as f64;
                            let digit = fpart.floor();
                            nb.push(DIGITS[digit as usize] as char);
                            fpart -= digit;
                        }
                    }

                    Some(Variable::new_arr(Macaroni::string_to_arr(&nb)))
                }, Val::Arr(_) => panic!("tobase called with Arr") }
            }, Val::Arr(_) => panic!("tobase called with Arr") }
        }

        fn wrap(args: &[Variable]) -> Option<Variable> {
            let ref x = args[0];
            Some(Variable::new_arr(vec![x.val.clone()]))
        }

        fn print(args: &[Variable]) -> Option<Variable> {
            let ref x = args[0];
            print!("{}", match x.val {
                Val::Arr(ref s) => Macaroni::arr_to_string(s),
                Val::Num(_) => panic!("print called with Num")
            });
            None
        }

        fn read(_: &[Variable]) -> Option<Variable> {
            let mut line = String::new();
            io::stdin().read_line(&mut line).unwrap();
            Some(Variable::new_arr(Macaroni::string_to_arr(&line)))
        }

        fn rand(_: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(rand::random()))
        }

        fn arr_to_string(arr: &Vec<Val>) -> String {
            arr.iter().map(|x| match x {
                &Val::Num(n) => n,
                &Val::Arr(_) => panic!("arr_to_string called with non-string")
            } as u8 as char).collect::<String>()
        }

        fn string_to_arr(str: &String) -> Vec<Val> {
            str.chars().map(|c| Val::Num(c as u8 as f64)).collect()
        }
    }
}
<commit_msg>fix some formatting<commit_after>extern crate rand;

pub mod macaroni {
    use rand;
    use std::collections::HashMap;
    use std::io;
    use std::rc::Rc;

    const DIGITS: &'static [u8] = b"0123456789";
    const EPSILON: f64 = 0.000001;
    const PRECISION: i32 = 10;

    #[derive(Clone)]
    enum Val {
        Num(f64),
        Arr(Vec<Val>)
    }

    #[derive(Clone)]
    struct Variable {
        val: Val,
        var: Option<String>
    }

    impl Variable {
        fn by_name(name: String) -> Variable {
            Variable { val: Val::Num(0f64), var: Some(name) } // TODO
        }
        fn new_num(n: f64) -> Variable {
            Variable { val: Val::Num(n), var: None }
        }
        fn new_arr(a: Vec<Val>) -> Variable {
            Variable { val: Val::Arr(a), var: None }
        }
    }

    #[derive(Clone)]
    enum Token {
        Var(Variable),
        Op { func: Rc<Fn(&[Variable]) -> Option<Variable>>, arity: usize },
        Label(String),
        Goto(String)
    }

    pub struct Macaroni {
        vars: Vec<Variable>
    }

    impl Macaroni {
        pub fn new() -> Macaroni {
            Macaroni { vars: Vec::<Variable>::new() }
        }

        pub fn run(&self, code: String) {
            self.run_tokens(&Macaroni::tokenize(code));
        }

        fn tokenize(code: String) -> Vec<Token> {
            let mut tokens = Vec::<String>::new();
            let mut token = String::new();
            for ch in code.chars() {
                if token.starts_with("\"") {
                    token.push(ch);
                    if ch == '"' {
                        tokens.push(token);
                        token = String::new();
                    }
                } else { match ch {
                    'a'...'z' | 'A'...'Z' | '0'...'9' | '_' | '-' => {
                        token.push(ch);
                    },
                    ' ' | '\n' | '\t' => {
                        if !token.is_empty() {
                            tokens.push(token);
                            token = String::new();
                        }
                    },
                    '"' | '/' | '\\' => {
                        if token.is_empty() {
                            token.push(ch);
                        } else {
                            panic!("unexpected {}", token);
                        }
                    },
                    _ => { panic!("unrecognized char {}", ch); }
                } }
            }
            if !token.is_empty() { tokens.push(token); }
            tokens.iter().map(|t|
                if t.chars().all(|ch| ch.is_digit(10) || ch == '-') {
                    Token::Var(Variable::new_num(t.parse::<f64>().unwrap()))
                } else { match t.chars().next().unwrap() {
                    '"' => {
                        Token::Var(Variable::new_arr(Macaroni::string_to_arr(
                            &t[1..t.len() - 1].to_string())))
                    },
                    '/' => {
                        Token::Label(t[1..t.len()].to_string())
                    },
                    '\\' => {
                        Token::Goto(t[1..t.len()].to_string())
                    },
                    _ => { match &t[..] {
                        "add" => Token::Op {
                            func: Rc::new(Macaroni::add), arity: 2
                        },
                        "multiply" => Token::Op {
                            func: Rc::new(Macaroni::multiply), arity: 2
                        },
                        "floor" => Token::Op {
                            func: Rc::new(Macaroni::floor), arity: 1
                        },
                        "pow" => Token::Op {
                            func: Rc::new(Macaroni::pow), arity: 2
                        },
                        "tobase" => Token::Op {
                            func: Rc::new(Macaroni::tobase), arity: 2
                        },
                        "wrap" => Token::Op {
                            func: Rc::new(Macaroni::wrap), arity: 1
                        },
                        "print" => Token::Op {
                            func: Rc::new(Macaroni::print), arity: 1
                        },
                        "read" => Token::Op {
                            func: Rc::new(Macaroni::read), arity: 0
                        },
                        "rand" => Token::Op {
                            func: Rc::new(Macaroni::rand), arity: 0
                        },
                        _ => Token::Var(Variable::by_name(t.clone()))
                    } }
                } }).collect::<Vec<Token>>()
        }

        fn run_tokens(&self, program: &[Token]) {
            let mut label_addrs: HashMap<String, usize> = HashMap::new();
            let mut i: usize = 0;
            while let Some(t) = program.get(i) {
                match t {
                    &Token::Op { .. } => {
                        self.execute_op(&program, &mut i);
                    },
                    &Token::Label(ref label) => {
                        label_addrs.entry(label.clone()).or_insert(i);
                        i += 1;
                    },
                    &Token::Goto(ref label) => {
                        i = label_addrs.entry(label.clone())
                            .or_insert_with(||
                                self.find_label(program, label, i)
                                    .expect(&format!("{:#08x}: is a GOTO to \
                                                     label {:?}, which does \
                                                     not exist", i, label)[..])
                            ).clone();
                    },
                    _ => {
                        i += 1;
                    }
                }
            }
        }

        fn execute_op(&self, program: &[Token], i: &mut usize) -> Option<Variable> {
            let (func, arity) = match program.get(i.clone()) {
                Some(&Token::Op { ref func, arity }) => (func, arity),
                Some(_) => panic!("Macaroni::execute_op() called on {:#08x}, \
                                  but instruction is not OP", i),
                None => panic!("Macaroni::execute_op() called on out-of-bounds \
                               index {:#08x}", i)
            };
            *i += 1;
            let mut args: Vec<Variable> = Vec::with_capacity(arity);
            while args.len() < arity {
                match program.get(i.clone()) {
                    Some(&Token::Var(ref v)) => {
                        args.push(v.clone());
                        *i += 1;
                    },
                    Some(&Token::Op { .. }) => {
                        match self.execute_op(program, i) {
                            Some(v) => args.push(v),
                            None => panic!("nested OP ending before {:#08x} \
                                           returned nothing", i)
                        }
                    }
                    Some(_) => panic!("{:#08x} is not valid as an OP argument; \
                                      it should be a VAR or an OP", i),
                    None => panic!("{:#08x}: expected OP argument (VAR or OP); \
                                   found end of program", i)
                }
            }
            func(&args[..])
        }

        /// Searches the program for the specified label. Returns the position
        /// of the label in the program, or `None` if it was not found.
        ///
        /// `index` merely specifies a starting point. The entire `program`
        /// is always searched, starting at `index` and wrapping around
        /// if necessary.
        ///
        /// # Examples
        ///
        /// ```
        /// use Token::*;
        ///
        /// let print_func = Box::new(|s| println!("{}", s));
        /// let program = vec![
        ///     Label(String::from("loop")),
        ///     Op({ func: print, arity: 1 }),
        ///     Variable(String::from("Hello, world!")),
        ///     Goto(String::from("loop"))
        /// ];
        /// assert_eq!(find_label(program, String::from("loop"), 0), Some(0));
        /// assert_eq!(find_label(program, String::from("cleanup"), 0), None);
        /// ```
        fn find_label(&self, program: &[Token], desired_label: &str,
                index: usize) -> Option<usize> {
            let enumerated = program.iter().enumerate();
            for (i, token) in enumerated.clone()
                                        .skip(index)
                                        .chain(enumerated.take(index)) {
                if let Token::Label(ref label) = *token {
                    if label == desired_label {
                        return Some(i);
                    }
                }
            }
            None
        }

        fn add(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("add called with Arr")
            } + match args[1].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("add called with Arr")
            }))
        }

        fn multiply(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("multiply called with Arr")
            } * match args[1].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("multiply called with Arr")
            }))
        }

        fn floor(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("floor called with Arr")
            }.floor()))
        }

        fn pow(args: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(match args[0].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("pow called with Arr")
            }.powf(match args[1].val {
                Val::Num(n) => n,
                Val::Arr(_) => panic!("pow called with Arr")
            })))
        }

        fn tobase(args: &[Variable]) -> Option<Variable> {
            match args[0].val { Val::Num(n) => {
                match args[1].val { Val::Num(m) => {
                    let (base, mut ipart, mut fpart) =
                        (m as i64, n.floor() as i64, n - n.floor());
                    let neg = ipart < 0;

                    // convert integer part
                    let mut nb = String::new();
                    while ipart != 0 {
                        nb.insert(0, DIGITS[(ipart % base) as usize] as char);
                        ipart /= base;
                    }

                    // handle negatives and zero (we must do this
                    // before converting float part)
                    if neg { nb.insert(0, '-'); }
                    if nb.is_empty() { nb.push('0'); }

                    // convert float part
                    if fpart > EPSILON {
                        nb.push('.');
                        for _ in 0..PRECISION {
                            if fpart <= EPSILON { break; }
                            fpart *= base as f64;
                            let digit = fpart.floor();
                            nb.push(DIGITS[digit as usize] as char);
                            fpart -= digit;
                        }
                    }

                    Some(Variable::new_arr(Macaroni::string_to_arr(&nb)))
                }, Val::Arr(_) => panic!("tobase called with Arr") }
            }, Val::Arr(_) => panic!("tobase called with Arr") }
        }

        fn wrap(args: &[Variable]) -> Option<Variable> {
            let ref x = args[0];
            Some(Variable::new_arr(vec![x.val.clone()]))
        }

        fn print(args: &[Variable]) -> Option<Variable> {
            let ref x = args[0];
            print!("{}", match x.val {
                Val::Arr(ref s) => Macaroni::arr_to_string(s),
                Val::Num(_) => panic!("print called with Num")
            });
            None
        }

        fn read(_: &[Variable]) -> Option<Variable> {
            let mut line = String::new();
            io::stdin().read_line(&mut line).unwrap();
            Some(Variable::new_arr(Macaroni::string_to_arr(&line)))
        }

        fn rand(_: &[Variable]) -> Option<Variable> {
            Some(Variable::new_num(rand::random()))
        }

        fn arr_to_string(arr: &Vec<Val>) -> String {
            arr.iter().map(|x| match x {
                &Val::Num(n) => n,
                &Val::Arr(_) => panic!("arr_to_string called with non-string")
            } as u8 as char).collect::<String>()
        }

        fn string_to_arr(str: &String) -> Vec<Val> {
            str.chars().map(|c| Val::Num(c as u8 as f64)).collect()
        }
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use std::c_str::CString;

mod ffi;

#[deriving(Show)]
pub struct CpuInfo {
    num_cores: int,
    num_logical_cpus: int,
    total_logical_cpus: int,
    l1_data_cache: Option<int>,
    l1_instruction_cache: Option<int>,
    l2_cache: Option<int>,
    l3_cache: Option<int>,
}

pub fn is_present() -> bool {
    unsafe {
        ffi::cpuid_present() == 1
    }
}

pub fn version() -> String {
    let version_string = unsafe {
        let ptr = ffi::cpuid_lib_version();
        CString::new(ptr, false)
    };
    version_string.as_str().unwrap().to_string()
}

pub fn error() -> String {
    let error_string = unsafe {
        let ptr = ffi::cpuid_error();
        CString::new(ptr, false)
    };
    error_string.as_str().unwrap().to_string()
}

pub fn identify() -> Result<CpuInfo, String> {
    let mut raw = ffi::cpu_raw_data_t {
        basic_cpuid: [[0, ..ffi::MAX_CPUID_LEVEL], ..4u],
        ext_cpuid: [[0, ..ffi::MAX_EXT_CPUID_LEVEL], ..4u],
        intel_fn4: [[0, ..ffi::MAX_INTELFN4_LEVEL], ..4u],
        intel_fn11: [[0, ..ffi::MAX_INTELFN11_LEVEL], ..4u],
    };
    let raw_result = unsafe {
        ffi::cpuid_get_raw_data(&mut raw)
    };
    if raw_result != 0 {
        return Err(error());
    }
    let mut data = ffi::cpu_id_t {
        vendor_str: [0, ..ffi::VENDOR_STR_MAX],
        brand_str: [0, ..ffi::BRAND_STR_MAX],
        vendor: 0,
        flags: [0u8, ..ffi::CPU_FLAGS_MAX],
        family: 0,
        model: 0,
        stepping: 0,
        ext_family: 0,
        ext_model: 0,
        num_cores: 0,
        num_logical_cpus: 0,
        total_logical_cpus: 0,
        l1_data_cache: 0,
        l1_instruction_cache: 0,
        l2_cache: 0,
        l3_cache: 0,
        l1_assoc: 0,
        l2_assoc: 0,
        l3_assoc: 0,
        l1_cacheline: 0,
        l2_cacheline: 0,
        l3_cacheline: 0,
        cpu_codename: [0, ..64],
        sse_size: 0,
        detection_hints: [0u8, ..ffi::CPU_HINTS_MAX],
    };
    let identify_result = unsafe {
        ffi::cpu_identify(&mut raw, &mut data)
    };
    if identify_result != 0 {
        Err(error())
    } else {
        Ok(CpuInfo {
            num_cores: data.num_cores as int,
            num_logical_cpus: data.num_logical_cpus as int,
            total_logical_cpus: data.total_logical_cpus as int,
            l1_data_cache: if data.l1_data_cache != -1 { Some(data.l1_data_cache as int) } else { None },
            l1_instruction_cache: if data.l1_instruction_cache != -1 { Some(data.l1_instruction_cache as int) } else { None },
            l2_cache: if data.l2_cache != -1 { Some(data.l2_cache as int) } else { None },
            l3_cache: if data.l3_cache != -1 { Some(data.l3_cache as int) } else { None },
        })
    }
}

#[test]
fn test_is_present() {
    assert!(is_present());
}
<commit_msg>Added vendor, brand and codename strings to CpuInfo.<commit_after>extern crate libc;

use std::c_str::CString;

mod ffi;

#[deriving(Show)]
pub struct CpuInfo {
    vendor: String,
    brand: String,
    codename: String,
    num_cores: int,
    num_logical_cpus: int,
    total_logical_cpus: int,
    l1_data_cache: Option<int>,
    l1_instruction_cache: Option<int>,
    l2_cache: Option<int>,
    l3_cache: Option<int>,
}

pub fn is_present() -> bool {
    unsafe {
        ffi::cpuid_present() == 1
    }
}

pub fn version() -> String {
    let version_string = unsafe {
        let ptr = ffi::cpuid_lib_version();
        CString::new(ptr, false)
    };
    version_string.as_str().unwrap().to_string()
}

pub fn error() -> String {
    let error_string = unsafe {
        let ptr = ffi::cpuid_error();
        CString::new(ptr, false)
    };
    error_string.as_str().unwrap().to_string()
}

pub fn identify() -> Result<CpuInfo, String> {
    let mut raw = ffi::cpu_raw_data_t {
        basic_cpuid: [[0, ..ffi::MAX_CPUID_LEVEL], ..4u],
        ext_cpuid: [[0, ..ffi::MAX_EXT_CPUID_LEVEL], ..4u],
        intel_fn4: [[0, ..ffi::MAX_INTELFN4_LEVEL], ..4u],
        intel_fn11: [[0, ..ffi::MAX_INTELFN11_LEVEL], ..4u],
    };
    let raw_result = unsafe {
        ffi::cpuid_get_raw_data(&mut raw)
    };
    if raw_result != 0 {
        return Err(error());
    }
    let mut data = ffi::cpu_id_t {
        vendor_str: [0, ..ffi::VENDOR_STR_MAX],
        brand_str: [0, ..ffi::BRAND_STR_MAX],
        vendor: 0,
        flags: [0u8, ..ffi::CPU_FLAGS_MAX],
        family: 0,
        model: 0,
        stepping: 0,
        ext_family: 0,
        ext_model: 0,
        num_cores: 0,
        num_logical_cpus: 0,
        total_logical_cpus: 0,
        l1_data_cache: 0,
        l1_instruction_cache: 0,
        l2_cache: 0,
        l3_cache: 0,
        l1_assoc: 0,
        l2_assoc: 0,
        l3_assoc: 0,
        l1_cacheline: 0,
        l2_cacheline: 0,
        l3_cacheline: 0,
        cpu_codename: [0, ..64],
        sse_size: 0,
        detection_hints: [0u8, ..ffi::CPU_HINTS_MAX],
    };
    let identify_result = unsafe {
        ffi::cpu_identify(&mut raw, &mut data)
    };
    if identify_result != 0 {
        Err(error())
    } else {
        Ok(CpuInfo {
            vendor: String::from_utf8(data.vendor_str.iter().map(|&x| x as u8).collect()).ok().expect("Invalid vendor string"),
            brand: String::from_utf8(data.brand_str.iter().map(|&x| x as u8).collect()).ok().expect("Invalid brand string"),
            codename: String::from_utf8(data.cpu_codename.iter().map(|&x| x as u8).collect()).ok().expect("Invalid codename string"),
            num_cores: data.num_cores as int,
            num_logical_cpus: data.num_logical_cpus as int,
            total_logical_cpus: data.total_logical_cpus as int,
            l1_data_cache: if data.l1_data_cache != -1 { Some(data.l1_data_cache as int) } else { None },
            l1_instruction_cache: if data.l1_instruction_cache != -1 { Some(data.l1_instruction_cache as int) } else { None },
            l2_cache: if data.l2_cache != -1 { Some(data.l2_cache as int) } else { None },
            l3_cache: if data.l3_cache != -1 { Some(data.l3_cache as int) } else { None },
        })
    }
}

#[test]
fn test_is_present() {
    assert!(is_present());
}
<|endoftext|>


<commit_before>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::transmute;

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
}

pub fn any(data: *const raw::c_void, length: usize, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(data, length as libc::size_t, name_cstr.as_ptr());
  }
}

pub fn i32(data: *const i32, name: &str) {
  unsafe { any(transmute(data), 4, name); }
}

pub fn u32(data: *const u32, name: &str) {
  unsafe { any(transmute(data), 4, name); }
}

pub fn str(data: *const [u8], name: &str) {
  unsafe { any(transmute(data), data.len(), name); }
}
<commit_msg>Update lib.rs<commit_after>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::transmute;

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
}

pub fn any(data: *const raw::c_void, length: usize, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(data, length as libc::size_t, name_cstr.as_ptr());
  }
}

pub fn i32(data: *const i32, name: &str) {
  unsafe { any(transmute(data), 4, name); }
}

pub fn u32(data: *const u32, name: &str) {
  unsafe { any(transmute(data), 4, name); }
}

pub fn bytes(data: *const [u8], name: &str) {
  unsafe { any(transmute(data), *data.len(), name); }
}
<|endoftext|>