<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str, ptr, mem};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char, c_void};
use super::simple_stream::bstream::Bstream;

extern "C" {
    fn register_writer_tx(tx: *mut c_void);
    fn register_stop_tx(tx: *mut c_void);
    fn to_c_test();
}

#[no_mangle]
pub extern "C" fn start(address: *const c_char,
    handler: extern fn(*const c_char, c_int),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    println!("Rust - start()");

    println!("Calling test external");
    unsafe {
        to_c_test();
    }

    let mut r_address;
    unsafe {
        r_address = CStr::from_ptr(address);
    }
    let s_address = r_address.to_bytes();
    let host_address = match str::from_utf8(s_address) {
        Ok(safe_str) => safe_str,
        Err(_) => {
            println!("Invalid host address");
            return -1 as c_int;
        }
    };

    println!("Rust - address: {}", host_address);

    // Create and register a way to kill this client
    let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    let kill_tx = k_tx.clone();
    let mut k_tx_ptr = Box::new(k_tx);

    println!("calling register_stop_tx");

    let mut k_tx_ptr_clone = k_tx_ptr.clone();
    unsafe {
        let mut k_tx_as_void_ptr: *mut c_void = mem::transmute(k_tx_ptr_clone);
        //register_stop_tx(&mut *k_tx_as_void_ptr);
    }
    //
    // // Writer thread's channel
    // let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    // let mut w_tx_ptr = Box::new(w_tx);
    // unsafe {
    //     register_writer_tx(&mut *w_tx_ptr);
    // }
    //
    // println!("Attempting connect to: {}", host_address);

    // let result = TcpStream::connect(host_address);
    // if result.is_err() {
    //     println!("Error connecting to {} - {}", host_address, result.unwrap_err());
    //     return -1 as c_int;
    // }
    // println!("Connected");
    // on_connect_handler();
    //
    // let stream = result.unwrap();
    // let client = Bstream::new(stream);
    //
    // let r_client = client.clone();
    // let r_kill_tx = kill_tx.clone();
    //
    // let w_client = client.clone();
    // let w_kill_tx = kill_tx.clone();
    //
    // // Start the reader thread
    // thread::Builder::new()
    //     .name("ReaderThread".to_string())
    //     .spawn(move||{
    //         reader_thread(r_client, handler, r_kill_tx)
    //     }).unwrap();
    //
    // // Start the writer thread
    // thread::Builder::new()
    //     .name("WriterThread".to_string())
    //     .spawn(move||{
    //         writer_thread(w_rx, w_client, w_kill_tx)
    //     }).unwrap();
    //
    // // Wait for the kill signal
    // match kill_rx.recv() {
    //     Ok(_) => { }
    //     Err(e) => {
    //         println!("Error on kill channel: {}", e);
    //         return -1 as c_int;
    //     }
    // };
    // on_disconnect_handler();

    // Exit out in standard C fashion
    0 as c_int
}

// /// Connects to the provided address, (eg "123.123.123.123:3000") and registers
// /// the on data received handler
// #[no_mangle]
// pub extern "C" fn connect(address: *const c_char,
//     handler: extern fn(*const c_char, c_int),
//     on_connect_handler: extern fn(),
//     on_disconnect_handler: extern fn()) -> c_int {
//
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//
//
//     78 as c_int
//
//
//     let mut r_address;
//     unsafe {
//         r_address = CStr::from_ptr(address);
//     }
//     let s_address = r_address.to_bytes();
//     let host_address = match str::from_utf8(s_address) {
//         Ok(safe_str) => safe_str,
//         Err(_) => {
//             println!("Invalid host address");
//             return -1 as c_int;
//         }
//     };
//
//     // Create and register a way to kill this client
//     let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
//     let kill_tx = k_tx.clone();
//     let mut k_tx_ptr = Box::new(k_tx);
//     unsafe {
//         register_stop_tx(&mut *k_tx_ptr);
//     }
//
//     // Writer thread's channel
//     let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
//     let mut w_tx_ptr = Box::new(w_tx);
//     unsafe {
//         register_writer_tx(&mut *w_tx_ptr);
//     }
//
//     println!("Attempting connect to: {}", host_address);
//
//     let result = TcpStream::connect(host_address);
//     if result.is_err() {
//         println!("Error connecting to {} - {}", host_address, result.unwrap_err());
//         return -1 as c_int;
//     }
//     println!("Connected");
//     on_connect_handler();
//
//     let stream = result.unwrap();
//     let client = Bstream::new(stream);
//
//     let r_client = client.clone();
//     let r_kill_tx = kill_tx.clone();
//
//     let w_client = client.clone();
//     let w_kill_tx = kill_tx.clone();
//
//     // Start the reader thread
//     thread::Builder::new()
//         .name("ReaderThread".to_string())
//         .spawn(move||{
//             reader_thread(r_client, handler, r_kill_tx)
//         }).unwrap();
//
//     // Start the writer thread
//     thread::Builder::new()
//         .name("WriterThread".to_string())
//         .spawn(move||{
//             writer_thread(w_rx, w_client, w_kill_tx)
//         }).unwrap();
//
//     // Wait for the kill signal
//     match kill_rx.recv() {
//         Ok(_) => { }
//         Err(e) => {
//             println!("Error on kill channel: {}", e);
//             return -1 as c_int;
//         }
//     };
//     on_disconnect_handler();
//
//     // Exit out in standard C fashion
//     0 as c_int
// }

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn send_to_writer(w_tx: *mut Sender<Vec<u8>>,
                                 buffer: *const c_char,
                                 count: c_int,
                                 k_tx: *mut Sender<()>) -> c_int {
    if count < 1 {
        println!("Error - count must be greater than zero");
        return -1 as c_int;
    }

    let num_elts = count as usize;
    let mut n_buffer = Vec::<u8>::with_capacity(num_elts);
    for x in 0..num_elts as isize {
        unsafe {
            n_buffer.push(ptr::read(buffer.offset(x)) as u8);
        }
    }

    unsafe {
        match (*w_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                println!("Error sending buffer: {}", e);
                let _ = (*k_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream,
                 event_handler: extern fn(*const c_char, c_int),
                 kill_tx: Sender<()>) {

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        event_handler(c_buffer.as_ptr(), buffer.len() as c_int);
                    }).unwrap();
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Reader thread finished");
    let _ = kill_tx.send(());
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream, kill_tx: Sender<()>) {
    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        println!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Writer thread finished");
    let _ = kill_tx.send(());
}
<commit_msg>Debugging<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str, ptr, mem};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char, c_void};
use super::simple_stream::bstream::Bstream;

extern "C" {
    fn register_writer_tx(tx: *mut c_void);
    fn register_stop_tx(tx: *mut c_void);
    fn to_c_test();
}

#[no_mangle]
pub extern "C" fn start(address: *const c_char,
    handler: extern fn(*const c_char, c_int),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    println!("Rust - start()");

    unsafe {
        // handler();
        on_connect_handler();
        on_disconnect_handler();
    }

    // println!("Calling test external");
    // unsafe {
    //     to_c_test();
    // }
    //
    // let mut r_address;
    // unsafe {
    //     r_address = CStr::from_ptr(address);
    // }
    // let s_address = r_address.to_bytes();
    // let host_address = match str::from_utf8(s_address) {
    //     Ok(safe_str) => safe_str,
    //     Err(_) => {
    //         println!("Invalid host address");
    //         return -1 as c_int;
    //     }
    // };
    //
    // println!("Rust - address: {}", host_address);
    //
    // // Create and register a way to kill this client
    // let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    // let kill_tx = k_tx.clone();
    // let mut k_tx_ptr = Box::new(k_tx);
    //
    // println!("calling register_stop_tx");
    //
    // let mut k_tx_ptr_clone = k_tx_ptr.clone();
    // unsafe {
    //     let mut k_tx_as_void_ptr: *mut c_void = mem::transmute(k_tx_ptr_clone);
    //     register_stop_tx(&mut *k_tx_as_void_ptr);
    // }
    //
    // // Writer thread's channel
    // let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    // let mut w_tx_ptr = Box::new(w_tx);
    // unsafe {
    //     register_writer_tx(&mut *w_tx_ptr);
    // }
    //
    // println!("Attempting connect to: {}", host_address);

    // let result = TcpStream::connect(host_address);
    // if result.is_err() {
    //     println!("Error connecting to {} - {}", host_address, result.unwrap_err());
    //     return -1 as c_int;
    // }
    // println!("Connected");
    // on_connect_handler();
    //
    // let stream = result.unwrap();
    // let client = Bstream::new(stream);
    //
    // let r_client = client.clone();
    // let r_kill_tx = kill_tx.clone();
    //
    // let w_client = client.clone();
    // let w_kill_tx = kill_tx.clone();
    //
    // // Start the reader thread
    // thread::Builder::new()
    //     .name("ReaderThread".to_string())
    //     .spawn(move||{
    //         reader_thread(r_client, handler, r_kill_tx)
    //     }).unwrap();
    //
    // // Start the writer thread
    // thread::Builder::new()
    //     .name("WriterThread".to_string())
    //     .spawn(move||{
    //         writer_thread(w_rx, w_client, w_kill_tx)
    //     }).unwrap();
    //
    // // Wait for the kill signal
    // match kill_rx.recv() {
    //     Ok(_) => { }
    //     Err(e) => {
    //         println!("Error on kill channel: {}", e);
    //         return -1 as c_int;
    //     }
    // };
    // on_disconnect_handler();

    // Exit out in standard C fashion
    0 as c_int
}

