<commit_before>#[macro_use]
extern crate log;

#[cfg(windows)]
extern crate pdcurses;
#[cfg(unix)]
extern crate ncurses;

use std::ffi::CString;

#[cfg(windows)]
use pdcurses as curses;
#[cfg(windows)]
pub use pdcurses::chtype;
#[cfg(unix)]
use ncurses::ll as curses;
#[cfg(unix)]
pub use ncurses::ll::chtype;

mod input;
pub use self::input::*;

#[cfg(windows)]
mod windows;
#[cfg(windows)]
pub use self::windows::*;
#[cfg(unix)]
mod unix;
#[cfg(unix)]
pub use self::unix::*;

pub const OK: i32 = 0;
pub const ERR: i32 = -1;

#[derive(Copy, Clone, Debug)]
pub struct Window {
    #[cfg(windows)]
    _window: *mut curses::WINDOW,
    #[cfg(unix)]
    _window: curses::WINDOW,
}

impl Window {
    /// Sets the current attributes of the given window to attributes.
    pub fn attrset(&self, attributes: chtype) -> i32 {
        _attrset(self._window, attributes)
    }

    /// Copies blanks (i.e. the background chtype) to every cell of the window.
    pub fn erase(&self) -> i32 {
        unsafe { curses::werase(self._window) }
    }

    /// Read a character from the terminal associated with the window.
    ///
    /// In nodelay mode, if there is no input waiting, None is returned. In delay mode,
    /// the program will hang until the system  passes text through to the program. Depending on
    /// the setting of cbreak(), this will be after one character or after the first newline.
    /// Unless noecho() has been set, the character will also be echoed into the designated window.
    ///
    /// If keypad() is TRUE, and a function key is pressed, the token for that function key will be
    /// returned instead of the raw characters.
    /// If nodelay(win, TRUE) has been called on the window and no input is waiting, None is
    /// returned.
    pub fn getch(&self) -> Option<Input> {
        let i = unsafe { curses::wgetch(self._window) };
        if i < 0 {
            None
        } else if i <= '~' as i32 {
            Some(Input::Character(i as u8 as char))
        } else {
            Some(to_special_keycode(i))
        }
    }

    /// Return the maximum x value of this Window, in other words the number of columns.
    pub fn get_max_x(&self) -> i32 {
        unsafe { curses::getmaxx(self._window) }
    }

    /// Return the maximum y value of this Window, in other words the number of rows.
    pub fn get_max_y(&self) -> i32 {
        unsafe { curses::getmaxy(self._window) }
    }

    /// Controls whether getch() returns function/special keys as single key codes (e.g., the left
    /// arrow key as KEY_LEFT).
    ///
    /// Per X/Open, the default for keypad mode is OFF. You'll probably want it on. With keypad
    /// mode off, if a special key is pressed, getch() does nothing or returns ERR.
    pub fn keypad(&self, use_keypad: bool) -> i32 {
        unsafe { curses::keypad(self._window, use_keypad as u8) }
    }

    /// The cursor associated with the window is moved to the given location.
    ///
    /// This does not move the physical cursor of the terminal until refresh() is called.  The
    /// position specified is relative to the upper left corner of the window, which is (0,0).
    pub fn mv(&self, y: i32, x: i32) -> i32 {
        unsafe { curses::wmove(self._window, y, x) }
    }

    /// moves the cursor to the specified position and adds ch to the specified window
    pub fn mvaddch(&self, y: i32, x: i32, ch: char) -> i32 {
        unsafe { curses::mvwaddch(self._window, y, x, ch as chtype) }
    }

    /// Write all the characters of the string str to the given window. The functionality is
    /// similar to calling waddch() once for each character in the string.
    pub fn mvaddstr(&self, y: i32, x: i32, string: &str) -> i32 {
        let s = CString::new(string).unwrap();
        unsafe { curses::mvwaddstr(self._window, y, x, s.as_ptr()) }
    }

    ///Add a string to the window at the current cursor position.
    pub fn printw(&self, string: &str) -> i32 {
        let s = CString::new(string).unwrap();
        unsafe { curses::wprintw(self._window, s.as_ptr()) }
    }

    /// Copies the named window to the physical terminal screen, taking into account what
    /// is already there in order to optimize cursor movement.
    ///
    /// This function must be called to get any output on the terminal, as other routines only
    /// manipulate data structures. Unless leaveok() has been enabled, the physical cursor of the
    /// terminal is left at the location of the window's cursor.
    pub fn refresh(&self) -> i32 {
        unsafe { curses::wrefresh(self._window) }
    }

    /// Controls whether wgetch() is a non-blocking call. If the option is enabled, and
    /// no input is ready, wgetch() will return ERR. If disabled, wgetch() will hang until input is
    /// ready.
    pub fn nodelay(&self, enabled: bool) -> i32 {
        unsafe { curses::nodelay(self._window, enabled as u8) as i32 }
    }

    /// Set blocking or non-blocking reads for the specified window.
    ///
    /// The delay is measured in milliseconds. If it's negative, a blocking read is used; if zero,
    /// then non-blocking reads are done -- if no input is waiting, ERR is returned immediately.
    /// If the delay is positive, the read blocks for the delay period; if the period expires,
    /// ERR is returned.
    pub fn timeout(&self, milliseconds: i32) {
        unsafe { curses::wtimeout(self._window, milliseconds) }
    }
}

/// Alters the appearance of the cursor
///
///  A visibility of 0 makes it disappear; 1 makes it appear "normal" (usually an underline) and 2
/// makes it "highly visible" (usually a block).
pub fn curs_set(visibility: i32) -> i32 {
    unsafe { curses::curs_set(visibility) }
}

/// Should be called before exiting or escaping from curses mode temporarily.
///
/// It will restore tty modes, move the cursor to the lower left corner of the screen and reset the
/// terminal into the proper non-visual mode.  To resume curses after a temporary escape, call
/// refresh() or doupdate().
pub fn endwin() -> i32 {
    unsafe { curses::endwin() }
}

/// Indicates if the terminal supports, and can maniplulate color.
pub fn has_colors() -> bool {
    unsafe { curses::has_colors() > 0 }
}

/// Initialize the curses system, this must be the first function that is called.
///
/// Returns a Window struct that is used to access Window specific functions.
pub fn initscr() -> Window {
    let window_pointer = unsafe { curses::initscr() };
    Window { _window: window_pointer }
}

/// Changes the definition of a color-pair.
///
/// It takes three arguments: the number of the color-pair to be redefined, and the new values of
/// the foreground and background colors. The pair number must be between 0 and COLOR_PAIRS - 1,
/// inclusive. The foreground and background must be between 0 and COLORS - 1, inclusive. If the
/// color pair was previously initialized, the screen is refreshed, and all occurrences of that
/// color-pair are changed to the new definition.
pub fn init_pair(pair_index: i16, foreground_color: i16, background_color: i16) -> i32 {
    unsafe { curses::init_pair(pair_index, foreground_color, background_color) as i32 }
}

/// Suspends the program for the specified number of milliseconds.
pub fn napms(ms: i32) -> i32 {
    unsafe { curses::napms(ms) }
}

/// Enables the translation of a carriage return into a newline on input.
///
/// nonl() disables this. Initially, the translation does occur.
pub fn nl() -> i32 {
    unsafe { curses::nl() }
}

/// Disables echoing typed characters.
///
/// Initially, input characters are echoed. Subsequent calls to echo() and noecho() do not flush
/// type-ahead.
pub fn noecho() -> i32 {
    unsafe { curses::noecho() }
}

/// Attempts to resize the screen to the given size.
///
/// resize_term() is effectively two functions: When called with nonzero values for nlines and
/// ncols, it attempts to resize the screen to the given size. When called with (0, 0), it merely
/// adjusts the internal structures to match the current size after the screen is resized by the
/// user. If you want to support user resizing, you should check for getch() returning KEY_RESIZE,
/// and/or call is_termresized() at appropriate times; if either condition occurs, call
/// resize_term(0, 0). Then, with either user or programmatic resizing, you'll have to resize any
/// windows you've created.
pub fn resize_term(nlines: i32, ncols: i32) -> i32 {
    _resize_term(nlines, ncols)
}

/// Initializes eight basic colors (black, red, green, yellow, blue, magenta, cyan,
/// and white), and two global variables; COLORS and COLOR_PAIRS (respectively defining the
/// maximum number of colors and color-pairs the terminal is capable of displaying).
pub fn start_color() -> i32 {
    unsafe { curses::start_color() as i32 }
}

/// Allows the use of -1 as a foreground or background color with init_pair().
///
/// Calls assume_default_colors(-1, -1); -1 represents the foreground or background color that
/// the terminal had at startup.
pub fn use_default_colors() -> i32 {
    unsafe { curses::use_default_colors() }
}
<commit_msg>Fixed range check on getch() return value<commit_after>#[macro_use]
extern crate log;

#[cfg(windows)]
extern crate pdcurses;
#[cfg(unix)]
extern crate ncurses;

use std::ffi::CString;

#[cfg(windows)]
use pdcurses as curses;
#[cfg(windows)]
pub use pdcurses::chtype;
#[cfg(unix)]
use ncurses::ll as curses;
#[cfg(unix)]
pub use ncurses::ll::chtype;

mod input;
pub use self::input::*;

#[cfg(windows)]
mod windows;
#[cfg(windows)]
pub use self::windows::*;
#[cfg(unix)]
mod unix;
#[cfg(unix)]
pub use self::unix::*;

pub const OK: i32 = 0;
pub const ERR: i32 = -1;

#[derive(Copy, Clone, Debug)]
pub struct Window {
    #[cfg(windows)]
    _window: *mut curses::WINDOW,
    #[cfg(unix)]
    _window: curses::WINDOW,
}

impl Window {
    /// Sets the current attributes of the given window to attributes.
    pub fn attrset(&self, attributes: chtype) -> i32 {
        _attrset(self._window, attributes)
    }

    /// Copies blanks (i.e. the background chtype) to every cell of the window.
    pub fn erase(&self) -> i32 {
        unsafe { curses::werase(self._window) }
    }

    /// Read a character from the terminal associated with the window.
    ///
    /// In nodelay mode, if there is no input waiting, None is returned. In delay mode,
    /// the program will hang until the system  passes text through to the program. Depending on
    /// the setting of cbreak(), this will be after one character or after the first newline.
    /// Unless noecho() has been set, the character will also be echoed into the designated window.
    ///
    /// If keypad() is TRUE, and a function key is pressed, the token for that function key will be
    /// returned instead of the raw characters.
    /// If nodelay(win, TRUE) has been called on the window and no input is waiting, None is
    /// returned.
    pub fn getch(&self) -> Option<Input> {
        let i = unsafe { curses::wgetch(self._window) };
        if i < 0 {
            None
        } else if i <= u8::max_value() as i32 {
            Some(Input::Character(i as u8 as char))
        } else {
            Some(to_special_keycode(i))
        }
    }

    /// Return the maximum x value of this Window, in other words the number of columns.
    pub fn get_max_x(&self) -> i32 {
        unsafe { curses::getmaxx(self._window) }
    }

    /// Return the maximum y value of this Window, in other words the number of rows.
    pub fn get_max_y(&self) -> i32 {
        unsafe { curses::getmaxy(self._window) }
    }

