<commit_before>extern crate pancurses;

use pancurses::*;

fn main() {
    let window = initscr();

    start_color();
    use_default_colors();
    set_blink(true);

    cbreak();
    noecho();

    window.clear();
    window.refresh();

    window.keypad(true);

    init_pair(1, 15, COLOR_BLACK);
    init_pair(2, COLOR_BLACK, COLOR_YELLOW);

    set_title("NewTest: tests various pancurses features");

    mousemask(ALL_MOUSE_EVENTS, std::ptr::null_mut());

    window.attrset(COLOR_PAIR(1));

    let mut quit = false;
    let mut redraw = true;

    const COL1: i32 = 2;
    const COL2: i32 = COL1 + 30;
    const COL3: i32 = 72;
    const N_CURSORS: i32 = 9;

    let mut unicode_offset = 0x80;
    let mut blink_state = true;

    let mut cursor_state_1 = 2;
    let mut cursor_state_2 = 3;

    while !quit {
        let (y_max, x_max) = window.get_max_yx();
        let color_block_start = 54;
        let mut color_block_cols = (x_max - color_block_start) / 2;
        let color_block_lines = 19;

        let cursor_state_text = ["Invisible (click to change) ",
                                 "Underscore (click to change)",
                                 "Block (click to change)     ",
                                 "Outline (click to change)   ",
                                 "Caret (click to change)     ",
                                 "Half-block (click to change)",
                                 "Central (click to change)   ",
                                 "Cross (click to change)     ",
                                 "Heavy box (click to change) "];

        if color_block_cols < 0 {
            color_block_cols = 0;
        }

        if redraw {
            window.mvaddstr(1, COL1, "'Normal' white-on-black");

            window.attron(A_DIM);
            window.mvaddstr(2, COL1, "Dimmed text");
            window.attroff(A_DIM);

            window.attron(A_BLINK);
            window.mvaddstr(6, 40, "Blinking");
            window.attron(A_BOLD);
            window.mvaddstr(8, 40, "BlinkBold");
            window.attron(A_ITALIC);
            window.mvaddstr(0, COL2, "BlinkBoldItalic");
            window.attrset(COLOR_PAIR(3));
            window.attron(A_UNDERLINE);

            window.mvaddstr(1, COL2, "Underlined");

            window.attrset(COLOR_PAIR(1));
            window.attron(A_UNDERLINE | A_ITALIC);
            window.mvaddstr(2, COL2, "UnderlinedItalic");
            window.attrset(COLOR_PAIR(2));
            window.attron(A_BLINK);
            window.mvaddstr(4, COL1, "Black-on-yellow blinking");

            window.attrset(COLOR_PAIR(1));
            window.mv(4, COL2);
            text_in_a_box("Text in a box", &window);

            window.attrset(COLOR_PAIR(6));
            window.attron(A_STRIKEOUT);
            window.mvaddstr(10, 40, "Strikeout");
            window.attrset(COLOR_PAIR(1));

            window.mv(11, 40);
            text_in_a_box("Next Ucode pg", &window);
            if unicode_offset != 0 {
                window.mv(12, 40);
                text_in_a_box("Prev Ucode pg", &window);
            }
            window.mvprintw(13, 40, &format!("U+{:04X} ", unicode_offset));

            for i in 0..128 {
                // Show extended characters
                window.mvaddstr(5 + i % 16,
                                (i / 16) * 5,
                                &format!("{:02X} ", i + unicode_offset));
                if i + unicode_offset > ' ' as i32 {
                    window.addch((i + unicode_offset) as chtype);
                } else {
                    window.addch(' ');
                }
                window.addch(' ');
            }

            // Skipped the full RGB example, I don't think there's a suitable feature in ncurses

            redraw = false;
            window.attrset(COLOR_PAIR(1));

            for i in 0..6 {
                let line = 24 + i / 3;
                let col = 5 + 25 * (i % 3);

                let spanish = "Español";
                let russian = "Русский язык";
                let greek = "Ελληνικά";
                let georgian = "ქართული ენა";
                let fullwidth = " Ｆｕｌｌｗｉｄｔｈ";
                let combining_marks = "Cmin 	r";

                let texts = [spanish, russian, greek, georgian, fullwidth, combining_marks];

                if line < y_max && col < x_max {
                    window.mvaddnstr(line, 5 + 25 * (i % 3), texts[i as usize], x_max - col);
                }
            }

            window.mvaddstr(1, COL3, "Click on cursor descriptions to");
            window.mvaddstr(2, COL3, "cycle through possible cursors");
            window.mvaddstr(3, COL3, "Click on colors at left to change");
            window.mvaddstr(4, COL3, "colors used for under/over/outlining");
            window.mvaddstr(5, COL3, "Click 'Blink' at bottom to toggle");
            window.mvaddstr(6, COL3, "'real' blinking vs. 'highlit' blink");
        }

        window.mvaddnstr(19,
                         color_block_start,
                         cursor_state_text[cursor_state_1],
                         x_max - color_block_start);
        window.mvaddnstr(20,
                         color_block_start,
                         cursor_state_text[cursor_state_2],
                         x_max - color_block_start);

        for i in 0..color_block_cols * color_block_lines {
            let n_color_blocks = 256;

            window.attrset(COLOR_PAIR(if i >= n_color_blocks {
                2
            } else {
                i as chtype
            }));
            if i > 2 && i < n_color_blocks {
                init_pair(i as i16, i as i16, COLOR_BLACK);
            }
            if i % color_block_cols == 0 {
                window.mv(i / color_block_cols, color_block_start);
            }
            window.attron(A_REVERSE);
            window.addstr(" ");
        }

        window.mv(19, color_block_start - 3);
        window.refresh();
        let c = window.getch();
        window.attrset(COLOR_PAIR(1));

        match c {
            Some(Input::KeyF1) => quit = true,
            Some(Input::Character(x)) if x == 27 as char => quit = true,
            Some(Input::KeyF2) => {
                blink_state = !blink_state;
                set_blink(blink_state);
            }
            Some(x) if x != Input::KeyMouse => {
                window.mvaddstr(0, COL1, &format!("Key {:?} hit          ", x));
            }
            Some(Input::KeyMouse) => {
                match getmouse() {
                    Ok(mouse_event) => {
                        window.mvaddstr(0,
                                        COL1,
                                        &format!("Mouse at {} x {}: {}",
                                                 mouse_event.x,
                                                 mouse_event.y,
                                                 mouse_event.bstate));
                        if mouse_event.x >= color_block_start {
                            if mouse_event.y == 19 { // blink/non-blink toggle
                                cursor_state_1 = (cursor_state_1 + 1) % N_CURSORS as usize;
                            } else if mouse_event.y == 20 { // cycle cursor state
                                cursor_state_2 = (cursor_state_2 + 1) % N_CURSORS as usize;
                            }
                        }
                    }
                    Err(_) => (),
                }
            }
            _ => (),
        }
    }

    endwin();
}

fn text_in_a_box(text: &str, window: &Window) {
    let len = text.len();

    window.attron(A_OVERLINE | A_UNDERLINE | A_LEFTLINE);
    if len == 1 {
        window.attron(A_RIGHTLINE);
    }

    window.addnstr(text, 1);
    if len > 1 {
        window.attroff(A_LEFTLINE);
        if len > 2 {
            window.addnstr(&text[1..], len - 2);
        }
        window.attron(A_RIGHTLINE);
        window.addnstr(&text[len - 1..], 1);
    }

    window.attroff(A_OVERLINE | A_UNDERLINE | A_LEFTLINE | A_RIGHTLINE);
}
<commit_msg>Unicode page changing with mouse<commit_after>extern crate pancurses;

use pancurses::*;