// /// Connects to the provided address, (eg "123.123.123.123:3000") and registers
// /// the on data received handler
// #[no_mangle]
// pub extern "C" fn connect(address: *const c_char,
//     handler: extern fn(*const c_char, c_int),
//     on_connect_handler: extern fn(),
//     on_disconnect_handler: extern fn()) -> c_int {
//
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//     println!("Rust - connect");
//
//
//     78 as c_int
//
//
//     let mut r_address;
//     unsafe {
//         r_address = CStr::from_ptr(address);
//     }
//     let s_address = r_address.to_bytes();
//     let host_address = match str::from_utf8(s_address) {
//         Ok(safe_str) => safe_str,
//         Err(_) => {
//             println!("Invalid host address");
//             return -1 as c_int;
//         }
//     };
//
//     // Create and register a way to kill this client
//     let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
//     let kill_tx = k_tx.clone();
//     let mut k_tx_ptr = Box::new(k_tx);
//     unsafe {
//         register_stop_tx(&mut *k_tx_ptr);
//     }
//
//     // Writer thread's channel
//     let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
//     let mut w_tx_ptr = Box::new(w_tx);
//     unsafe {
//         register_writer_tx(&mut *w_tx_ptr);
//     }
//
//     println!("Attempting connect to: {}", host_address);
//
//     let result = TcpStream::connect(host_address);
//     if result.is_err() {
//         println!("Error connecting to {} - {}", host_address, result.unwrap_err());
//         return -1 as c_int;
//     }
//     println!("Connected");
//     on_connect_handler();
//
//     let stream = result.unwrap();
//     let client = Bstream::new(stream);
//
//     let r_client = client.clone();
//     let r_kill_tx = kill_tx.clone();
//
//     let w_client = client.clone();
//     let w_kill_tx = kill_tx.clone();
//
//     // Start the reader thread
//     thread::Builder::new()
//         .name("ReaderThread".to_string())
//         .spawn(move||{
//             reader_thread(r_client, handler, r_kill_tx)
//         }).unwrap();
//
//     // Start the writer thread
//     thread::Builder::new()
//         .name("WriterThread".to_string())
//         .spawn(move||{
//             writer_thread(w_rx, w_client, w_kill_tx)
//         }).unwrap();
//
//     // Wait for the kill signal
//     match kill_rx.recv() {
//         Ok(_) => { }
//         Err(e) => {
//             println!("Error on kill channel: {}", e);
//             return -1 as c_int;
//         }
//     };
//     on_disconnect_handler();
//
//     // Exit out in standard C fashion
//     0 as c_int
// }

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn send_to_writer(w_tx: *mut Sender<Vec<u8>>,
                                 buffer: *const c_char,
                                 count: c_int,
                                 k_tx: *mut Sender<()>) -> c_int {
    if count < 1 {
        println!("Error - count must be greater than zero");
        return -1 as c_int;
    }

    let num_elts = count as usize;
    let mut n_buffer = Vec::<u8>::with_capacity(num_elts);
    for x in 0..num_elts as isize {
        unsafe {
            n_buffer.push(ptr::read(buffer.offset(x)) as u8);
        }
    }

    unsafe {
        match (*w_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                println!("Error sending buffer: {}", e);
                let _ = (*k_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream,
                 event_handler: extern fn(*const c_char, c_int),
                 kill_tx: Sender<()>) {

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        event_handler(c_buffer.as_ptr(), buffer.len() as c_int);
                    }).unwrap();
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Reader thread finished");
    let _ = kill_tx.send(());
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream, kill_tx: Sender<()>) {
    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        println!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Writer thread finished");
    let _ = kill_tx.send(());
}
<|endoftext|>


<commit_before>//! Hyper client bindings for unix domain sockets

// Std lib
use std::io;

// Third party
use futures::future::{self, FutureResult};
use futures::{Future, IntoFuture};
use hyper::client::connect::{Connect, Connected, Destination};
use tokio_uds::UnixStream;

use super::Uri;

const UNIX_SCHEME: &str = "unix";

/// A type which implements hyper's client connector interface
/// for unix domain sockets
///
/// `UnixConnector` instances assume uri's
/// constructued with `hyperlocal::Uri::new()` which produce uris with a `unix://`
/// scheme
///
/// # examples
///
/// ```no_run
/// extern crate hyper;
/// extern crate hyperlocal;
///
/// let client = hyper::Client::builder()
///    .build::<_, hyper::Body>(hyperlocal::UnixConnector::new());
/// ```
#[derive(Clone)]
pub struct UnixConnector;

impl UnixConnector {
    pub fn new() -> Self {
        UnixConnector
    }
}

impl Connect for UnixConnector {
    type Transport = UnixStream;
    type Error = io::Error;
    type Future = FutureResult<(UnixStream, Connected), io::Error>;

    fn connect(&self, destination: Destination) -> Self::Future {
        if destination.scheme() != UNIX_SCHEME {
            return future::err(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("Invalid uri {:?}", destination),
            ));
        }
        match Uri::socket_path_dest(&destination) {
            Some(ref path) => UnixStream::connect(path)
                                .wait() // We have to block because we
                                .map(|s| (s, Connected::new()))
                                .into_future(),
            _ => future::err(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("Invalid uri {:?}", destination),
            )),
        }
    }
}
<commit_msg>Fix use of blocking wait() that can stall the runtime.<commit_after>//! Hyper client bindings for unix domain sockets

// Std lib
use std::io;

// Third party
use futures::{Async, Future, Poll};
use hyper::client::connect::{Connect, Connected, Destination};
use tokio_uds::{ConnectFuture as StreamConnectFuture, UnixStream};

use super::Uri;

const UNIX_SCHEME: &str = "unix";

/// A type which implements hyper's client connector interface
/// for unix domain sockets
///
/// `UnixConnector` instances assume uri's
/// constructued with `hyperlocal::Uri::new()` which produce uris with a `unix://`
/// scheme
///
/// # examples
///
/// ```no_run
/// extern crate hyper;
/// extern crate hyperlocal;
///
/// let client = hyper::Client::builder()
///    .build::<_, hyper::Body>(hyperlocal::UnixConnector::new());
/// ```
#[derive(Clone)]
pub struct UnixConnector;

impl UnixConnector {
    pub fn new() -> Self {
        UnixConnector
    }
}

impl Connect for UnixConnector {
    type Transport = UnixStream;
    type Error = io::Error;
    type Future = ConnectFuture;

    fn connect(&self, destination: Destination) -> Self::Future {
        ConnectFuture::Start(destination)
    }
}

pub enum ConnectFuture {
    Start(Destination),
    Connect(StreamConnectFuture),
}

impl Future for ConnectFuture {
    type Item = (UnixStream, Connected);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            let next_state = match self {
                ConnectFuture::Start(destination) => {
                    if destination.scheme() != UNIX_SCHEME {
                        return Err(io::Error::new(
                            io::ErrorKind::InvalidInput,
                            format!("Invalid uri {:?}", destination),
                        ));
                    }

                    let path = match Uri::socket_path_dest(&destination) {
                        Some(path) => path,

                        None => return Err(io::Error::new(
                            io::ErrorKind::InvalidInput,
                            format!("Invalid uri {:?}", destination),
                        )),
                    };

                    ConnectFuture::Connect(UnixStream::connect(&path))
                },

                ConnectFuture::Connect(f) => match f.poll() {
                    Ok(Async::Ready(stream)) => return Ok(Async::Ready((stream, Connected::new()))),
                    Ok(Async::NotReady) => return Ok(Async::NotReady),
                    Err(err) => return Err(err),
                },
            };

            *self = next_state;
        }
    }
}
<|endoftext|>


<commit_before>extern crate rustyline;

fn main() {
    rustyline::readline();
}
<commit_msg>Update example to match against Option<String> returned by readline<commit_after>extern crate rustyline;

fn main() {
    let readline = rustyline::readline();
    match readline {
        Some(line) => println!("Line: {:?}",line),
        None       => println!("No input"),
    }
}
<|endoftext|>


<commit_before>use std::result;
mod operand;
use operand::Operand;
extern crate r68k_common;
use r68k_common::constants::*;
mod constants;
use constants::*;

mod memory;
use memory::Memory;
mod assembler;
mod disassembler;

// type alias for exception handling
pub type Result<T> = result::Result<T, Exception>;
type OperandDecoder = fn(u16, Size, u32, &Memory) -> Vec<Operand>;
type InstructionEncoder = fn(&OpcodeInstance, u16, u32, &mut Memory) -> u32;
type InstructionSelector = fn(&OpcodeInstance) -> bool;
extern crate regex;

#[derive(Debug)]
pub enum Exception {
     IllegalInstruction(u16, u32), // ir, pc
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Size {
	Unsized, Byte, Word, Long
}

impl fmt::Display for Size {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Size::Unsized => write!(f, ""),
            Size::Byte => write!(f, ".B"),
            Size::Word => write!(f, ".W"),
            Size::Long => write!(f, ".L"),
        }
    }
}

// #[derive(Clone, Copy)]
pub struct OpcodeInfo<'a> {
    mask: u32,
    matching: u32,
    ea_mask: u16,
    size: Size,
    decoder: OperandDecoder,
    mnemonic: &'a str,
    encoder: InstructionEncoder,
    selector: InstructionSelector,
}
#[derive(Debug)]
pub struct OpcodeInstance<'a> {
    mnemonic: &'a str,
    size: Size,
	operands: Vec<Operand>,
}

