<commit_before>/*! Example IRC bot

    This sample bot uses the library to connect to Freenode, under the nickname "rustirclib###"
    (where ### is a random number). It then joins the channel ##rustirclib, says hello, and prints
    to standard output any messages sent to the channel.

    Any incoming message of the form "rustirclib###: some message" will elicit a generic response.

    Any incoming message of the form "!rustirclib### quit" will cause the bot to shut down.
 */

#[crate_id = "github.com/kballard/rust-irclib#ircbot:0.1"];
#[crate_type = "bin"];

extern crate irc;

use irc::conn::{Conn, Line, Event, IRCCmd, IRCCode, IRCAction};

use std::{rand, str};
use std::rand::Rng;

fn main() {
    let mut opts = irc::conn::Options::new("chat.freenode.net", irc::conn::DefaultPort);

    let nick = format!("rustirclib{}", rand::task_rng().gen_range(100u, 1000u));
    opts.nick = nick.as_slice();
    match irc::conn::connect(opts, (), |c,e,_| handler(c,e)) {
        Ok(()) => println!("Exiting..."),
        Err(err) => println!("Connection error: {}", err)
    }
}

fn handler(conn: &mut Conn, event: Event) {
    match event {
        irc::conn::Connected => println!("Connected"),
        irc::conn::Disconnected => println!("Disconnected"),
        irc::conn::LineReceived(line) => {
            match line {
                Line{command: IRCCode(1), ..} => {
                    println!("Logged in");
                    // we've logged in
                    conn.join(bytes!("##rustirclib"), [])
                }
                Line{command: IRCCmd(~"JOIN"), args, prefix: Some(prefix) } => {
                    if prefix.nick() != conn.me().nick() {
                        return;
                    }
                    if args.is_empty() {
                        let line = Line{command: IRCCmd(~"JOIN"), args: args, prefix: Some(prefix)};
                        println!("ERROR: Invalid JOIN message received: {}", line_desc(&line));
                        return;
                    }
                    let chan = args[0];
                    conn.privmsg(chan, bytes!("Hello"));
                    let chan = str::from_utf8(chan).unwrap_or("(invalid utf8)");
                    println!("JOINED: {}", chan);
                }
                Line{command: IRCCmd(cmd@~"PRIVMSG"), args, prefix } |
                Line{command: IRCCmd(cmd@~"NOTICE"), args, prefix } => {
                    let (src, dst, msg) = match prefix {
                        Some(_) if args.len() == 2 => {
                            let mut args = args;
                            let (dst, msg) = (args.swap_remove(0).unwrap(), args[0]);
                            (prefix.as_ref().unwrap().nick(), dst, msg)
                        }
                        _ => {
                            print!("ERROR: Unexpected {} line: ", cmd);
                            let line = Line{command: IRCCmd(cmd), args: args, prefix: prefix};
                            println!("{}", line_desc(&line));
                            return;
                        }
                    };
                    let dsts = str::from_utf8(dst).unwrap_or("(invalid utf8)");
                    let srcs = str::from_utf8(src).unwrap_or("(invalid utf8)");
                    let msgs = str::from_utf8(msg).unwrap_or("(invalid utf8)");
                    println!("<-- {}({}) {}: {}", cmd, dsts, srcs, msgs);
                    handle_privmsg(conn, msg, src, dst)
                }
                Line{command: IRCAction(dst), args, prefix } => {
                    let (src, msg) = match prefix {
                        Some(_) if args.len() == 1 => {
                            let msg = args[0];
                            (prefix.as_ref().unwrap().nick(), msg)
                        }
                        _ => {
                            let line = Line{command: IRCAction(dst), args: args, prefix: prefix};
                            println!("ERROR: Unexpected ACTION line: {}", line_desc(&line));
                            return;
                        }
                    };
                    let dst = str::from_utf8(dst).unwrap_or("(invalid utf8)");
                    let src = str::from_utf8(src).unwrap_or("(invalid utf8)");
                    let msg = str::from_utf8(msg).unwrap_or("(invalid utf8)");
                    println!("<-- PRIVMSG({}) {} {}", dst, src, msg);
                }
                _ => ()
            }
        }
    }
}

fn handle_privmsg(conn: &mut Conn, msg: &[u8], src: &[u8], dst: &[u8]) {
    enum MsgType<'a> {
        DirectedMessage,
        CommandMessage(&'a [u8]),
        NormalMessage
    }
    let msgtype = {
        let nick = conn.me().nick();
        if msg.starts_with(nick) && msg.slice_from(nick.len()).starts_with(bytes!(": ")) &&
        msg.len() > nick.len() + 2 {
            DirectedMessage
        } else if msg.starts_with(bytes!("!")) && msg.slice_from(1).starts_with(nick) &&
                msg.slice_from(nick.len()+1).starts_with(bytes!(" ")) {
            let args = msg.slice_from(conn.me().nick().len()+2);
            let mut argit = args.split(|&b| b == ' ' as u8).skip_while(|v| v.is_empty());
            match argit.next() {
                Some(arg) => CommandMessage(arg),
                None => CommandMessage(bytes!(""))
            }
        } else {
            NormalMessage
        }
    };
    match msgtype {
        DirectedMessage => {
            let reply = if dst == conn.me().nick() { src } else { dst };
            let msg = src + bytes!(": Hello");
            conn.privmsg(reply, msg);
            let src = str::from_utf8(conn.me().nick()).unwrap_or("(invalid utf8)");
            let reply = str::from_utf8(reply).unwrap_or("(invalid utf8)");
            let msg = str::from_utf8(msg).unwrap_or("(invalid utf8)");
            println!("--> PRIVMSG({}) {}: {}", reply, src, msg);
        }
        CommandMessage(cmd) if cmd == bytes!("quit") => {
            println!("Quitting...");
            conn.quit([]);
        }
        _ => ()
    }
}

fn line_desc(line: &Line) -> ~str {
    let raw = line.to_raw();
    str::from_utf8_lossy(raw).into_owned()
}
<commit_msg>Update for latest rustc<commit_after>/*! Example IRC bot

    This sample bot uses the library to connect to Freenode, under the nickname "rustirclib###"
    (where ### is a random number). It then joins the channel ##rustirclib, says hello, and prints
    to standard output any messages sent to the channel.

    Any incoming message of the form "rustirclib###: some message" will elicit a generic response.

    Any incoming message of the form "!rustirclib### quit" will cause the bot to shut down.
 */

#[crate_id = "github.com/kballard/rust-irclib#ircbot:0.1"];
#[crate_type = "bin"];

extern crate irc;
extern crate rand;

use irc::conn::{Conn, Line, Event, IRCCmd, IRCCode, IRCAction};

use std::str;
use rand::Rng;

fn main() {
    let mut opts = irc::conn::Options::new("chat.freenode.net", irc::conn::DefaultPort);

    let nick = format!("rustirclib{}", rand::task_rng().gen_range(100u, 1000u));
    opts.nick = nick.as_slice();
    match irc::conn::connect(opts, (), |c,e,_| handler(c,e)) {
        Ok(()) => println!("Exiting..."),
        Err(err) => println!("Connection error: {}", err)
    }
}

fn handler(conn: &mut Conn, event: Event) {
    match event {
        irc::conn::Connected => println!("Connected"),
        irc::conn::Disconnected => println!("Disconnected"),
        irc::conn::LineReceived(line) => {
            match line {
                Line{command: IRCCode(1), ..} => {
                    println!("Logged in");
                    // we've logged in
                    conn.join(bytes!("##rustirclib"), [])
                }
                Line{command: IRCCmd(~"JOIN"), args, prefix: Some(prefix) } => {
                    if prefix.nick() != conn.me().nick() {
                        return;
                    }
                    if args.is_empty() {
                        let line = Line{command: IRCCmd(~"JOIN"), args: args, prefix: Some(prefix)};
                        println!("ERROR: Invalid JOIN message received: {}", line_desc(&line));
                        return;
                    }
                    let chan = args[0];
                    conn.privmsg(chan, bytes!("Hello"));
                    let chan = str::from_utf8(chan).unwrap_or("(invalid utf8)");
                    println!("JOINED: {}", chan);
                }
                Line{command: IRCCmd(cmd@~"PRIVMSG"), args, prefix } |
                Line{command: IRCCmd(cmd@~"NOTICE"), args, prefix } => {
                    let (src, dst, msg) = match prefix {
                        Some(_) if args.len() == 2 => {
                            let mut args = args;
                            let (dst, msg) = (args.swap_remove(0).unwrap(), args[0]);
                            (prefix.as_ref().unwrap().nick(), dst, msg)
                        }
                        _ => {
                            print!("ERROR: Unexpected {} line: ", cmd);
                            let line = Line{command: IRCCmd(cmd), args: args, prefix: prefix};
                            println!("{}", line_desc(&line));
                            return;
                        }
                    };
                    let dsts = str::from_utf8(dst).unwrap_or("(invalid utf8)");
                    let srcs = str::from_utf8(src).unwrap_or("(invalid utf8)");
                    let msgs = str::from_utf8(msg).unwrap_or("(invalid utf8)");
                    println!("<-- {}({}) {}: {}", cmd, dsts, srcs, msgs);
                    handle_privmsg(conn, msg, src, dst)
                }
                Line{command: IRCAction(dst), args, prefix } => {
                    let (src, msg) = match prefix {
                        Some(_) if args.len() == 1 => {
                            let msg = args[0];
                            (prefix.as_ref().unwrap().nick(), msg)
                        }
                        _ => {
                            let line = Line{command: IRCAction(dst), args: args, prefix: prefix};
                            println!("ERROR: Unexpected ACTION line: {}", line_desc(&line));
                            return;
                        }
                    };
                    let dst = str::from_utf8(dst).unwrap_or("(invalid utf8)");
                    let src = str::from_utf8(src).unwrap_or("(invalid utf8)");
                    let msg = str::from_utf8(msg).unwrap_or("(invalid utf8)");
                    println!("<-- PRIVMSG({}) {} {}", dst, src, msg);
                }
                _ => ()
            }
        }
    }
}