fn main() {
    let window = initscr();

    start_color();
    use_default_colors();
    set_blink(true);

    cbreak();
    noecho();

    window.clear();
    window.refresh();

    window.keypad(true);

    init_pair(1, 15, COLOR_BLACK);
    init_pair(2, COLOR_BLACK, COLOR_YELLOW);

    set_title("NewTest: tests various pancurses features");

    mousemask(ALL_MOUSE_EVENTS, std::ptr::null_mut());

    window.attrset(COLOR_PAIR(1));

    let mut quit = false;
    let mut redraw = true;

    const COL1: i32 = 2;
    const COL2: i32 = COL1 + 30;
    const COL3: i32 = 72;
    const N_CURSORS: i32 = 9;

    let mut unicode_offset = 0x80;
    let mut blink_state = true;

    let mut cursor_state_1 = 2;
    let mut cursor_state_2 = 3;

    while !quit {
        let (y_max, x_max) = window.get_max_yx();
        let color_block_start = 54;
        let mut color_block_cols = (x_max - color_block_start) / 2;
        let color_block_lines = 19;

        let cursor_state_text = ["Invisible (click to change) ",
                                 "Underscore (click to change)",
                                 "Block (click to change)     ",
                                 "Outline (click to change)   ",
                                 "Caret (click to change)     ",
                                 "Half-block (click to change)",
                                 "Central (click to change)   ",
                                 "Cross (click to change)     ",
                                 "Heavy box (click to change) "];

        if color_block_cols < 0 {
            color_block_cols = 0;
        }

        if redraw {
            window.mvaddstr(1, COL1, "'Normal' white-on-black");

            window.attron(A_DIM);
            window.mvaddstr(2, COL1, "Dimmed text");
            window.attroff(A_DIM);

            window.attron(A_BLINK);
            window.mvaddstr(6, 40, "Blinking");
            window.attron(A_BOLD);
            window.mvaddstr(8, 40, "BlinkBold");
            window.attron(A_ITALIC);
            window.mvaddstr(0, COL2, "BlinkBoldItalic");
            window.attrset(COLOR_PAIR(3));
            window.attron(A_UNDERLINE);

            window.mvaddstr(1, COL2, "Underlined");

            window.attrset(COLOR_PAIR(1));
            window.attron(A_UNDERLINE | A_ITALIC);
            window.mvaddstr(2, COL2, "UnderlinedItalic");
            window.attrset(COLOR_PAIR(2));
            window.attron(A_BLINK);
            window.mvaddstr(4, COL1, "Black-on-yellow blinking");

            window.attrset(COLOR_PAIR(1));
            window.mv(4, COL2);
            text_in_a_box("Text in a box", &window);

            window.attrset(COLOR_PAIR(6));
            window.attron(A_STRIKEOUT);
            window.mvaddstr(10, 40, "Strikeout");
            window.attrset(COLOR_PAIR(1));

            window.mv(11, 40);
            text_in_a_box("Next Ucode pg", &window);
            if unicode_offset != 0 {
                window.mv(12, 40);
                text_in_a_box("Prev Ucode pg", &window);
            }
            window.mvprintw(13, 40, &format!("U+{:04X} ", unicode_offset));

            for i in 0..128 {
                // Show extended characters
                window.mvaddstr(5 + i % 16,
                                (i / 16) * 5,
                                &format!("{:02X} ", i + unicode_offset));
                if i + unicode_offset > ' ' as i32 {
                    window.addch((i + unicode_offset) as chtype);
                } else {
                    window.addch(' ');
                }
                window.addch(' ');
            }

            // Skipped the full RGB example, I don't think there's a suitable feature in ncurses

            redraw = false;
            window.attrset(COLOR_PAIR(1));

            for i in 0..6 {
                let line = 24 + i / 3;
                let col = 5 + 25 * (i % 3);

                let spanish = "Español";
                let russian = "Русский язык";
                let greek = "Ελληνικά";
                let georgian = "ქართული ენა";
                let fullwidth = " Ｆｕｌｌｗｉｄｔｈ";
                let combining_marks = "Cmin 	r";

                let texts = [spanish, russian, greek, georgian, fullwidth, combining_marks];

                if line < y_max && col < x_max {
                    window.mvaddnstr(line, 5 + 25 * (i % 3), texts[i as usize], x_max - col);
                }
            }

            window.mvaddstr(1, COL3, "Click on cursor descriptions to");
            window.mvaddstr(2, COL3, "cycle through possible cursors");
            window.mvaddstr(3, COL3, "Click on colors at left to change");
            window.mvaddstr(4, COL3, "colors used for under/over/outlining");
            window.mvaddstr(5, COL3, "Click 'Blink' at bottom to toggle");
            window.mvaddstr(6, COL3, "'real' blinking vs. 'highlit' blink");
        }

        window.mvaddnstr(19,
                         color_block_start,
                         cursor_state_text[cursor_state_1],
                         x_max - color_block_start);
        window.mvaddnstr(20,
                         color_block_start,
                         cursor_state_text[cursor_state_2],
                         x_max - color_block_start);

        for i in 0..color_block_cols * color_block_lines {
            let n_color_blocks = 256;

            window.attrset(COLOR_PAIR(if i >= n_color_blocks {
                2
            } else {
                i as chtype
            }));
            if i > 2 && i < n_color_blocks {
                init_pair(i as i16, i as i16, COLOR_BLACK);
            }
            if i % color_block_cols == 0 {
                window.mv(i / color_block_cols, color_block_start);
            }
            window.attron(A_REVERSE);
            window.addstr(" ");
        }

        window.mv(19, color_block_start - 3);
        window.refresh();
        let c = window.getch();
        window.attrset(COLOR_PAIR(1));

        match c {
            Some(Input::KeyF1) => quit = true,
            Some(Input::Character(x)) if x == 27 as char => quit = true,
            Some(Input::KeyF2) => {
                blink_state = !blink_state;
                set_blink(blink_state);
            }
            Some(x) if x != Input::KeyMouse => {
                window.mvaddstr(0, COL1, &format!("Key {:?} hit          ", x));
            }
            Some(Input::KeyMouse) => {
                match getmouse() {
                    Ok(mouse_event) => {
                        window.mvaddstr(0,
                                        COL1,
                                        &format!("Mouse at {} x {}: {}",
                                                 mouse_event.x,
                                                 mouse_event.y,
                                                 mouse_event.bstate));
                        if mouse_event.x >= color_block_start {
                            if mouse_event.y == 19 { // blink/non-blink toggle
                                cursor_state_1 = (cursor_state_1 + 1) % N_CURSORS as usize;
                            } else if mouse_event.y == 20 { // cycle cursor state
                                cursor_state_2 = (cursor_state_2 + 1) % N_CURSORS as usize;
                            }
                        } else if mouse_event.x >= 40 && mouse_event.x < 40 + 10 {
                            if mouse_event.y == 11 {
                                redraw = true;
                                unicode_offset += 0x80;
                            } else if (mouse_event.y == 12 && unicode_offset != 0) {
                                redraw = true;
                                unicode_offset -= 0x80;
                            }
                        }
                    }
                    Err(_) => (),
                }
            }
            _ => (),
        }
    }

    endwin();
}

fn text_in_a_box(text: &str, window: &Window) {
    let len = text.len();

    window.attron(A_OVERLINE | A_UNDERLINE | A_LEFTLINE);
    if len == 1 {
        window.attron(A_RIGHTLINE);
    }

    window.addnstr(text, 1);
    if len > 1 {
        window.attroff(A_LEFTLINE);
        if len > 2 {
            window.addnstr(&text[1..], len - 2);
        }
        window.attron(A_RIGHTLINE);
        window.addnstr(&text[len - 1..], 1);
    }

    window.attroff(A_OVERLINE | A_UNDERLINE | A_LEFTLINE | A_RIGHTLINE);
}
<|endoftext|>


<commit_before>use std::fmt;
use std::marker::PhantomFn;
use libc::{c_char, c_void};

use block::Block;
use runtime::{Class, Object, Sel};

enum Code {
    Slice(&'static str),
    Owned(String),
}

/// An Objective-C type encoding.
///
/// For more information, see Apple's documentation:
/// https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
pub struct Encoding {
    code: Code,
}

impl Encoding {
    /// Returns self as a `str`.
    pub fn as_str(&self) -> &str {
        match self.code {
            Code::Slice(code) => code,
            Code::Owned(ref code) => code,
        }
    }
}

impl Clone for Encoding {
    fn clone(&self) -> Encoding {
        let code = match self.code {
            Code::Slice(code) => Code::Slice(code),
            Code::Owned(ref code) => Code::Owned(code.clone()),
        };
        Encoding { code: code }
    }
}

impl PartialEq for Encoding {
    fn eq(&self, other: &Encoding) -> bool {
        self.as_str() == other.as_str()
    }
}

impl fmt::Debug for Encoding {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

pub fn from_static_str(code: &'static str) -> Encoding {
    Encoding { code: Code::Slice(code) }
}

/// Types that have an Objective-C type encoding.
///
/// Unsafe because Objective-C will make assumptions about the type (like its
/// size and alignment) from its encoding, so the implementer must verify that
/// the encoding is accurate.
pub unsafe trait Encode : PhantomFn<Self> {
    /// Returns the Objective-C type encoding for Self.
    fn encode() -> Encoding;
}

macro_rules! encode_impls {
    ($($t:ty : $s:expr,)*) => ($(
        unsafe impl Encode for $t {
            fn encode() -> Encoding { from_static_str($s) }
        }
    )*);
}

encode_impls!(
    i8: "c",
    i16: "s",
    i32: "i",
    i64: "q",
    u8: "C",
    u16: "S",
    u32: "I",
    u64: "Q",
    f32: "f",
    f64: "d",
    bool: "B",
    (): "v",
    *mut c_char: "*",
    *const c_char: "r*",
    *mut c_void: "^v",
    *const c_void: "r^v",
    Sel: ":",
);

unsafe impl Encode for isize {
    #[cfg(target_pointer_width = "32")]
    fn encode() -> Encoding { i32::encode() }

    #[cfg(target_pointer_width = "64")]
    fn encode() -> Encoding { i64::encode() }
}

unsafe impl Encode for usize {
    #[cfg(target_pointer_width = "32")]
    fn encode() -> Encoding { u32::encode() }

    #[cfg(target_pointer_width = "64")]
    fn encode() -> Encoding { u64::encode() }
}

macro_rules! encode_message_impl {
    ($code:expr, $name:ident) => (
        encode_message_impl!($code, $name,);
    );
    ($code:expr, $name:ident, $($t:ident),*) => (
        unsafe impl<'a $(, $t)*> $crate::Encode for &'a $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<'a $(, $t)*> $crate::Encode for &'a mut $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<'a $(, $t)*> $crate::Encode for Option<&'a $name<$($t),*>> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<'a $(, $t)*> $crate::Encode for Option<&'a mut $name<$($t),*>> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<$($t),*> $crate::Encode for *const $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<$($t),*> $crate::Encode for *mut $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }
    );
}

encode_message_impl!("@", Object);

encode_message_impl!("#", Class);

encode_message_impl!("@?", Block, A, R);

#[cfg(test)]
mod tests {
    use runtime::{Class, Object, Sel};
    use super::Encode;