    /// Controls whether getch() returns function/special keys as single key codes (e.g., the left
    /// arrow key as KEY_LEFT).
    ///
    /// Per X/Open, the default for keypad mode is OFF. You'll probably want it on. With keypad
    /// mode off, if a special key is pressed, getch() does nothing or returns ERR.
    pub fn keypad(&self, use_keypad: bool) -> i32 {
        unsafe { curses::keypad(self._window, use_keypad as u8) }
    }

    /// The cursor associated with the window is moved to the given location.
    ///
    /// This does not move the physical cursor of the terminal until refresh() is called.  The
    /// position specified is relative to the upper left corner of the window, which is (0,0).
    pub fn mv(&self, y: i32, x: i32) -> i32 {
        unsafe { curses::wmove(self._window, y, x) }
    }

    /// moves the cursor to the specified position and adds ch to the specified window
    pub fn mvaddch(&self, y: i32, x: i32, ch: char) -> i32 {
        unsafe { curses::mvwaddch(self._window, y, x, ch as chtype) }
    }

    /// Write all the characters of the string str to the given window. The functionality is
    /// similar to calling waddch() once for each character in the string.
    pub fn mvaddstr(&self, y: i32, x: i32, string: &str) -> i32 {
        let s = CString::new(string).unwrap();
        unsafe { curses::mvwaddstr(self._window, y, x, s.as_ptr()) }
    }

    ///Add a string to the window at the current cursor position.
    pub fn printw(&self, string: &str) -> i32 {
        let s = CString::new(string).unwrap();
        unsafe { curses::wprintw(self._window, s.as_ptr()) }
    }

    /// Copies the named window to the physical terminal screen, taking into account what
    /// is already there in order to optimize cursor movement.
    ///
    /// This function must be called to get any output on the terminal, as other routines only
    /// manipulate data structures. Unless leaveok() has been enabled, the physical cursor of the
    /// terminal is left at the location of the window's cursor.
    pub fn refresh(&self) -> i32 {
        unsafe { curses::wrefresh(self._window) }
    }

    /// Controls whether wgetch() is a non-blocking call. If the option is enabled, and
    /// no input is ready, wgetch() will return ERR. If disabled, wgetch() will hang until input is
    /// ready.
    pub fn nodelay(&self, enabled: bool) -> i32 {
        unsafe { curses::nodelay(self._window, enabled as u8) as i32 }
    }

    /// Set blocking or non-blocking reads for the specified window.
    ///
    /// The delay is measured in milliseconds. If it's negative, a blocking read is used; if zero,
    /// then non-blocking reads are done -- if no input is waiting, ERR is returned immediately.
    /// If the delay is positive, the read blocks for the delay period; if the period expires,
    /// ERR is returned.
    pub fn timeout(&self, milliseconds: i32) {
        unsafe { curses::wtimeout(self._window, milliseconds) }
    }
}

/// Alters the appearance of the cursor
///
///  A visibility of 0 makes it disappear; 1 makes it appear "normal" (usually an underline) and 2
/// makes it "highly visible" (usually a block).
pub fn curs_set(visibility: i32) -> i32 {
    unsafe { curses::curs_set(visibility) }
}

/// Should be called before exiting or escaping from curses mode temporarily.
///
/// It will restore tty modes, move the cursor to the lower left corner of the screen and reset the
/// terminal into the proper non-visual mode.  To resume curses after a temporary escape, call
/// refresh() or doupdate().
pub fn endwin() -> i32 {
    unsafe { curses::endwin() }
}

/// Indicates if the terminal supports, and can maniplulate color.
pub fn has_colors() -> bool {
    unsafe { curses::has_colors() > 0 }
}

/// Initialize the curses system, this must be the first function that is called.
///
/// Returns a Window struct that is used to access Window specific functions.
pub fn initscr() -> Window {
    let window_pointer = unsafe { curses::initscr() };
    Window { _window: window_pointer }
}

/// Changes the definition of a color-pair.
///
/// It takes three arguments: the number of the color-pair to be redefined, and the new values of
/// the foreground and background colors. The pair number must be between 0 and COLOR_PAIRS - 1,
/// inclusive. The foreground and background must be between 0 and COLORS - 1, inclusive. If the
/// color pair was previously initialized, the screen is refreshed, and all occurrences of that
/// color-pair are changed to the new definition.
pub fn init_pair(pair_index: i16, foreground_color: i16, background_color: i16) -> i32 {
    unsafe { curses::init_pair(pair_index, foreground_color, background_color) as i32 }
}

/// Suspends the program for the specified number of milliseconds.
pub fn napms(ms: i32) -> i32 {
    unsafe { curses::napms(ms) }
}

/// Enables the translation of a carriage return into a newline on input.
///
/// nonl() disables this. Initially, the translation does occur.
pub fn nl() -> i32 {
    unsafe { curses::nl() }
}

/// Disables echoing typed characters.
///
/// Initially, input characters are echoed. Subsequent calls to echo() and noecho() do not flush
/// type-ahead.
pub fn noecho() -> i32 {
    unsafe { curses::noecho() }
}

/// Attempts to resize the screen to the given size.
///
/// resize_term() is effectively two functions: When called with nonzero values for nlines and
/// ncols, it attempts to resize the screen to the given size. When called with (0, 0), it merely
/// adjusts the internal structures to match the current size after the screen is resized by the
/// user. If you want to support user resizing, you should check for getch() returning KEY_RESIZE,
/// and/or call is_termresized() at appropriate times; if either condition occurs, call
/// resize_term(0, 0). Then, with either user or programmatic resizing, you'll have to resize any
/// windows you've created.
pub fn resize_term(nlines: i32, ncols: i32) -> i32 {
    _resize_term(nlines, ncols)
}

/// Initializes eight basic colors (black, red, green, yellow, blue, magenta, cyan,
/// and white), and two global variables; COLORS and COLOR_PAIRS (respectively defining the
/// maximum number of colors and color-pairs the terminal is capable of displaying).
pub fn start_color() -> i32 {
    unsafe { curses::start_color() as i32 }
}

/// Allows the use of -1 as a foreground or background color with init_pair().
///
/// Calls assume_default_colors(-1, -1); -1 represents the foreground or background color that
/// the terminal had at startup.
pub fn use_default_colors() -> i32 {
    unsafe { curses::use_default_colors() }
}
<|endoftext|>


<commit_before>//! Kill Ring

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Action {
    Kill,
    Yank(usize),
    Other,
}

pub struct KillRing {
    slots: Vec<String>,
    index: usize,
    last_action: Action,
}

impl KillRing {
    /// Create a new kill-ring of the given `size`.
    pub fn new(size: usize) -> KillRing {
        KillRing {
            slots: Vec::with_capacity(size),
            index: 0,
            last_action: Action::Other,
        }
    }

    /// Reset last_astion state.
    pub fn reset(&mut self) {
        self.last_action = Action::Other;
    }

    /// Add `text` to the kill-ring.
    pub fn kill(&mut self, text: &str, forward: bool) {
        match self.last_action {
            Action::Kill => {
                if self.slots.capacity() == 0 {
                    // disabled
                    return;
                }
                if forward {
                    // append
                    self.slots[self.index].push_str(text);
                } else {
                    // prepend
                    self.slots[self.index] = String::from(text) + &self.slots[self.index];
                }
            }
            _ => {
                self.last_action = Action::Kill;
                if self.slots.capacity() == 0 {
                    // disabled
                    return;
                }
                if self.index == self.slots.capacity() - 1 {
                    // full
                    self.index = 0;
                } else if !self.slots.is_empty() {
                    self.index += 1;
                }
                if self.index == self.slots.len() {
                    self.slots.push(String::from(text))
                } else {
                    self.slots[self.index] = String::from(text);
                }
            }
        }
    }

    /// Yank previously killed text.
    /// Return `None` when kill-ring is empty.
    pub fn yank(&mut self) -> Option<&String> {
        if self.slots.len() == 0 {
            None
        } else {
            self.last_action = Action::Yank(self.slots[self.index].len());
            Some(&self.slots[self.index])
        }
    }