fn handle_privmsg(conn: &mut Conn, msg: &[u8], src: &[u8], dst: &[u8]) {
    enum MsgType<'a> {
        DirectedMessage,
        CommandMessage(&'a [u8]),
        NormalMessage
    }
    let msgtype = {
        let nick = conn.me().nick();
        if msg.starts_with(nick) && msg.slice_from(nick.len()).starts_with(bytes!(": ")) &&
        msg.len() > nick.len() + 2 {
            DirectedMessage
        } else if msg.starts_with(bytes!("!")) && msg.slice_from(1).starts_with(nick) &&
                msg.slice_from(nick.len()+1).starts_with(bytes!(" ")) {
            let args = msg.slice_from(conn.me().nick().len()+2);
            let mut argit = args.split(|&b| b == ' ' as u8).skip_while(|v| v.is_empty());
            match argit.next() {
                Some(arg) => CommandMessage(arg),
                None => CommandMessage(bytes!(""))
            }
        } else {
            NormalMessage
        }
    };
    match msgtype {
        DirectedMessage => {
            let reply = if dst == conn.me().nick() { src } else { dst };
            let msg = src + bytes!(": Hello");
            conn.privmsg(reply, msg);
            let src = str::from_utf8(conn.me().nick()).unwrap_or("(invalid utf8)");
            let reply = str::from_utf8(reply).unwrap_or("(invalid utf8)");
            let msg = str::from_utf8(msg).unwrap_or("(invalid utf8)");
            println!("--> PRIVMSG({}) {}: {}", reply, src, msg);
        }
        CommandMessage(cmd) if cmd == bytes!("quit") => {
            println!("Quitting...");
            conn.quit([]);
        }
        _ => ()
    }
}

fn line_desc(line: &Line) -> ~str {
    let raw = line.to_raw();
    str::from_utf8_lossy(raw).into_owned()
}
<|endoftext|>


<commit_before>// The following was originally taken and adapated from exa source
// repo: https://github.com/ogham/exa
// commit: b9eb364823d0d4f9085eb220233c704a13d0f611
// license: MIT - Copyright (c) 2014 Benjamin Sago

//! System calls for getting the terminal size.
//!
//! Getting the terminal size is performed using an ioctl command that takes
//! the file handle to the terminal -- which in this case, is stdout -- and
//! populates a structure containing the values.
//!
//! The size is needed when the user wants the output formatted into columns:
//! the default grid view, or the hybrid grid-details view.

#[cfg(not(target_os = "windows"))]
extern crate libc;
#[cfg(target_os = "windows")]
extern crate kernel32;
#[cfg(target_os = "windows")]
extern crate winapi;

#[cfg(target_os = "windows")]
use kernel32::{GetConsoleScreenBufferInfo, GetStdHandle};
#[cfg(target_os = "windows")]
use winapi::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT, STD_OUTPUT_HANDLE};

#[cfg(not(target_os = "windows"))]
use std::mem::zeroed;
#[cfg(not(target_os = "windows"))]
use libc::{STDOUT_FILENO, c_int, c_ulong, c_ushort};

/// The number of rows and columns of a terminal.
#[cfg(not(target_os = "windows"))]
#[repr(C)]
struct Winsize {
    ws_row: c_ushort,
    ws_col: c_ushort,
}

// Unfortunately the actual command is not standardised...
#[cfg(any(target_os = "linux", target_os = "android"))]
static TIOCGWINSZ: c_ulong = 0x5413;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "bitrig",
          target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "netbsd",
          target_os = "openbsd"))]
static TIOCGWINSZ: c_ulong = 0x40087468;

#[cfg(target_os = "solaris")]
static TIOCGWINSZ: c_ulong = 0x5468;

extern "C" {
#[cfg(not(target_os = "windows"))]
    pub fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int;
}

/// Runs the ioctl command. Returns (0, 0) if output is not to a terminal, or
/// there is an error. (0, 0) is an invalid size to have anyway, which is why
/// it can be used as a nil value.
#[cfg(not(target_os = "windows"))]
unsafe fn get_dimensions() -> Winsize {
    let mut window: Winsize = zeroed();
    let result = ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut window);

    if result == -1 {
        zeroed()
    } else {
        window
    }
}

/// Query the current processes's output, returning its width and height as a
/// number of characters. Returns `None` if the output isn't to a terminal.
#[cfg(not(target_os = "windows"))]
pub fn dimensions() -> Option<(usize, usize)> {
    let w = unsafe { get_dimensions() };

    if w.ws_col == 0 || w.ws_row == 0 {
        None
    } else {
        Some((w.ws_col as usize, w.ws_row as usize))
    }
}

#[cfg(target_os = "windows")]
pub fn dimensions() -> Option<(usize, usize)> {
        let null_coord = COORD{
            X: 0,
            Y: 0,
        };
        let null_smallrect = SMALL_RECT{
            Left: 0,
            Top: 0,
            Right: 0,
            Bottom: 0,
        };

        let stdout_h = unsafe { GetStdHandle(STD_OUTPUT_HANDLE) };
        let mut console_data = CONSOLE_SCREEN_BUFFER_INFO{
            dwSize: null_coord,
            dwCursorPosition: null_coord,
            wAttributes: 0,
            srWindow: null_smallrect,
            dwMaximumWindowSize: null_coord,
        };

        if unsafe { GetConsoleScreenBufferInfo(stdout_h, &mut console_data) } != 0 {
            Some(((console_data.srWindow.Right - console_data.srWindow.Left) as usize, (console_data.srWindow.Bottom - console_data.srWindow.Top) as usize))
        } else {
            None
        }
}
<commit_msg>fix: uses libc::winsize instead of homegrown<commit_after>// The following was originally taken and adapated from exa source
// repo: https://github.com/ogham/exa
// commit: b9eb364823d0d4f9085eb220233c704a13d0f611
// license: MIT - Copyright (c) 2014 Benjamin Sago

//! System calls for getting the terminal size.
//!
//! Getting the terminal size is performed using an ioctl command that takes
//! the file handle to the terminal -- which in this case, is stdout -- and
//! populates a structure containing the values.
//!
//! The size is needed when the user wants the output formatted into columns:
//! the default grid view, or the hybrid grid-details view.

#[cfg(not(target_os = "windows"))]
extern crate libc;
#[cfg(target_os = "windows")]
extern crate kernel32;
#[cfg(target_os = "windows")]
extern crate winapi;

#[cfg(target_os = "windows")]
use kernel32::{GetConsoleScreenBufferInfo, GetStdHandle};
#[cfg(target_os = "windows")]
use winapi::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT, STD_OUTPUT_HANDLE};

#[cfg(not(target_os = "windows"))]
use std::mem::zeroed;
#[cfg(not(target_os = "windows"))]
use libc::{STDOUT_FILENO, c_int, c_ulong, winsize};

// Unfortunately the actual command is not standardised...
#[cfg(any(target_os = "linux", target_os = "android"))]
static TIOCGWINSZ: c_ulong = 0x5413;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "bitrig",
          target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "netbsd",
          target_os = "openbsd"))]
static TIOCGWINSZ: c_ulong = 0x40087468;

#[cfg(target_os = "solaris")]
static TIOCGWINSZ: c_ulong = 0x5468;

extern "C" {
#[cfg(not(target_os = "windows"))]
    pub fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int;
}

/// Runs the ioctl command. Returns (0, 0) if output is not to a terminal, or
/// there is an error. (0, 0) is an invalid size to have anyway, which is why
/// it can be used as a nil value.
#[cfg(not(target_os = "windows"))]
unsafe fn get_dimensions() -> winsize {
    let mut window: winsize = zeroed();
    let result = ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut window);

    if result == -1 {
        zeroed()
    } else {
        window
    }
}

/// Query the current processes's output, returning its width and height as a
/// number of characters. Returns `None` if the output isn't to a terminal.
#[cfg(not(target_os = "windows"))]
pub fn dimensions() -> Option<(usize, usize)> {
    let w = unsafe { get_dimensions() };

    if w.ws_col == 0 || w.ws_row == 0 {
        None
    } else {
        Some((w.ws_col as usize, w.ws_row as usize))
    }
}