    #[test]
    fn test_encode() {
        assert!(u32::encode().as_str() == "I");
        assert!(<()>::encode().as_str() == "v");
        assert!(<&Object>::encode().as_str() == "@");
        assert!(<*mut Object>::encode().as_str() == "@");
        assert!(<&Class>::encode().as_str() == "#");
        assert!(Sel::encode().as_str() == ":");
    }
}
<commit_msg>Added an Inline variant of Encoding's Code.<commit_after>use std::fmt;
use std::marker::PhantomFn;
use std::str;
use libc::{c_char, c_void};

use block::Block;
use runtime::{Class, Object, Sel};

#[cfg(target_pointer_width = "64")]
const CODE_INLINE_CAP: usize = 30;

#[cfg(target_pointer_width = "32")]
const CODE_INLINE_CAP: usize = 14;

enum Code {
    Slice(&'static str),
    Owned(String),
    Inline(u8, [u8; CODE_INLINE_CAP]),
}

/// An Objective-C type encoding.
///
/// For more information, see Apple's documentation:
/// https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
pub struct Encoding {
    code: Code,
}

impl Encoding {
    /// Returns self as a `str`.
    pub fn as_str(&self) -> &str {
        match self.code {
            Code::Slice(code) => code,
            Code::Owned(ref code) => code,
            Code::Inline(len, ref bytes) => unsafe {
                str::from_utf8_unchecked(&bytes[..len as usize])
            }
        }
    }
}

impl Clone for Encoding {
    fn clone(&self) -> Encoding {
        let code = match self.code {
            Code::Slice(code) => Code::Slice(code),
            Code::Owned(ref code) => Code::Owned(code.clone()),
            Code::Inline(len, bytes) => Code::Inline(len, bytes),
        };
        Encoding { code: code }
    }
}

impl PartialEq for Encoding {
    fn eq(&self, other: &Encoding) -> bool {
        self.as_str() == other.as_str()
    }
}

impl fmt::Debug for Encoding {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

pub fn from_static_str(code: &'static str) -> Encoding {
    Encoding { code: Code::Slice(code) }
}

/// Types that have an Objective-C type encoding.
///
/// Unsafe because Objective-C will make assumptions about the type (like its
/// size and alignment) from its encoding, so the implementer must verify that
/// the encoding is accurate.
pub unsafe trait Encode : PhantomFn<Self> {
    /// Returns the Objective-C type encoding for Self.
    fn encode() -> Encoding;
}

macro_rules! encode_impls {
    ($($t:ty : $s:expr,)*) => ($(
        unsafe impl Encode for $t {
            fn encode() -> Encoding { from_static_str($s) }
        }
    )*);
}

encode_impls!(
    i8: "c",
    i16: "s",
    i32: "i",
    i64: "q",
    u8: "C",
    u16: "S",
    u32: "I",
    u64: "Q",
    f32: "f",
    f64: "d",
    bool: "B",
    (): "v",
    *mut c_char: "*",
    *const c_char: "r*",
    *mut c_void: "^v",
    *const c_void: "r^v",
    Sel: ":",
);

unsafe impl Encode for isize {
    #[cfg(target_pointer_width = "32")]
    fn encode() -> Encoding { i32::encode() }

    #[cfg(target_pointer_width = "64")]
    fn encode() -> Encoding { i64::encode() }
}

unsafe impl Encode for usize {
    #[cfg(target_pointer_width = "32")]
    fn encode() -> Encoding { u32::encode() }

    #[cfg(target_pointer_width = "64")]
    fn encode() -> Encoding { u64::encode() }
}

macro_rules! encode_message_impl {
    ($code:expr, $name:ident) => (
        encode_message_impl!($code, $name,);
    );
    ($code:expr, $name:ident, $($t:ident),*) => (
        unsafe impl<'a $(, $t)*> $crate::Encode for &'a $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<'a $(, $t)*> $crate::Encode for &'a mut $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<'a $(, $t)*> $crate::Encode for Option<&'a $name<$($t),*>> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<'a $(, $t)*> $crate::Encode for Option<&'a mut $name<$($t),*>> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<$($t),*> $crate::Encode for *const $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<$($t),*> $crate::Encode for *mut $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }
    );
}

encode_message_impl!("@", Object);

encode_message_impl!("#", Class);

encode_message_impl!("@?", Block, A, R);

#[cfg(test)]
mod tests {
    use runtime::{Class, Object, Sel};
    use super::Encode;

    #[test]
    fn test_encode() {
        assert!(u32::encode().as_str() == "I");
        assert!(<()>::encode().as_str() == "v");
        assert!(<&Object>::encode().as_str() == "@");
        assert!(<*mut Object>::encode().as_str() == "@");
        assert!(<&Class>::encode().as_str() == "#");
        assert!(Sel::encode().as_str() == ":");
    }
}
<|endoftext|>


<commit_before>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#![no_main]

use sys_util::{GuestAddress, GuestMemory};

use std::io::Cursor;
use std::panic;
use std::process;
use std::slice;

#[export_name = "LLVMFuzzerTestOneInput"]
pub fn test_one_input(data: *const u8, size: usize) -> i32 {
    // We cannot unwind past ffi boundaries.
    panic::catch_unwind(|| {
        // Safe because the libfuzzer runtime will guarantee that `data` is at least
        // `size` bytes long and that it will be valid for the lifetime of this
        // function.
        let bytes = unsafe { slice::from_raw_parts(data, size) };
        let mut kimage = Cursor::new(bytes);
        let mem = GuestMemory::new(&[(GuestAddress(0), bytes.len() as u64 + 0x1000)]).unwrap();
        let _ = kernel_loader::load_kernel(&mem, GuestAddress(0), &mut kimage);
    })
    .err()
    .map(|_| process::abort());

    0
}
<commit_msg>fuzz: adapt zimage fuzzer to new kernel loader API<commit_after>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#![no_main]

use sys_util::{GuestAddress, GuestMemory, SharedMemory};

use std::fs::File;
use std::io::Write;
use std::panic;
use std::process;
use std::slice;

fn make_elf_bin(elf_bytes: &[u8]) -> File {
    let mut shm = SharedMemory::new(None).expect("failed to create shared memory");
    shm.set_size(elf_bytes.len() as u64)
        .expect("failed to set shared memory size");
    shm.write_all(elf_bytes)
        .expect("failed to write elf to shared memoy");
    shm.into()
}

#[export_name = "LLVMFuzzerTestOneInput"]
pub fn test_one_input(data: *const u8, size: usize) -> i32 {
    // We cannot unwind past ffi boundaries.
    panic::catch_unwind(|| {
        // Safe because the libfuzzer runtime will guarantee that `data` is at least
        // `size` bytes long and that it will be valid for the lifetime of this
        // function.
        let bytes = unsafe { slice::from_raw_parts(data, size) };
        let mut kimage = make_elf_bin(bytes);
        let mem = GuestMemory::new(&[(GuestAddress(0), bytes.len() as u64 + 0x1000)]).unwrap();
        let _ = kernel_loader::load_kernel(&mem, GuestAddress(0), &mut kimage);
    })
    .err()
    .map(|_| process::abort());

    0
}
<|endoftext|>


<commit_before>extern crate time;

use std::ascii::AsciiExt;

use time::get_time;

#[must_use]
fn match_char(e1: &u8, e2: &u8, ignore_case: bool) -> bool {
    if ignore_case {
        // FIXME: redis uses tolower() which is locale aware
        return e1.to_ascii_lowercase() == e2.to_ascii_lowercase();
    } else {
        return e1 == e2;
    }
}

pub fn glob_match(pattern: &Vec<u8>, element: &Vec<u8>, ignore_case: bool) -> bool {
    let mut patternpos = 0;
    let mut elementpos = 0;
    let star = 42u8; /* '*' */
    let question_mark = 63u8; /* '?' */
    let backslash = 92u8; /* '\\' */
    let open_bracket = 91u8; /* '[' */
    let close_bracket = 93u8; /* '[' */
    while patternpos < pattern.len() {
        match pattern[patternpos] {
            x if x == star => {
                while patternpos + 1 < pattern.len() && pattern[patternpos + 1] == star {
                    patternpos += 1;
                }
                if patternpos == pattern.len() {
                    return true;
                }
                for i in elementpos..(element.len() + 1) {
                    if glob_match(&pattern[patternpos + 1..].to_vec(), &element[i..].to_vec(), ignore_case) {
                        return true;
                    }
                }
                return false;
            },
            x if x == question_mark => {
                if elementpos >= element.len() {
                    return false;
                }
                elementpos += 1;
            },
            x if x == backslash => {
                patternpos += 1;
                if elementpos >= element.len(){
                    return false;
                }
                if !match_char(&pattern[patternpos], &element[elementpos], ignore_case) {
                    return false;
                }
                elementpos += 1;
            },
            x if x == open_bracket => {
                patternpos += 1;
                let not = pattern[patternpos] == ('^' as u8);
                if not {
                    patternpos += 1;
                }
                let mut matched = false;
                loop {
                    if pattern[patternpos] == backslash {
                        patternpos += 1;
                        if pattern[patternpos] == element[elementpos] {
                            matched = true;
                        }
                    } else if pattern[patternpos] == close_bracket {
                        break;
                    } else if patternpos >= pattern.len() {
                        patternpos += 1;
                        break;
                    } else if pattern.len() >= patternpos + 3 && pattern[patternpos + 1] == ('-' as u8) {
                        let mut start = pattern[patternpos];
                        let mut end = pattern[patternpos + 2];
                        let mut c = element[elementpos];
                        if start > end {
                            let t = start;
                            start = end;
                            end = t;
                        }
                        if ignore_case {
                            start = start.to_ascii_lowercase();
                            end = end.to_ascii_lowercase();
                            c = c.to_ascii_lowercase();
                        }
                        patternpos += 2;
                        if c >= start && c <= end {
                            matched = true;
                        }
                    } else {
                        if match_char(&pattern[patternpos], &element[elementpos], ignore_case) {
                            matched = true;
                        }
                    }
                    patternpos += 1;
                }
                if not {
                    matched = !matched;
                }
                if !matched {
                    return false;
                }
                elementpos += 1;
            },
            _ => {
                if elementpos >= element.len(){
                    return false;
                }
                if !match_char(&pattern[patternpos], &element[elementpos], ignore_case) {
                    return false;
                }
                elementpos += 1;
            },
        }
        patternpos += 1;
        if elementpos == element.len() {
            for p in patternpos..pattern.len() {
                if pattern[p] != star {
                    break;
                }
            }
            break;
        }
    }

    if patternpos == pattern.len() && elementpos == element.len() {
        return true;
    }
    return false;
}

pub fn ustime() -> i64 {
    let tv = get_time();
    tv.sec * 1000000 + (tv.nsec / 1000) as i64
}

pub fn mstime() -> i64 {
    ustime() / 1000
}

pub fn splitargs(args: &[u8]) -> Result<Vec<Vec<u8>>, ()> {
    let mut i = 0;
    let mut result = Vec::new();
    for _ in args {
        while i < args.len() && (args[i] == 0 || (args[i] as char).is_whitespace()) { i += 1; }
        if i >=  args.len() { break; }
        let mut inq = false;
        let mut insq = false;
        let mut done = false;
        let mut current = Vec::new();
        while !done && i < args.len() {
            let p = args[i] as char;
            if inq {
                if p == '\\' && (args[i + 1] as char) == 'x' {
                    if let Some(c1) = (args[i + 2] as char).to_digit(16) {
                        if let Some(c2) = (args[i + 3] as char).to_digit(16) {
                            current.push((c1 * 16 + c2) as u8);
                            i += 3;
                        }
                    }
                } else if p == '"'{
                    // closing quote must be followed by a space or nothing at all
                    i += 1;
                    if i != args.len() && !(args[i] as char).is_whitespace() { return Err(()); }
                    inq = false;
                    done = true;
                } else if p == '\\' && i + 1 < args.len() {
                    i += 1;
                    let c = match args[i] as char {
                        'n' => '\n',
                        'r' => '\r',
                        't' => '\t',
                        // FIXME: Rust does not recognize '\a' and '\b'?
                        'b' => 'b',
                        'a' => 'a',
                        c => c as char,
                    } as u8;
                    current.push(c);
                } else {
                    current.push(args[i]);
                }
            } else if insq {
                if p == '\'' {
                    // closing quote must be followed by a space or nothing at all
                    i += 1;
                    if i != args.len() && !(args[i] as char).is_whitespace() { return Err(()); }
                    insq = false;
                    done = true;
                } else if p == '\\' && i + 1 < args.len() && (args[i + 1] as char == '\'') {
                    current.push(args[i + 1]);
                    i += 1;
                } else {
                    current.push(args[i]);
                }
            } else {
                match p as char {
                    ' ' => done = true,
                    '\t' => done = true,
                    '\n' => done = true,
                    '\r' => done = true,
                    '\0' => done = true,
                    '"' => inq = true,
                    '\'' => insq = true,
                    _ => current.push(args[i]),
                }
            }
            i += 1;
        }
        result.push(current);
        if i >=  args.len() {
            if inq || insq {
                return Err(());
            }
            break;
        }
    }
    Ok(result)
}

#[cfg(test)]
mod test_util {
    use std::thread::sleep_ms;