    /// Yank killed text stored in previous slot.
    /// Return `None` when the previous command was not a yank.
    pub fn yank_pop(&mut self) -> Option<(usize, &String)> {
        match self.last_action {
            Action::Yank(yank_size) => {
                if self.slots.len() == 0 {
                    return None;
                }
                if self.index == 0 {
                    self.index = self.slots.len() - 1;
                } else {
                    self.index -= 1;
                }
                self.last_action = Action::Yank(self.slots[self.index].len());
                Some((yank_size, &self.slots[self.index]))
            }
            _ => None,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Action, KillRing};

    #[test]
    fn disabled() {
        let mut kill_ring = KillRing::new(0);
        kill_ring.kill("text", true);
        assert!(kill_ring.slots.is_empty());
        assert_eq!(0, kill_ring.index);
        assert_eq!(Action::Kill, kill_ring.last_action);

        assert_eq!(None, kill_ring.yank());
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn one_kill() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", true);
        assert_eq!(0, kill_ring.index);
        assert_eq!(1, kill_ring.slots.len());
        assert_eq!("word1", kill_ring.slots[0]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn kill_kill_forward() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", true);
        kill_ring.kill(" word2", true);
        assert_eq!(0, kill_ring.index);
        assert_eq!(1, kill_ring.slots.len());
        assert_eq!("word1 word2", kill_ring.slots[0]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn kill_kill_backward() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", false);
        kill_ring.kill("word2 ", false);
        assert_eq!(0, kill_ring.index);
        assert_eq!(1, kill_ring.slots.len());
        assert_eq!("word2 word1", kill_ring.slots[0]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn kill_other_kill() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", true);
        kill_ring.reset();
        kill_ring.kill("word2", true);
        assert_eq!(1, kill_ring.index);
        assert_eq!(2, kill_ring.slots.len());
        assert_eq!("word1", kill_ring.slots[0]);
        assert_eq!("word2", kill_ring.slots[1]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn many_kill() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", true);
        kill_ring.reset();
        kill_ring.kill("word2", true);
        kill_ring.reset();
        kill_ring.kill("word3", true);
        kill_ring.reset();
        kill_ring.kill("word4", true);
        assert_eq!(1, kill_ring.index);
        assert_eq!(2, kill_ring.slots.len());
        assert_eq!("word3", kill_ring.slots[0]);
        assert_eq!("word4", kill_ring.slots[1]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn yank() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", true);
        kill_ring.reset();
        kill_ring.kill("word2", true);

        assert_eq!(Some(&"word2".to_string()), kill_ring.yank());
        assert_eq!(Action::Yank(5), kill_ring.last_action);
        assert_eq!(Some(&"word2".to_string()), kill_ring.yank());
        assert_eq!(Action::Yank(5), kill_ring.last_action);
    }

    #[test]
    fn yank_pop() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", true);
        kill_ring.reset();
        kill_ring.kill("longword2", true);

        assert_eq!(None, kill_ring.yank_pop());
        kill_ring.yank();
        assert_eq!(Some((9, &"word1".to_string())), kill_ring.yank_pop());
        assert_eq!(Some((5, &"longword2".to_string())), kill_ring.yank_pop());
        assert_eq!(Some((9, &"word1".to_string())), kill_ring.yank_pop());
    }
}

// Ctrl-K -> delete to kill ring (forward) (killLine)
// Ctrl-U -> erase to kill ring (backward) (resetLine)
// Ctrl-W -> erase word to kill ring (backward) (unixWordRubout)
//
// Meta Ctrl-H -> deletePreviousWord
// Meta Delete -> deletePreviousWord
// Meta D -> deleteNextWord
// Meta-Y/y -> yankPop
//
// Ctrl-Y -> paste from buffer (yank)
//
// resetLine
// unixWordRubout
// deletePreviousWord
// deleteNextWord
// killLine
//
// yank
// yankPop
//
// echo hello world
// Ctrl-W Ctrl-W Ctrl-Y
// echo hello
// echo
// echo hello world
//
// echo hello world
// Ctrl-W
// echo hello rust
// Ctrl-W Ctrl-Y Meta-Y
// echo hello world
// Meta-Y
//
<commit_msg>Remove notes.<commit_after>//! Kill Ring

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Action {
    Kill,
    Yank(usize),
    Other,
}

pub struct KillRing {
    slots: Vec<String>,
    index: usize,
    last_action: Action,
}

impl KillRing {
    /// Create a new kill-ring of the given `size`.
    pub fn new(size: usize) -> KillRing {
        KillRing {
            slots: Vec::with_capacity(size),
            index: 0,
            last_action: Action::Other,
        }
    }

    /// Reset last_astion state.
    pub fn reset(&mut self) {
        self.last_action = Action::Other;
    }

    /// Add `text` to the kill-ring.
    pub fn kill(&mut self, text: &str, forward: bool) {
        match self.last_action {
            Action::Kill => {
                if self.slots.capacity() == 0 {
                    // disabled
                    return;
                }
                if forward {
                    // append
                    self.slots[self.index].push_str(text);
                } else {
                    // prepend
                    self.slots[self.index] = String::from(text) + &self.slots[self.index];
                }
            }
            _ => {
                self.last_action = Action::Kill;
                if self.slots.capacity() == 0 {
                    // disabled
                    return;
                }
                if self.index == self.slots.capacity() - 1 {
                    // full
                    self.index = 0;
                } else if !self.slots.is_empty() {
                    self.index += 1;
                }
                if self.index == self.slots.len() {
                    self.slots.push(String::from(text))
                } else {
                    self.slots[self.index] = String::from(text);
                }
            }
        }
    }

    /// Yank previously killed text.
    /// Return `None` when kill-ring is empty.
    pub fn yank(&mut self) -> Option<&String> {
        if self.slots.len() == 0 {
            None
        } else {
            self.last_action = Action::Yank(self.slots[self.index].len());
            Some(&self.slots[self.index])
        }
    }

    /// Yank killed text stored in previous slot.
    /// Return `None` when the previous command was not a yank.
    pub fn yank_pop(&mut self) -> Option<(usize, &String)> {
        match self.last_action {
            Action::Yank(yank_size) => {
                if self.slots.len() == 0 {
                    return None;
                }
                if self.index == 0 {
                    self.index = self.slots.len() - 1;
                } else {
                    self.index -= 1;
                }
                self.last_action = Action::Yank(self.slots[self.index].len());
                Some((yank_size, &self.slots[self.index]))
            }
            _ => None,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Action, KillRing};

    #[test]
    fn disabled() {
        let mut kill_ring = KillRing::new(0);
        kill_ring.kill("text", true);
        assert!(kill_ring.slots.is_empty());
        assert_eq!(0, kill_ring.index);
        assert_eq!(Action::Kill, kill_ring.last_action);

        assert_eq!(None, kill_ring.yank());
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn one_kill() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", true);
        assert_eq!(0, kill_ring.index);
        assert_eq!(1, kill_ring.slots.len());
        assert_eq!("word1", kill_ring.slots[0]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn kill_kill_forward() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", true);
        kill_ring.kill(" word2", true);
        assert_eq!(0, kill_ring.index);
        assert_eq!(1, kill_ring.slots.len());
        assert_eq!("word1 word2", kill_ring.slots[0]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn kill_kill_backward() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", false);
        kill_ring.kill("word2 ", false);
        assert_eq!(0, kill_ring.index);
        assert_eq!(1, kill_ring.slots.len());
        assert_eq!("word2 word1", kill_ring.slots[0]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn kill_other_kill() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", true);
        kill_ring.reset();
        kill_ring.kill("word2", true);
        assert_eq!(1, kill_ring.index);
        assert_eq!(2, kill_ring.slots.len());
        assert_eq!("word1", kill_ring.slots[0]);
        assert_eq!("word2", kill_ring.slots[1]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn many_kill() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", true);
        kill_ring.reset();
        kill_ring.kill("word2", true);
        kill_ring.reset();
        kill_ring.kill("word3", true);
        kill_ring.reset();
        kill_ring.kill("word4", true);
        assert_eq!(1, kill_ring.index);
        assert_eq!(2, kill_ring.slots.len());
        assert_eq!("word3", kill_ring.slots[0]);
        assert_eq!("word4", kill_ring.slots[1]);
        assert_eq!(Action::Kill, kill_ring.last_action);
    }

    #[test]
    fn yank() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", true);
        kill_ring.reset();
        kill_ring.kill("word2", true);

        assert_eq!(Some(&"word2".to_string()), kill_ring.yank());
        assert_eq!(Action::Yank(5), kill_ring.last_action);
        assert_eq!(Some(&"word2".to_string()), kill_ring.yank());
        assert_eq!(Action::Yank(5), kill_ring.last_action);
    }

    #[test]
    fn yank_pop() {
        let mut kill_ring = KillRing::new(2);
        kill_ring.kill("word1", true);
        kill_ring.reset();
        kill_ring.kill("longword2", true);

        assert_eq!(None, kill_ring.yank_pop());
        kill_ring.yank();
        assert_eq!(Some((9, &"word1".to_string())), kill_ring.yank_pop());
        assert_eq!(Some((5, &"longword2".to_string())), kill_ring.yank_pop());
        assert_eq!(Some((9, &"word1".to_string())), kill_ring.yank_pop());
    }
}
<|endoftext|>


<commit_before>//! Module for exposing interfaces to a D-Bus manager.
//!
//! The `bus` crate makes it easy to expose interfaces on the D-Bus. Objects are created and added
//! to servers which delegate messages across the objects. The standard interfaces such as
//! properties and introspection are provided automatically.
//!
//! Servers may also be created to listen for signals and handle them.

#[macro_use]
extern crate bitflags;

mod arguments;
mod connection;
mod error;
mod interface;
mod message;
mod object;
mod runner;
mod server;
mod target;
mod value;

pub use connection::Connection;
pub use connection::ReleaseNameReply;
pub use connection::RequestNameFlags;
pub use connection::{ALLOW_REPLACEMENT, REPLACE_EXISTING, DO_NOT_QUEUE};
pub use connection::RequestNameReply;
pub use error::Error;
pub use interface::Annotation;
pub use interface::Argument;
pub use interface::ChildrenList;
pub use interface::ErrorMessage;
pub use interface::Interface;
pub use interface::Interfaces;
pub use interface::Method;
pub use interface::MethodHandler;
pub use interface::MethodResult;
pub use interface::Property;
pub use interface::PropertyReadHandler;
pub use interface::PropertyReadWriteHandler;
pub use interface::PropertyWriteHandler;
pub use interface::Signal;
pub use message::Message;
pub use message::MessageType;
pub use object::Object;
pub use runner::Runner;
pub use server::Server;
pub use target::Target;
pub use value::*;
<commit_msg>warnings: warn on missing docs<commit_after>#![warn(missing_docs)]

//! Module for exposing interfaces to a D-Bus manager.
//!
//! The `bus` crate makes it easy to expose interfaces on the D-Bus. Objects are created and added
//! to servers which delegate messages across the objects. The standard interfaces such as
//! properties and introspection are provided automatically.
//!
//! Servers may also be created to listen for signals and handle them.

#[macro_use]
extern crate bitflags;

mod arguments;
mod connection;
mod error;
mod interface;
mod message;
mod object;
mod runner;
mod server;
mod target;
mod value;

pub use connection::Connection;
pub use connection::ReleaseNameReply;
pub use connection::RequestNameFlags;
pub use connection::{ALLOW_REPLACEMENT, REPLACE_EXISTING, DO_NOT_QUEUE};
pub use connection::RequestNameReply;
pub use error::Error;
pub use interface::Annotation;
pub use interface::Argument;
pub use interface::ChildrenList;
pub use interface::ErrorMessage;
pub use interface::Interface;
pub use interface::Interfaces;
pub use interface::Method;
pub use interface::MethodHandler;
pub use interface::MethodResult;
pub use interface::Property;
pub use interface::PropertyReadHandler;
pub use interface::PropertyReadWriteHandler;
pub use interface::PropertyWriteHandler;
pub use interface::Signal;
pub use message::Message;
pub use message::MessageType;
pub use object::Object;
pub use runner::Runner;
pub use server::Server;
pub use target::Target;
pub use value::*;
<|endoftext|>


<commit_before>// For explanation of lint checks, run `rustc -W help`
// This is adapted from
// https://github.com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md
#![forbid(bad_style, exceeding_bitshifts, mutable_transmutes, no_mangle_const_items,
unknown_crate_types, warnings)]
#![deny(deprecated, drop_with_repr_extern, improper_ctypes, //missing_docs,
non_shorthand_field_patterns, overflowing_literals, plugin_as_library,
private_no_mangle_fns, private_no_mangle_statics, stable_features, unconditional_recursion,
unknown_lints, unsafe_code, unused, unused_allocation, unused_attributes,
unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, unused_extern_crates, unused_import_braces,
unused_qualifications, unused_results, variant_size_differences)]
#![allow(box_pointers, fat_ptr_transmutes, missing_copy_implementations,
missing_debug_implementations)]

///! # multihash
///!
///! Implementation of [multihash](https://github.com/jbenet/multihash)
///! in Rust.
/// Representation of a Multiaddr.

extern crate sodiumoxide;
extern crate rustc_serialize;

use rustc_serialize::hex::FromHex;

use sodiumoxide::crypto::hash::{sha256, sha512};
use std::io;

pub use self::hashes::*;
pub mod hashes;

/// Encode a string into a multihash
///
/// # Examples
///
/// Simple construction
///
/// ```
/// use multihash::{encode, HashTypes};
///
/// assert_eq!(
///     encode(HashTypes::SHA2256, "hello world").unwrap(),
///     "1220b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
/// );
/// ```
///
pub fn encode(wanttype: HashTypes, input: &str) -> io::Result<String> {
    let digest = match wanttype {
        HashTypes::SHA2256 => dig_to_vec(&(sha256::hash(input.as_bytes())[..])),
        HashTypes::SHA2512 => dig_to_vec(&(sha512::hash(input.as_bytes())[..])),
        _ => None,
    };

    match digest {
        Some(digest) => {
            let mut bytes = Vec::new();

            bytes.push(wanttype.code());
            bytes.push(digest.len() as u8);
            bytes.extend(digest);

            Ok(to_hex(bytes))
        },
        None => Err(io::Error::new(io::ErrorKind::Other, "Unsupported hash type"))
    }
}

/// Encode a string into a multihash
///
/// # Examples
///
/// Simple construction
///
/// ```
/// use multihash::{decode, HashTypes, Multihash};
///
/// assert_eq!(
///     decode("1220b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9").unwrap(),
///     Multihash {
///         alg: HashTypes::SHA2256,
///         digest: "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
///     }
/// );
/// ```
///
pub fn decode(input: &str) -> io::Result<Multihash> {
    if input.len() > 129 {
        return Err(io::Error::new(io::ErrorKind::Other, "Too long"));
    }

    if input.len() < 3 {
        return Err(io::Error::new(io::ErrorKind::Other, "Too short"));
    }

    let hex_input = input.from_hex();

    if hex_input.is_err() {
        return Err(io::Error::new(io::ErrorKind::Other, "Failed to parse hex string"));
    }

    let code = hex_input.unwrap()[0];

    match HashTypes::from_code(code) {
        Some(alg) => {
            Ok(Multihash {
                alg: alg,
                digest: &input[4..],
            })
        },
        None => {
            Err(io::Error::new(io::ErrorKind::Other, format!("Unkown code {:?}", code)))
        }
    }
}

#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Multihash<'a> {
    pub alg: HashTypes,
    pub digest: &'a str,
}

/// Convert bytes to a hex representation
fn to_hex(bytes: Vec<u8>) -> String {
    bytes.iter().rev().map(|x| {
        format!("{:02x}", x)
    }).rev().collect()
}

fn dig_to_vec (input: &[u8]) -> Option<Vec<u8>> {
    let mut bytes = Vec::new();
    bytes.extend(&input[..]);
    Some(bytes)
}
<commit_msg>Remove the `drop_with_repr_extern` lint.<commit_after>// For explanation of lint checks, run `rustc -W help`
// This is adapted from
// https://github.com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md
#![forbid(bad_style, exceeding_bitshifts, mutable_transmutes, no_mangle_const_items,
unknown_crate_types, warnings)]
#![deny(deprecated, improper_ctypes, //missing_docs,
non_shorthand_field_patterns, overflowing_literals, plugin_as_library,
private_no_mangle_fns, private_no_mangle_statics, stable_features, unconditional_recursion,
unknown_lints, unsafe_code, unused, unused_allocation, unused_attributes,
unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, unused_extern_crates, unused_import_braces,
unused_qualifications, unused_results, variant_size_differences)]
#![allow(box_pointers, fat_ptr_transmutes, missing_copy_implementations,
missing_debug_implementations)]