use std::fmt;
impl<'a> fmt::Debug for OpcodeInfo<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            _ => write!(f, "[some fn]"),
        }
    }
}
impl<'a> fmt::Display for OpcodeInstance<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.operands.len() {
            0 => write!(f, "{}{}", self.mnemonic, self.size),
            1 => write!(f, "{}{}\t{}", self.mnemonic, self.size, self.operands[0]),
            2 => write!(f, "{}{}\t{},{}", self.mnemonic, self.size, self.operands[0], self.operands[1]),
            _ => panic!("more than two operands {:?}", self)
        }
    }
}
impl<'a> OpcodeInstance<'a> {
    pub fn length(&self) -> u32 {
        1 + self.operands.iter().map(|op| op.extension_words()).fold(0, |i,j|i+j)
    }
}
macro_rules! instruction {
    ($mask:expr, $matching:expr, $ea_mask:expr, $size:expr, $mnemonic:expr, $decoder:ident) => (OpcodeInfo { mask: $mask, matching: $matching, size: $size, mnemonic: $mnemonic, decoder: disassembler::$decoder, encoder: assembler::nop_encoder, selector: assembler::nop_selector, ea_mask: $ea_mask});
    ($mask:expr, $matching:expr, $ea_mask:expr, $size:expr, $mnemonic:expr, $decoder:ident, $selector:ident, $encoder:ident) => (OpcodeInfo { mask: $mask, matching: $matching, size: $size, mnemonic: $mnemonic, decoder: disassembler::$decoder, encoder: assembler::$encoder, selector: assembler::$selector, ea_mask: $ea_mask})
}
fn generate<'a>() -> Vec<OpcodeInfo<'a>> {
    vec![
        instruction!(MASK_OUT_X_EA, OP_ADD | BYTE_SIZED | DEST_EA, EA_MEMORY_ALTERABLE, Size::Byte, "ADD", decode_dx_ea, is_dx_ea, encode_dx_ea),
        instruction!(MASK_OUT_X_EA, OP_ADD | BYTE_SIZED | DEST_DX, EA_ALL_EXCEPT_AN, Size::Byte, "ADD", decode_ea_dx, is_ea_dx, encode_ea_dx),
        instruction!(MASK_OUT_X_EA, OP_ADD | WORD_SIZED | DEST_EA, EA_MEMORY_ALTERABLE, Size::Word, "ADD", decode_dx_ea, is_dx_ea, encode_dx_ea),
        instruction!(MASK_OUT_X_EA, OP_ADD | WORD_SIZED | DEST_DX, EA_ALL, Size::Word, "ADD", decode_ea_dx, is_ea_dx, encode_ea_dx),
        instruction!(MASK_OUT_X_EA, OP_ADD | LONG_SIZED | DEST_EA, EA_MEMORY_ALTERABLE, Size::Long, "ADD", decode_dx_ea, is_dx_ea, encode_dx_ea),
        instruction!(MASK_OUT_X_EA, OP_ADD | LONG_SIZED | DEST_DX, EA_ALL, Size::Long, "ADD", decode_ea_dx, is_ea_dx, encode_ea_dx),
        instruction!(MASK_OUT_X_EA, OP_ADD | DEST_AX_WORD, EA_ALL, Size::Word, "ADDA", decode_ea_ax, is_ea_ax, encode_ea_ax),
        instruction!(MASK_OUT_X_EA, OP_ADD | DEST_AX_LONG, EA_ALL, Size::Long, "ADDA", decode_ea_ax, is_ea_ax, encode_ea_ax),
        instruction!(MASK_OUT_EA, OP_ADDI | BYTE_SIZED, EA_DATA_ALTERABLE, Size::Byte, "ADDI", decode_imm_ea, is_imm_ea, encode_imm_ea),
        instruction!(MASK_OUT_EA, OP_ADDI | WORD_SIZED, EA_DATA_ALTERABLE, Size::Word, "ADDI", decode_imm_ea, is_imm_ea, encode_imm_ea),
        instruction!(MASK_OUT_EA, OP_ADDI | LONG_SIZED, EA_DATA_ALTERABLE, Size::Long, "ADDI", decode_imm_ea, is_imm_ea, encode_imm_ea),
    ]
}

#[cfg(test)]
mod tests {
    use operand::Operand;
    use memory::{MemoryVec, Memory};
    use assembler::{Assembler, encode_instruction};
    use disassembler::{disassemble, disassemble_first};

    use super::{Size, Exception};
    use regex::Regex;

    extern crate itertools;
    use self::itertools::assert_equal;
    #[test]
    fn roundtrips_from_opcode() {
        let opcode = 0xd511;
        let mut mem = &mut MemoryVec { mem: vec![opcode]} ;
        let asm = {
            let inst = disassemble_first(mem);
            format!("{}", inst)
        };
        let pc = 0;
        let a = Assembler::new();
        let inst = a.parse_assembler(asm.as_str());
        let new_pc = encode_instruction(asm.as_str(), &inst, pc, mem);
        assert_eq!(2, new_pc);
        assert_eq!(opcode, mem.read_word(pc));
    }
    #[test]
    fn roundtrips_from_asm() {
        let mut mem = &mut MemoryVec { mem: vec![0x00,0x00,0x00,0x00]} ;
        let pc = 0;
        let asm = "ADD.B\tD2,(A1)";
        let a = Assembler::new();
        let inst = a.parse_assembler(asm);
        encode_instruction(asm, &inst, pc, mem);
        let inst = disassemble_first(mem);

        assert_eq!(asm, format!("{}", inst));
    }

    fn opcodes(mask: u32, matching: u32) -> Vec<u16> {
        (matching..0x10000u32)
            .filter(|opcode| (opcode & mask) == matching)
            .map(|v|v as u16).collect::<Vec<u16>>()
    }

    #[test]
    #[ignore]
    fn roundtrips() {
        let a = Assembler::new();
        for opcode in 0x0600..0xe000 {
            let pc = 0;
            let extension_word_mask = 0b1111_1000_1111_1111;
            // bits 8-10 should always be zero in the ea extension word
            // as we don't know which word will be seen as the ea extension word
            // (as opposed to immediate operand values) just make sure these aren't set.
            let dasm_mem = &mut MemoryVec { mem: vec![opcode, 0x001f, 0x00a4, 0x1234 & extension_word_mask, 0x5678 & extension_word_mask]} ;
            match disassemble(pc, dasm_mem) {
                Err(Exception::IllegalInstruction(opcode, _)) => println!("{:04x}:\t\tinvalid", opcode),
                Ok(inst) => {
                    let asm = format!("{}", inst);
                    let inst = a.parse_assembler(asm.as_str());
                    let mut asm_mem = &mut MemoryVec { mem: vec![0x0000, 0x0000, 0x0000, 0x0000, 0x0000]};
                    let new_pc = encode_instruction(asm.as_str(), &inst, pc, asm_mem);
                    assert_eq!(inst.length()*2, new_pc);
                    let new_opcode = asm_mem.read_word(pc);
                    if opcode != new_opcode {
                        panic!("{:04x} | {:04x}: {}", opcode, new_opcode, asm);
                    } else {
                        println!("{:04x}: {}", opcode, asm);
                    }
                    if inst.length() > 1 {
                        let old_ex1 = dasm_mem.read_word(pc+2);
                        let new_ex1 = asm_mem.read_word(pc+2);
                        if old_ex1 != new_ex1 {println!("ew1")};
                        assert_eq!(old_ex1, new_ex1);
                    };
                    if inst.length() > 2 {
                        let old_ex2 = dasm_mem.read_word(pc+4);
                        let new_ex2 = asm_mem.read_word(pc+4);
                        if old_ex2 != new_ex2 {println!("ew2")};
                        assert_eq!(old_ex2, new_ex2);
                    };
                    if inst.length() > 3 {
                        let old_ex3 = dasm_mem.read_word(pc+6);
                        let new_ex3 = asm_mem.read_word(pc+6);
                        if old_ex3 != new_ex3 {println!("ew3")};
                        assert_eq!(old_ex3, new_ex3);
                    };
                }
            }
        }
    }
}<commit_msg>Make assembler/disassembler modules public<commit_after>use std::result;
mod operand;
use operand::Operand;
extern crate r68k_common;
use r68k_common::constants::*;
mod constants;
use constants::*;

mod memory;
use memory::Memory;
pub mod assembler;
pub mod disassembler;

// type alias for exception handling
pub type Result<T> = result::Result<T, Exception>;
type OperandDecoder = fn(u16, Size, u32, &Memory) -> Vec<Operand>;
type InstructionEncoder = fn(&OpcodeInstance, u16, u32, &mut Memory) -> u32;
type InstructionSelector = fn(&OpcodeInstance) -> bool;
extern crate regex;

#[derive(Debug)]
pub enum Exception {
     IllegalInstruction(u16, u32), // ir, pc
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Size {
	Unsized, Byte, Word, Long
}

impl fmt::Display for Size {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Size::Unsized => write!(f, ""),
            Size::Byte => write!(f, ".B"),
            Size::Word => write!(f, ".W"),
            Size::Long => write!(f, ".L"),
        }
    }
}

// #[derive(Clone, Copy)]
pub struct OpcodeInfo<'a> {
    mask: u32,
    matching: u32,
    ea_mask: u16,
    size: Size,
    decoder: OperandDecoder,
    mnemonic: &'a str,
    encoder: InstructionEncoder,
    selector: InstructionSelector,
}
#[derive(Debug)]
pub struct OpcodeInstance<'a> {
    mnemonic: &'a str,
    size: Size,
	operands: Vec<Operand>,
}