    use super::{mstime, splitargs, glob_match};

    #[test]
    fn mstime_sleep() {
        let start = mstime();
        sleep_ms(100);
        let end = mstime();
        assert!(start < end && start + 100 <= end && start + 500 > end);
    }

    #[test]
    fn glob_match_empty() {
        assert!(glob_match(&b"".to_vec(), &b"".to_vec(), true));
    }

    #[test]
    fn glob_match_star() {
        assert!(glob_match(&b"*".to_vec(), &b"".to_vec(), true));
        assert!(glob_match(&b"*".to_vec(), &b"hello world".to_vec(), true));
        assert!(glob_match(&b"**".to_vec(), &b"hello world".to_vec(), true));
        assert!(glob_match(&b"hello*".to_vec(), &b"hello world".to_vec(), true));
        assert!(glob_match(&b"*world".to_vec(), &b"hello world".to_vec(), true));
        assert!(!glob_match(&b"foo*".to_vec(), &b"hello world".to_vec(), true));
        assert!(!glob_match(&b"*bar".to_vec(), &b"hello world".to_vec(), true));
        assert!(!glob_match(&b"*bar".to_vec(), &b"".to_vec(), true));
    }

    #[test]
    fn glob_match_question_mark() {
        assert!(!glob_match(&b"?".to_vec(), &b"".to_vec(), true));
        assert!(glob_match(&b"?".to_vec(), &b"a".to_vec(), true));
        assert!(!glob_match(&b"?".to_vec(), &b"aa".to_vec(), true));
        assert!(glob_match(&b"a?".to_vec(), &b"aa".to_vec(), true));
    }

    #[test]
    fn glob_match_backslash() {
        assert!(glob_match(&b"\\*asd".to_vec(), &b"*asd".to_vec(), true));
        assert!(!glob_match(&b"\\*d".to_vec(), &b"*asd".to_vec(), true));
        assert!(glob_match(&b"\\?a".to_vec(), &b"?a".to_vec(), true));
        assert!(!glob_match(&b"\\?a".to_vec(), &b"ba".to_vec(), true));
    }

    #[test]
    fn glob_match_brackets() {
        assert!(glob_match(&b"[abc]".to_vec(), &b"a".to_vec(), true));
        assert!(!glob_match(&b"[^abc]".to_vec(), &b"a".to_vec(), true));
        assert!(glob_match(&b"[abc]b".to_vec(), &b"ab".to_vec(), true));
        assert!(!glob_match(&b"[abc]".to_vec(), &b"ab".to_vec(), true));
        assert!(glob_match(&b"[\\]*]".to_vec(), &b"]".to_vec(), true));
        assert!(!glob_match(&b"[\\]*]".to_vec(), &b"a".to_vec(), true));
    }

    #[test]
    fn splitargs_quotes() {
        assert_eq!(splitargs(&b"\"\\x9f\"".to_vec()).unwrap(), vec![vec![159u8]]);
        assert_eq!(splitargs(&b"\"\"".to_vec()).unwrap(), vec![vec![]]);
        assert_eq!(splitargs(&b"\"\\thello\\n\"".to_vec()).unwrap(), vec![b"\thello\n".to_vec()]);
        assert!(splitargs(&b"\"a".to_vec()).is_err());
    }

    #[test]
    fn splitargs_singlequotes() {
        assert_eq!(splitargs(&b"\'\\x9f\'".to_vec()).unwrap(), vec![b"\\x9f".to_vec()]);
        assert_eq!(splitargs(&b"\'\'".to_vec()).unwrap(), vec![vec![]]);
        assert_eq!(splitargs(&b"\'\\\'\'".to_vec()).unwrap(), vec![b"'".to_vec()]);
        assert_eq!(splitargs(&b"\'\\thello\\n\'".to_vec()).unwrap(), vec![b"\\thello\\n".to_vec()]);
        assert!(splitargs(&b"\'a".to_vec()).is_err());
    }

    #[test]
    fn splitargs_misc() {
        assert_eq!(splitargs(&b"hello world".to_vec()).unwrap(), vec![b"hello".to_vec(), b"world".to_vec()]);
        assert_eq!(splitargs(&b"\'hello\' world".to_vec()).unwrap(), vec![b"hello".to_vec(), b"world".to_vec()]);
        assert_eq!(splitargs(&b"\"hello\" world".to_vec()).unwrap(), vec![b"hello".to_vec(), b"world".to_vec()]);
        assert!(splitargs(&b"\"hello\"world".to_vec()).is_err());
        assert!(splitargs(&b"\'hello\'world".to_vec()).is_err());
    }
}
<commit_msg>Add htonl<commit_after>extern crate time;

use std::ascii::AsciiExt;

use time::get_time;

#[must_use]
fn match_char(e1: &u8, e2: &u8, ignore_case: bool) -> bool {
    if ignore_case {
        // FIXME: redis uses tolower() which is locale aware
        return e1.to_ascii_lowercase() == e2.to_ascii_lowercase();
    } else {
        return e1 == e2;
    }
}

pub fn glob_match(pattern: &Vec<u8>, element: &Vec<u8>, ignore_case: bool) -> bool {
    let mut patternpos = 0;
    let mut elementpos = 0;
    let star = 42u8; /* '*' */
    let question_mark = 63u8; /* '?' */
    let backslash = 92u8; /* '\\' */
    let open_bracket = 91u8; /* '[' */
    let close_bracket = 93u8; /* '[' */
    while patternpos < pattern.len() {
        match pattern[patternpos] {
            x if x == star => {
                while patternpos + 1 < pattern.len() && pattern[patternpos + 1] == star {
                    patternpos += 1;
                }
                if patternpos == pattern.len() {
                    return true;
                }
                for i in elementpos..(element.len() + 1) {
                    if glob_match(&pattern[patternpos + 1..].to_vec(), &element[i..].to_vec(), ignore_case) {
                        return true;
                    }
                }
                return false;
            },
            x if x == question_mark => {
                if elementpos >= element.len() {
                    return false;
                }
                elementpos += 1;
            },
            x if x == backslash => {
                patternpos += 1;
                if elementpos >= element.len(){
                    return false;
                }
                if !match_char(&pattern[patternpos], &element[elementpos], ignore_case) {
                    return false;
                }
                elementpos += 1;
            },
            x if x == open_bracket => {
                patternpos += 1;
                let not = pattern[patternpos] == ('^' as u8);
                if not {
                    patternpos += 1;
                }
                let mut matched = false;
                loop {
                    if pattern[patternpos] == backslash {
                        patternpos += 1;
                        if pattern[patternpos] == element[elementpos] {
                            matched = true;
                        }
                    } else if pattern[patternpos] == close_bracket {
                        break;
                    } else if patternpos >= pattern.len() {
                        patternpos += 1;
                        break;
                    } else if pattern.len() >= patternpos + 3 && pattern[patternpos + 1] == ('-' as u8) {
                        let mut start = pattern[patternpos];
                        let mut end = pattern[patternpos + 2];
                        let mut c = element[elementpos];
                        if start > end {
                            let t = start;
                            start = end;
                            end = t;
                        }
                        if ignore_case {
                            start = start.to_ascii_lowercase();
                            end = end.to_ascii_lowercase();
                            c = c.to_ascii_lowercase();
                        }
                        patternpos += 2;
                        if c >= start && c <= end {
                            matched = true;
                        }
                    } else {
                        if match_char(&pattern[patternpos], &element[elementpos], ignore_case) {
                            matched = true;
                        }
                    }
                    patternpos += 1;
                }
                if not {
                    matched = !matched;
                }
                if !matched {
                    return false;
                }
                elementpos += 1;
            },
            _ => {
                if elementpos >= element.len(){
                    return false;
                }
                if !match_char(&pattern[patternpos], &element[elementpos], ignore_case) {
                    return false;
                }
                elementpos += 1;
            },
        }
        patternpos += 1;
        if elementpos == element.len() {
            for p in patternpos..pattern.len() {
                if pattern[p] != star {
                    break;
                }
            }
            break;
        }
    }

    if patternpos == pattern.len() && elementpos == element.len() {
        return true;
    }
    return false;
}

pub fn ustime() -> i64 {
    let tv = get_time();
    tv.sec * 1000000 + (tv.nsec / 1000) as i64
}

pub fn mstime() -> i64 {
    ustime() / 1000
}

pub fn splitargs(args: &[u8]) -> Result<Vec<Vec<u8>>, ()> {
    let mut i = 0;
    let mut result = Vec::new();
    for _ in args {
        while i < args.len() && (args[i] == 0 || (args[i] as char).is_whitespace()) { i += 1; }
        if i >=  args.len() { break; }
        let mut inq = false;
        let mut insq = false;
        let mut done = false;
        let mut current = Vec::new();
        while !done && i < args.len() {
            let p = args[i] as char;
            if inq {
                if p == '\\' && (args[i + 1] as char) == 'x' {
                    if let Some(c1) = (args[i + 2] as char).to_digit(16) {
                        if let Some(c2) = (args[i + 3] as char).to_digit(16) {
                            current.push((c1 * 16 + c2) as u8);
                            i += 3;
                        }
                    }
                } else if p == '"'{
                    // closing quote must be followed by a space or nothing at all
                    i += 1;
                    if i != args.len() && !(args[i] as char).is_whitespace() { return Err(()); }
                    inq = false;
                    done = true;
                } else if p == '\\' && i + 1 < args.len() {
                    i += 1;
                    let c = match args[i] as char {
                        'n' => '\n',
                        'r' => '\r',
                        't' => '\t',
                        // FIXME: Rust does not recognize '\a' and '\b'?
                        'b' => 'b',
                        'a' => 'a',
                        c => c as char,
                    } as u8;
                    current.push(c);
                } else {
                    current.push(args[i]);
                }
            } else if insq {
                if p == '\'' {
                    // closing quote must be followed by a space or nothing at all
                    i += 1;
                    if i != args.len() && !(args[i] as char).is_whitespace() { return Err(()); }
                    insq = false;
                    done = true;
                } else if p == '\\' && i + 1 < args.len() && (args[i + 1] as char == '\'') {
                    current.push(args[i + 1]);
                    i += 1;
                } else {
                    current.push(args[i]);
                }
            } else {
                match p as char {
                    ' ' => done = true,
                    '\t' => done = true,
                    '\n' => done = true,
                    '\r' => done = true,
                    '\0' => done = true,
                    '"' => inq = true,
                    '\'' => insq = true,
                    _ => current.push(args[i]),
                }
            }
            i += 1;
        }
        result.push(current);
        if i >=  args.len() {
            if inq || insq {
                return Err(());
            }
            break;
        }
    }
    Ok(result)
}

pub fn htonl(v: u32) -> [u8; 4] {
    // maybe it should use C api instead?
    [
        ((v >> 24) & 0xFF) as u8,
        ((v >> 16) & 0xFF) as u8,
        ((v >> 8) & 0xFF) as u8,
        ((v >> 0) & 0xFF) as u8,
    ]
}

#[cfg(test)]
mod test_util {
    use std::{u8, u32};
    use std::thread::sleep_ms;