#[cfg(target_os = "windows")]
pub fn dimensions() -> Option<(usize, usize)> {
        let null_coord = COORD{
            X: 0,
            Y: 0,
        };
        let null_smallrect = SMALL_RECT{
            Left: 0,
            Top: 0,
            Right: 0,
            Bottom: 0,
        };

        let stdout_h = unsafe { GetStdHandle(STD_OUTPUT_HANDLE) };
        let mut console_data = CONSOLE_SCREEN_BUFFER_INFO{
            dwSize: null_coord,
            dwCursorPosition: null_coord,
            wAttributes: 0,
            srWindow: null_smallrect,
            dwMaximumWindowSize: null_coord,
        };

        if unsafe { GetConsoleScreenBufferInfo(stdout_h, &mut console_data) } != 0 {
            Some(((console_data.srWindow.Right - console_data.srWindow.Left) as usize, (console_data.srWindow.Bottom - console_data.srWindow.Top) as usize))
        } else {
            None
        }
}
<|endoftext|>


<commit_before>//! Modified 2016 Garrett Berg <vitiral@gmail.com>
//! Copyright 2015 Dawid Ciężarkiewicz
//! See LICENSE-MPL
//!
//! Non-thread-shareable, simple and efficient Circular Buffer
//! implementation that can store N elements when full (typical circular
//! buffer implementations store N-1) without using separate flags.
//!
//! Uses only `core` so can be used in `#[no_std]` projects by using
//! `no_std` feature.
#![no_std]
#![feature(const_fn)]
#![feature(test)]

use core::option::Option::{self, Some, None};
use core::marker::PhantomData;

extern crate test as test;

const CBUF_DATA_BIT: usize = !((usize::max_value() << 1) >> 1);

/// Circular Buffer
///
/// Turns a slice into a Circular buffer with head and tail indexes.
#[derive(Debug)]
pub struct CBuf<'a, T: 'a> {
    buf: &'a mut [T],
    ctrl: CBufControl<T>,
}

/// Circular Buffer Control
///
/// Implements the actual logic of Circular Buffer, but requires passing &[T]
/// to `get` and `put`.
#[derive(Debug)]
pub struct CBufControl<T> {
    head: usize,
    tail: usize,
    phantom: PhantomData<T>,
}

#[cfg(not(feature = "no_std"))]
impl<'a, T: Clone> CBuf<'a, T>
    where T: Clone
{
    /// Create new CBuf
    ///
    /// Length (not capacity) will be used to store elements
    /// in the circular buffer.
    pub fn new(buf: &'a mut [T]) -> CBuf<T> {
        debug_assert!(buf.len() < CBUF_DATA_BIT);

        CBuf {
            buf: buf,
            ctrl: CBufControl::new(),
        }
    }

    /// Is buffer full?
    #[inline]
    pub fn is_full(&self) -> bool {
        self.ctrl.is_full()
    }

    /// Is buffer empty?
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.ctrl.is_empty()
    }

    /// Peek next element from the CBuf without removing it
    ///
    /// Returns `None` if buffer is empty.
    #[inline]
    pub fn peek(&mut self) -> Option<T> {
        self.ctrl.peek(self.buf)
    }

    /// Peek next element from the CBuf without removing it
    ///
    /// Makes the buffer misbehave if it's empty.
    #[inline]
    pub fn peek_unchecked(&mut self) -> T {
        self.ctrl.peek_unchecked(self.buf)
    }

    /// Remove one element from the CBuf
    ///
    /// Returns `None` if buffer is empty.
    #[inline]
    pub fn get(&mut self) -> Option<T> {
        self.ctrl.get(self.buf)
    }

    /// Remove one element from the CBuf
    ///
    /// Makes the buffer misbehave if it's empty.
    #[inline]
    pub fn get_unchecked(&mut self) -> T {
        self.ctrl.get_unchecked(self.buf)
    }

    /// Add element the buffer
    ///
    /// Ignores the write if buffer is full.
    #[inline]
    pub fn put(&mut self, val: T) {
        self.ctrl.put(self.buf, val)
    }

    /// Add element the buffer
    ///
    /// Makes the buffer misbehave if it's full.
    #[inline]
    pub fn put_unchecked(&mut self, val: T) {
        self.ctrl.put_unchecked(self.buf, val)
    }
}

impl<T: Clone> CBufControl<T> {
    pub fn new() -> CBufControl<T> {
        CBufControl {
            tail: 0,
            head: 0,
            phantom: PhantomData,
        }
    }

    /// See corresponding method of CBuf
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.head == self.tail
    }

    /// See corresponding method of CBuf
    #[inline]
    pub fn is_full(&self) -> bool {
        (self.head ^ self.tail) == CBUF_DATA_BIT
    }

    /// See corresponding method of CBuf
    pub fn get(&mut self, buf: &[T]) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        Some(self.get_unchecked(buf))
    }

    /// See corresponding method of CBuf
    pub fn get_unchecked(&mut self, buf: &[T]) -> T {
        let val = buf[self.tail & !CBUF_DATA_BIT].clone();

        self.tail += 1;

        if (self.tail & !CBUF_DATA_BIT) >= buf.len() {
            self.tail = (self.tail - buf.len()) ^ CBUF_DATA_BIT;
        }

        val
    }

    /// See corresponding method of CBuf
    pub fn peek(&mut self, buf: &[T]) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        Some(self.peek_unchecked(buf))
    }

    /// See corresponding method of CBuf
    pub fn peek_unchecked(&mut self, buf: &[T]) -> T {
        buf[self.tail & !CBUF_DATA_BIT].clone()
    }

    /// See corresponding method of CBuf
    pub fn put(&mut self, buf: &mut [T], val: T) {
        if self.is_full() {
            return;
        }
        self.put_unchecked(buf, val)
    }

    /// See corresponding method of CBuf
    pub fn put_unchecked(&mut self, buf: &mut [T], val: T) {
        buf[self.head & !CBUF_DATA_BIT] = val;

        self.head += 1;

        if (self.head & !CBUF_DATA_BIT) >= buf.len() {
            self.head = (self.head - buf.len()) ^ CBUF_DATA_BIT;
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use test::Bencher;
    use test;

    #[test]
    fn basic_ctl() {
        let mut buf = &mut [0u8, 2];
        let mut cbuf = CBufControl::<u8>::new();

        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        cbuf.put(buf, 3);
        cbuf.put(buf, 4);
        cbuf.put(buf, 42); // will have no effect
        cbuf.put(buf, 42); // will have no effect
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        assert_eq!(cbuf.peek(buf).unwrap(), 3);
        cbuf.peek(buf).unwrap();
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        assert_eq!(cbuf.get(buf).unwrap(), 3);
        assert_eq!(cbuf.get(buf).unwrap(), 4);
        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        assert!(cbuf.get(buf).is_none());
        assert!(cbuf.get(buf).is_none());
        cbuf.put(buf, 42);
        assert_eq!(cbuf.get(buf).unwrap(), 42);
    }

    #[test]
    fn basic_cbuf() {
        let mut buf = &mut [0u8, 0u8];
        let mut cbuf = CBuf::new(buf);

        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        cbuf.put(3);
        cbuf.put(4);
        cbuf.put(42); // will have no effect
        cbuf.put(42); // will have no effect
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        assert_eq!(cbuf.peek().unwrap(), 3);
        cbuf.peek().unwrap();
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        assert_eq!(cbuf.get().unwrap(), 3);
        assert_eq!(cbuf.get().unwrap(), 4);
        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        assert!(cbuf.get().is_none());
        assert!(cbuf.get().is_none());
        cbuf.put(42);
        assert_eq!(cbuf.get().unwrap(), 42);
    }

    #[test]
    fn patterns() {
        let mut buf = [0u8, 7];
        let mut cbuf = CBufControl::<u8>::new();

        let mut cur_len = 0;
        let mut put_val = 0;
        let mut get_val = 0;

        for pattern in 0..256 {
            if cur_len == 0 {
                assert!(cbuf.is_empty());
            }
            if cur_len == buf.len() {
                assert!(cbuf.is_full());
            }

            for bit_i in 0..8 {
                match pattern & (1 << bit_i) == 0 {
                    true => {
                        if cbuf.is_empty() {
                            assert!(cbuf.peek(&buf).is_none());
                            assert!(cbuf.get(&buf).is_none());
                        } else {
                            assert!(cbuf.peek(&buf).unwrap() == get_val);
                            let val = cbuf.get(&buf).unwrap();
                            assert!(val == get_val);
                            get_val = get_val.wrapping_add(1);
                            cur_len -= 1;
                        }
                    }
                    false => {
                        if cbuf.is_full() {
                            cbuf.put(&mut buf, put_val);
                            assert!(cbuf.is_full());
                        } else {
                            cbuf.put(&mut buf, put_val);
                            put_val = put_val.wrapping_add(1);
                            cur_len += 1;
                        }
                    }
                }
            }
        }
    }

    #[bench]
    pub fn put_and_get(b: &mut Bencher) {
        let buf = &mut [0u8; 256];
        let mut cbuf = CBuf::new(buf);

        b.iter(|| {
            cbuf.put(0u8);
            cbuf.get();
        });

        test::black_box(cbuf.get());
    }

    #[bench]
    pub fn put_unchecked_and_get(b: &mut Bencher) {
        let buf = &mut [0u8; 256];
        let mut cbuf = CBuf::new(buf);

        b.iter(|| {
            cbuf.put_unchecked(0u8);
            cbuf.get_unchecked();
        });

        test::black_box(cbuf.get());
    }
}
<commit_msg>Improve documentation<commit_after>// Modified 2016 Garrett Berg <vitiral@gmail.com>
// Copyright 2015 Dawid Ciężarkiewicz
// See LICENSE-MPL
//

//! Non-thread-shareable, simple and efficient Circular Buffer
//! implementation that can store N elements when full (typical circular
//! buffer implementations store N-1) without using separate flags.
//!
//! Uses only `core` so can be used in `#[no_std]` projects by using
//! `no_std` feature.
#![no_std]
#![feature(const_fn)]
#![feature(test)]

use core::option::Option::{self, Some, None};
use core::marker::PhantomData;

extern crate test as test;

const CBUF_DATA_BIT: usize = !((usize::max_value() << 1) >> 1);

/// Circular Buffer
///
/// Turns a slice into a Circular buffer with head and tail indexes.
#[derive(Debug)]
pub struct CBuf<'a, T: 'a> {
    buf: &'a mut [T],
    ctrl: CBufControl<T>,
}

/// Circular Buffer Control
///
/// Implements the actual logic of Circular Buffer, but requires passing &[T]
/// to `get` and `put`.
#[derive(Debug)]
pub struct CBufControl<T> {
    head: usize,
    tail: usize,
    phantom: PhantomData<T>,
}

#[cfg(not(feature = "no_std"))]
impl<'a, T: Clone> CBuf<'a, T>
    where T: Clone
{
    /// Create new CBuf
    ///
    /// Length (not capacity) will be used to store elements
    /// in the circular buffer.
    pub fn new(buf: &'a mut [T]) -> CBuf<T> {
        debug_assert!(buf.len() < CBUF_DATA_BIT);

        CBuf {
            buf: buf,
            ctrl: CBufControl::new(),
        }
    }

    /// Is buffer full?
    #[inline]
    pub fn is_full(&self) -> bool {
        self.ctrl.is_full()
    }

    /// Is buffer empty?
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.ctrl.is_empty()
    }

    /// Peek next element from the CBuf without removing it
    ///
    /// Returns `None` if buffer is empty.
    #[inline]
    pub fn peek(&mut self) -> Option<T> {
        self.ctrl.peek(self.buf)
    }

    /// Peek next element from the CBuf without removing it
    ///
    /// Makes the buffer misbehave if it's empty.
    #[inline]
    pub fn peek_unchecked(&mut self) -> T {
        self.ctrl.peek_unchecked(self.buf)
    }

    /// Remove one element from the CBuf
    ///
    /// Returns `None` if buffer is empty.
    #[inline]
    pub fn get(&mut self) -> Option<T> {
        self.ctrl.get(self.buf)
    }

    /// Remove one element from the CBuf
    ///
    /// Makes the buffer misbehave if it's empty.
    #[inline]
    pub fn get_unchecked(&mut self) -> T {
        self.ctrl.get_unchecked(self.buf)
    }

    /// Add element the buffer
    ///
    /// Ignores the write if buffer is full.
    #[inline]
    pub fn put(&mut self, val: T) {
        self.ctrl.put(self.buf, val)
    }

    /// Add element the buffer
    ///
    /// Makes the buffer misbehave if it's full.
    #[inline]
    pub fn put_unchecked(&mut self, val: T) {
        self.ctrl.put_unchecked(self.buf, val)
    }
}