use std::fmt;
impl<'a> fmt::Debug for OpcodeInfo<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            _ => write!(f, "[some fn]"),
        }
    }
}
impl<'a> fmt::Display for OpcodeInstance<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.operands.len() {
            0 => write!(f, "{}{}", self.mnemonic, self.size),
            1 => write!(f, "{}{}\t{}", self.mnemonic, self.size, self.operands[0]),
            2 => write!(f, "{}{}\t{},{}", self.mnemonic, self.size, self.operands[0], self.operands[1]),
            _ => panic!("more than two operands {:?}", self)
        }
    }
}
impl<'a> OpcodeInstance<'a> {
    pub fn length(&self) -> u32 {
        1 + self.operands.iter().map(|op| op.extension_words()).fold(0, |i,j|i+j)
    }
}
macro_rules! instruction {
    ($mask:expr, $matching:expr, $ea_mask:expr, $size:expr, $mnemonic:expr, $decoder:ident) => (OpcodeInfo { mask: $mask, matching: $matching, size: $size, mnemonic: $mnemonic, decoder: disassembler::$decoder, encoder: assembler::nop_encoder, selector: assembler::nop_selector, ea_mask: $ea_mask});
    ($mask:expr, $matching:expr, $ea_mask:expr, $size:expr, $mnemonic:expr, $decoder:ident, $selector:ident, $encoder:ident) => (OpcodeInfo { mask: $mask, matching: $matching, size: $size, mnemonic: $mnemonic, decoder: disassembler::$decoder, encoder: assembler::$encoder, selector: assembler::$selector, ea_mask: $ea_mask})
}
fn generate<'a>() -> Vec<OpcodeInfo<'a>> {
    vec![
        instruction!(MASK_OUT_X_EA, OP_ADD | BYTE_SIZED | DEST_EA, EA_MEMORY_ALTERABLE, Size::Byte, "ADD", decode_dx_ea, is_dx_ea, encode_dx_ea),
        instruction!(MASK_OUT_X_EA, OP_ADD | BYTE_SIZED | DEST_DX, EA_ALL_EXCEPT_AN, Size::Byte, "ADD", decode_ea_dx, is_ea_dx, encode_ea_dx),
        instruction!(MASK_OUT_X_EA, OP_ADD | WORD_SIZED | DEST_EA, EA_MEMORY_ALTERABLE, Size::Word, "ADD", decode_dx_ea, is_dx_ea, encode_dx_ea),
        instruction!(MASK_OUT_X_EA, OP_ADD | WORD_SIZED | DEST_DX, EA_ALL, Size::Word, "ADD", decode_ea_dx, is_ea_dx, encode_ea_dx),
        instruction!(MASK_OUT_X_EA, OP_ADD | LONG_SIZED | DEST_EA, EA_MEMORY_ALTERABLE, Size::Long, "ADD", decode_dx_ea, is_dx_ea, encode_dx_ea),
        instruction!(MASK_OUT_X_EA, OP_ADD | LONG_SIZED | DEST_DX, EA_ALL, Size::Long, "ADD", decode_ea_dx, is_ea_dx, encode_ea_dx),
        instruction!(MASK_OUT_X_EA, OP_ADD | DEST_AX_WORD, EA_ALL, Size::Word, "ADDA", decode_ea_ax, is_ea_ax, encode_ea_ax),
        instruction!(MASK_OUT_X_EA, OP_ADD | DEST_AX_LONG, EA_ALL, Size::Long, "ADDA", decode_ea_ax, is_ea_ax, encode_ea_ax),
        instruction!(MASK_OUT_EA, OP_ADDI | BYTE_SIZED, EA_DATA_ALTERABLE, Size::Byte, "ADDI", decode_imm_ea, is_imm_ea, encode_imm_ea),
        instruction!(MASK_OUT_EA, OP_ADDI | WORD_SIZED, EA_DATA_ALTERABLE, Size::Word, "ADDI", decode_imm_ea, is_imm_ea, encode_imm_ea),
        instruction!(MASK_OUT_EA, OP_ADDI | LONG_SIZED, EA_DATA_ALTERABLE, Size::Long, "ADDI", decode_imm_ea, is_imm_ea, encode_imm_ea),
    ]
}

#[cfg(test)]
mod tests {
    use operand::Operand;
    use memory::{MemoryVec, Memory};
    use assembler::{Assembler, encode_instruction};
    use disassembler::{disassemble, disassemble_first};

    use super::{Size, Exception};
    use regex::Regex;

    extern crate itertools;
    use self::itertools::assert_equal;
    #[test]
    fn roundtrips_from_opcode() {
        let opcode = 0xd511;
        let mut mem = &mut MemoryVec { mem: vec![opcode]} ;
        let asm = {
            let inst = disassemble_first(mem);
            format!("{}", inst)
        };
        let pc = 0;
        let a = Assembler::new();
        let inst = a.parse_assembler(asm.as_str());
        let new_pc = encode_instruction(asm.as_str(), &inst, pc, mem);
        assert_eq!(2, new_pc);
        assert_eq!(opcode, mem.read_word(pc));
    }
    #[test]
    fn roundtrips_from_asm() {
        let mut mem = &mut MemoryVec { mem: vec![0x00,0x00,0x00,0x00]} ;
        let pc = 0;
        let asm = "ADD.B\tD2,(A1)";
        let a = Assembler::new();
        let inst = a.parse_assembler(asm);
        encode_instruction(asm, &inst, pc, mem);
        let inst = disassemble_first(mem);

        assert_eq!(asm, format!("{}", inst));
    }

    fn opcodes(mask: u32, matching: u32) -> Vec<u16> {
        (matching..0x10000u32)
            .filter(|opcode| (opcode & mask) == matching)
            .map(|v|v as u16).collect::<Vec<u16>>()
    }

    #[test]
    #[ignore]
    fn roundtrips() {
        let a = Assembler::new();
        for opcode in 0x0600..0xe000 {
            let pc = 0;
            let extension_word_mask = 0b1111_1000_1111_1111;
            // bits 8-10 should always be zero in the ea extension word
            // as we don't know which word will be seen as the ea extension word
            // (as opposed to immediate operand values) just make sure these aren't set.
            let dasm_mem = &mut MemoryVec { mem: vec![opcode, 0x001f, 0x00a4, 0x1234 & extension_word_mask, 0x5678 & extension_word_mask]} ;
            match disassemble(pc, dasm_mem) {
                Err(Exception::IllegalInstruction(opcode, _)) => println!("{:04x}:\t\tinvalid", opcode),
                Ok(inst) => {
                    let asm = format!("{}", inst);
                    let inst = a.parse_assembler(asm.as_str());
                    let mut asm_mem = &mut MemoryVec { mem: vec![0x0000, 0x0000, 0x0000, 0x0000, 0x0000]};
                    let new_pc = encode_instruction(asm.as_str(), &inst, pc, asm_mem);
                    assert_eq!(inst.length()*2, new_pc);
                    let new_opcode = asm_mem.read_word(pc);
                    if opcode != new_opcode {
                        panic!("{:04x} | {:04x}: {}", opcode, new_opcode, asm);
                    } else {
                        println!("{:04x}: {}", opcode, asm);
                    }
                    if inst.length() > 1 {
                        let old_ex1 = dasm_mem.read_word(pc+2);
                        let new_ex1 = asm_mem.read_word(pc+2);
                        if old_ex1 != new_ex1 {println!("ew1")};
                        assert_eq!(old_ex1, new_ex1);
                    };
                    if inst.length() > 2 {
                        let old_ex2 = dasm_mem.read_word(pc+4);
                        let new_ex2 = asm_mem.read_word(pc+4);
                        if old_ex2 != new_ex2 {println!("ew2")};
                        assert_eq!(old_ex2, new_ex2);
                    };
                    if inst.length() > 3 {
                        let old_ex3 = dasm_mem.read_word(pc+6);
                        let new_ex3 = asm_mem.read_word(pc+6);
                        if old_ex3 != new_ex3 {println!("ew3")};
                        assert_eq!(old_ex3, new_ex3);
                    };
                }
            }
        }
    }
}<|endoftext|>


<commit_before>/*!
`crypto_secretbox_xsalsa20poly1305`, a particular
combination of Salsa20 and Poly1305 specified in
[Cryptography in NaCl](http://nacl.cr.yp.to/valid.html).

This function is conjectured to meet the standard notions of privacy and
authenticity.
*/
use libc::{c_ulonglong, c_int};
use std::intrinsics::volatile_set_memory;
use utils::marshal;
use randombytes::randombytes_into;

#[link(name = "sodium")]
extern {
    fn crypto_secretbox_xsalsa20poly1305(c: *mut u8,
                                         m: *const u8,
                                         mlen: c_ulonglong,
                                         n: *const u8,
                                         k: *const u8) -> c_int;
    fn crypto_secretbox_xsalsa20poly1305_open(m: *mut u8,
                                              c: *const u8,
                                              clen: c_ulonglong,
                                              n: *const u8,
                                              k: *const u8) -> c_int;
}

pub const KEYBYTES: uint = 32;
pub const NONCEBYTES: uint = 24;

/**
 * `Key` for symmetric authenticated encryption
 *
 * When a `Key` goes out of scope its contents
 * will be zeroed out
 */
pub struct Key(pub [u8, ..KEYBYTES]);

newtype_drop!(Key)
newtype_clone!(Key)

/**
 * `Nonce` for symmetric authenticated encryption
 */
pub struct Nonce(pub [u8, ..NONCEBYTES]);