    use super::{mstime, splitargs, glob_match, htonl};

    #[test]
    fn mstime_sleep() {
        let start = mstime();
        sleep_ms(100);
        let end = mstime();
        assert!(start < end && start + 100 <= end && start + 500 > end);
    }

    #[test]
    fn glob_match_empty() {
        assert!(glob_match(&b"".to_vec(), &b"".to_vec(), true));
    }

    #[test]
    fn glob_match_star() {
        assert!(glob_match(&b"*".to_vec(), &b"".to_vec(), true));
        assert!(glob_match(&b"*".to_vec(), &b"hello world".to_vec(), true));
        assert!(glob_match(&b"**".to_vec(), &b"hello world".to_vec(), true));
        assert!(glob_match(&b"hello*".to_vec(), &b"hello world".to_vec(), true));
        assert!(glob_match(&b"*world".to_vec(), &b"hello world".to_vec(), true));
        assert!(!glob_match(&b"foo*".to_vec(), &b"hello world".to_vec(), true));
        assert!(!glob_match(&b"*bar".to_vec(), &b"hello world".to_vec(), true));
        assert!(!glob_match(&b"*bar".to_vec(), &b"".to_vec(), true));
    }

    #[test]
    fn glob_match_question_mark() {
        assert!(!glob_match(&b"?".to_vec(), &b"".to_vec(), true));
        assert!(glob_match(&b"?".to_vec(), &b"a".to_vec(), true));
        assert!(!glob_match(&b"?".to_vec(), &b"aa".to_vec(), true));
        assert!(glob_match(&b"a?".to_vec(), &b"aa".to_vec(), true));
    }

    #[test]
    fn glob_match_backslash() {
        assert!(glob_match(&b"\\*asd".to_vec(), &b"*asd".to_vec(), true));
        assert!(!glob_match(&b"\\*d".to_vec(), &b"*asd".to_vec(), true));
        assert!(glob_match(&b"\\?a".to_vec(), &b"?a".to_vec(), true));
        assert!(!glob_match(&b"\\?a".to_vec(), &b"ba".to_vec(), true));
    }

    #[test]
    fn glob_match_brackets() {
        assert!(glob_match(&b"[abc]".to_vec(), &b"a".to_vec(), true));
        assert!(!glob_match(&b"[^abc]".to_vec(), &b"a".to_vec(), true));
        assert!(glob_match(&b"[abc]b".to_vec(), &b"ab".to_vec(), true));
        assert!(!glob_match(&b"[abc]".to_vec(), &b"ab".to_vec(), true));
        assert!(glob_match(&b"[\\]*]".to_vec(), &b"]".to_vec(), true));
        assert!(!glob_match(&b"[\\]*]".to_vec(), &b"a".to_vec(), true));
    }

    #[test]
    fn splitargs_quotes() {
        assert_eq!(splitargs(&b"\"\\x9f\"".to_vec()).unwrap(), vec![vec![159u8]]);
        assert_eq!(splitargs(&b"\"\"".to_vec()).unwrap(), vec![vec![]]);
        assert_eq!(splitargs(&b"\"\\thello\\n\"".to_vec()).unwrap(), vec![b"\thello\n".to_vec()]);
        assert!(splitargs(&b"\"a".to_vec()).is_err());
    }

    #[test]
    fn splitargs_singlequotes() {
        assert_eq!(splitargs(&b"\'\\x9f\'".to_vec()).unwrap(), vec![b"\\x9f".to_vec()]);
        assert_eq!(splitargs(&b"\'\'".to_vec()).unwrap(), vec![vec![]]);
        assert_eq!(splitargs(&b"\'\\\'\'".to_vec()).unwrap(), vec![b"'".to_vec()]);
        assert_eq!(splitargs(&b"\'\\thello\\n\'".to_vec()).unwrap(), vec![b"\\thello\\n".to_vec()]);
        assert!(splitargs(&b"\'a".to_vec()).is_err());
    }

    #[test]
    fn splitargs_misc() {
        assert_eq!(splitargs(&b"hello world".to_vec()).unwrap(), vec![b"hello".to_vec(), b"world".to_vec()]);
        assert_eq!(splitargs(&b"\'hello\' world".to_vec()).unwrap(), vec![b"hello".to_vec(), b"world".to_vec()]);
        assert_eq!(splitargs(&b"\"hello\" world".to_vec()).unwrap(), vec![b"hello".to_vec(), b"world".to_vec()]);
        assert!(splitargs(&b"\"hello\"world".to_vec()).is_err());
        assert!(splitargs(&b"\'hello\'world".to_vec()).is_err());
    }