///! # multihash
///!
///! Implementation of [multihash](https://github.com/jbenet/multihash)
///! in Rust.
/// Representation of a Multiaddr.

extern crate sodiumoxide;
extern crate rustc_serialize;

use rustc_serialize::hex::FromHex;

use sodiumoxide::crypto::hash::{sha256, sha512};
use std::io;

pub use self::hashes::*;
pub mod hashes;

/// Encode a string into a multihash
///
/// # Examples
///
/// Simple construction
///
/// ```
/// use multihash::{encode, HashTypes};
///
/// assert_eq!(
///     encode(HashTypes::SHA2256, "hello world").unwrap(),
///     "1220b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
/// );
/// ```
///
pub fn encode(wanttype: HashTypes, input: &str) -> io::Result<String> {
    let digest = match wanttype {
        HashTypes::SHA2256 => dig_to_vec(&(sha256::hash(input.as_bytes())[..])),
        HashTypes::SHA2512 => dig_to_vec(&(sha512::hash(input.as_bytes())[..])),
        _ => None,
    };

    match digest {
        Some(digest) => {
            let mut bytes = Vec::new();

            bytes.push(wanttype.code());
            bytes.push(digest.len() as u8);
            bytes.extend(digest);

            Ok(to_hex(bytes))
        },
        None => Err(io::Error::new(io::ErrorKind::Other, "Unsupported hash type"))
    }
}

/// Encode a string into a multihash
///
/// # Examples
///
/// Simple construction
///
/// ```
/// use multihash::{decode, HashTypes, Multihash};
///
/// assert_eq!(
///     decode("1220b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9").unwrap(),
///     Multihash {
///         alg: HashTypes::SHA2256,
///         digest: "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
///     }
/// );
/// ```
///
pub fn decode(input: &str) -> io::Result<Multihash> {
    if input.len() > 129 {
        return Err(io::Error::new(io::ErrorKind::Other, "Too long"));
    }

    if input.len() < 3 {
        return Err(io::Error::new(io::ErrorKind::Other, "Too short"));
    }

    let hex_input = input.from_hex();

    if hex_input.is_err() {
        return Err(io::Error::new(io::ErrorKind::Other, "Failed to parse hex string"));
    }

    let code = hex_input.unwrap()[0];

    match HashTypes::from_code(code) {
        Some(alg) => {
            Ok(Multihash {
                alg: alg,
                digest: &input[4..],
            })
        },
        None => {
            Err(io::Error::new(io::ErrorKind::Other, format!("Unkown code {:?}", code)))
        }
    }
}

#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Multihash<'a> {
    pub alg: HashTypes,
    pub digest: &'a str,
}

/// Convert bytes to a hex representation
fn to_hex(bytes: Vec<u8>) -> String {
    bytes.iter().rev().map(|x| {
        format!("{:02x}", x)
    }).rev().collect()
}

fn dig_to_vec (input: &[u8]) -> Option<Vec<u8>> {
    let mut bytes = Vec::new();
    bytes.extend(&input[..]);
    Some(bytes)
}
<|endoftext|>


<commit_before>#![feature(vec_push_all)]

pub struct JsonEncoder {
    buffer: Vec<u8>
}

impl JsonEncoder {
    pub fn new() -> JsonEncoder {
        JsonEncoder{buffer: Vec::new()}
    }

    #[inline(always)]
    pub fn encode_raw(&mut self, raw: &[u8]) {
        self.buffer.push_all(raw);
    }

    pub fn into_vec(self) -> Vec<u8> {
        self.buffer
    }

    pub fn with_buf<F>(&mut self, f: F) where F: Fn(&mut Vec<u8>) {
        f(&mut self.buffer);
    }

    #[inline(always)]
    pub fn encode_str_noescape(&mut self, raw_str: &str) {
        self.buffer.push(b'"');
        self.buffer.push_all(raw_str.as_bytes());
        self.buffer.push(b'"');
    }

    fn escape_bytes(&mut self, bytes: &[u8]) {
        let mut start = 0;

        for (i, byte) in bytes.iter().enumerate() {
            let escaped = match *byte {
                b'"' => b"\\\"",
                b'\\' => b"\\\\",
                b'\x08' => b"\\b",
                b'\x0c' => b"\\f",
                b'\n' => b"\\n",
                b'\r' => b"\\r",
                b'\t' => b"\\t",
                _ => {
                    continue;
                }
            };

            if start < i {
                self.encode_raw(&bytes[start..i]);
            }

            self.encode_raw(escaped);

            start = i + 1;
        }

        if start != bytes.len() {
            self.encode_raw(&bytes[start..]);
        }
    }

    pub fn encode_decimal_str(&mut self, value: u64) {
        self.buffer.push(b'"');
        self.encode_u64_decimal(value);
        self.buffer.push(b'"');
    }

    // encodes as decimal string
    #[inline(always)]
    fn encode_u64_decimal(&mut self, value: u64) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 20;

        if value == 0 {
            self.buffer.push(b'0');
            return;
        }

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    #[inline(always)]
    pub fn encode_str(&mut self, s: &str) {
        self.buffer.push(b'"');
        self.escape_bytes(s.as_bytes());
        self.buffer.push(b'"');
    }

    #[inline(always)]
    pub fn encode_i32(&mut self, value: i32) {
        if value == 0 {
            self.buffer.push(b'0');
        } else if value > 0 {
            self.encode_u31(value as u32);
        } else {
            self.buffer.push(b'-');
            self.encode_u31((-value) as u32);
        }
    }

    // encodes a 31-bit unsigned integer != 0
    fn encode_u31(&mut self, value: u32) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 10;
        debug_assert!(value != 0);

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    pub fn encode_obj<F>(&mut self, f: F) where F: Fn(&mut JsonObjectEncoder) {
        self.buffer.push(b'{');
        {
            f(&mut JsonObjectEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b'}');
    }

    pub fn encode_array<F>(&mut self, f: F) where F: Fn(&mut JsonArrayEncoder) {
        self.buffer.push(b'[');
        {
            f(&mut JsonArrayEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b']');
    }

}

pub struct JsonObjectEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonObjectEncoder<'a> {
    // XXX: name MAY NOT include escapable characters
    #[inline(always)]
    pub fn encode_field<F:Fn(&mut JsonEncoder)>(&mut self, name: &str, f: F) {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        self.js.encode_str_noescape(name);
        self.js.buffer.push(b':');

        f(self.js);
    }

    #[inline(always)]
    pub fn encode_field_array<F:Fn(&mut JsonArrayEncoder)>(&mut self, name: &str, f: F) {
        self.encode_field(name, |js| js.encode_array(|jsa| f(jsa)));
    }
}

pub struct JsonArrayEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonArrayEncoder<'a> {
    #[inline(always)]
    pub fn encode_elm<F:Fn(&mut JsonEncoder)>(&mut self, f: F) {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        f(self.js);
    }

    #[inline(always)]
    pub fn encode_elm_i32(&mut self, val: i32) {
        self.encode_elm(|j| j.encode_i32(val));
    }
}

#[test]
fn test_json_obj_encoder() {
    use std::str;

    let mut js = JsonEncoder::new();
    js.encode_obj(|_|{});
    assert_eq!(b"{}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
    });
    assert_eq!(b"{\"total\":31}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
    });
    assert_eq!(b"{\"total\":31,\"next\":\"abc\"}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
        jso.encode_field("tags", |js| {
                js.encode_array(|jsa| {
                        jsa.encode_elm(|js| js.encode_i32(1));
                        jsa.encode_elm(|js| js.encode_i32(2));
                });
        });
    });
    assert_eq!("{\"total\":31,\"next\":\"abc\",\"tags\":[1,2]}", str::from_utf8(&js.into_vec()[..]).unwrap());
}
<commit_msg>Add helper method<commit_after>#![feature(vec_push_all)]

pub struct JsonEncoder {
    buffer: Vec<u8>
}

impl JsonEncoder {
    pub fn new() -> JsonEncoder {
        JsonEncoder{buffer: Vec::new()}
    }

    #[inline(always)]
    pub fn encode_raw(&mut self, raw: &[u8]) {
        self.buffer.push_all(raw);
    }

    pub fn into_vec(self) -> Vec<u8> {
        self.buffer
    }

    pub fn with_buf<F>(&mut self, f: F) where F: Fn(&mut Vec<u8>) {
        f(&mut self.buffer);
    }

    #[inline(always)]
    pub fn encode_str_noescape(&mut self, raw_str: &str) {
        self.buffer.push(b'"');
        self.buffer.push_all(raw_str.as_bytes());
        self.buffer.push(b'"');
    }

    fn escape_bytes(&mut self, bytes: &[u8]) {
        let mut start = 0;

        for (i, byte) in bytes.iter().enumerate() {
            let escaped = match *byte {
                b'"' => b"\\\"",
                b'\\' => b"\\\\",
                b'\x08' => b"\\b",
                b'\x0c' => b"\\f",
                b'\n' => b"\\n",
                b'\r' => b"\\r",
                b'\t' => b"\\t",
                _ => {
                    continue;
                }
            };

            if start < i {
                self.encode_raw(&bytes[start..i]);
            }

            self.encode_raw(escaped);

            start = i + 1;
        }

        if start != bytes.len() {
            self.encode_raw(&bytes[start..]);
        }
    }

    pub fn encode_decimal_str(&mut self, value: u64) {
        self.buffer.push(b'"');
        self.encode_u64_decimal(value);
        self.buffer.push(b'"');
    }