newtype_clone!(Nonce)

pub static ZEROBYTES: uint = 32;
pub static BOXZEROBYTES: uint = 16;

/**
 * `gen_key()` randomly generates a secret key
 *
 * THREAD SAFETY: `gen_key()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
pub fn gen_key() -> Key {
    let mut key = [0, ..KEYBYTES];
    randombytes_into(key);
    Key(key)
}

/**
 * `gen_nonce()` randomly generates a nonce
 *
 * THREAD SAFETY: `gen_key()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
pub fn gen_nonce() -> Nonce {
    let mut nonce = [0, ..NONCEBYTES];
    randombytes_into(nonce);
    Nonce(nonce)
}

/**
 * `seal()` encrypts and authenticates a message `m` using a secret key `k` and a
 * nonce `n`.  It returns a ciphertext `c`.
 */
pub fn seal(m: &[u8],
            &Nonce(n): &Nonce,
            &Key(k): &Key) -> Vec<u8> {
    let (c, _) = marshal(m, ZEROBYTES, BOXZEROBYTES, |dst, src, len| {
        unsafe {
            crypto_secretbox_xsalsa20poly1305(dst, src, len, n.as_ptr(), k.as_ptr())
        }
    });
    c
}

/**
 * `open()` verifies and decrypts a ciphertext `c` using a secret key `k` and a nonce `n`.
 * It returns a plaintext `Some(m)`.
 * If the ciphertext fails verification, `open()` returns `None`.
 */
pub fn open(c: &[u8],
            &Nonce(n): &Nonce,
            &Key(k): &Key) -> Option<Vec<u8>> {
    if c.len() < BOXZEROBYTES {
        return None
    }
    let (m, ret) = marshal(c, BOXZEROBYTES, ZEROBYTES, |dst, src, len| {
        unsafe {
            crypto_secretbox_xsalsa20poly1305_open(dst,
                                                   src,
                                                   len,
                                                   n.as_ptr(),
                                                   k.as_ptr())
        }
    });
    if ret == 0 {
        Some(m)
    } else {
        None
    }
}

#[test]
fn test_seal_open() {
    use randombytes::randombytes;
    for i in range(0, 256u) {
        let k = gen_key();
        let m = randombytes(i);
        let n = gen_nonce();
        let c = seal(m.as_slice(), &n, &k);
        let opened = open(c.as_slice(), &n, &k);
        assert!(Some(m) == opened);
    }
}

#[test]
fn test_seal_open_tamper() {
    use randombytes::randombytes;
    for i in range(0, 32u) {
        let k = gen_key();
        let m = randombytes(i);
        let n = gen_nonce();
        let mut cv = seal(m.as_slice(), &n, &k);
        let c = cv.as_mut_slice();
        for i in range(0, c.len()) {
            c[i] ^= 0x20;
            assert!(None == open(c, &n, &k));
            c[i] ^= 0x20;
        }
    }
}

#[test]
fn test_vector_1() {
    let firstkey = Key([0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
                       ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
                       ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
                       ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89]);
    let nonce = Nonce([0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
                      ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
                      ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37]);
    let m = vec![0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
             ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
             ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
             ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
             ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
             ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
             ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
             ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
             ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
             ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
             ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
             ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
             ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
             ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
             ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
             ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
             ,0x5e,0x07,0x05];

    let c_expected = vec![0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
                      ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
                      ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
                      ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
                      ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
                      ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
                      ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
                      ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
                      ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
                      ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
                      ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
                      ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
                      ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
                      ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
                      ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
                      ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
                      ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
                      ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
                      ,0xe3,0x55,0xa5];
    let c = seal(m.as_slice(), &nonce, &firstkey);
    assert!(c == c_expected);
    let m2 = open(c.as_slice(), &nonce, &firstkey);
    assert!(Some(m) == m2);
}
<commit_msg>make ZEROBYTES and BOXZEROBYTES const and hidden<commit_after>/*!
`crypto_secretbox_xsalsa20poly1305`, a particular
combination of Salsa20 and Poly1305 specified in
[Cryptography in NaCl](http://nacl.cr.yp.to/valid.html).

This function is conjectured to meet the standard notions of privacy and
authenticity.
*/
use libc::{c_ulonglong, c_int};
use std::intrinsics::volatile_set_memory;
use utils::marshal;
use randombytes::randombytes_into;

#[link(name = "sodium")]
extern {
    fn crypto_secretbox_xsalsa20poly1305(c: *mut u8,
                                         m: *const u8,
                                         mlen: c_ulonglong,
                                         n: *const u8,
                                         k: *const u8) -> c_int;
    fn crypto_secretbox_xsalsa20poly1305_open(m: *mut u8,
                                              c: *const u8,
                                              clen: c_ulonglong,
                                              n: *const u8,
                                              k: *const u8) -> c_int;
}

pub const KEYBYTES: uint = 32;
pub const NONCEBYTES: uint = 24;

/**
 * `Key` for symmetric authenticated encryption
 *
 * When a `Key` goes out of scope its contents
 * will be zeroed out
 */
pub struct Key(pub [u8, ..KEYBYTES]);

newtype_drop!(Key)
newtype_clone!(Key)

/**
 * `Nonce` for symmetric authenticated encryption
 */
pub struct Nonce(pub [u8, ..NONCEBYTES]);

newtype_clone!(Nonce)

const ZEROBYTES: uint = 32;
const BOXZEROBYTES: uint = 16;

/**
 * `gen_key()` randomly generates a secret key
 *
 * THREAD SAFETY: `gen_key()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
pub fn gen_key() -> Key {
    let mut key = [0, ..KEYBYTES];
    randombytes_into(key);
    Key(key)
}

/**
 * `gen_nonce()` randomly generates a nonce
 *
 * THREAD SAFETY: `gen_key()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
pub fn gen_nonce() -> Nonce {
    let mut nonce = [0, ..NONCEBYTES];
    randombytes_into(nonce);
    Nonce(nonce)
}

/**
 * `seal()` encrypts and authenticates a message `m` using a secret key `k` and a
 * nonce `n`.  It returns a ciphertext `c`.
 */
pub fn seal(m: &[u8],
            &Nonce(n): &Nonce,
            &Key(k): &Key) -> Vec<u8> {
    let (c, _) = marshal(m, ZEROBYTES, BOXZEROBYTES, |dst, src, len| {
        unsafe {
            crypto_secretbox_xsalsa20poly1305(dst, src, len, n.as_ptr(), k.as_ptr())
        }
    });
    c
}

/**
 * `open()` verifies and decrypts a ciphertext `c` using a secret key `k` and a nonce `n`.
 * It returns a plaintext `Some(m)`.
 * If the ciphertext fails verification, `open()` returns `None`.
 */
pub fn open(c: &[u8],
            &Nonce(n): &Nonce,
            &Key(k): &Key) -> Option<Vec<u8>> {
    if c.len() < BOXZEROBYTES {
        return None
    }
    let (m, ret) = marshal(c, BOXZEROBYTES, ZEROBYTES, |dst, src, len| {
        unsafe {
            crypto_secretbox_xsalsa20poly1305_open(dst,
                                                   src,
                                                   len,
                                                   n.as_ptr(),
                                                   k.as_ptr())
        }
    });
    if ret == 0 {
        Some(m)
    } else {
        None
    }
}

#[test]
fn test_seal_open() {
    use randombytes::randombytes;
    for i in range(0, 256u) {
        let k = gen_key();
        let m = randombytes(i);
        let n = gen_nonce();
        let c = seal(m.as_slice(), &n, &k);
        let opened = open(c.as_slice(), &n, &k);
        assert!(Some(m) == opened);
    }
}

#[test]
fn test_seal_open_tamper() {
    use randombytes::randombytes;
    for i in range(0, 32u) {
        let k = gen_key();
        let m = randombytes(i);
        let n = gen_nonce();
        let mut cv = seal(m.as_slice(), &n, &k);
        let c = cv.as_mut_slice();
        for i in range(0, c.len()) {
            c[i] ^= 0x20;
            assert!(None == open(c, &n, &k));
            c[i] ^= 0x20;
        }
    }
}

#[test]
fn test_vector_1() {
    let firstkey = Key([0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
                       ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
                       ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
                       ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89]);
    let nonce = Nonce([0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
                      ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
                      ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37]);
    let m = vec![0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
             ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
             ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
             ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
             ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
             ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
             ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
             ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
             ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
             ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
             ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
             ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
             ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
             ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
             ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
             ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
             ,0x5e,0x07,0x05];

    let c_expected = vec![0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
                      ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
                      ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
                      ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
                      ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
                      ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
                      ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
                      ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
                      ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
                      ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
                      ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
                      ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
                      ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
                      ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
                      ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
                      ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
                      ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
                      ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
                      ,0xe3,0x55,0xa5];
    let c = seal(m.as_slice(), &nonce, &firstkey);
    assert!(c == c_expected);
    let m2 = open(c.as_slice(), &nonce, &firstkey);
    assert!(Some(m) == m2);
}
<|endoftext|>


<commit_before>#[derive(Debug, PartialEq, Eq)]
pub struct Palindrome {
    v: Vec<(u64, u64)>,
}

impl Palindrome {
    pub fn new(a: u64, b: u64) -> Palindrome {
        Palindrome { v: vec![(a, b)] }
    }

    pub fn insert(&mut self, a: u64, b: u64) {
        self.v.push((a, b))
    }
}

fn is_palindrome(value: u64) -> bool {
    let mut v = value;
    let mut r = 0;

    while v > 0 {
        r = r * 10 + v % 10;
        v /= 10;
    }

    r == value
}