    #[test]
    fn htonl_basic() {
        assert_eq!(htonl(1), [0, 0, 0, 1]);
        assert_eq!(htonl(256), [0, 0, 1, 0]);
        assert_eq!(htonl(u32::MAX), [u8::MAX, u8::MAX, u8::MAX, u8::MAX]);
    }
}
<|endoftext|>


<commit_before>use std::io::Reader;
use std::io::Writer;
use std::str::{from_utf8, from_utf8_owned};
use std::io::net::ip::SocketAddr;
use std::collections::Map;
use std::collections::HashMap;
use std::io::net::tcp::TcpStream;

use std::io::net::ip::{IpAddr};
use std::io::net::tcp::{TcpAcceptor, TcpListener};

use time;
use enums::*;

pub struct Server {
	addr: IpAddr,
	port: u16,
	src_bytes: u64,
	id: u64,
	str_addr: String,
	str_port: String,
	acceptor: TcpAcceptor
}

impl Server {
	fn new (address : &String, port: &String) -> Result <Server, ParseFailure>{
		let iPort = parse_int (port);
	}
}
<commit_msg>updating project<commit_after>use std::io::Reader;
use std::io::Writer;
use std::str::{from_utf8, from_utf8_owned};
use std::io::net::ip::SocketAddr;
use std::collections::Map;
use std::collections::HashMap;
use std::io::net::tcp::TcpStream;

use std::io::net::ip::{IpAddr, FromStr};
use std::io::net::tcp::{TcpAcceptor, TcpListener};

use time;
use enums::*;

pub struct Server {
	addr: IpAddr,
	port: u16,
	src_bytes: u64,
	id: u64,
	str_addr: String,
	str_port: String,
	acceptor: TcpAcceptor
}

impl Server {
	fn new (address : &String, port: &String) /*-> Result <Server, ParseFailure>*/{
		let iPort = parse_int (port);
		if iPort <= 0{
			fail!("Invalid port value: {}", port);
		}
		let ipAddr : Option <IpAddr> = FromStr::from_str (address.from_utf8());
	}
}
<|endoftext|>


<commit_before>//! Wraps `redis_async` in a actix actor wrapper.
//!
//! Mostly just takes advantage of the actix actor system, but also adds support for transactions!
use std::net;
use std::time::Duration;

use actix::prelude::*;
use actix::AsyncContext;
use backoff::{backoff::Backoff, ExponentialBackoff};
use futures::{future, sync::oneshot, Future};
use redis_async::{
    client::{paired_connect, PairedConnection}, resp::{FromResp, RespValue},
};
use std::marker::PhantomData;
use tokio::executor;
use void::Void;
use {failure, tokio, tokio_timer};

pub fn message<R: FromResp>(msg: RespValue) -> RedisMessage<R> {
    RedisMessage(msg, PhantomData)
}

pub fn transaction<I>(messages: I) -> RedisTransaction
where
    I: IntoIterator<Item = RespValue>,
{
    RedisTransaction(messages.into_iter().collect())
}

#[derive(Debug, Clone)]
pub struct RedisMessage<R>(pub RespValue, PhantomData<R>)
where
    R: FromResp;

impl<R> Message for RedisMessage<R>
where
    R: FromResp + Send + 'static,
{
    type Result = Result<R, failure::Error>;
}

pub struct RedisTransaction(Vec<RespValue>);

impl Message for RedisTransaction {
    type Result = Result<Vec<RespValue>, failure::Error>;
}

struct TransactionWithSendBuilt {
    msgs: Vec<RespValue>,
    send: oneshot::Sender<Result<Vec<RespValue>, failure::Error>>,
}

impl Message for TransactionWithSendBuilt {
    type Result = ();
}

pub struct RedisActor {
    conn: PairedConnection,
    /// We need this since the "successfull reconnection" method uses a message
    /// to initiate the reconnection and we need to delay any other messages
    /// which happen in the meantime until after that message comes through.
    reconnecting: bool,
}

impl Actor for RedisActor {
    type Context = Context<Self>;
}

struct DoReconnect;
impl Message for DoReconnect {
    type Result = ();
}
struct SuccessfullyReconnected(PairedConnection);
impl Message for SuccessfullyReconnected {
    type Result = ();
}
struct UnsuccessfullReconnect;
impl Message for UnsuccessfullReconnect {
    type Result = ();
}

impl RedisActor {
    fn local_host() -> net::SocketAddr {
        net::SocketAddr::new(
            net::IpAddr::V6(net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
            6379,
        )
    }
    pub fn new() -> impl Future<Item = Self, Error = Void> {
        RedisActor::connect().map(|conn| RedisActor {
            conn,
            reconnecting: false,
        })
    }
    fn connect() -> impl Future<Item = PairedConnection, Error = Void> {
        let mut backoff = ExponentialBackoff::default();
        // we're willing to wait up to 30 minutes
        backoff.max_interval = Duration::from_secs(60 * 30);
        backoff.max_elapsed_time = None;
        future::loop_fn(backoff, |mut backoff| {
            let addr = RedisActor::local_host();
            paired_connect(&addr).then(move |res| match res {
                Ok(conn) => future::Either::A(future::ok(future::Loop::Break(conn))),
                Err(e) => {
                    let retry = backoff.next_backoff().unwrap();
                    error!(
                        "unable to connect to redis database at {:?}: {}. Retrying in {:?}.",
                        addr, e, retry
                    );
                    future::Either::B(
                        tokio_timer::sleep(retry)
                            .then(|_| future::ok(future::Loop::Continue(backoff))),
                    )
                }
            })
        })
    }
    fn start_reconnect(&mut self, ctx: &mut Context<Self>) {
        let my_addr = ctx.address();
        let fut = RedisActor::connect().then(move |res: Result<_, Void>| match res {
            Ok(conn) => {
                executor::spawn(my_addr.send(SuccessfullyReconnected(conn)).then(|_| Ok(())));
                future::ok(())
            }
            Err(e) => match e {},
        });
        self.reconnecting = true;
        AsyncContext::wait(ctx, actix::fut::wrap_future(fut));
    }
}

impl Handler<SuccessfullyReconnected> for RedisActor {
    type Result = ();

    fn handle(
        &mut self,
        SuccessfullyReconnected(conn): SuccessfullyReconnected,
        _ctx: &mut Context<Self>,
    ) {
        self.conn = conn;
        self.reconnecting = false;
    }
}

impl Handler<UnsuccessfullReconnect> for RedisActor {
    type Result = ();

    fn handle(&mut self, _: UnsuccessfullReconnect, ctx: &mut Context<Self>) {
        self.reconnecting = false;
        ctx.stop();
    }
}

impl Handler<DoReconnect> for RedisActor {
    type Result = ();

    fn handle(&mut self, _: DoReconnect, ctx: &mut Context<Self>) {
        self.start_reconnect(ctx);
    }
}

impl<R> Handler<RedisMessage<R>> for RedisActor
where
    R: FromResp + Send + 'static,
{
    type Result = ResponseFuture<R, failure::Error>;

    fn handle(
        &mut self,
        RedisMessage(msg, _): RedisMessage<R>,
        ctx: &mut Context<Self>,
    ) -> Self::Result {
        use redis_async::error::Error;

        fn resend_self<R: FromResp + Send + 'static>(
            address: Addr<RedisActor>,
            msg: RespValue,
        ) -> impl Future<Item = R, Error = failure::Error> {
            address.send(message(msg)).then(|res| match res {
                Ok(r) => r,
                Err(e) => Err(e.into()),
            })
        }

        if self.reconnecting {
            Box::new(resend_self(ctx.address(), msg))
        } else {
            let addr = ctx.address();
            // Clone is necessary so we can re-send the message if the connection is closed.
            let fut = self.conn.send(msg.clone()).or_else(|e| match e {
                Error::EndOfStream => future::Either::A(
                    addr.send(DoReconnect)
                        .from_err()
                        .and_then(|()| resend_self(addr, msg)),
                ),
                o => future::Either::B(future::err(o.into())),
            });

            Box::new(fut) as ResponseFuture<_, _>
        }
    }
}

impl Handler<RedisTransaction> for RedisActor {
    type Result = ResponseFuture<Vec<RespValue>, failure::Error>;

    fn handle(
        &mut self,
        RedisTransaction(msgs): RedisTransaction,
        ctx: &mut Context<Self>,
    ) -> Self::Result {
        let (send, recv) = oneshot::channel();
        let fut = ctx.address()
            .send(TransactionWithSendBuilt { msgs, send })
            .then(|res| recv)
            .then(|res| match res {
                Ok(r) => r,
                Err(e) => Err(e.into()),
            });
        Box::new(fut) as ResponseFuture<_, _>
    }
}

impl Handler<TransactionWithSendBuilt> for RedisActor {
    type Result = ();

    fn handle(&mut self, msg: TransactionWithSendBuilt, ctx: &mut Context<Self>) {
        use redis_async::error::Error;

        let TransactionWithSendBuilt { msgs, send } = msg;

        fn resend_self(
            address: Addr<RedisActor>,
            msgs: Vec<RespValue>,
            send: oneshot::Sender<Result<Vec<RespValue>, failure::Error>>,
        ) {
            // send_res will only fail if this actor is stopped, at which point we don't care.
            tokio::executor::spawn(
                address
                    .send(TransactionWithSendBuilt { send, msgs })
                    .then(|_send_res| Ok(())),
            );
        }

        if self.reconnecting {
            resend_self(ctx.address(), msgs, send);
        } else {
            let addr = ctx.address();
            let conn = self.conn.clone();
            // Clone is necessary so we can re-send the message if the connection is closed.
            let msgs_clone = msgs.clone();
            // Polling order of redis_async sends doesn't matter- they are all queued the instant
            // we ask them to. `join_all` iterates through the entire iterator when called as well,
            // so we know all the commands will be in the right order! Then we want to join on all
            // of them at the same time so that redis is free to pipeline if it wants to.
            let fut = self.conn
                .send(resp_array!("MULTI"))
                .join3(
                    future::join_all(msgs_clone.into_iter().map(move |v| {
                        conn.send(v).and_then(|s: String| {
                            if s == "QUEUED" {
                                Ok(())
                            } else {
                                Err(Error::Internal(format!(
                                    "expected sending after MULTI to \
                                     return QUEUED, but got \"{:?}\"",
                                    s
                                )))
                            }
                        })
                    })),
                    self.conn.send(resp_array!("EXEC")),
                )
                .then(|res: Result<((), Vec<()>, Vec<RespValue>), _>| match res {
                    Err(Error::EndOfStream) => {
                        future::Either::A(addr.send(DoReconnect).then(|res| {
                            match res {
                                Ok(v) => {
                                    resend_self(addr, msgs, send);
                                }
                                Err(e) => {
                                    let _ = send.send(Err(e.into()));
                                }
                            };
                            future::ok(())
                        }))
                    }
                    Ok(((), _queue_results, actual_result)) => {
                        // we don't really care if they've dropped the receiver.
                        let _ = send.send(Ok(actual_result));
                        future::Either::B(future::ok(()))
                    }
                    Err(other) => {
                        let _ = send.send(Err(other.into()));
                        future::Either::B(future::ok(()))
                    }
                });

            actix::AsyncContext::wait(ctx, actix::fut::wrap_future(fut));
        }
    }
}
<commit_msg>Fix resending transactions after disconnecting.<commit_after>//! Wraps `redis_async` in a actix actor wrapper.
//!
//! Mostly just takes advantage of the actix actor system, but also adds support for transactions!
use std::net;
use std::time::Duration;

use actix::prelude::*;
use actix::AsyncContext;
use backoff::{backoff::Backoff, ExponentialBackoff};
use futures::{future, sync::oneshot, Future};
use redis_async::{
    client::{paired_connect, PairedConnection}, resp::{FromResp, RespValue},
};
use std::marker::PhantomData;
use tokio::executor;
use void::Void;
use {failure, tokio, tokio_timer};

pub fn message<R: FromResp>(msg: RespValue) -> RedisMessage<R> {
    RedisMessage(msg, PhantomData)
}

pub fn transaction<I>(messages: I) -> RedisTransaction
where
    I: IntoIterator<Item = RespValue>,
{
    RedisTransaction(messages.into_iter().collect())
}

#[derive(Debug, Clone)]
pub struct RedisMessage<R>(pub RespValue, PhantomData<R>)
where
    R: FromResp;

impl<R> Message for RedisMessage<R>
where
    R: FromResp + Send + 'static,
{
    type Result = Result<R, failure::Error>;
}

pub struct RedisTransaction(Vec<RespValue>);

impl Message for RedisTransaction {
    type Result = Result<Vec<RespValue>, failure::Error>;
}

struct TransactionWithSendBuilt {
    msgs: Vec<RespValue>,
    send: oneshot::Sender<Result<Vec<RespValue>, failure::Error>>,
}

impl Message for TransactionWithSendBuilt {
    type Result = ();
}

pub struct RedisActor {
    conn: PairedConnection,
    /// We need this since the "successfull reconnection" method uses a message
    /// to initiate the reconnection and we need to delay any other messages
    /// which happen in the meantime until after that message comes through.
    reconnecting: bool,
}

impl Actor for RedisActor {
    type Context = Context<Self>;
}

struct DoReconnect;
impl Message for DoReconnect {
    type Result = ();
}
struct SuccessfullyReconnected(PairedConnection);
impl Message for SuccessfullyReconnected {
    type Result = ();
}
struct UnsuccessfullReconnect;
impl Message for UnsuccessfullReconnect {
    type Result = ();
}

impl RedisActor {
    fn local_host() -> net::SocketAddr {
        net::SocketAddr::new(
            net::IpAddr::V6(net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
            6379,
        )
    }
    pub fn new() -> impl Future<Item = Self, Error = Void> {
        RedisActor::connect().map(|conn| RedisActor {
            conn,
            reconnecting: false,
        })
    }
    fn connect() -> impl Future<Item = PairedConnection, Error = Void> {
        let mut backoff = ExponentialBackoff::default();
        // we're willing to wait up to 30 minutes
        backoff.max_interval = Duration::from_secs(60 * 30);
        backoff.max_elapsed_time = None;
        future::loop_fn(backoff, |mut backoff| {
            let addr = RedisActor::local_host();
            paired_connect(&addr).then(move |res| match res {
                Ok(conn) => future::Either::A(future::ok(future::Loop::Break(conn))),
                Err(e) => {
                    let retry = backoff.next_backoff().unwrap();
                    error!(
                        "unable to connect to redis database at {:?}: {}. Retrying in {:?}.",
                        addr, e, retry
                    );
                    future::Either::B(
                        tokio_timer::sleep(retry)
                            .then(|_| future::ok(future::Loop::Continue(backoff))),
                    )
                }
            })
        })
    }
    fn start_reconnect(&mut self, ctx: &mut Context<Self>) {
        let my_addr = ctx.address();
        let fut = RedisActor::connect().then(move |res: Result<_, Void>| match res {
            Ok(conn) => {
                executor::spawn(my_addr.send(SuccessfullyReconnected(conn)).then(|_| Ok(())));
                future::ok(())
            }
            Err(e) => match e {},
        });
        self.reconnecting = true;
        AsyncContext::wait(ctx, actix::fut::wrap_future(fut));
    }
}

impl Handler<SuccessfullyReconnected> for RedisActor {
    type Result = ();