impl<T: Clone> CBufControl<T> {
    pub fn new() -> CBufControl<T> {
        CBufControl {
            tail: 0,
            head: 0,
            phantom: PhantomData,
        }
    }

    /// See corresponding method of CBuf
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.head == self.tail
    }

    /// See corresponding method of CBuf
    #[inline]
    pub fn is_full(&self) -> bool {
        (self.head ^ self.tail) == CBUF_DATA_BIT
    }

    /// See corresponding method of CBuf
    pub fn get(&mut self, buf: &[T]) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        Some(self.get_unchecked(buf))
    }

    /// See corresponding method of CBuf
    pub fn get_unchecked(&mut self, buf: &[T]) -> T {
        let val = buf[self.tail & !CBUF_DATA_BIT].clone();

        self.tail += 1;

        if (self.tail & !CBUF_DATA_BIT) >= buf.len() {
            self.tail = (self.tail - buf.len()) ^ CBUF_DATA_BIT;
        }

        val
    }

    /// See corresponding method of CBuf
    pub fn peek(&mut self, buf: &[T]) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        Some(self.peek_unchecked(buf))
    }

    /// See corresponding method of CBuf
    pub fn peek_unchecked(&mut self, buf: &[T]) -> T {
        buf[self.tail & !CBUF_DATA_BIT].clone()
    }

    /// See corresponding method of CBuf
    pub fn put(&mut self, buf: &mut [T], val: T) {
        if self.is_full() {
            return;
        }
        self.put_unchecked(buf, val)
    }

    /// See corresponding method of CBuf
    pub fn put_unchecked(&mut self, buf: &mut [T], val: T) {
        buf[self.head & !CBUF_DATA_BIT] = val;

        self.head += 1;

        if (self.head & !CBUF_DATA_BIT) >= buf.len() {
            self.head = (self.head - buf.len()) ^ CBUF_DATA_BIT;
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use test::Bencher;
    use test;

    #[test]
    fn basic_ctl() {
        let mut buf = &mut [0u8, 2];
        let mut cbuf = CBufControl::<u8>::new();

        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        cbuf.put(buf, 3);
        cbuf.put(buf, 4);
        cbuf.put(buf, 42); // will have no effect
        cbuf.put(buf, 42); // will have no effect
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        assert_eq!(cbuf.peek(buf).unwrap(), 3);
        cbuf.peek(buf).unwrap();
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        assert_eq!(cbuf.get(buf).unwrap(), 3);
        assert_eq!(cbuf.get(buf).unwrap(), 4);
        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        assert!(cbuf.get(buf).is_none());
        assert!(cbuf.get(buf).is_none());
        cbuf.put(buf, 42);
        assert_eq!(cbuf.get(buf).unwrap(), 42);
    }

    #[test]
    fn basic_cbuf() {
        let mut buf = &mut [0u8, 0u8];
        let mut cbuf = CBuf::new(buf);

        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        cbuf.put(3);
        cbuf.put(4);
        cbuf.put(42); // will have no effect
        cbuf.put(42); // will have no effect
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        assert_eq!(cbuf.peek().unwrap(), 3);
        cbuf.peek().unwrap();
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        assert_eq!(cbuf.get().unwrap(), 3);
        assert_eq!(cbuf.get().unwrap(), 4);
        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        assert!(cbuf.get().is_none());
        assert!(cbuf.get().is_none());
        cbuf.put(42);
        assert_eq!(cbuf.get().unwrap(), 42);
    }

    #[test]
    fn patterns() {
        let mut buf = [0u8, 7];
        let mut cbuf = CBufControl::<u8>::new();

        let mut cur_len = 0;
        let mut put_val = 0;
        let mut get_val = 0;

        for pattern in 0..256 {
            if cur_len == 0 {
                assert!(cbuf.is_empty());
            }
            if cur_len == buf.len() {
                assert!(cbuf.is_full());
            }

            for bit_i in 0..8 {
                match pattern & (1 << bit_i) == 0 {
                    true => {
                        if cbuf.is_empty() {
                            assert!(cbuf.peek(&buf).is_none());
                            assert!(cbuf.get(&buf).is_none());
                        } else {
                            assert!(cbuf.peek(&buf).unwrap() == get_val);
                            let val = cbuf.get(&buf).unwrap();
                            assert!(val == get_val);
                            get_val = get_val.wrapping_add(1);
                            cur_len -= 1;
                        }
                    }
                    false => {
                        if cbuf.is_full() {
                            cbuf.put(&mut buf, put_val);
                            assert!(cbuf.is_full());
                        } else {
                            cbuf.put(&mut buf, put_val);
                            put_val = put_val.wrapping_add(1);
                            cur_len += 1;
                        }
                    }
                }
            }
        }
    }

    #[bench]
    pub fn put_and_get(b: &mut Bencher) {
        let buf = &mut [0u8; 256];
        let mut cbuf = CBuf::new(buf);

        b.iter(|| {
            cbuf.put(0u8);
            cbuf.get();
        });

        test::black_box(cbuf.get());
    }

    #[bench]
    pub fn put_unchecked_and_get(b: &mut Bencher) {
        let buf = &mut [0u8; 256];
        let mut cbuf = CBuf::new(buf);

        b.iter(|| {
            cbuf.put_unchecked(0u8);
            cbuf.get_unchecked();
        });

        test::black_box(cbuf.get());
    }
}
<|endoftext|>


<commit_before>//#[macro_export]
macro_rules! __print(
  ($($arg:tt)*) => ({
    use io::Writer;
    write!(::terminal::GLOBAL.lock(), $($arg)*).ok();
  })
);

#[macro_export]
macro_rules! log(
  ($lvl: expr, $($arg:tt)*) => ({
    __print!("[{}:{} {}]: ", $lvl, file!(), line!());
    __print!($($arg)*);
    __print!("\n");
  })
);

#[macro_export]
macro_rules! debug(
  ($($arg:tt)*) => (log!("DEBUG", $($arg)*))
);

#[macro_export]
macro_rules! warn(
  ($($arg:tt)*) => (log!("WARN", $($arg)*))
);

#[macro_export]
macro_rules! info(
  ($($arg:tt)*) => (log!("INFO", $($arg)*))
);

#[macro_export]
macro_rules! trace(
  ($($arg:tt)*) => (log!("TRACE", $($arg)*))
);
<commit_msg>Fix race and potential deadlock with printing/logging<commit_after>use core::fmt::Arguments;
use io::Writer;

pub fn write(args: Arguments) {
  // Arguments are already evaluated, so dead-lock is avoided
  ::terminal::GLOBAL.lock().write_fmt(args).ok();
}

//#[macro_export]
macro_rules! __print(
  ($($arg:tt)*) => (::log::write(format_args!($($arg)*)))
);

#[macro_export]
macro_rules! log(
  ($lvl: expr, $($arg:tt)*) => (
    // Must be one print for atomicity
    __print!("[{}:{} {}]: {}\n", $lvl, file!(), line!(), format_args!($($arg)*))
  )
);

#[macro_export]
macro_rules! debug(
  ($($arg:tt)*) => (log!("DEBUG", $($arg)*))
);

#[macro_export]
macro_rules! warn(
  ($($arg:tt)*) => (log!("WARN", $($arg)*))
);

#[macro_export]
macro_rules! info(
  ($($arg:tt)*) => (log!("INFO", $($arg)*))
);

#[macro_export]
macro_rules! trace(
  ($($arg:tt)*) => (log!("TRACE", $($arg)*))
);
<|endoftext|>


<commit_before>extern crate capstone;

#[macro_use]
extern crate clap;

#[macro_use]
extern crate log;

extern crate stderrlog;

use capstone::prelude::*;
use capstone::{Arch, Endian, ExtraMode, Mode};
use clap::{App, Arg, ArgGroup};
use std::fmt::Display;
use std::fs::File;
use std::io::prelude::*;
use std::io;
use std::process::exit;
use std::str::FromStr;

const DEFAULT_CAPACITY: usize = 1024;

trait ExpectExit<T> {
    fn expect_exit(self) -> T;
}

impl<T, E> ExpectExit<T> for Result<T, E>
where
    E: Display,
{
    fn expect_exit(self) -> T {
        match self {
            Ok(t) => t,
            Err(e) => {
                eprintln!("error: {}", e);
                exit(1);
            }
        }
    }
}

/// We can't iterate over enums declared in another crate, so we declare a private enum that
/// shadows the values
macro_rules! arch_conversions {
    (
        $arg_struct:ident = $cs_struct:ident
        [ $( $name:ident, )* ]
    ) => {
        arg_enum!{
            #[derive(PartialEq, Debug)]
            pub enum $arg_struct {
                $( $name, )*
            }
        }

        impl From<$arg_struct> for $cs_struct {
            fn from(arch_arg: $arg_struct) -> $cs_struct {
                match arch_arg {
                    $( $arg_struct::$name => $cs_struct::$name, )*
                }
            }
        }

        impl From<$cs_struct> for $arg_struct {
            fn from(arch_arg: $cs_struct) -> $arg_struct {
                match arch_arg {
                    $( $cs_struct::$name => $arg_struct::$name, )*
                }
            }
        }
    }
}

arch_conversions!(
    ArchArg = Arch
    [
        ARM,
        ARM64,
        MIPS,
        X86,
        PPC,
        SPARC,
        SYSZ,
        XCORE,
    ]
);

arch_conversions!(
    ModeArg = Mode
    [
        Arm,
        Mode16,
        Mode32,
        Mode64,
        Thumb,
        Mips3,
        Mips32R6,
        MipsGP64,
        V9,
        Default,
    ]
);

arch_conversions!(
    ExtraModeArg = ExtraMode
    [
        MClass,
        V8,
        Micro,
    ]
);

/// Print register names
fn reg_names<T, I>(cs: &Capstone, regs: T) -> String
where
    T: Iterator<Item = I>,
    I: Into<RegId>,
{
    let names: Vec<String> = regs.map(|x| cs.reg_name(x.into()).unwrap()).collect();
    names.join(", ")
}

/// Print instruction group names
fn group_names<T, I>(cs: &Capstone, regs: T) -> String
where
    T: Iterator<Item = I>,
    I: Into<InsnGroupId>,
{
    let names: Vec<String> = regs.map(|x| cs.group_name(x.into()).unwrap()).collect();
    names.join(", ")
}

/// Select only hex bytes from input
fn unhexed_bytes(input: Vec<u8>) -> Vec<u8> {
    let mut output: Vec<u8> = Vec::new();
    let mut curr_byte_str = String::with_capacity(2);
    for b_u8 in input {
        let b = char::from(b_u8);
        if ('0' <= b && b <= '9') || ('a' <= b && b <= 'f') || ('A' <= b && b <= 'F') {
            curr_byte_str.push(b);
        }

        if curr_byte_str.len() == 2 {
            debug!("  curr_byte_str={:?}", curr_byte_str);
            let byte = u8::from_str_radix(&curr_byte_str, 16).expect("Unexpect hex parse error");
            output.push(byte);
            curr_byte_str.clear();
        }
    }

    if log::max_level() >= log::LevelFilter::Info {
        let output_hex: Vec<String> = output.iter().map(|x| format!("{:02x}", x)).collect();
        info!("unhexed_output = {:?}", output_hex);
    }

    output
}

fn disasm<T: Iterator<Item = ExtraMode>>(
    arch: Arch,
    mode: Mode,
    extra_mode: T,
    endian: Option<Endian>,
    code: &[u8],
    addr: u64,
    show_detail: bool,
) {
    info!("Got {} bytes", code.len());
    let mut cs = Capstone::new_raw(arch, mode, extra_mode, endian).expect_exit();

    if show_detail {
        cs.set_detail(true).expect("Failed to set detail");
    }

    let stdout = io::stdout();
    let mut handle = stdout.lock();

    for i in cs.disasm_all(code, addr).expect_exit().iter() {
        let bytes: Vec<_> = i.bytes().iter().map(|x| format!("{:02x}", x)).collect();
        let bytes = bytes.join(" ");
        writeln!(
            &mut handle,
            "{:-10x}:  {:35} {:7} {}",
            i.address(),
            bytes,
            i.mnemonic().unwrap(),
            i.op_str().unwrap_or("")
        );

        if show_detail {
            let detail = cs.insn_detail(&i).expect("Failed to get insn detail");

            let output: &[(&str, String)] = &[
                ("insn id:", format!("{:?}", i.id().0)),
                ("read regs:", reg_names(&cs, detail.regs_read())),
                ("write regs:", reg_names(&cs, detail.regs_write())),
                ("insn groups:", group_names(&cs, detail.groups())),
            ];

            for &(ref name, ref message) in output.iter() {
                writeln!(&mut handle, "{:13}{:12} {}", "", name, message);
            }
        }
    }
}

fn main() {
    // Lowercase arches
    let _arches: Vec<String> = ArchArg::variants()
        .iter()
        .map(|x| x.to_lowercase())
        .collect();
    let arches: Vec<&str> = _arches.iter().map(|x| x.as_str()).collect();

    // Lowercase modes
    let _modes: Vec<String> = ModeArg::variants()
        .iter()
        .map(|x| x.to_lowercase())
        .collect();
    let modes: Vec<&str> = _modes.iter().map(|x| x.as_str()).collect();

    // Lowercase extra modes
    let _extra_modes: Vec<String> = ExtraModeArg::variants()
        .iter()
        .map(|x| x.to_lowercase())
        .collect();
    let extra_modes: Vec<&str> = _extra_modes.iter().map(|x| x.as_str()).collect();

    let matches = App::new("capstone-rs disassembler tool")
        .about("Disassembles binary file")
        .arg(
            Arg::with_name("file")
                .short("f")
                .long("file")
                .help("input file with binary instructions")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("stdin")
                .short("s")
                .long("stdin")
                .help("read binary instructions from stdin")
                .takes_value(false),
        )
        .arg(
            Arg::with_name("code")
                .short("c")
                .long("code")
                .help("instruction bytes (implies --hex)")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("address")
                .short("r")
                .long("addr")
                .help("address of code")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("v")
                .short("v")
                .multiple(true)
                .help("Sets the level of verbosity"),
        )
        .arg(
            Arg::with_name("hex")
                .short("x")
                .long("hex")
                .help("Treat input has hex; only select characters that are [a-fA-F0-9]")
                .takes_value(false),
        )
        .arg(
            Arg::with_name("DETAIL")
                .short("d")
                .long("detail")
                .help("Print details about instructions")
                .takes_value(false),
        )
        .arg(
            Arg::with_name("ARCH")
                .short("a")
                .long("arch")
                .help("Architecture")
                .takes_value(true)
                .required(true)
                .possible_values(arches.as_slice())
                .case_insensitive(true),
        )
        .arg(
            Arg::with_name("MODE")
                .short("m")
                .long("mode")
                .help("Mode")
                .takes_value(true)
                .required(true)
                .possible_values(modes.as_slice())
                .case_insensitive(true),
        )
        .arg(
            Arg::with_name("EXTRA_MODE")
                .short("e")
                .long("extra")
                .help("Extra Mode")
                .takes_value(true)
                .required(false)
                .possible_values(extra_modes.as_slice())
                .case_insensitive(true)
                .multiple(true),
        )
        .arg(
            Arg::with_name("ENDIAN")
                .short("n")
                .long("endian")
                .help("Endianness")
                .takes_value(true)
                .required(false)
                .possible_values(&["little", "big"])
                .case_insensitive(true),
        )
        .group(
            ArgGroup::with_name("INPUT")
                .arg("file")
                .arg("stdin")
                .arg("code")
                .required(true),
        )
        .get_matches();

    let direct_input_bytes: Vec<u8> = if let Some(file_path) = matches.value_of("file") {
        let mut file = File::open(file_path).expect_exit();
        let capacity = match file.metadata() {
            Err(_) => DEFAULT_CAPACITY,
            Ok(metadata) => metadata.len() as usize,
        };
        let mut buf = Vec::with_capacity(capacity as usize);
        file.read_to_end(&mut buf).expect_exit();
        buf
    } else if let Some(code) = matches.value_of("code") {
        code.as_bytes().iter().map(|x| *x).collect()
    } else {
        let mut buf = Vec::with_capacity(DEFAULT_CAPACITY);
        let stdin = std::io::stdin();
        stdin.lock().read_to_end(&mut buf).expect_exit();
        buf
    };

    stderrlog::new()
        .verbosity(matches.occurrences_of("v") as usize)
        .init()
        .unwrap();

    let is_hex = matches.is_present("hex") || matches.is_present("code");
    info!("is_hex = {:?}", is_hex);

    let show_detail = matches.is_present("DETAIL");
    info!("show_detail = {:?}", show_detail);

    let arch: Arch = ArchArg::from_str(matches.value_of("ARCH").unwrap())
        .unwrap()
        .into();
    info!("Arch = {:?}", arch);

    let mode: Mode = ModeArg::from_str(matches.value_of("MODE").unwrap())
        .unwrap()
        .into();
    info!("Mode = {:?}", mode);

    let extra_mode: Vec<_> = match matches.values_of("EXTRA_MODE") {
        None => Vec::with_capacity(0),
        Some(x) => x
            .map(|x| ExtraMode::from(ExtraModeArg::from_str(x).unwrap()))
            .collect(),
    };
    info!("ExtraMode = {:?}", extra_mode);

    let endian: Option<Endian> = matches
        .value_of("ENDIAN")
        .map(|x| Endian::from_str(x).expect_exit());
    info!("Endian = {:?}", endian);

    let address =
        u64::from_str_radix(matches.value_of("address").unwrap_or("1000"), 16).expect_exit();
    info!("Address = 0x{:x}", address);

    let input_bytes = if is_hex {
        unhexed_bytes(direct_input_bytes)
    } else {
        direct_input_bytes
    };

    disasm(
        arch,
        mode,
        extra_mode.iter().map(|x| *x),
        endian,
        input_bytes.as_slice(),
        address,
        show_detail,
    );
}
<commit_msg>Ignore unused result error<commit_after>extern crate capstone;

#[macro_use]
extern crate clap;

#[macro_use]
extern crate log;

extern crate stderrlog;

use capstone::prelude::*;
use capstone::{Arch, Endian, ExtraMode, Mode};
use clap::{App, Arg, ArgGroup};
use std::fmt::Display;
use std::fs::File;
use std::io::prelude::*;
use std::io;
use std::process::exit;
use std::str::FromStr;

const DEFAULT_CAPACITY: usize = 1024;

trait ExpectExit<T> {
    fn expect_exit(self) -> T;
}

impl<T, E> ExpectExit<T> for Result<T, E>
where
    E: Display,
{
    fn expect_exit(self) -> T {
        match self {
            Ok(t) => t,
            Err(e) => {
                eprintln!("error: {}", e);
                exit(1);
            }
        }
    }
}

/// We can't iterate over enums declared in another crate, so we declare a private enum that
/// shadows the values
macro_rules! arch_conversions {
    (
        $arg_struct:ident = $cs_struct:ident
        [ $( $name:ident, )* ]
    ) => {
        arg_enum!{
            #[derive(PartialEq, Debug)]
            pub enum $arg_struct {
                $( $name, )*
            }
        }

        impl From<$arg_struct> for $cs_struct {
            fn from(arch_arg: $arg_struct) -> $cs_struct {
                match arch_arg {
                    $( $arg_struct::$name => $cs_struct::$name, )*
                }
            }
        }

        impl From<$cs_struct> for $arg_struct {
            fn from(arch_arg: $cs_struct) -> $arg_struct {
                match arch_arg {
                    $( $cs_struct::$name => $arg_struct::$name, )*
                }
            }
        }
    }
}

arch_conversions!(
    ArchArg = Arch
    [
        ARM,
        ARM64,
        MIPS,
        X86,
        PPC,
        SPARC,
        SYSZ,
        XCORE,
    ]
);

arch_conversions!(
    ModeArg = Mode
    [
        Arm,
        Mode16,
        Mode32,
        Mode64,
        Thumb,
        Mips3,
        Mips32R6,
        MipsGP64,
        V9,
        Default,
    ]
);

arch_conversions!(
    ExtraModeArg = ExtraMode
    [
        MClass,
        V8,
        Micro,
    ]
);

/// Print register names
fn reg_names<T, I>(cs: &Capstone, regs: T) -> String
where
    T: Iterator<Item = I>,
    I: Into<RegId>,
{
    let names: Vec<String> = regs.map(|x| cs.reg_name(x.into()).unwrap()).collect();
    names.join(", ")
}

/// Print instruction group names
fn group_names<T, I>(cs: &Capstone, regs: T) -> String
where
    T: Iterator<Item = I>,
    I: Into<InsnGroupId>,
{
    let names: Vec<String> = regs.map(|x| cs.group_name(x.into()).unwrap()).collect();
    names.join(", ")
}

/// Select only hex bytes from input
fn unhexed_bytes(input: Vec<u8>) -> Vec<u8> {
    let mut output: Vec<u8> = Vec::new();
    let mut curr_byte_str = String::with_capacity(2);
    for b_u8 in input {
        let b = char::from(b_u8);
        if ('0' <= b && b <= '9') || ('a' <= b && b <= 'f') || ('A' <= b && b <= 'F') {
            curr_byte_str.push(b);
        }

        if curr_byte_str.len() == 2 {
            debug!("  curr_byte_str={:?}", curr_byte_str);
            let byte = u8::from_str_radix(&curr_byte_str, 16).expect("Unexpect hex parse error");
            output.push(byte);
            curr_byte_str.clear();
        }
    }

    if log::max_level() >= log::LevelFilter::Info {
        let output_hex: Vec<String> = output.iter().map(|x| format!("{:02x}", x)).collect();
        info!("unhexed_output = {:?}", output_hex);
    }

    output
}

fn disasm<T: Iterator<Item = ExtraMode>>(
    arch: Arch,
    mode: Mode,
    extra_mode: T,
    endian: Option<Endian>,
    code: &[u8],
    addr: u64,
    show_detail: bool,
) {
    info!("Got {} bytes", code.len());
    let mut cs = Capstone::new_raw(arch, mode, extra_mode, endian).expect_exit();

    if show_detail {
        cs.set_detail(true).expect("Failed to set detail");
    }

    let stdout = io::stdout();
    let mut handle = stdout.lock();

    for i in cs.disasm_all(code, addr).expect_exit().iter() {
        let bytes: Vec<_> = i.bytes().iter().map(|x| format!("{:02x}", x)).collect();
        let bytes = bytes.join(" ");
        writeln!(
            &mut handle,
            "{:-10x}:  {:35} {:7} {}",
            i.address(),
            bytes,
            i.mnemonic().unwrap(),
            i.op_str().unwrap_or("")
        ).is_ok();

        if show_detail {
            let detail = cs.insn_detail(&i).expect("Failed to get insn detail");

            let output: &[(&str, String)] = &[
                ("insn id:", format!("{:?}", i.id().0)),
                ("read regs:", reg_names(&cs, detail.regs_read())),
                ("write regs:", reg_names(&cs, detail.regs_write())),
                ("insn groups:", group_names(&cs, detail.groups())),
            ];

            for &(ref name, ref message) in output.iter() {
                writeln!(&mut handle, "{:13}{:12} {}", "", name, message).is_ok();
            }
        }
    }
}

fn main() {
    // Lowercase arches
    let _arches: Vec<String> = ArchArg::variants()
        .iter()
        .map(|x| x.to_lowercase())
        .collect();
    let arches: Vec<&str> = _arches.iter().map(|x| x.as_str()).collect();

    // Lowercase modes
    let _modes: Vec<String> = ModeArg::variants()
        .iter()
        .map(|x| x.to_lowercase())
        .collect();
    let modes: Vec<&str> = _modes.iter().map(|x| x.as_str()).collect();

    // Lowercase extra modes
    let _extra_modes: Vec<String> = ExtraModeArg::variants()
        .iter()
        .map(|x| x.to_lowercase())
        .collect();
    let extra_modes: Vec<&str> = _extra_modes.iter().map(|x| x.as_str()).collect();

    let matches = App::new("capstone-rs disassembler tool")
        .about("Disassembles binary file")
        .arg(
            Arg::with_name("file")
                .short("f")
                .long("file")
                .help("input file with binary instructions")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("stdin")
                .short("s")
                .long("stdin")
                .help("read binary instructions from stdin")
                .takes_value(false),
        )
        .arg(
            Arg::with_name("code")
                .short("c")
                .long("code")
                .help("instruction bytes (implies --hex)")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("address")
                .short("r")
                .long("addr")
                .help("address of code")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("v")
                .short("v")
                .multiple(true)
                .help("Sets the level of verbosity"),
        )
        .arg(
            Arg::with_name("hex")
                .short("x")
                .long("hex")
                .help("Treat input has hex; only select characters that are [a-fA-F0-9]")
                .takes_value(false),
        )
        .arg(
            Arg::with_name("DETAIL")
                .short("d")
                .long("detail")
                .help("Print details about instructions")
                .takes_value(false),
        )
        .arg(
            Arg::with_name("ARCH")
                .short("a")
                .long("arch")
                .help("Architecture")
                .takes_value(true)
                .required(true)
                .possible_values(arches.as_slice())
                .case_insensitive(true),
        )
        .arg(
            Arg::with_name("MODE")
                .short("m")
                .long("mode")
                .help("Mode")
                .takes_value(true)
                .required(true)
                .possible_values(modes.as_slice())
                .case_insensitive(true),
        )
        .arg(
            Arg::with_name("EXTRA_MODE")
                .short("e")
                .long("extra")
                .help("Extra Mode")
                .takes_value(true)
                .required(false)
                .possible_values(extra_modes.as_slice())
                .case_insensitive(true)
                .multiple(true),
        )
        .arg(
            Arg::with_name("ENDIAN")
                .short("n")
                .long("endian")
                .help("Endianness")
                .takes_value(true)
                .required(false)
                .possible_values(&["little", "big"])
                .case_insensitive(true),
        )
        .group(
            ArgGroup::with_name("INPUT")
                .arg("file")
                .arg("stdin")
                .arg("code")
                .required(true),
        )
        .get_matches();

    let direct_input_bytes: Vec<u8> = if let Some(file_path) = matches.value_of("file") {
        let mut file = File::open(file_path).expect_exit();
        let capacity = match file.metadata() {
            Err(_) => DEFAULT_CAPACITY,
            Ok(metadata) => metadata.len() as usize,
        };
        let mut buf = Vec::with_capacity(capacity as usize);
        file.read_to_end(&mut buf).expect_exit();
        buf
    } else if let Some(code) = matches.value_of("code") {
        code.as_bytes().iter().map(|x| *x).collect()
    } else {
        let mut buf = Vec::with_capacity(DEFAULT_CAPACITY);
        let stdin = std::io::stdin();
        stdin.lock().read_to_end(&mut buf).expect_exit();
        buf
    };

    stderrlog::new()
        .verbosity(matches.occurrences_of("v") as usize)
        .init()
        .unwrap();

    let is_hex = matches.is_present("hex") || matches.is_present("code");
    info!("is_hex = {:?}", is_hex);

    let show_detail = matches.is_present("DETAIL");
    info!("show_detail = {:?}", show_detail);

    let arch: Arch = ArchArg::from_str(matches.value_of("ARCH").unwrap())
        .unwrap()
        .into();
    info!("Arch = {:?}", arch);

    let mode: Mode = ModeArg::from_str(matches.value_of("MODE").unwrap())
        .unwrap()
        .into();
    info!("Mode = {:?}", mode);

    let extra_mode: Vec<_> = match matches.values_of("EXTRA_MODE") {
        None => Vec::with_capacity(0),
        Some(x) => x
            .map(|x| ExtraMode::from(ExtraModeArg::from_str(x).unwrap()))
            .collect(),
    };
    info!("ExtraMode = {:?}", extra_mode);

    let endian: Option<Endian> = matches
        .value_of("ENDIAN")
        .map(|x| Endian::from_str(x).expect_exit());
    info!("Endian = {:?}", endian);

    let address =
        u64::from_str_radix(matches.value_of("address").unwrap_or("1000"), 16).expect_exit();
    info!("Address = 0x{:x}", address);

    let input_bytes = if is_hex {
        unhexed_bytes(direct_input_bytes)
    } else {
        direct_input_bytes
    };

    disasm(
        arch,
        mode,
        extra_mode.iter().map(|x| *x),
        endian,
        input_bytes.as_slice(),
        address,
        show_detail,
    );
}
<|endoftext|>


<commit_before>use std::io;
use std::mem;

use bytes::{BufMut, Bytes, BytesMut};
use nom::{self, Needed};
use tokio_util::codec::{Decoder, Encoder, Framed};

use imap_proto;
use imap_proto::types::{Request, RequestId, Response};

pub struct ImapCodec {
    decode_need_message_bytes: usize,
}

impl Default for ImapCodec {
    fn default() -> Self {
        Self {
            decode_need_message_bytes: 0,
        }
    }
}

impl<'a> Decoder for ImapCodec {
    type Item = ResponseData;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> {
        if self.decode_need_message_bytes > buf.len() {
            return Ok(None);
        }
        let (response, rsp_len) = match imap_proto::Response::from_bytes(buf) {
            Ok((remaining, response)) => {
                // This SHOULD be acceptable/safe: BytesMut storage memory is
                // allocated on the heap and should not move. It will not be
                // freed as long as we keep a reference alive, which we do
                // by retaining a reference to the split buffer, below.
                let response = unsafe { mem::transmute(response) };
                (response, buf.len() - remaining.len())
            }
            Err(nom::Err::Incomplete(Needed::Size(min))) => {
                self.decode_need_message_bytes = min;
                return Ok(None);
            }
            Err(nom::Err::Incomplete(_)) => {
                return Ok(None);
            }
            Err(nom::Err::Error((_input, err_kind)))
            | Err(nom::Err::Failure((_input, err_kind))) => {
                return Err(io::Error::new(
                    io::ErrorKind::Other,
                    format!("{:?} during parsing of {:?}", err_kind, buf),
                ));
            }
        };
        let raw = buf.split_to(rsp_len).freeze();
        self.decode_need_message_bytes = 0;
        Ok(Some(ResponseData { raw, response }))
    }
}