pub fn palindrome_products(min: u64, max: u64) -> Option<(Palindrome, Palindrome)> {
    if min > max {
        return None;
    }

    let mut min_value = u64::MAX;
    let mut max_value = u64::MIN;

    let mut min_set = Palindrome::new(0, 0);
    let mut max_set = Palindrome::new(0, 0);

    for i in min..=max {
        for j in i..=max {
            let v = i * j;
            if !is_palindrome(v) {
                continue;
            }

            if v < min_value {
                min_value = v;
                min_set = Palindrome::new(i, j);
            } else if v == min_value {
                min_set.insert(i, j);
            } else if v > max_value {
                max_value = v;
                max_set = Palindrome::new(i, j);
            } else if v == max_value {
                max_set.insert(i, j);
            }
        }
    }

    if min_value == u64::MAX {
        None
    } else {
        Some((min_set, max_set))
    }
}
<commit_msg>Use std::cmp::Ordering<commit_after>use std::cmp::Ordering;

#[derive(Debug, PartialEq, Eq)]
pub struct Palindrome {
    v: Vec<(u64, u64)>,
}

impl Palindrome {
    pub fn new(a: u64, b: u64) -> Palindrome {
        Palindrome { v: vec![(a, b)] }
    }

    //pub fn value(&self) -> u64 {
    //    unimplemented!("return the value of this palindrome")
    //}

    pub fn insert(&mut self, a: u64, b: u64) {
        self.v.push((a, b))
    }
}

fn is_palindrome(value: u64) -> bool {
    let mut v = value;
    let mut r = 0;

    while v > 0 {
        r = r * 10 + v % 10;
        v /= 10;
    }

    r == value
}

pub fn palindrome_products(min: u64, max: u64) -> Option<(Palindrome, Palindrome)> {
    if min > max {
        return None;
    }

    let mut min_value = u64::MAX;
    let mut max_value = u64::MIN;

    let mut min_set = Palindrome::new(0, 0);
    let mut max_set = Palindrome::new(0, 0);

    for i in min..=max {
        for j in i..=max {
            let v = i * j;
            if !is_palindrome(v) {
                continue;
            }

            match v.cmp(&min_value) {
                Ordering::Less => {
                    min_value = v;
                    min_set = Palindrome::new(i, j);
                }
                Ordering::Equal => {
                    min_set.insert(i, j);
                }
                _ => {}
            }

            match v.cmp(&max_value) {
                Ordering::Greater => {
                    max_value = v;
                    max_set = Palindrome::new(i, j);
                }
                Ordering::Equal => {
                    max_set.insert(i, j);
                }
                _ => {}
            }
        }
    }

    if min_value == u64::MAX {
        None
    } else {
        Some((min_set, max_set))
    }
}
<|endoftext|>


<commit_before>extern crate regex;
extern crate toml;

use self::regex::Error as RegexError;
use self::toml::ParserError as ParseTomlError;

use constant::{self, ME};
use std::num::ParseIntError;
use std::error::Error;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::io::Error as IoError;

#[derive(Debug)]
pub enum CliError {
    Config(ConfigError),
    Cron(CronError),
    Essential(EssentialLack),
    Io(IoError),
    ParseInt(ParseIntError),
    ParseToml(ParseTomlError),
    Regex(RegexError),
    RunningPlace(RunningPlaceError),
    Usage(Usage),
}
impl Display for CliError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match *self {
            CliError::Config(ref e)       => e.fmt(f),
            CliError::Cron(ref e)         => e.fmt(f),
            CliError::Essential(ref e)    => e.fmt(f),
            CliError::Io(ref e)           => e.fmt(f),
            CliError::ParseInt(ref e)     => e.fmt(f),
            CliError::ParseToml(ref e)    => e.fmt(f),
            CliError::Regex(ref e)        => e.fmt(f),
            CliError::RunningPlace(ref e) => e.fmt(f),
            CliError::Usage(ref u)        => u.fmt(f),
        }
    }
}
impl Error for CliError {
    fn cause(&self) -> Option<&Error> {
        match *self {
            CliError::Config(ref e)       => Some(e),
            CliError::Cron(ref e)         => Some(e),
            CliError::Essential(ref e)    => Some(e),
            CliError::Io(ref e)           => Some(e),
            CliError::ParseInt(ref e)     => Some(e),
            CliError::ParseToml(ref e)    => Some(e),
            CliError::Regex(ref e)        => Some(e),
            CliError::RunningPlace(ref e) => Some(e),
            CliError::Usage(ref u)        => Some(u),
        }
    }

    fn description(&self) -> &str {
        match *self {
            CliError::Config(ref e)       => e.description(),
            CliError::Cron(ref e)         => e.description(),
            CliError::Essential(ref e)    => e.description(),
            CliError::Io(ref e)           => e.description(),
            CliError::ParseInt(ref e)     => e.description(),
            CliError::ParseToml(ref e)    => e.description(),
            CliError::Regex(ref e)        => e.description(),
            CliError::RunningPlace(ref e) => e.description(),
            CliError::Usage(ref u)        => u.description(),
        }
    }
}
impl From<ConfigError> for CliError {
    fn from(e: ConfigError) -> CliError {
        CliError::Config(e)
    }
}
impl From<CronError> for CliError {
    fn from(e: CronError) -> CliError {
        CliError::Cron(e)
    }
}
impl From<EssentialLack> for CliError {
    fn from(e: EssentialLack) -> CliError {
        CliError::Essential(e)
    }
}
impl From<IoError> for CliError {
    fn from(e: IoError) -> CliError {
        CliError::Io(e)
    }
}
impl From<ParseIntError> for CliError {
    fn from(e: ParseIntError) -> CliError {
        CliError::ParseInt(e)
    }
}
impl From<ParseTomlError> for CliError {
    fn from(e: ParseTomlError) -> CliError {
        CliError::ParseToml(e)
    }
}
impl From<RegexError> for CliError {
    fn from(e: RegexError) -> CliError {
        CliError::Regex(e)
    }
}
impl From<RunningPlaceError> for CliError {
    fn from(e: RunningPlaceError) -> CliError {
        CliError::RunningPlace(e)
    }
}
impl From<Usage> for CliError {
    fn from(u: Usage) -> CliError {
        CliError::Usage(u)
    }
}

#[derive(Debug, PartialEq)]
pub enum ConfigErrorKind {
    Something,
    InvalidKey,
    NonStringValue,
    NotFoundBurnAfter,
    NotFoundSweepPeriod,
    NotFoundSweepTime,
    BurnAfter,
    SweepPeriod,
    SweepTime,
}
#[derive(Debug, PartialEq)]
pub struct ConfigError {
    kind: ConfigErrorKind,
}
impl ConfigError {
    pub fn new(kind: ConfigErrorKind) -> ConfigError {
        ConfigError { kind: kind }
    }
}
impl Display for ConfigError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", match self.kind {
            ConfigErrorKind::Something           => r#"Something went to wrong"#,
            ConfigErrorKind::InvalidKey          => r#"Cannot set this key"#,
            ConfigErrorKind::NonStringValue      => r#"Please set values as "String""#,
            ConfigErrorKind::NotFoundBurnAfter   => r#"Please set [burn]after param"#,
            ConfigErrorKind::NotFoundSweepPeriod => r#"Please set [sweep]period param"#,
            ConfigErrorKind::NotFoundSweepTime   => r#"Please set [sweep]time param"#,
            ConfigErrorKind::BurnAfter           => r#"Please set value like "3days" or "1week" as "[burn]after""#,
            ConfigErrorKind::SweepPeriod         => r#"Please set "daily" or "weekly" as "[sweep]period""#,
            ConfigErrorKind::SweepTime           => r#"Please set value from "00:00" to "23:59" as "[sweep]time""#,
        })
    }
}
impl Error for ConfigError {
    fn description(&self) -> &str { "invalid parameters" }
}

#[derive(Debug, PartialEq)]
pub enum CronErrorKind {
    BinExistsInInvalidDir,
    InvalidCharacterCode,
    InvalidPath,
    FailedToWrite,
}
#[derive(Debug, PartialEq)]
pub struct CronError {
    kind: CronErrorKind,
}
impl CronError {
    pub fn new(kind: CronErrorKind) -> Self {
        CronError { kind: kind }
    }
}
impl Display for CronError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", match self.kind {
            CronErrorKind::BinExistsInInvalidDir => "The \"bin\" exists in directory whose path include non-UTF-8 charecter code",
            CronErrorKind::InvalidCharacterCode  => "The \"cron\" file consists of non-UTF-8 character code",
            CronErrorKind::InvalidPath           => "The path to current directory include non-UTF-8 character code",
            CronErrorKind::FailedToWrite         => "Failed to write new \"cron\" file"
        })
    }
}
impl Error for CronError {
    fn description(&self) -> &str { "problems around cron" }
}

#[derive(Debug, PartialEq)]
pub enum EssentialKind {
    WorkingDir,
    StorageDir,
    ConfigFile,
    IgnoreFile,
}
#[derive(Debug, PartialEq)]
pub struct EssentialLack {
    what: EssentialKind,
}
impl EssentialLack {
    pub fn new(what: EssentialKind) -> EssentialLack {
        EssentialLack { what: what }
    }
}
impl Display for EssentialLack {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{} does not exist", match self.what {
            EssentialKind::WorkingDir => format!("\"{}\" directory", constant::WORKING_DIR_NAME),
            EssentialKind::StorageDir => format!("\"{}\" directory", constant::STORAGE_DIR_NAME),
            EssentialKind::ConfigFile => format!("\"{}\" file"     , constant::CONFIG_FILE_NAME),
            EssentialKind::IgnoreFile => format!("\"{}\" file"     , constant::IGNORE_FILE_NAME),
        })
    }
}
impl Error for EssentialLack {
    fn description(&self) -> &str { "essential file does not exist" }
}