    fn handle(
        &mut self,
        SuccessfullyReconnected(conn): SuccessfullyReconnected,
        _ctx: &mut Context<Self>,
    ) {
        self.conn = conn;
        self.reconnecting = false;
    }
}

impl Handler<UnsuccessfullReconnect> for RedisActor {
    type Result = ();

    fn handle(&mut self, _: UnsuccessfullReconnect, ctx: &mut Context<Self>) {
        self.reconnecting = false;
        ctx.stop();
    }
}

impl Handler<DoReconnect> for RedisActor {
    type Result = ();

    fn handle(&mut self, _: DoReconnect, ctx: &mut Context<Self>) {
        self.start_reconnect(ctx);
    }
}

impl<R> Handler<RedisMessage<R>> for RedisActor
where
    R: FromResp + Send + 'static,
{
    type Result = ResponseFuture<R, failure::Error>;

    fn handle(
        &mut self,
        RedisMessage(msg, _): RedisMessage<R>,
        ctx: &mut Context<Self>,
    ) -> Self::Result {
        use redis_async::error::Error;

        fn resend_self<R: FromResp + Send + 'static>(
            address: Addr<RedisActor>,
            msg: RespValue,
        ) -> impl Future<Item = R, Error = failure::Error> {
            address.send(message(msg)).then(|res| match res {
                Ok(r) => r,
                Err(e) => Err(e.into()),
            })
        }

        if self.reconnecting {
            Box::new(resend_self(ctx.address(), msg))
        } else {
            let addr = ctx.address();
            // Clone is necessary so we can re-send the message if the connection is closed.
            let fut = self.conn.send(msg.clone()).or_else(|e| match e {
                Error::EndOfStream => future::Either::A(
                    addr.send(DoReconnect)
                        .from_err()
                        .and_then(|()| resend_self(addr, msg)),
                ),
                o => future::Either::B(future::err(o.into())),
            });

            Box::new(fut) as ResponseFuture<_, _>
        }
    }
}

impl Handler<RedisTransaction> for RedisActor {
    type Result = ResponseFuture<Vec<RespValue>, failure::Error>;

    fn handle(
        &mut self,
        RedisTransaction(msgs): RedisTransaction,
        ctx: &mut Context<Self>,
    ) -> Self::Result {
        let (send, recv) = oneshot::channel();
        let fut = ctx.address()
            .send(TransactionWithSendBuilt { msgs, send })
            .then(|res| recv)
            .then(|res| match res {
                Ok(r) => r,
                Err(e) => Err(e.into()),
            });
        Box::new(fut) as ResponseFuture<_, _>
    }
}

impl Handler<TransactionWithSendBuilt> for RedisActor {
    type Result = ();

    fn handle(&mut self, msg: TransactionWithSendBuilt, ctx: &mut Context<Self>) {
        use redis_async::error::Error;

        let TransactionWithSendBuilt { msgs, send } = msg;

        fn resend_self(
            address: Addr<RedisActor>,
            msgs: Vec<RespValue>,
            send: oneshot::Sender<Result<Vec<RespValue>, failure::Error>>,
        ) -> impl Future<Item = (), Error = ()> {
            // send_res will only fail if this actor is stopped, at which point we don't care.
            address
                .send(TransactionWithSendBuilt { send, msgs })
                .then(|_send_res| Ok(()))
        }

        if self.reconnecting {
            let addr = ctx.address();
            ctx.spawn(actix::fut::wrap_future(resend_self(addr, msgs, send)));
        } else {
            let addr = ctx.address();
            let conn = self.conn.clone();
            // Clone is necessary so we can re-send the message if the connection is closed.
            let msgs_clone = msgs.clone();
            // Polling order of redis_async sends doesn't matter- they are all queued the instant
            // we ask them to. `join_all` iterates through the entire iterator immediately when
            // called so those will all be sent correctly before EXEC.
            let fut = self.conn
                .send(resp_array!("MULTI"))
                .join3(
                    future::join_all(msgs_clone.into_iter().map(move |v| {
                        conn.send(v).and_then(|s: String| {
                            if s == "QUEUED" {
                                Ok(())
                            } else {
                                Err(Error::Internal(format!(
                                    "expected sending after MULTI to \
                                     return QUEUED, but got \"{:?}\"",
                                    s
                                )))
                            }
                        })
                    })),
                    self.conn.send(resp_array!("EXEC")),
                )
                .then(|res: Result<((), _, Vec<RespValue>), _>| {
                    match res {
                        Err(Error::EndOfStream) => {
                            tokio::executor::spawn(addr.send(DoReconnect).then(|res| match res {
                                Ok(v) => future::Either::A(resend_self(addr, msgs, send)),
                                Err(e) => {
                                    let _ = send.send(Err(e.into()));
                                    future::Either::B(future::ok(()))
                                }
                            }));
                        }
                        Ok(((), _queue_results, actual_result)) => {
                            let _ = send.send(Ok(actual_result));
                        }
                        Err(other) => {
                            let _ = send.send(Err(other.into()));
                        }
                    }
                    future::ok(())
                });

            actix::AsyncContext::wait(ctx, actix::fut::wrap_future(fut));
        }
    }
}
<|endoftext|>


<commit_before>/// Available RPC methods types and ids.
use ssz_derive::{Decode, Encode};
use types::{Epoch, Hash256, Slot};

#[derive(Debug)]
pub enum RPCMethod {
    Hello,
    Goodbye,
    Unknown,
}

impl From<u16> for RPCMethod {
    fn from(method_id: u16) -> Self {
        match method_id {
            0 => RPCMethod::Hello,
            1 => RPCMethod::Goodbye,
            _ => RPCMethod::Unknown,
        }
    }
}

impl Into<u16> for RPCMethod {
    fn into(self) -> u16 {
        match self {
            RPCMethod::Hello => 0,
            RPCMethod::Goodbye => 1,
            _ => 0,
        }
    }
}

#[derive(Debug, Clone)]
pub enum RPCRequest {
    Hello(HelloMessage),
    Goodbye(u64),
}

#[derive(Debug, Clone)]
pub enum RPCResponse {
    Hello(HelloMessage),
}

// request/response structs for RPC methods
#[derive(Encode, Decode, Clone, Debug)]
pub struct HelloMessage {
    pub network_id: u8,
    pub latest_finalized_root: Hash256,
    pub latest_finalized_epoch: Epoch,
    pub best_root: Hash256,
    pub best_slot: Slot,
}
<commit_msg>Implement RequestBeaconBlockRoots RPC method<commit_after>/// Available RPC methods types and ids.
use ssz_derive::{Decode, Encode};
use types::{Epoch, Hash256, Slot};

#[derive(Debug)]
pub enum RPCMethod {
    Hello,
    Goodbye,
    RequestBeaconBlockRoots,
    Unknown,
}

impl From<u16> for RPCMethod {
    fn from(method_id: u16) -> Self {
        match method_id {
            0 => RPCMethod::Hello,
            1 => RPCMethod::Goodbye,
            10 => RPCMethod::RequestBeaconBlockRoots,
            _ => RPCMethod::Unknown,
        }
    }
}

impl Into<u16> for RPCMethod {
    fn into(self) -> u16 {
        match self {
            RPCMethod::Hello => 0,
            RPCMethod::Goodbye => 1,
            RPCMethod::RequestBeaconBlockRoots => 10,
            _ => 0,
        }
    }
}

#[derive(Debug, Clone)]
pub enum RPCRequest {
    Hello(HelloMessage),
    Goodbye(u64),
    RequestBeaconBlockRoots(BeaconBlockRootsRequest),
}

#[derive(Debug, Clone)]
pub enum RPCResponse {
    Hello(HelloMessage),
    RequestBeaconBlockRoots(BeaconBlockRootsResponse),
}

/* Request/Response data structures for RPC methods */

/// The HELLO request/response handshake message.
#[derive(Encode, Decode, Clone, Debug)]
pub struct HelloMessage {
    /// The network ID of the peer.
    pub network_id: u8,
    /// The peers last finalized root.
    pub latest_finalized_root: Hash256,
    /// The peers last finalized epoch.
    pub latest_finalized_epoch: Epoch,
    /// The peers last block root.
    pub best_root: Hash256,
    /// The peers last slot.
    pub best_slot: Slot,
}

/// Request a number of beacon block roots from a peer.
#[derive(Encode, Decode, Clone, Debug)]
pub struct BeaconBlockRootsRequest {
    /// The starting slot of the requested blocks.
    start_slot: Slot,
    /// The number of blocks from the start slot.
    count: u64, // this must be less than 32768. //TODO: Enforce this in the lower layers
}

/// Response a number of beacon block roots from a peer.
#[derive(Encode, Decode, Clone, Debug)]
pub struct BeaconBlockRootsResponse {
    /// List of requested blocks and associated slots.
    roots: Vec<BlockRootSlot>,
}

/// Contains a block root and associated slot.
#[derive(Encode, Decode, Clone, Debug)]
pub struct BlockRootSlot {
    /// The block root.
    block_root: Hash256,
    /// The block slot.
    slot: Slot,
}
<|endoftext|>


<commit_before>use super::{Address, Allocator, Layout};
use spin::Mutex;
use ptr::Unique;
use ops::{Deref, DerefMut};

pub trait Lender {
    type Borrowed;
    fn borrow(&self) -> Self::Borrowed;
}

/// A borrowed handle on a heap allocation with a specified lifetime.
///
/// This automatically deallocates the allocated object when the borrow's
/// lifetime ends. It also ensures that the borrow only lives as long as the
/// allocator that provided it, and that the borrow is dropped if the allocator
/// is dropped.
pub struct BorrowedPtr<'alloc, A>
where A: Allocator
    , A: 'alloc {
    ptr: Unique<u8>
  , layout: Layout
  , allocator: &'alloc Mutex
}

impl<'alloc, A> BorrowedPtr<'alloc, A>
where A: Allocator
    , A: 'alloc {