    // encodes as decimal string
    #[inline(always)]
    fn encode_u64_decimal(&mut self, value: u64) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 20;

        if value == 0 {
            self.buffer.push(b'0');
            return;
        }

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    #[inline(always)]
    pub fn encode_str(&mut self, s: &str) {
        self.buffer.push(b'"');
        self.escape_bytes(s.as_bytes());
        self.buffer.push(b'"');
    }

    #[inline(always)]
    pub fn encode_i32(&mut self, value: i32) {
        if value == 0 {
            self.buffer.push(b'0');
        } else if value > 0 {
            self.encode_u31(value as u32);
        } else {
            self.buffer.push(b'-');
            self.encode_u31((-value) as u32);
        }
    }

    // encodes a 31-bit unsigned integer != 0
    fn encode_u31(&mut self, value: u32) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 10;
        debug_assert!(value != 0);

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    pub fn encode_obj<F>(&mut self, f: F) where F: Fn(&mut JsonObjectEncoder) {
        self.buffer.push(b'{');
        {
            f(&mut JsonObjectEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b'}');
    }

    pub fn encode_array<F>(&mut self, f: F) where F: Fn(&mut JsonArrayEncoder) {
        self.buffer.push(b'[');
        {
            f(&mut JsonArrayEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b']');
    }

}

pub struct JsonObjectEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonObjectEncoder<'a> {
    // XXX: name MAY NOT include escapable characters
    #[inline(always)]
    pub fn encode_field<F:Fn(&mut JsonEncoder)>(&mut self, name: &str, f: F) {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        self.js.encode_str_noescape(name);
        self.js.buffer.push(b':');

        f(self.js);
    }

    #[inline(always)]
    pub fn encode_field_array<F:Fn(&mut JsonArrayEncoder)>(&mut self, name: &str, f: F) {
        self.encode_field(name, |js| js.encode_array(|jsa| f(jsa)));
    }
}

pub struct JsonArrayEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonArrayEncoder<'a> {
    #[inline(always)]
    pub fn encode_elm<F:Fn(&mut JsonEncoder)>(&mut self, f: F) {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        f(self.js);
    }

    #[inline(always)]
    pub fn encode_elm_i32(&mut self, val: i32) {
        self.encode_elm(|j| j.encode_i32(val));
    }

    #[inline(always)]
    pub fn encode_elm_str(&mut self, s: &str) {
        self.encode_elm(|j| j.encode_str(s));
    }
}

#[test]
fn test_json_obj_encoder() {
    use std::str;

    let mut js = JsonEncoder::new();
    js.encode_obj(|_|{});
    assert_eq!(b"{}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
    });
    assert_eq!(b"{\"total\":31}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
    });
    assert_eq!(b"{\"total\":31,\"next\":\"abc\"}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
        jso.encode_field("tags", |js| {
                js.encode_array(|jsa| {
                        jsa.encode_elm(|js| js.encode_i32(1));
                        jsa.encode_elm(|js| js.encode_i32(2));
                });
        });
    });
    assert_eq!("{\"total\":31,\"next\":\"abc\",\"tags\":[1,2]}", str::from_utf8(&js.into_vec()[..]).unwrap());
}
<|endoftext|>


<commit_before>#![feature(libc)]
extern crate libc;

pub fn readline() -> Option<String> {
    // Buffer to hold readline input
    let buffer = String::new();

    let isatty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
    if isatty  {
        println!("stdin is a tty");
    } else {
        println!("stdin is not a tty");
    }

    buffer
}
<commit_msg>Split out tty check to a separate function<commit_after>#![feature(libc)]
extern crate libc;

fn isatty() -> bool {
    let isatty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
    isatty
}

pub fn readline() -> Option<String> {
    if isatty() {
        Some(buffer)
    } else {
        None
    }
}

<|endoftext|>


<commit_before>#![crate_name="postgres_macros"]
#![crate_type="dylib"]
#![feature(plugin_registrar)]

extern crate libc;
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use std::c_str::CString;
use std::mem;
use std::gc::Gc;
use syntax::ast::{TokenTree, ExprLit, LitStr, Expr, Ident};
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::parse::token::{InternedString, COMMA, EOF};
use syntax::parse;
use syntax::parse::parser::Parser;

mod ffi {
    use libc::{c_char, c_int};

    pub struct ParseResult {
        pub success: c_int,
        pub error_message: *const c_char,
        pub index: c_int,
        pub num_params: c_int,
    }

    #[link(name="parser", kind="static")]
    extern {
        pub fn init_parser();
        pub fn parse_query(query: *const c_char, result: *mut ParseResult);
    }
}

struct ParseInfo {
    num_params: uint,
}

struct ParseError {
    message: CString,
    index: uint,
}

#[plugin_registrar]
#[doc(hidden)]
pub fn registrar(reg: &mut Registry) {
    reg.register_macro("sql", expand_sql);
    reg.register_macro("execute", expand_execute);
    unsafe { ffi::init_parser() }
}

fn expand_sql(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
              -> Box<MacResult> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                Vec::from_slice(tts));

    let query_expr = cx.expand_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp)
    };

    match parse(query.get()) {
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    MacExpr::new(query_expr)
}

fn expand_execute(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                  -> Box<MacResult> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                Vec::from_slice(tts));

    let conn = parser.parse_expr();

    if !parser.eat(&COMMA) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let query_expr = cx.expand_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp),
    };

    if !parser.eat(&COMMA) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let args = match parse_args(cx, &mut parser) {
        Some(args) => args,
        None => return DummyResult::expr(sp),
    };

    match parse(query.get()) {
        Ok(ref info) if info.num_params != args.len() =>
            cx.span_err(sp, format!("Expected {} query parameters but got {}",
                                    info.num_params, args.len()).as_slice()),
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    let ident = Ident::new(token::intern("execute"));
    let args = cx.expr_vec(sp, args);
    MacExpr::new(cx.expr_method_call(sp, conn, ident, vec![query_expr, args]))
}

fn parse_error(cx: &mut ExtCtxt, sp: Span, err: ParseError) {
    cx.span_err(sp, format!("Invalid syntax at position {}: {}",
                            err.index,
                            err.message.as_str().unwrap()).as_slice());
}

fn parse_str_lit(cx: &mut ExtCtxt, e: &Expr) -> Option<InternedString> {
    match e.node {
        ExprLit(lit) => {
            match lit.node {
                LitStr(ref s, _) => Some(s.clone()),
                _ => {
                    cx.span_err(e.span, "expected string literal");
                    None
                }
            }
        }
        _ => {
            cx.span_err(e.span, "expected string literal");
            None
        }
    }
}

fn parse_args(cx: &mut ExtCtxt, parser: &mut Parser) -> Option<Vec<Gc<Expr>>> {
    let mut args = Vec::new();

    while parser.token != EOF {
        args.push(parser.parse_expr());

        if !parser.eat(&COMMA) && parser.token != EOF {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    Some(args)
}

fn parse(query: &str) -> Result<ParseInfo, ParseError> {
    unsafe {
        ffi::init_parser();
        let mut result = mem::uninitialized();
        query.with_c_str(|query| {
            ffi::parse_query(query, &mut result);
        });
        match result.success != 0 {
            true => Ok(ParseInfo {
                num_params: result.num_params as uint,
            }),
            false => Err(ParseError {
                message: CString::new(result.error_message, true),
                index: result.index as uint,
            }),
        }
    }
}
<commit_msg>Update for API changes<commit_after>#![crate_name="postgres_macros"]
#![crate_type="dylib"]
#![feature(plugin_registrar)]

extern crate libc;
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use std::c_str::CString;
use std::mem;
use std::gc::Gc;
use syntax::ast::{TokenTree, ExprLit, LitStr, Expr, Ident};
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::parse::token;
use syntax::parse::token::{InternedString, COMMA, EOF};
use syntax::parse;
use syntax::parse::parser::Parser;

mod ffi {
    use libc::{c_char, c_int};

    pub struct ParseResult {
        pub success: c_int,
        pub error_message: *const c_char,
        pub index: c_int,
        pub num_params: c_int,
    }

    #[link(name="parser", kind="static")]
    extern {
        pub fn init_parser();
        pub fn parse_query(query: *const c_char, result: *mut ParseResult);
    }
}

struct ParseInfo {
    num_params: uint,
}

struct ParseError {
    message: CString,
    index: uint,
}

#[plugin_registrar]
#[doc(hidden)]
pub fn registrar(reg: &mut Registry) {
    reg.register_macro("sql", expand_sql);
    reg.register_macro("execute", expand_execute);
    unsafe { ffi::init_parser() }
}

fn expand_sql(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
              -> Box<MacResult> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                Vec::from_slice(tts));

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp)
    };

    match parse(query.get()) {
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    MacExpr::new(query_expr)
}

fn expand_execute(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                  -> Box<MacResult> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                Vec::from_slice(tts));

    let conn = parser.parse_expr();

    if !parser.eat(&COMMA) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp),
    };

    if !parser.eat(&COMMA) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let args = match parse_args(cx, &mut parser) {
        Some(args) => args,
        None => return DummyResult::expr(sp),
    };

    match parse(query.get()) {
        Ok(ref info) if info.num_params != args.len() =>
            cx.span_err(sp, format!("Expected {} query parameters but got {}",
                                    info.num_params, args.len()).as_slice()),
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    let ident = Ident::new(token::intern("execute"));
    let args = cx.expr_vec(sp, args);
    MacExpr::new(cx.expr_method_call(sp, conn, ident, vec![query_expr, args]))
}

fn parse_error(cx: &mut ExtCtxt, sp: Span, err: ParseError) {
    cx.span_err(sp, format!("Invalid syntax at position {}: {}",
                            err.index,
                            err.message.as_str().unwrap()).as_slice());
}

fn parse_str_lit(cx: &mut ExtCtxt, e: &Expr) -> Option<InternedString> {
    match e.node {
        ExprLit(lit) => {
            match lit.node {
                LitStr(ref s, _) => Some(s.clone()),
                _ => {
                    cx.span_err(e.span, "expected string literal");
                    None
                }
            }
        }
        _ => {
            cx.span_err(e.span, "expected string literal");
            None
        }
    }
}