#[derive(Debug, PartialEq)]
pub struct RunningPlaceError {
    dir: String,
}
impl RunningPlaceError {
    pub fn new(dir: String) -> RunningPlaceError {
        RunningPlaceError { dir: dir }
    }
}
impl Display for RunningPlaceError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "Cannot run in \"{}\" directory", self.dir)
    }
}
impl Error for RunningPlaceError {
    fn description(&self) -> &str { "cannot run in banned directories" }
}

#[derive(Debug, PartialEq)]
pub enum UsageKind {
    Nothing,
    Help,
    Version,
    Init,
    Config,
    Ignore,
    Sweep,
    Burn,
    Start,
    End,
    Destroy,
    Patrol,
}
impl UsageKind {
    fn command(&self) -> &str {
        match *self {
            UsageKind::Nothing => "<Command>",
            UsageKind::Help    => "help",
            UsageKind::Version => "version",
            UsageKind::Init    => "init",
            UsageKind::Config  => "config",
            UsageKind::Ignore  => "ignore",
            UsageKind::Sweep   => "sweep",
            UsageKind::Burn    => "burn",
            UsageKind::Start   => "start",
            UsageKind::End     => "end",
            UsageKind::Destroy => "destroy",
            UsageKind::Patrol  => "patrol",
        }
    }

    fn common_usage(&self) -> String {
        format!("{} {}", ME, self.command())
    }

    fn usages(&self) -> Vec<String> {
        match *self {
            UsageKind::Help   => vec![format!("{} <SubCommand>", self.common_usage())],
            UsageKind::Config => vec![
                format!("{} set <Key> <Value>", self.common_usage()),
                format!("{} init"             , self.common_usage()),
            ],
            UsageKind::Ignore => vec![
                format!("{} add <File> ..."   , self.common_usage()),
                format!("{} remove <File> ...", self.common_usage()),
                format!("{} current"          , self.common_usage()),
                format!("{} clear"            , self.common_usage()),
            ],
            UsageKind::Sweep => vec![format!("{} [indeed]", self.common_usage())],
            UsageKind::Burn  => vec![format!("{} [indeed]", self.common_usage())],
            _ => vec![self.common_usage()],
        }
    }

    fn description(&self) -> &str {
        match *self {
            UsageKind::Nothing => "Keep your directories clean!",
            UsageKind::Help    => "Display usage for each command.",
            UsageKind::Version => "Display the version of this software.",
            UsageKind::Init    => "Register current directory.",
            UsageKind::Config  => "Change parameter.",
            UsageKind::Ignore  => "Change \"non-dust\" file's list.",
            UsageKind::Sweep   => "Sweep \"dust\" files and empty directories in current directory.",
            UsageKind::Burn    => "Burn \"sweeped\" files.",
            UsageKind::Start   => "Register with \"cron\" for autonomous operation.",
            UsageKind::End     => "Unregister from \"cron\".",
            UsageKind::Destroy => "Unregister current directory.",
            UsageKind::Patrol  => "Keep \"cron\" file clean.",
        }
    }

    fn sub_descriptions(&self) -> Vec<String> {
        match *self {
            UsageKind::Nothing => vec![
                format!("{}{}", "help    # ", UsageKind::Help   .description()),
                format!("{}{}", "version # ", UsageKind::Version.description()),
                format!("{}{}", "init    # ", UsageKind::Init   .description()),
                format!("{}{}", "config  # ", UsageKind::Config .description()),
                format!("{}{}", "ignore  # ", UsageKind::Ignore .description()),
                format!("{}{}", "sweep   # ", UsageKind::Sweep  .description()),
                format!("{}{}", "burn    # ", UsageKind::Burn   .description()),
                format!("{}{}", "start   # ", UsageKind::Start  .description()),
                format!("{}{}", "end     # ", UsageKind::End    .description()),
                format!("{}{}", "destroy # ", UsageKind::Destroy.description()),
                format!("{}{}", "patrol  # ", UsageKind::Patrol .description()),
            ],
            UsageKind::Config => vec![
                "set  # Set parameter"       .to_string(),
                "init # Initialize configure".to_string(),
            ],
            UsageKind::Ignore => {
                let file_expression = "\"non-dust\" file's list";
                vec![
                    format!("add     # Add specified files to {}"        , file_expression),
                    format!("remove  # Remove specified files from {}"   , file_expression),
                    format!("current # Replace {} with current all files", file_expression),
                    format!("clear   # Clear {}"                         , file_expression),
                ]
            },
            UsageKind::Sweep => vec![
                "(none) # Sweep \"dust\"s fakely".to_string(),
                "indeed # Sweep \"dust\"s indeed".to_string(),
            ],
            UsageKind::Burn => vec![
                "(none) # Burn expired \"dust box\"s fakely".to_string(),
                "indeed # Burn expired \"dust box\"s indeed".to_string(),
            ],
            _ => Vec::new(),
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct Usage {
    kind: UsageKind,
}
impl Usage {
    pub fn new(kind: UsageKind) -> Usage {
        Usage { kind: kind }
    }

    fn message(&self) -> String {
        let usage = self.kind
            .usages()
            .iter()
            .fold(String::new(), |message, line| {
                message + "    " + line + "\n"
            });

        let main = format!("Usage:\n{}\nDescription:\n    {}\n", usage, self.kind.description());

        let sub_description = self.kind
            .sub_descriptions()
            .iter()
            .fold(String::new(), |message, line| {
                message + "    " + line + "\n"
            });

        if sub_description.is_empty() {
            main
        } else {
            format!("{}{}{}", main, "\nCommand:\n", sub_description)
        }
    }
}
impl Display for Usage {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", self.message())
    }
}
impl Error for Usage {
    fn description(&self) -> &str { "show usage" }
}
<commit_msg>[Feature] Change help message for "sweep"<commit_after>extern crate regex;
extern crate toml;

use self::regex::Error as RegexError;
use self::toml::ParserError as ParseTomlError;

use constant::{self, ME};
use std::num::ParseIntError;
use std::error::Error;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::io::Error as IoError;

#[derive(Debug)]
pub enum CliError {
    Config(ConfigError),
    Cron(CronError),
    Essential(EssentialLack),
    Io(IoError),
    ParseInt(ParseIntError),
    ParseToml(ParseTomlError),
    Regex(RegexError),
    RunningPlace(RunningPlaceError),
    Usage(Usage),
}
impl Display for CliError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match *self {
            CliError::Config(ref e)       => e.fmt(f),
            CliError::Cron(ref e)         => e.fmt(f),
            CliError::Essential(ref e)    => e.fmt(f),
            CliError::Io(ref e)           => e.fmt(f),
            CliError::ParseInt(ref e)     => e.fmt(f),
            CliError::ParseToml(ref e)    => e.fmt(f),
            CliError::Regex(ref e)        => e.fmt(f),
            CliError::RunningPlace(ref e) => e.fmt(f),
            CliError::Usage(ref u)        => u.fmt(f),
        }
    }
}
impl Error for CliError {
    fn cause(&self) -> Option<&Error> {
        match *self {
            CliError::Config(ref e)       => Some(e),
            CliError::Cron(ref e)         => Some(e),
            CliError::Essential(ref e)    => Some(e),
            CliError::Io(ref e)           => Some(e),
            CliError::ParseInt(ref e)     => Some(e),
            CliError::ParseToml(ref e)    => Some(e),
            CliError::Regex(ref e)        => Some(e),
            CliError::RunningPlace(ref e) => Some(e),
            CliError::Usage(ref u)        => Some(u),
        }
    }

    fn description(&self) -> &str {
        match *self {
            CliError::Config(ref e)       => e.description(),
            CliError::Cron(ref e)         => e.description(),
            CliError::Essential(ref e)    => e.description(),
            CliError::Io(ref e)           => e.description(),
            CliError::ParseInt(ref e)     => e.description(),
            CliError::ParseToml(ref e)    => e.description(),
            CliError::Regex(ref e)        => e.description(),
            CliError::RunningPlace(ref e) => e.description(),
            CliError::Usage(ref u)        => u.description(),
        }
    }
}
impl From<ConfigError> for CliError {
    fn from(e: ConfigError) -> CliError {
        CliError::Config(e)
    }
}
impl From<CronError> for CliError {
    fn from(e: CronError) -> CliError {
        CliError::Cron(e)
    }
}
impl From<EssentialLack> for CliError {
    fn from(e: EssentialLack) -> CliError {
        CliError::Essential(e)
    }
}
impl From<IoError> for CliError {
    fn from(e: IoError) -> CliError {
        CliError::Io(e)
    }
}
impl From<ParseIntError> for CliError {
    fn from(e: ParseIntError) -> CliError {
        CliError::ParseInt(e)
    }
}
impl From<ParseTomlError> for CliError {
    fn from(e: ParseTomlError) -> CliError {
        CliError::ParseToml(e)
    }
}
impl From<RegexError> for CliError {
    fn from(e: RegexError) -> CliError {
        CliError::Regex(e)
    }
}
impl From<RunningPlaceError> for CliError {
    fn from(e: RunningPlaceError) -> CliError {
        CliError::RunningPlace(e)
    }
}
impl From<Usage> for CliError {
    fn from(u: Usage) -> CliError {
        CliError::Usage(u)
    }
}