impl Encoder<&Request> for ImapCodec {
    type Error = io::Error;
    fn encode(&mut self, msg: &Request, dst: &mut BytesMut) -> Result<(), io::Error> {
        dst.put(msg.0.as_bytes());
        dst.put_u8(b' ');
        dst.put_slice(&msg.1);
        dst.put(b"\r\n".as_ref());
        Ok(())
    }
}

#[derive(Debug)]
pub struct ResponseData {
    raw: Bytes,
    // This reference is really scoped to the lifetime of the `raw`
    // member, but unfortunately Rust does not allow that yet. It
    // is transmuted to `'static` by the `Decoder`, instead, and
    // references returned to callers of `ResponseData` are limited
    // to the lifetime of the `ResponseData` struct.
    //
    // `raw` is never mutated during the lifetime of `ResponseData`,
    // and `Response` does not not implement any specific drop glue.
    response: Response<'static>,
}

impl ResponseData {
    pub fn request_id(&self) -> Option<&RequestId> {
        match self.response {
            Response::Done { ref tag, .. } => Some(tag),
            _ => None,
        }
    }
    pub fn parsed<'a>(&'a self) -> &'a Response {
        &self.response
    }
}

pub type ImapTransport<T> = Framed<T, ImapCodec>;
<commit_msg>Remove redundant import<commit_after>use std::io;
use std::mem;