fn parse_args(cx: &mut ExtCtxt, parser: &mut Parser) -> Option<Vec<Gc<Expr>>> {
    let mut args = Vec::new();

    while parser.token != EOF {
        args.push(parser.parse_expr());

        if !parser.eat(&COMMA) && parser.token != EOF {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    Some(args)
}

fn parse(query: &str) -> Result<ParseInfo, ParseError> {
    unsafe {
        ffi::init_parser();
        let mut result = mem::uninitialized();
        query.with_c_str(|query| {
            ffi::parse_query(query, &mut result);
        });
        match result.success != 0 {
            true => Ok(ParseInfo {
                num_params: result.num_params as uint,
            }),
            false => Err(ParseError {
                message: CString::new(result.error_message, true),
                index: result.index as uint,
            }),
        }
    }
}
<|endoftext|>


<commit_before>//! nom, eating data byte by byte
//!
//! nom is a parser combinator library with a focus on safe parsing,
//! streaming patterns, and as much as possible zero copy.
//!
//! The code is available on [Github](https://github.com/Geal/nom)
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate nom;
//!
//! use nom::{IResult,digit};
//! use nom::IResult::*;
//!
//! // Parser definition
//!
//! use std::str;
//! use std::str::FromStr;
//!
//! named!(parens<i64>, delimited!(
//!     char!('('),
//!     expr,
//!     char!(')')
//!   )
//! );
//!
//! named!(i64_digit<i64>,
//!   map_res!(
//!     map_res!(
//!       digit,
//!       str::from_utf8
//!     ),
//!     FromStr::from_str
//!   )
//! );
//!
//! // We transform an integer string into a i64
//! // we look for a digit suite, and try to convert it.
//! // if either str::from_utf8 or FromStr::from_str fail,
//! // the parser will fail
//! named!(factor<i64>,
//!   alt!(
//!     i64_digit
//!   | parens
//!   )
//! );
//!
//! // we define acc as mutable to update its value whenever a new term is found
//! named!(term <i64>,
//!   chain!(
//!     mut acc: factor  ~
//!              many0!(
//!                alt!(
//!                  tap!(mul: preceded!(tag!("*"), factor) => acc = acc * mul) |
//!                  tap!(div: preceded!(tag!("/"), factor) => acc = acc / div)
//!                )
//!              ),
//!     || { return acc }
//!   )
//! );
//!
//! named!(expr <i64>,
//!   chain!(
//!     mut acc: term  ~
//!              many0!(
//!                alt!(
//!                  tap!(add: preceded!(tag!("+"), term) => acc = acc + add) |
//!                  tap!(sub: preceded!(tag!("-"), term) => acc = acc - sub)
//!                )
//!              ),
//!     || { return acc }
//!   )
//! );
//!
//! fn main() {
//!   assert_eq!(expr(b"1+2"),         IResult::Done(&b""[..], 3));
//!   assert_eq!(expr(b"12+6-4+3"),    IResult::Done(&b""[..], 17));
//!   assert_eq!(expr(b"1+2*3+4"),     IResult::Done(&b""[..], 11));
//!
//!   assert_eq!(expr(b"(2)"),         IResult::Done(&b""[..], 2));
//!   assert_eq!(expr(b"2*(3+4)"),     IResult::Done(&b""[..], 14));
//!   assert_eq!(expr(b"2*2/(5-1)+3"), IResult::Done(&b""[..], 4));
//! }
//! ```
#![cfg_attr(feature = "core", feature(no_std))]
#![cfg_attr(feature = "core", feature(collections))]
#![cfg_attr(feature = "core", no_std)]
#![cfg_attr(feature = "nightly", feature(test))]
#![cfg_attr(feature = "nightly", feature(const_fn))]

#[cfg(feature = "core")]
extern crate collections;
#[cfg(feature = "regexp")]
extern crate regex;
#[cfg(feature = "regexp_macros")]
#[macro_use] extern crate lazy_static;
#[cfg(feature = "nightly")]
extern crate test;

#[cfg(feature = "core")]
mod std {
#[macro_use]
  pub use core::{fmt, iter, option, ops, slice, mem};
  pub use collections::{boxed, vec, string};
  pub mod prelude {
    pub use core::prelude as v1;
  }
}

pub use self::util::*;

#[cfg(feature = "verbose-errors")]
pub use self::verbose_errors::*;

#[cfg(not(feature = "verbose-errors"))]
pub use self::simple_errors::*;

pub use self::internal::*;
pub use self::macros::*;
pub use self::methods::*;
pub use self::bytes::*;
pub use self::bits::*;

pub use self::nom::*;
pub use self::character::*;
pub use self::whitespace::*;

#[cfg(feature = "regexp")]
pub use self::regexp::*;

#[cfg(not(feature = "core"))]
#[cfg(feature = "stream")]
pub use self::stream::*;

#[cfg(not(feature = "core"))]
pub use self::str::*;

#[macro_use] mod util;

#[cfg(feature = "verbose-errors")] #[macro_use] mod verbose_errors;

#[cfg(not(feature = "verbose-errors"))] #[macro_use] mod simple_errors;

#[macro_use] mod internal;
#[macro_use] mod macros;
#[macro_use] mod methods;
#[macro_use] mod bytes;
#[macro_use] mod bits;

#[macro_use] mod nom;
#[macro_use] mod character;
#[macro_use] mod whitespace;

#[cfg(feature = "regexp")]
#[macro_use] mod regexp;

#[macro_use]
#[cfg(not(feature = "core"))]
#[cfg(feature = "stream")]
mod stream;

#[cfg(not(feature = "core"))]
mod str;
<commit_msg>do not activate the whitespace module on core<commit_after>//! nom, eating data byte by byte
//!
//! nom is a parser combinator library with a focus on safe parsing,
//! streaming patterns, and as much as possible zero copy.
//!
//! The code is available on [Github](https://github.com/Geal/nom)
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate nom;
//!
//! use nom::{IResult,digit};
//! use nom::IResult::*;
//!
//! // Parser definition
//!
//! use std::str;
//! use std::str::FromStr;
//!
//! named!(parens<i64>, delimited!(
//!     char!('('),
//!     expr,
//!     char!(')')
//!   )
//! );
//!
//! named!(i64_digit<i64>,
//!   map_res!(
//!     map_res!(
//!       digit,
//!       str::from_utf8
//!     ),
//!     FromStr::from_str
//!   )
//! );
//!
//! // We transform an integer string into a i64
//! // we look for a digit suite, and try to convert it.
//! // if either str::from_utf8 or FromStr::from_str fail,
//! // the parser will fail
//! named!(factor<i64>,
//!   alt!(
//!     i64_digit
//!   | parens
//!   )
//! );
//!
//! // we define acc as mutable to update its value whenever a new term is found
//! named!(term <i64>,
//!   chain!(
//!     mut acc: factor  ~
//!              many0!(
//!                alt!(
//!                  tap!(mul: preceded!(tag!("*"), factor) => acc = acc * mul) |
//!                  tap!(div: preceded!(tag!("/"), factor) => acc = acc / div)
//!                )
//!              ),
//!     || { return acc }
//!   )
//! );
//!
//! named!(expr <i64>,
//!   chain!(
//!     mut acc: term  ~
//!              many0!(
//!                alt!(
//!                  tap!(add: preceded!(tag!("+"), term) => acc = acc + add) |
//!                  tap!(sub: preceded!(tag!("-"), term) => acc = acc - sub)
//!                )
//!              ),
//!     || { return acc }
//!   )
//! );
//!
//! fn main() {
//!   assert_eq!(expr(b"1+2"),         IResult::Done(&b""[..], 3));
//!   assert_eq!(expr(b"12+6-4+3"),    IResult::Done(&b""[..], 17));
//!   assert_eq!(expr(b"1+2*3+4"),     IResult::Done(&b""[..], 11));
//!
//!   assert_eq!(expr(b"(2)"),         IResult::Done(&b""[..], 2));
//!   assert_eq!(expr(b"2*(3+4)"),     IResult::Done(&b""[..], 14));
//!   assert_eq!(expr(b"2*2/(5-1)+3"), IResult::Done(&b""[..], 4));
//! }
//! ```
#![cfg_attr(feature = "core", feature(no_std))]
#![cfg_attr(feature = "core", feature(collections))]
#![cfg_attr(feature = "core", no_std)]
#![cfg_attr(feature = "nightly", feature(test))]
#![cfg_attr(feature = "nightly", feature(const_fn))]

#[cfg(feature = "core")]
extern crate collections;
#[cfg(feature = "regexp")]
extern crate regex;
#[cfg(feature = "regexp_macros")]
#[macro_use] extern crate lazy_static;
#[cfg(feature = "nightly")]
extern crate test;

#[cfg(feature = "core")]
mod std {
#[macro_use]
  pub use core::{fmt, iter, option, ops, slice, mem};
  pub use collections::{boxed, vec, string};
  pub mod prelude {
    pub use core::prelude as v1;
  }
}

pub use self::util::*;

#[cfg(feature = "verbose-errors")]
pub use self::verbose_errors::*;

#[cfg(not(feature = "verbose-errors"))]
pub use self::simple_errors::*;

pub use self::internal::*;
pub use self::macros::*;
pub use self::methods::*;
pub use self::bytes::*;
pub use self::bits::*;

pub use self::nom::*;
pub use self::character::*;

#[cfg(not(feature = "core"))]
pub use self::whitespace::*;

#[cfg(feature = "regexp")]
pub use self::regexp::*;

#[cfg(not(feature = "core"))]
#[cfg(feature = "stream")]
pub use self::stream::*;

#[cfg(not(feature = "core"))]
pub use self::str::*;

#[macro_use] mod util;

#[cfg(feature = "verbose-errors")] #[macro_use] mod verbose_errors;

#[cfg(not(feature = "verbose-errors"))] #[macro_use] mod simple_errors;

#[macro_use] mod internal;
#[macro_use] mod macros;
#[macro_use] mod methods;
#[macro_use] mod bytes;
#[macro_use] mod bits;

#[macro_use] mod nom;
#[macro_use] mod character;

#[macro_use]
#[cfg(not(feature = "core"))]
mod whitespace;

#[cfg(feature = "regexp")]
#[macro_use] mod regexp;

#[macro_use]
#[cfg(not(feature = "core"))]
#[cfg(feature = "stream")]
mod stream;

#[cfg(not(feature = "core"))]
mod str;
<|endoftext|>


<commit_before>#![feature(plugin, custom_derive)]
#![plugin(serde_macros)]

#[macro_use]
extern crate nom;
extern crate serde;

#[cfg(test)] extern crate serde_json;

pub use self::models::*;
pub use self::parsing::*;
mod models;
mod parsing;

<commit_msg>document root level lib.rs<commit_after>//! # boxcars (also written boxca-rs)
//!
//! boxcars is an example of a [Rocket League](http://www.rocketleaguegame.com/) replay parser
//! written in rust using [nom](https://github.com/Geal/nom) for parsing and
//! [serde](https://github.com/serde-rs/serde) for serialization. Emphasis on example, as this
//! library in no way competes with the other feature complete parsers such as
//! [Octane](https://github.com/tfausak/octane) and
//! [RocketLeagueReplayParser](https://github.com/jjbott/RocketLeagueReplayParser). Rather let the
//! project be a good example of Rust code using nom, and serde as extensive examples are hard to
//! come by. While lacking feature completeness and user friendly error message -- among other
//! issues, tests and documentation strive to be thorough.
#![feature(plugin, custom_derive)]
#![plugin(serde_macros)]

#[macro_use]
extern crate nom;
extern crate serde;

#[cfg(test)] extern crate serde_json;

pub use self::models::*;
pub use self::parsing::*;
mod models;
mod parsing;

<|endoftext|>


<commit_before>// Copyright 2017 Jeremy Wall <jeremy@marzhillstudios.com>
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// #![feature(trace_macros,log_syntax)]

//! # ucg, A universal configuration grammar.
//!
//! Ucg defines a common grammar for describing a collection of configuration values.
//! ucg allows you to specify configuration values with a syntax that that is immutable,
//! comoposable with copy-on-write semantics, and safe.
//!
//! ## Example
//!
//! ```ucg
//! // named bindings
//! let host = "mysql.internal.net";
//! let port = 8080
//!
//! // format strings
//! let connstr = "mysql://@:@" % (host, port);
//!
//! // tuples
//! let dbconf = {
//!     connstr = connstr,
//!     database = "mydb",
//!     // lists
//!     tables = ["posts", "comments", "users"],
//! };
//! ```
//!
//! ## Syntax
//!
//! ucg is a safe language with type inference that tries to guarantee that it will halt.
//! A valid ucg file is composesed of a series of statements. Statements are any valid
//! ucg expression terminated by a semicolon.
//!
//! ### Reserved words
//!
//! The following words are reserved in ucg and can't be used as named bindings.
//!
//! * let
//! * import
//! * as
//! * select
//! * macro
//! * env
//!
//! ### Primitive types
//!
//! ucg has a relatively simple syntax with 3 primitive types, Int, Float, and String.
//!
//! * An Int is any integer number.
//!
//! ```ucg
//! 1; // a single Integer
//! ```
//!
//! * A Float is any number with a decimal point.
//!
//! ```ucg
//! 1.0; // A typical float.
//! 1. // You can leave off the 0 after the decimal point.
//! .1 // the leading 0 is also optional.
//! ```
//!
//! * A String is any quoted text. Backslashes within a string escape the next preceding
//! character.
//!
//! ``` ucg
//! "foo"; // a smiple string
//! "I'm a \"fine\" looking string"; // escaped quotes in a string.
//! ```
//!
//! ### Complex types
//!
//! ucg has two complex data types, Lists and Tuples.
//!
//! * Lists are surrounded with square brackets `[ ]` and have comma separated elements.
//!
//! ```ucg
//! [1, 2, 3]; // A simple list of numbers.
//!
//! [[1, 2], [3, 4]] // A deep list with embedded lists inside.
//! ```
//!
//! Lists are 0 indexed and you can index into them using the dotted selector syntax.
//!
//! ```ucg
//! let mylist = [0, 1, 2, 3];
//!
//! let zero = mylist.0;
//! ```
//!
//! * Tuple's are an ordered collection of name, value pairs. They are bounded by curly braces `{ }`
//! and contain name = value pairs separated by commas. Trailing commas are permitted. The name must
//! be a bareword without quotes.
//!
//! ```ucg
//! let mytuple = {
//!     field1 = "value1",
//!     field2 = "value2",
//! };
//! ```
//!
//! Tuples can be indexed using dotted selector syntax.
//!
//! ```ucg
//! let field = mytuple.fields1;
//! ```
//!
//! ### Expressions
//!
//! #### Selectors
//!
//! Selectors are references to a bound value in ucg. They can index arbitrarily deep into either tuples or lists.
//! The head of a selector can be any expression that resolves to a tuple or list. Optionally a selector can also be
//! followed by either a bareword to index a tuple field or an integer to index a list position.
//!
//! The simplest selector is just a reference to a bound value by name.
//!
//! ```ucg
//! let mytuple = {
//!     field1 = "a string",
//!     field2 = [{
//!         subfield1 = 1,
//!     }];
//! };
//!
//! mytuple.field2.0; // descend into a deeply nested tuple and array.
//! ```
//!
//! The `env` variable is a reserved variable that always contains a tuple with any environment
//! variables in it.
//!
//! Attempting to reference an enviroment variable that does not exist is a compile error.
//!
//! #### Binary operators
//!
//! ucg supports the following operators, +, -, *, /; Each one is type safe and infers the types from the values they operate on.
//! The operators expect both the left and right operands to be of the same type. All of the operators are valid on integers and floats.
//! The + operator can additionally concatenate strings or arrays.
//!
//! ```ucg
//! 1 + 1; // result is 2
//! "foo " + "bar" // result is "foo bar"
//! [1,2] + [3,4]; // result is [1,2,3,4]
//! ```
//!
//! #### Copy expressions
//!
//! ucg Tuples support a form of reuse with copy on write semantics. You can copy a tuple and selectively overwrite fields or add new
//! fields to it with the copy expression. To perform a copy first reference the tuple by a bound name and then use `{ field = value, ... }`
//! syntax to copy with overridden fields  or add completely new fields. When replacing a preexisting field with a new value you cannot
//! change the type of the field. This allows you to define a typed shape for a tuple with default values and then provide new values for
//! some or all of the fields while still enforcing the same types for those fields. Adding completely new fields has no such restriction.
//!
//! ```ucg
//! let base = {
//!     field1 = "value1",
//!     field2 = 100,
//!     field3 = 5.6,
//! };
//!
//! let overridden = base{
//!     field1 = "new value"
//! };
//!
//! let expanded = base{
//!     field2 = 200,
//!     field3 = "look ma a new field",
//! };
//! ```
//!
//! The following will cause an error because the overriden field's value does not match the original.
//!
//! ```ucg
//! let bad = base{
//!     field1 = 300, // Error!!! must be a string.
//! };
//!
//! ```
//!
//! #### Conditional data
//!
//! ucg supports a limited form of conditional data selection of using the select expression. A select expression starts with the `select`
//! keyword and is followed by a an expression resolving to a string naming the field to select, an expression resolving to the default value,
//! and a tuple to select the field from. If the field selected is not in the tuple then the default value will be used.
//!
//! ```ucg
//! let want = "baz";
//!
//! //     field  default
//! select want, "quux", {
//!     baz = "foo",
//!     fuzz = "bang",
//! }; // result will be "foo"
//!
//! //     field    default
//! select "quack", "quux", {
//!     baz = "foo",
//!     fuzz = "bang",
//! }; // result will be "quux"
//! ```
//!
//! #### Macros
//!
//! Macros look like functions but they are resolved at compile time and configurations don't execute so they never appear in output.
//! They are useful for constructing tuples of a certain shape or otherwise promoting data reuse. You define a macro with the `macro`
//! keyword followed by the arguments in parentheses and then a tuple.
//!
//! ```ucg
//! let myfunc = macro (arg1, arg2) {
//!     host = arg1,
//!     port = arg2,
//!     connstr = "couchdb://@:@" % (arg1, arg2),
//! }
//!
//! let my_dbconf = myfunc("couchdb.example.org", "9090");
//!
//! let my_dbhost = dbconf.host;
//! ```
//!
//! macros always resolve to a tuple. If you want to get a single value out you can use selector syntax to retrieve it.
//!
//! ### Statements
//!
//! There are 3 kinds of statements in a ucg configuration file. expression statements, let statements, and import statements.
//! All ucg statements must be terminated by a semicolon.
//!
//! * expression statements
//!
//! The simplest and least useful is the expression statement. It is any valid expression followed by a semicolon.
//!
//! ```ucg
//! 1;
//! 4 / 2;
//! "foo";
//! "foo" + "bar";
//! ```
//!
//! Despite the fact that these are valid the results are thrown away and can essentially be considered a noop. If we
//! ever create a repl for ucg statements they may prove more useful.
//!
//!  * Let statements
//!
//! The let expression binds the result of any valid expression to a name. It starts with the `let` keyword and is followed by
//! the name of the binding, an `=`, and a valid ucg expression.
//!
//! ```ucg
//! let name = "foo";
//! ```
//!
//! * Import statement
//!
//! The import statement imports the contents of another ucg file into the current file with a name. The imported files bound
//! values are exposed as a tuple in the referencing file. It starts with the `import` keyword and is followed by a quoted path
//! to the ucg file, the keyword `as`, and a name for the imported values.
//!
//! ```ucg
//! import "dbconfigs.ucg" as dbconfigs;
//!
//! let mysqlconf = dbconfigs.mysql;
//! ```
#[macro_use]
extern crate nom;
#[macro_use]
extern crate nom_locate;
extern crate serde_json;

#[macro_use]
pub mod ast;
#[macro_use]
pub mod tokenizer;
pub mod parse;
pub mod build;
pub mod convert;
pub mod error;

mod format;

pub use ast::Value;
pub use ast::Expression;
pub use ast::Statement;

pub use parse::parse;
pub use build::Builder;
pub use build::Val;
<commit_msg>Update language spec with the NULL empty type.<commit_after>// Copyright 2017 Jeremy Wall <jeremy@marzhillstudios.com>
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// #![feature(trace_macros,log_syntax)]

//! # ucg, A universal configuration grammar.
//!
//! Ucg defines a common grammar for describing a collection of configuration values.
//! ucg allows you to specify configuration values with a syntax that that is immutable,
//! comoposable with copy-on-write semantics, and safe.
//!
//! ## Example
//!
//! ```ucg
//! // named bindings
//! let host = "mysql.internal.net";
//! let port = 8080
//!
//! // format strings
//! let connstr = "mysql://@:@" % (host, port);
//!
//! // tuples
//! let dbconf = {
//!     connstr = connstr,
//!     database = "mydb",
//!     // lists
//!     tables = ["posts", "comments", "users"],
//! };
//! ```
//!
//! ## Syntax
//!
//! ucg is a safe language with type inference that tries to guarantee that it will halt.
//! A valid ucg file is composesed of a series of statements. Statements are any valid
//! ucg expression terminated by a semicolon.
//!
//! ### Reserved words
//!
//! The following words are reserved in ucg and can't be used as named bindings.
//!
//! * let
//! * import
//! * as
//! * select
//! * macro
//! * env
//! * NULL
//!
//! ### Primitive types
//!
//! ucg has a relatively simple syntax with 3 primitive types, Int, Float, and String.
//!
//! * An Int is any integer number.
//!
//! ```ucg
//! 1; // a single Integer
//! ```
//!
//! * A Float is any number with a decimal point.
//!
//! ```ucg
//! 1.0; // A typical float.
//! 1. // You can leave off the 0 after the decimal point.
//! .1 // the leading 0 is also optional.
//! ```
//!
//! * A String is any quoted text. Backslashes within a string escape the next preceding
//! character.
//!
//! ``` ucg
//! "foo"; // a smiple string
//! "I'm a \"fine\" looking string"; // escaped quotes in a string.
//! ```
//!
//! * A NULL is an empty type. It represents no value.
//!
//! ```ucg
//! let empty = NULL;
//! ```
//!
//! ### Complex types
//!
//! ucg has two complex data types, Lists and Tuples.
//!
//! * Lists are surrounded with square brackets `[ ]` and have comma separated elements.
//!
//! ```ucg
//! [1, 2, 3]; // A simple list of numbers.
//!
//! [[1, 2], [3, 4]] // A deep list with embedded lists inside.
//! ```
//!
//! Lists are 0 indexed and you can index into them using the dotted selector syntax.
//!
//! ```ucg
//! let mylist = [0, 1, 2, 3];
//!
//! let zero = mylist.0;
//! ```
//!
//! * Tuple's are an ordered collection of name, value pairs. They are bounded by curly braces `{ }`
//! and contain name = value pairs separated by commas. Trailing commas are permitted. The name must
//! be a bareword without quotes.
//!
//! ```ucg
//! let mytuple = {
//!     field1 = "value1",
//!     field2 = "value2",
//! };
//! ```
//!
//! Tuples can be indexed using dotted selector syntax.
//!
//! ```ucg
//! let field = mytuple.fields1;
//! ```
//!
//! ### Expressions
//!
//! #### Selectors
//!
//! Selectors are references to a bound value in ucg. They can index arbitrarily deep into either tuples or lists.
//! The head of a selector can be any expression that resolves to a tuple or list. Optionally a selector can also be
//! followed by either a bareword to index a tuple field or an integer to index a list position.
//!
//! The simplest selector is just a reference to a bound value by name.
//!
//! ```ucg
//! let mytuple = {
//!     field1 = "a string",
//!     field2 = [{
//!         subfield1 = 1,
//!     }];
//! };
//!
//! mytuple.field2.0; // descend into a deeply nested tuple and array.
//! ```
//!
//! The `env` variable is a reserved variable that always contains a tuple with any environment
//! variables in it.
//!
//! Attempting to reference an enviroment variable that does not exist is a compile error.
//!
//! #### Binary operators
//!
//! ucg supports the following operators, +, -, *, /; Each one is type safe and infers the types from the values they operate on.
//! The operators expect both the left and right operands to be of the same type. All of the operators are valid on integers and floats.
//! The + operator can additionally concatenate strings or arrays.
//!
//! ```ucg
//! 1 + 1; // result is 2
//! "foo " + "bar" // result is "foo bar"
//! [1,2] + [3,4]; // result is [1,2,3,4]
//! ```
//!
//! #### Copy expressions
//!
//! ucg Tuples support a form of reuse with copy on write semantics. You can copy a tuple and selectively overwrite fields or add new
//! fields to it with the copy expression. To perform a copy first reference the tuple by a bound name and then use `{ field = value, ... }`
//! syntax to copy with overridden fields  or add completely new fields. When replacing a preexisting field with a new value you cannot
//! change the type of the field. This allows you to define a typed shape for a tuple with default values and then provide new values for
//! some or all of the fields while still enforcing the same types for those fields. Adding completely new fields has no such restriction.
//!
//! ```ucg
//! let base = {
//!     field1 = "value1",
//!     field2 = 100,
//!     field3 = 5.6,
//! };
//!
//! let overridden = base{
//!     field1 = "new value"
//! };
//!
//! let expanded = base{
//!     field2 = 200,
//!     field3 = "look ma a new field",
//! };
//! ```
//!
//! The following will cause an error because the overriden field's value does not match the original.
//!
//! ```ucg
//! let bad = base{
//!     field1 = 300, // Error!!! must be a string.
//! };
//!
//! ```
//!
//! #### Conditional data
//!
//! ucg supports a limited form of conditional data selection of using the select expression. A select expression starts with the `select`
//! keyword and is followed by a an expression resolving to a string naming the field to select, an expression resolving to the default value,
//! and a tuple to select the field from. If the field selected is not in the tuple then the default value will be used.
//!
//! ```ucg
//! let want = "baz";
//!
//! //     field  default
//! select want, "quux", {
//!     baz = "foo",
//!     fuzz = "bang",
//! }; // result will be "foo"
//!
//! //     field    default
//! select "quack", "quux", {
//!     baz = "foo",
//!     fuzz = "bang",
//! }; // result will be "quux"
//! ```
//!
//! #### Macros
//!
//! Macros look like functions but they are resolved at compile time and configurations don't execute so they never appear in output.
//! They are useful for constructing tuples of a certain shape or otherwise promoting data reuse. You define a macro with the `macro`
//! keyword followed by the arguments in parentheses and then a tuple.
//!
//! ```ucg
//! let myfunc = macro (arg1, arg2) {
//!     host = arg1,
//!     port = arg2,
//!     connstr = "couchdb://@:@" % (arg1, arg2),
//! }
//!
//! let my_dbconf = myfunc("couchdb.example.org", "9090");
//!
//! let my_dbhost = dbconf.host;
//! ```
//!
//! macros always resolve to a tuple. If you want to get a single value out you can use selector syntax to retrieve it.
//!
//! ### Statements
//!
//! There are 3 kinds of statements in a ucg configuration file. expression statements, let statements, and import statements.
//! All ucg statements must be terminated by a semicolon.
//!
//! * expression statements
//!
//! The simplest and least useful is the expression statement. It is any valid expression followed by a semicolon.
//!
//! ```ucg
//! 1;
//! 4 / 2;
//! "foo";
//! "foo" + "bar";
//! ```
//!
//! Despite the fact that these are valid the results are thrown away and can essentially be considered a noop. If we
//! ever create a repl for ucg statements they may prove more useful.
//!
//!  * Let statements
//!
//! The let expression binds the result of any valid expression to a name. It starts with the `let` keyword and is followed by
//! the name of the binding, an `=`, and a valid ucg expression.
//!
//! ```ucg
//! let name = "foo";
//! ```
//!
//! * Import statement
//!
//! The import statement imports the contents of another ucg file into the current file with a name. The imported files bound
//! values are exposed as a tuple in the referencing file. It starts with the `import` keyword and is followed by a quoted path
//! to the ucg file, the keyword `as`, and a name for the imported values.
//!
//! ```ucg
//! import "dbconfigs.ucg" as dbconfigs;
//!
//! let mysqlconf = dbconfigs.mysql;
//! ```
#[macro_use]
extern crate nom;
#[macro_use]
extern crate nom_locate;
extern crate serde_json;

#[macro_use]
pub mod ast;
#[macro_use]
pub mod tokenizer;
pub mod parse;
pub mod build;
pub mod convert;
pub mod error;

mod format;

pub use ast::Value;
pub use ast::Expression;
pub use ast::Statement;

pub use parse::parse;
pub use build::Builder;
pub use build::Val;
<|endoftext|>


<commit_before>#![allow(clippy::unreadable_literal)]

//! This crate contains parsers and readers for Pcap and Pcapng files.
//! It also contains a writer for Pcap files.
//!
//! For Pcap files see
//! [PcapReader](struct.PcapReader.html), [PcapParser](struct.PcapParser.html) and [PcapWriter](struct.PcapParser.html).
//!
//! For PcapNg files see
//! [PcapNgReader](struct.PcapNgReader.html) and [PcapNgParser](struct.PcapNgParser.html).

pub(crate) mod common;
pub use common::*;

pub(crate) mod errors;
pub use errors::*;

pub mod pcap;
pub use pcap::{PcapReader, PcapParser, PcapWriter};

pub mod pcapng;
pub use pcapng::{PcapNgReader, PcapNgParser};

pub(crate) mod peek_reader;<commit_msg>Fix link to documentation of PcapWriter<commit_after>#![allow(clippy::unreadable_literal)]

//! This crate contains parsers and readers for Pcap and Pcapng files.
//! It also contains a writer for Pcap files.
//!
//! For Pcap files see
//! [PcapReader](struct.PcapReader.html), [PcapParser](struct.PcapParser.html) and [PcapWriter](struct.PcapWriter.html).
//!
//! For PcapNg files see
//! [PcapNgReader](struct.PcapNgReader.html) and [PcapNgParser](struct.PcapNgParser.html).

pub(crate) mod common;
pub use common::*;

pub(crate) mod errors;
pub use errors::*;

pub mod pcap;
pub use pcap::{PcapReader, PcapParser, PcapWriter};

pub mod pcapng;
pub use pcapng::{PcapNgReader, PcapNgParser};

pub(crate) mod peek_reader;<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate crypto;
extern crate merkle;
extern crate capnp;

pub mod vm;
pub mod account;
pub mod transaction;
pub mod blockchain;
mod utils;
mod vm_capnp;

pub use utils::u256::U256;
pub use utils::gas::Gas;
pub use utils::hash::H256;
pub use utils::address::Address;
pub use utils::read_hex;

use std::io::BufReader;
use capnp::{serialize, message};
use log::LogLevel;

use vm_capnp::input_output::Reader;
use vm::{Machine, FakeVectorMachine};

#[no_mangle]
pub extern fn evaluate(ptr: *mut Reader) {
    let msg = unsafe {
        assert!(!ptr.is_null());
        &mut *ptr
    };
    // let io_reader = serialize::read_message(&mut msg, message::ReaderOptions::new()).expect("read message failed.");
    // let io = io_reader.get_root::<Reader>().expect("Failed to get VM IO.");
    // println!("{}", io.get_input().expect("FAILED").get_gas());

    let mut message = message::Builder::new_default();
    let mut msg = message.init_root::<vm_capnp::input_output::Builder>();
    msg.borrow().init_input();
    {
        let mut code = msg.borrow().get_input().unwrap().init_code(4);
        for i in 0..code.len() {
            code.set(i, &[b'0']);
        }
    }
    {
        let mut data = msg.borrow().get_input().unwrap().init_data(4);
        for i in 0..data.len() {
            data.set(i, &[b'0']);
        }
    }
    {
        msg.borrow().get_input().unwrap().set_gas(444);
    }
    let msg_reader = msg.as_reader();
    let mut code_vec = Vec::new();
    let mut data_vec = Vec::new();
    let in_code = msg_reader.get_input().unwrap().get_code().expect("").iter();
    let in_data = msg_reader.get_input().unwrap().get_data().expect("").iter();
    for in_char in in_code {
        code_vec.push(in_char.expect("character expected")[0]);
    }
    for in_char in in_data {
        data_vec.push(in_char.expect("character expected")[0]);
    }
    let gas = msg_reader.get_input().unwrap().get_gas();

    let mut machine = FakeVectorMachine::new(
        code_vec.as_slice()
        , data_vec.as_slice()
        , Gas::from(gas as isize));
    machine.fire();
    println!("gas used: {:?}", machine.used_gas());
    if log_enabled!(LogLevel::Info) {
        info!("gas used: {:?}", machine.used_gas());
    }
}
<commit_msg>Problem: usage doesn't reflect capnp schema<commit_after>#[macro_use]
extern crate log;
extern crate crypto;
extern crate merkle;
extern crate capnp;

pub mod vm;
pub mod account;
pub mod transaction;
pub mod blockchain;
mod utils;
mod vm_capnp;

pub use utils::u256::U256;
pub use utils::gas::Gas;
pub use utils::hash::H256;
pub use utils::address::Address;
pub use utils::read_hex;

use std::io::BufReader;
use capnp::{serialize, message};
use log::LogLevel;

use vm_capnp::input_output::Reader;
use vm::{Machine, FakeVectorMachine};

#[no_mangle]
pub extern fn evaluate(ptr: *mut Reader) {
    let msg = unsafe {
        assert!(!ptr.is_null());
        &mut *ptr
    };
    // let io_reader = serialize::read_message(&mut msg, message::ReaderOptions::new()).expect("read message failed.");
    // let io = io_reader.get_root::<Reader>().expect("Failed to get VM IO.");
    // println!("{}", io.get_input().expect("FAILED").get_gas());

    let mut message = message::Builder::new_default();
    let mut msg = message.init_root::<vm_capnp::input_output::Builder>();
    msg.borrow().init_input();
    {
        let mut code = msg.borrow().get_input().unwrap().init_code(4);
        for i in 0..code.len() {
            code.set(i, &[b'0']);
        }
    }
    {
        let mut data = msg.borrow().get_input().unwrap().init_data(4);
        for i in 0..data.len() {
            data.set(i, &[b'0']);
        }
    }
    {
        msg.borrow().get_input().unwrap().set_initial_gas(444);
    }
    let msg_reader = msg.as_reader();
    let mut code_vec = Vec::new();
    let mut data_vec = Vec::new();
    let in_code = msg_reader.get_input().unwrap().get_code().expect("").iter();
    let in_data = msg_reader.get_input().unwrap().get_data().expect("").iter();
    for in_char in in_code {
        code_vec.push(in_char.expect("character expected")[0]);
    }
    for in_char in in_data {
        data_vec.push(in_char.expect("character expected")[0]);
    }
    let gas = msg_reader.get_input().unwrap().get_initial_gas();

    let mut machine = FakeVectorMachine::new(
        code_vec.as_slice()
        , data_vec.as_slice()
        , Gas::from(gas as isize));
    machine.fire();
    println!("gas used: {:?}", machine.used_gas());
    if log_enabled!(LogLevel::Info) {
        info!("gas used: {:?}", machine.used_gas());
    }
}
<|endoftext|>