    #[inline]
    pub fn new( ptr: Address
                    , layout: Layout
                    , allocator: &'alloc Mutex)
                    -> Self {
        BorrowedPtr { ptr: unsafe { Unique::new(ptr) }
                    , layout: layout
                    , allocator: allocator
                    }

    }
}

impl<'alloc, A> Deref for BorrowedPtr<'alloc, A>
where A: Allocator
    , A: 'alloc {
    type Target = Address;
    fn deref(&self) ->  &Self::Target { &(*self.ptr) }
}

impl<'alloc, A> Drop for BorrowedPtr<'alloc, A>
where A: Allocator
    , A: 'alloc {
    fn drop(&mut self) {
        unsafe {
            self.allocator.lock().dealloc(*self.ptr, self.layout.clone())
        }
    }
}

/// A borrowed handle on a heap allocation with a specified lifetime.
///
/// This automatically deallocates the allocated object when the borrow's
/// lifetime ends. It also ensures that the borrow only lives as long as the
/// allocator that provided it, and that the borrow is dropped if the allocator
/// is dropped.
pub struct Borrowed<'alloc, A, T>
where A: Allocator
    , A: 'alloc {
    value: Unique<T>
  , allocator: &'alloc Mutex
}

impl<'alloc, A, T> Borrowed<'alloc, A, T>
where A: Allocator
    , A: 'alloc {

    #[inline]
    pub fn new( value: Unique<T>, allocator: &'alloc Mutex)
                    -> Self {
        Borrowed { value: value
                 , allocator: allocator
                 }

    }
}

impl<'alloc, A, T> Deref for Borrowed<'alloc, A, T>
where A: Allocator
    , A: 'alloc {
    type Target = T;
    fn deref(&self) ->  &Self::Target { unsafe { self.value.get() } }
}

impl<'alloc, A, T> DerefMut for Borrowed<'alloc, A, T>
where A: Allocator
    , A: 'alloc {
    fn deref_mut(&mut self) ->  &mut Self::Target {
        unsafe { self.value.get_mut() }
    }
}

impl<'alloc, A, T> Drop for Borrowed<'alloc, A, T>
where A: Allocator
    , A: 'alloc {
    fn drop(&mut self) {
        use mem::drop;
        let address = *self.value as Address;
        // ensure we drop the object _before_ deallocating it, so that
        // the object's destructor gets run first
        // i hope this is correct...
        drop(*self.value);
        unsafe {
            self.allocator.lock()
                .dealloc( address
                        , Layout::for_value(self.value.get()))
        }
    }
}
<commit_msg>[alloc] fix missing import for borrowed pointers<commit_after>use super::{Address, Allocator, Layout};
use ptr::Unique;
use ops::{Deref, DerefMut};
use spin::Mutex;

pub trait Lender {
    type Borrowed;
    fn borrow(&self) -> Self::Borrowed;
}

/// A borrowed handle on a heap allocation with a specified lifetime.
///
/// This automatically deallocates the allocated object when the borrow's
/// lifetime ends. It also ensures that the borrow only lives as long as the
/// allocator that provided it, and that the borrow is dropped if the allocator
/// is dropped.
// TODO: can we replace this with one generic implementation that works for
//       borrowed pointers, objects, and arrays? can that code be reused for
//       BorrowedFrame/BorrowedFrameRange as well?
//          - eliza, 02/21/2017
pub struct BorrowedPtr<'alloc, A>
where A: Allocator
    , A: 'alloc {
    ptr: Unique<u8>
  , layout: Layout
  , allocator: &'alloc Mutex
}

impl<'alloc, A> BorrowedPtr<'alloc, A>
where A: Allocator
    , A: 'alloc {

    #[inline]
    pub fn new( ptr: Address
                    , layout: Layout
                    , allocator: &'alloc Mutex)
                    -> Self {
        BorrowedPtr { ptr: unsafe { Unique::new(ptr) }
                    , layout: layout
                    , allocator: allocator
                    }

    }
}

impl<'alloc, A> Deref for BorrowedPtr<'alloc, A>
where A: Allocator
    , A: 'alloc {
    type Target = Address;
    fn deref(&self) ->  &Self::Target { &(*self.ptr) }
}

impl<'alloc, A> Drop for BorrowedPtr<'alloc, A>
where A: Allocator
    , A: 'alloc {
    fn drop(&mut self) {
        unsafe {
            self.allocator.lock().dealloc(*self.ptr, self.layout.clone())
        }
    }
}

/// A borrowed handle on a heap allocation with a specified lifetime.
///
/// This automatically deallocates the allocated object when the borrow's
/// lifetime ends. It also ensures that the borrow only lives as long as the
/// allocator that provided it, and that the borrow is dropped if the allocator
/// is dropped.
pub struct Borrowed<'alloc, A, T>
where A: Allocator
    , A: 'alloc {
    value: Unique<T>
  , allocator: &'alloc Mutex
}

impl<'alloc, A, T> Borrowed<'alloc, A, T>
where A: Allocator
    , A: 'alloc {

    #[inline]
    pub fn new( value: Unique<T>, allocator: &'alloc Mutex)
                    -> Self {
        Borrowed { value: value
                 , allocator: allocator
                 }

    }
}

impl<'alloc, A, T> Deref for Borrowed<'alloc, A, T>
where A: Allocator
    , A: 'alloc {
    type Target = T;
    fn deref(&self) ->  &Self::Target { unsafe { self.value.get() } }
}

impl<'alloc, A, T> DerefMut for Borrowed<'alloc, A, T>
where A: Allocator
    , A: 'alloc {
    fn deref_mut(&mut self) ->  &mut Self::Target {
        unsafe { self.value.get_mut() }
    }
}

impl<'alloc, A, T> Drop for Borrowed<'alloc, A, T>
where A: Allocator
    , A: 'alloc {
    fn drop(&mut self) {
        use mem::drop;
        let address = *self.value as Address;
        // ensure we drop the object _before_ deallocating it, so that
        // the object's destructor gets run first
        // i hope this is correct...
        drop(*self.value);
        unsafe {
            self.allocator.lock()
                .dealloc( address
                        , Layout::for_value(self.value.get()))
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{self, BufRead};
use std::mem;
use std::string::String;

use {Poll, Stream};

use io::AsyncRead;

/// Future for the [`lines`] function.
#[derive(Debug)]
pub struct Lines {
    io: A,
    line: String,
}

/// Creates a new stream from the I/O object given representing the lines of
/// input that are found on `A`.
///
/// This method takes an asynchronous I/O object, `a`, and returns a `Stream` of
/// lines that the object contains. The returned stream will reach its end once
/// `a` reaches EOF.
pub fn lines(a: A) -> Lines
    where A: AsyncRead + BufRead,
{
    Lines {
        io: a,
        line: String::new(),
    }
}

impl Lines {
    /// Returns the underlying I/O object.
    ///
    /// Note that this may lose data already read into internal buffers. It's
    /// recommended to only call this once the stream has reached its end.
    pub fn into_inner(self) -> A {
        self.io
    }
}

impl Stream for Lines
    where A: AsyncRead + BufRead,
{
    type Item = String;
    type Error = io::Error;

    fn poll(&mut self, cx: &mut Context<'_>) -> Poll<Option<String>, io::Error> {
        let n = ready!(self.io.read_line(&mut self.line));
        if n == 0 && self.line.len() == 0 {
            return Ok(None.into())
        }
        if self.line.ends_with("\n") {
            self.line.pop();
            if self.line.ends_with("\r") {
                self.line.pop();
            }
        }
        Ok(Some(mem::replace(&mut self.line, String::new())).into())
    }
}
<commit_msg>Remove io/disabled/lines.rs<commit_after><|endoftext|>