use bytes::{BufMut, Bytes, BytesMut};
use nom::{self, Needed};
use tokio_util::codec::{Decoder, Encoder, Framed};

use imap_proto::types::{Request, RequestId, Response};

pub struct ImapCodec {
    decode_need_message_bytes: usize,
}

impl Default for ImapCodec {
    fn default() -> Self {
        Self {
            decode_need_message_bytes: 0,
        }
    }
}

impl<'a> Decoder for ImapCodec {
    type Item = ResponseData;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> {
        if self.decode_need_message_bytes > buf.len() {
            return Ok(None);
        }
        let (response, rsp_len) = match imap_proto::Response::from_bytes(buf) {
            Ok((remaining, response)) => {
                // This SHOULD be acceptable/safe: BytesMut storage memory is
                // allocated on the heap and should not move. It will not be
                // freed as long as we keep a reference alive, which we do
                // by retaining a reference to the split buffer, below.
                let response = unsafe { mem::transmute(response) };
                (response, buf.len() - remaining.len())
            }
            Err(nom::Err::Incomplete(Needed::Size(min))) => {
                self.decode_need_message_bytes = min;
                return Ok(None);
            }
            Err(nom::Err::Incomplete(_)) => {
                return Ok(None);
            }
            Err(nom::Err::Error((_input, err_kind)))
            | Err(nom::Err::Failure((_input, err_kind))) => {
                return Err(io::Error::new(
                    io::ErrorKind::Other,
                    format!("{:?} during parsing of {:?}", err_kind, buf),
                ));
            }
        };
        let raw = buf.split_to(rsp_len).freeze();
        self.decode_need_message_bytes = 0;
        Ok(Some(ResponseData { raw, response }))
    }
}