#[derive(Debug, PartialEq)]
pub enum ConfigErrorKind {
    Something,
    InvalidKey,
    NonStringValue,
    NotFoundBurnAfter,
    NotFoundSweepPeriod,
    NotFoundSweepTime,
    BurnAfter,
    SweepPeriod,
    SweepTime,
}
#[derive(Debug, PartialEq)]
pub struct ConfigError {
    kind: ConfigErrorKind,
}
impl ConfigError {
    pub fn new(kind: ConfigErrorKind) -> ConfigError {
        ConfigError { kind: kind }
    }
}
impl Display for ConfigError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", match self.kind {
            ConfigErrorKind::Something           => r#"Something went to wrong"#,
            ConfigErrorKind::InvalidKey          => r#"Cannot set this key"#,
            ConfigErrorKind::NonStringValue      => r#"Please set values as "String""#,
            ConfigErrorKind::NotFoundBurnAfter   => r#"Please set [burn]after param"#,
            ConfigErrorKind::NotFoundSweepPeriod => r#"Please set [sweep]period param"#,
            ConfigErrorKind::NotFoundSweepTime   => r#"Please set [sweep]time param"#,
            ConfigErrorKind::BurnAfter           => r#"Please set value like "3days" or "1week" as "[burn]after""#,
            ConfigErrorKind::SweepPeriod         => r#"Please set "daily" or "weekly" as "[sweep]period""#,
            ConfigErrorKind::SweepTime           => r#"Please set value from "00:00" to "23:59" as "[sweep]time""#,
        })
    }
}
impl Error for ConfigError {
    fn description(&self) -> &str { "invalid parameters" }
}

#[derive(Debug, PartialEq)]
pub enum CronErrorKind {
    BinExistsInInvalidDir,
    InvalidCharacterCode,
    InvalidPath,
    FailedToWrite,
}
#[derive(Debug, PartialEq)]
pub struct CronError {
    kind: CronErrorKind,
}
impl CronError {
    pub fn new(kind: CronErrorKind) -> Self {
        CronError { kind: kind }
    }
}
impl Display for CronError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", match self.kind {
            CronErrorKind::BinExistsInInvalidDir => "The \"bin\" exists in directory whose path include non-UTF-8 charecter code",
            CronErrorKind::InvalidCharacterCode  => "The \"cron\" file consists of non-UTF-8 character code",
            CronErrorKind::InvalidPath           => "The path to current directory include non-UTF-8 character code",
            CronErrorKind::FailedToWrite         => "Failed to write new \"cron\" file"
        })
    }
}
impl Error for CronError {
    fn description(&self) -> &str { "problems around cron" }
}

#[derive(Debug, PartialEq)]
pub enum EssentialKind {
    WorkingDir,
    StorageDir,
    ConfigFile,
    IgnoreFile,
}
#[derive(Debug, PartialEq)]
pub struct EssentialLack {
    what: EssentialKind,
}
impl EssentialLack {
    pub fn new(what: EssentialKind) -> EssentialLack {
        EssentialLack { what: what }
    }
}
impl Display for EssentialLack {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{} does not exist", match self.what {
            EssentialKind::WorkingDir => format!("\"{}\" directory", constant::WORKING_DIR_NAME),
            EssentialKind::StorageDir => format!("\"{}\" directory", constant::STORAGE_DIR_NAME),
            EssentialKind::ConfigFile => format!("\"{}\" file"     , constant::CONFIG_FILE_NAME),
            EssentialKind::IgnoreFile => format!("\"{}\" file"     , constant::IGNORE_FILE_NAME),
        })
    }
}
impl Error for EssentialLack {
    fn description(&self) -> &str { "essential file does not exist" }
}

#[derive(Debug, PartialEq)]
pub struct RunningPlaceError {
    dir: String,
}
impl RunningPlaceError {
    pub fn new(dir: String) -> RunningPlaceError {
        RunningPlaceError { dir: dir }
    }
}
impl Display for RunningPlaceError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "Cannot run in \"{}\" directory", self.dir)
    }
}
impl Error for RunningPlaceError {
    fn description(&self) -> &str { "cannot run in banned directories" }
}

#[derive(Debug, PartialEq)]
pub enum UsageKind {
    Nothing,
    Help,
    Version,
    Init,
    Config,
    Ignore,
    Sweep,
    Burn,
    Start,
    End,
    Destroy,
    Patrol,
}
impl UsageKind {
    fn command(&self) -> &str {
        match *self {
            UsageKind::Nothing => "<Command>",
            UsageKind::Help    => "help",
            UsageKind::Version => "version",
            UsageKind::Init    => "init",
            UsageKind::Config  => "config",
            UsageKind::Ignore  => "ignore",
            UsageKind::Sweep   => "sweep",
            UsageKind::Burn    => "burn",
            UsageKind::Start   => "start",
            UsageKind::End     => "end",
            UsageKind::Destroy => "destroy",
            UsageKind::Patrol  => "patrol",
        }
    }

    fn common_usage(&self) -> String {
        format!("{} {}", ME, self.command())
    }

    fn usages(&self) -> Vec<String> {
        match *self {
            UsageKind::Help   => vec![format!("{} <SubCommand>", self.common_usage())],
            UsageKind::Config => vec![
                format!("{} set <Key> <Value>", self.common_usage()),
                format!("{} init"             , self.common_usage()),
            ],
            UsageKind::Ignore => vec![
                format!("{} add <File> ..."   , self.common_usage()),
                format!("{} remove <File> ...", self.common_usage()),
                format!("{} current"          , self.common_usage()),
                format!("{} clear"            , self.common_usage()),
            ],
            UsageKind::Sweep => vec![format!("{} [all] [indeed]", self.common_usage())],
            UsageKind::Burn  => vec![format!("{} [indeed]", self.common_usage())],
            _ => vec![self.common_usage()],
        }
    }

    fn description(&self) -> &str {
        match *self {
            UsageKind::Nothing => "Keep your directories clean!",
            UsageKind::Help    => "Display usage for each command.",
            UsageKind::Version => "Display the version of this software.",
            UsageKind::Init    => "Register current directory.",
            UsageKind::Config  => "Change parameter.",
            UsageKind::Ignore  => "Change \"non-dust\" file's list.",
            UsageKind::Sweep   => "Sweep \"dust\" files and empty directories in current directory.",
            UsageKind::Burn    => "Burn \"sweeped\" files.",
            UsageKind::Start   => "Register with \"cron\" for autonomous operation.",
            UsageKind::End     => "Unregister from \"cron\".",
            UsageKind::Destroy => "Unregister current directory.",
            UsageKind::Patrol  => "Keep \"cron\" file clean.",
        }
    }

    fn sub_descriptions(&self) -> Vec<String> {
        match *self {
            UsageKind::Nothing => vec![
                format!("{}{}", "help    # ", UsageKind::Help   .description()),
                format!("{}{}", "version # ", UsageKind::Version.description()),
                format!("{}{}", "init    # ", UsageKind::Init   .description()),
                format!("{}{}", "config  # ", UsageKind::Config .description()),
                format!("{}{}", "ignore  # ", UsageKind::Ignore .description()),
                format!("{}{}", "sweep   # ", UsageKind::Sweep  .description()),
                format!("{}{}", "burn    # ", UsageKind::Burn   .description()),
                format!("{}{}", "start   # ", UsageKind::Start  .description()),
                format!("{}{}", "end     # ", UsageKind::End    .description()),
                format!("{}{}", "destroy # ", UsageKind::Destroy.description()),
                format!("{}{}", "patrol  # ", UsageKind::Patrol .description()),
            ],
            UsageKind::Config => vec![
                "set  # Set parameter"       .to_string(),
                "init # Initialize configure".to_string(),
            ],
            UsageKind::Ignore => {
                let file_expression = "\"non-dust\" file's list";
                vec![
                    format!("add     # Add specified files to {}"        , file_expression),
                    format!("remove  # Remove specified files from {}"   , file_expression),
                    format!("current # Replace {} with current all files", file_expression),
                    format!("clear   # Clear {}"                         , file_expression),
                ]
            },
            UsageKind::Sweep => vec![
                "(none)     # Sweep fakely \"dust\"s"                                 .to_string(),
                "indeed     # Sweep indeed \"dust\"s"                                 .to_string(),
                "all        # Sweep fakely \"dust\"s including recently created files".to_string(),
                "all indeed # Sweep indeed \"dust\"s including recently created files".to_string(),
            ],
            UsageKind::Burn => vec![
                "(none) # Burn expired \"dust box\"s fakely".to_string(),
                "indeed # Burn expired \"dust box\"s indeed".to_string(),
            ],
            _ => Vec::new(),
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct Usage {
    kind: UsageKind,
}
impl Usage {
    pub fn new(kind: UsageKind) -> Usage {
        Usage { kind: kind }
    }

    fn message(&self) -> String {
        let usage = self.kind
            .usages()
            .iter()
            .fold(String::new(), |message, line| {
                message + "    " + line + "\n"
            });

        let main = format!("Usage:\n{}\nDescription:\n    {}\n", usage, self.kind.description());

        let sub_description = self.kind
            .sub_descriptions()
            .iter()
            .fold(String::new(), |message, line| {
                message + "    " + line + "\n"
            });

        if sub_description.is_empty() {
            main
        } else {
            format!("{}{}{}", main, "\nCommand:\n", sub_description)
        }
    }
}
impl Display for Usage {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", self.message())
    }
}
impl Error for Usage {
    fn description(&self) -> &str { "show usage" }
}
<|endoftext|>