impl Encoder<&Request> for ImapCodec {
    type Error = io::Error;
    fn encode(&mut self, msg: &Request, dst: &mut BytesMut) -> Result<(), io::Error> {
        dst.put(msg.0.as_bytes());
        dst.put_u8(b' ');
        dst.put_slice(&msg.1);
        dst.put(b"\r\n".as_ref());
        Ok(())
    }
}

#[derive(Debug)]
pub struct ResponseData {
    raw: Bytes,
    // This reference is really scoped to the lifetime of the `raw`
    // member, but unfortunately Rust does not allow that yet. It
    // is transmuted to `'static` by the `Decoder`, instead, and
    // references returned to callers of `ResponseData` are limited
    // to the lifetime of the `ResponseData` struct.
    //
    // `raw` is never mutated during the lifetime of `ResponseData`,
    // and `Response` does not not implement any specific drop glue.
    response: Response<'static>,
}

impl ResponseData {
    pub fn request_id(&self) -> Option<&RequestId> {
        match self.response {
            Response::Done { ref tag, .. } => Some(tag),
            _ => None,
        }
    }
    pub fn parsed<'a>(&'a self) -> &'a Response {
        &self.response
    }
}

pub type ImapTransport<T> = Framed<T, ImapCodec>;
<|endoftext|>


<commit_before>extern crate htwdresden;

use htwdresden::{Login, grades};

fn main() {
    let login = Login::new(include_str!("secret_login"),
                           include_str!("secret_password"));
    grades::get_courses(&login);
}
<commit_msg>trim whitespace from secret includes<commit_after>extern crate htwdresden;

use htwdresden::{Login, grades};

fn main() {
    let login = Login::new(include_str!("secret_login").trim(),
                           include_str!("secret_password").trim());
    grades::get_courses(&login);
}
<|endoftext|>


<commit_before>// Copyright (c) 2019 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

#[derive(Debug)]
pub enum DurationParseError {
    NoUnit,
    InvalidUnit,
    InvalidValue,
}

#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
pub enum RunStratagemCommandResult {
    FilesystemRequired,
    DurationOrderError,
    FilesystemDoesNotExist,
    StratagemServerProfileNotInstalled,
    ServerError,
    UnknownError,
}

#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct RunStratagemValidationError {
    pub code: RunStratagemCommandResult,
    pub message: String,
}

impl std::fmt::Display for DurationParseError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            DurationParseError::NoUnit => write!(f, "No unit specified."),
            DurationParseError::InvalidUnit => {
                write!(f, "Invalid unit. Valid units include 'h' and 'd'.")
            }
            DurationParseError::InvalidValue => {
                write!(f, "Invalid value specified. Must be a valid integer.")
            }
        }
    }
}

impl std::error::Error for DurationParseError {}

#[derive(Debug)]
pub enum ImlManagerCliError {
    ClientRequestError(iml_manager_client::ImlManagerClientError),
    TokioTimerError(tokio::timer::Error),
    IntParseError(std::num::ParseIntError),
    ParseDurationError(DurationParseError),
    RunStratagemValidationError(RunStratagemValidationError),
    SerdeJsonError(serde_json::error::Error),
}

impl std::fmt::Display for ImlManagerCliError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            ImlManagerCliError::ClientRequestError(ref err) => write!(f, "{}", err),
            ImlManagerCliError::TokioTimerError(ref err) => write!(f, "{}", err),
            ImlManagerCliError::IntParseError(ref err) => write!(f, "{}", err),
            ImlManagerCliError::ParseDurationError(ref err) => write!(f, "{}", err),
            ImlManagerCliError::RunStratagemValidationError(ref err) => write!(f, "{}", err),
            ImlManagerCliError::SerdeJsonError(ref err) => write!(f, "{}", err),
        }
    }
}

impl std::fmt::Display for RunStratagemValidationError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.message)
    }
}

impl std::error::Error for ImlManagerCliError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match *self {
            ImlManagerCliError::ClientRequestError(ref err) => Some(err),
            ImlManagerCliError::TokioTimerError(ref err) => Some(err),
            ImlManagerCliError::IntParseError(ref err) => Some(err),
            ImlManagerCliError::ParseDurationError(ref err) => Some(err),
            ImlManagerCliError::RunStratagemValidationError(ref err) => Some(err),
            ImlManagerCliError::SerdeJsonError(ref err) => Some(err),
        }
    }
}

impl std::error::Error for RunStratagemValidationError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

impl From<std::num::ParseIntError> for ImlManagerCliError {
    fn from(err: std::num::ParseIntError) -> Self {
        ImlManagerCliError::IntParseError(err)
    }
}

impl From<DurationParseError> for ImlManagerCliError {
    fn from(err: DurationParseError) -> Self {
        ImlManagerCliError::ParseDurationError(err)
    }
}

impl From<tokio::timer::Error> for ImlManagerCliError {
    fn from(err: tokio::timer::Error) -> Self {
        ImlManagerCliError::TokioTimerError(err)
    }
}

impl From<iml_manager_client::ImlManagerClientError> for ImlManagerCliError {
    fn from(err: iml_manager_client::ImlManagerClientError) -> Self {
        ImlManagerCliError::ClientRequestError(err)
    }
}

impl From<RunStratagemValidationError> for ImlManagerCliError {
    fn from(err: RunStratagemValidationError) -> Self {
        ImlManagerCliError::RunStratagemValidationError(err)
    }
}

impl From<serde_json::error::Error> for ImlManagerCliError {
    fn from(err: serde_json::error::Error) -> Self {
        ImlManagerCliError::SerdeJsonError(err)
    }
}
<commit_msg>Add Validation cases to RunStratagemCommandResult enum (#1031)<commit_after>// Copyright (c) 2019 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

#[derive(Debug)]
pub enum DurationParseError {
    NoUnit,
    InvalidUnit,
    InvalidValue,
}

#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
pub enum RunStratagemCommandResult {
    DurationOrderError,
    FilesystemRequired,
    FilesystemDoesNotExist,
    FilesystemUnavailable,
    InvalidArgument,
    Mdt0NotFound,
    Mdt0NotMounted,
    StratagemServerProfileNotInstalled,
    ServerError,
    UnknownError,
}

#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct RunStratagemValidationError {
    pub code: RunStratagemCommandResult,
    pub message: String,
}

impl std::fmt::Display for DurationParseError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            DurationParseError::NoUnit => write!(f, "No unit specified."),
            DurationParseError::InvalidUnit => {
                write!(f, "Invalid unit. Valid units include 'h' and 'd'.")
            }
            DurationParseError::InvalidValue => {
                write!(f, "Invalid value specified. Must be a valid integer.")
            }
        }
    }
}

impl std::error::Error for DurationParseError {}

#[derive(Debug)]
pub enum ImlManagerCliError {
    ClientRequestError(iml_manager_client::ImlManagerClientError),
    TokioTimerError(tokio::timer::Error),
    IntParseError(std::num::ParseIntError),
    ParseDurationError(DurationParseError),
    RunStratagemValidationError(RunStratagemValidationError),
    SerdeJsonError(serde_json::error::Error),
}

impl std::fmt::Display for ImlManagerCliError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            ImlManagerCliError::ClientRequestError(ref err) => write!(f, "{}", err),
            ImlManagerCliError::TokioTimerError(ref err) => write!(f, "{}", err),
            ImlManagerCliError::IntParseError(ref err) => write!(f, "{}", err),
            ImlManagerCliError::ParseDurationError(ref err) => write!(f, "{}", err),
            ImlManagerCliError::RunStratagemValidationError(ref err) => write!(f, "{}", err),
            ImlManagerCliError::SerdeJsonError(ref err) => write!(f, "{}", err),
        }
    }
}

impl std::fmt::Display for RunStratagemValidationError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.message)
    }
}

impl std::error::Error for ImlManagerCliError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match *self {
            ImlManagerCliError::ClientRequestError(ref err) => Some(err),
            ImlManagerCliError::TokioTimerError(ref err) => Some(err),
            ImlManagerCliError::IntParseError(ref err) => Some(err),
            ImlManagerCliError::ParseDurationError(ref err) => Some(err),
            ImlManagerCliError::RunStratagemValidationError(ref err) => Some(err),
            ImlManagerCliError::SerdeJsonError(ref err) => Some(err),
        }
    }
}

impl std::error::Error for RunStratagemValidationError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

impl From<std::num::ParseIntError> for ImlManagerCliError {
    fn from(err: std::num::ParseIntError) -> Self {
        ImlManagerCliError::IntParseError(err)
    }
}

impl From<DurationParseError> for ImlManagerCliError {
    fn from(err: DurationParseError) -> Self {
        ImlManagerCliError::ParseDurationError(err)
    }
}

impl From<tokio::timer::Error> for ImlManagerCliError {
    fn from(err: tokio::timer::Error) -> Self {
        ImlManagerCliError::TokioTimerError(err)
    }
}

impl From<iml_manager_client::ImlManagerClientError> for ImlManagerCliError {
    fn from(err: iml_manager_client::ImlManagerClientError) -> Self {
        ImlManagerCliError::ClientRequestError(err)
    }
}

impl From<RunStratagemValidationError> for ImlManagerCliError {
    fn from(err: RunStratagemValidationError) -> Self {
        ImlManagerCliError::RunStratagemValidationError(err)
    }
}

impl From<serde_json::error::Error> for ImlManagerCliError {
    fn from(err: serde_json::error::Error) -> Self {
        ImlManagerCliError::SerdeJsonError(err)
    }
}
<|endoftext|>