<commit_before>use alloc::boxed::Box;

use core::cmp;

use common::event::{KeyEvent, MouseEvent};

use drivers::io::{Io, Pio, ReadOnly, WriteOnly};

use graphics::display::VBEMODEINFO;

use fs::KScheme;

use drivers::kb_layouts::layouts;

pub struct Ps2Keyboard<'a> {
    bus: &'a mut Ps2
}

impl<'a> Ps2Keyboard<'a> {
    //TODO: Use result
    fn cmd(&mut self, command: u8) -> u8 {
        self.bus.wait_write();
        self.bus.data.write(command);
        self.bus.wait_read();
        self.bus.data.read()
    }
}

pub struct Ps2Mouse<'a> {
    bus: &'a mut Ps2
}

impl<'a> Ps2Mouse<'a> {
    //TODO: Use result
    fn cmd(&mut self, command: u8) -> u8 {
        self.bus.write(0xD4, command);
        self.bus.wait_read();
        self.bus.data.read()
    }
}

/// PS2
pub struct Ps2 {
    /// The data register
    data: Pio<u8>,
    /// The status register
    sts: ReadOnly<u8, Pio<u8>>,
    /// The command register
    cmd: WriteOnly<u8, Pio<u8>>,
    /// Left shift?
    lshift: bool,
    /// Right shift?
    rshift: bool,
    /// Caps lock?
    caps_lock: bool,
    /// Caps lock toggle
    caps_lock_toggle: bool,
    /// AltGr?
    altgr: bool,
    /// The mouse packet
    mouse_packet: [u8; 4],
    /// Mouse packet index
    mouse_i: usize,
    /// Mouse point x
    mouse_x: i32,
    /// Mouse point y
    mouse_y: i32,
    /// Layout for keyboard
    /// Default: English
    layout: layouts::Layout,
}

impl Ps2 {
    /// Create new PS2 data
    pub fn new() -> Box<Self> {
        let mut module = box Ps2 {
            data: Pio::new(0x60),
            sts: ReadOnly::new(Pio::new(0x64)),
            cmd: WriteOnly::new(Pio::new(0x64)),
            lshift: false,
            rshift: false,
            caps_lock: false,
            caps_lock_toggle: false,
            altgr: false,
            mouse_packet: [0; 4],
            mouse_i: 0,
            mouse_x: 0,
            mouse_y: 0,
            layout: layouts::Layout::English,
        };

        module.init();

        module
    }

    fn wait_read(&self) {
        while self.sts.read() & 1 == 0 {}
    }

    fn wait_write(&self) {
        while self.sts.read() & 2 == 2 {}
    }

    fn cmd(&mut self, command: u8) {
        self.wait_write();
        self.cmd.write(command);
    }

    fn read(&mut self, command: u8) -> u8 {
        self.cmd(command);
        self.wait_read();
        self.data.read()
    }

    fn write(&mut self, command: u8, data: u8) {
        self.cmd(command);
        self.wait_write();
        self.data.write(data);
    }

    fn keyboard<'a>(&'a mut self) -> Ps2Keyboard<'a> {
        Ps2Keyboard {
            bus: self
        }
    }

    fn mouse<'a>(&'a mut self) -> Ps2Mouse<'a> {
        Ps2Mouse {
            bus: self
        }
    }

    fn init(&mut self) {
        while (self.sts.read() & 0x1) == 1 {
            self.data.read();
        }

        // No interrupts, system flag set, clocks enabled, translation disabled
        self.write(0x60, 0b00000100);

        // Enable First Port
        self.cmd(0xAE);
        {
            let mut keyboard = self.keyboard();

            // Reset
            keyboard.cmd(0xFF);

            // Set defaults
            keyboard.cmd(0xF6);

            // Set LEDS
            keyboard.cmd(0xED);
            keyboard.cmd(0);

            // Set Scancode Map:
            keyboard.cmd(0xF0);
            keyboard.cmd(1);

            // Enable Streaming
            keyboard.cmd(0xF4);
        }

        // Enable Second Port
        self.cmd(0xA8);
        {
            let mut mouse = self.mouse();

            // Reset
            mouse.cmd(0xFF);

            // Set defaults
            mouse.cmd(0xF6);

            // Enable Streaming
            mouse.cmd(0xF4);
        }

        // Both interrupts, system flag set, clocks enabled, translation disabled
        self.write(0x60, 0b00000111);
    }

    /// Keyboard interrupt
    pub fn keyboard_interrupt(&mut self) -> Option<KeyEvent> {
        let mut scancode = self.data.read();

        if scancode == 0 {
            return None;
        } else if scancode == 0x2A {
            self.lshift = true;
        } else if scancode == 0xAA {
            self.lshift = false;
        } else if scancode == 0x36 {
            self.rshift = true;
        } else if scancode == 0xB6 {
            self.rshift = false;
        } else if scancode == 0x3A {
            if !self.caps_lock {
                self.caps_lock = true;
                self.caps_lock_toggle = true;
            } else {
                self.caps_lock_toggle = false;
            }
        } else if scancode == 0xBA {
            if self.caps_lock && !self.caps_lock_toggle {
                self.caps_lock = false;
            }
        } else if scancode == 0xE0 {
            let scancode_byte_2 = self.data.read();
            if scancode_byte_2 == 0x38 {
                self.altgr = true;
            } else if scancode_byte_2 == 0xB8 {
                self.altgr = false;
            } else {
                scancode = scancode_byte_2;
            }
        }

        let shift = self.caps_lock != (self.lshift || self.rshift);

        return Some(KeyEvent {
            character: layouts::char_for_scancode(scancode & 0x7F, shift, self.altgr, &self.layout),
            scancode: scancode & 0x7F,
            pressed: scancode < 0x80,
        });
    }

    /// Mouse interrupt
    pub fn mouse_interrupt(&mut self) -> Option<MouseEvent> {
        let byte = self.data.read();
        if self.mouse_i == 0 {
            if byte & 0x8 == 0x8 {
                self.mouse_packet[0] = byte;
                self.mouse_i += 1;
            }
        } else if self.mouse_i == 1 {
            self.mouse_packet[1] = byte;

            self.mouse_i += 1;
        } else {
            self.mouse_packet[2] = byte;

            let left_button = (self.mouse_packet[0] & 1) == 1;
            let right_button = (self.mouse_packet[0] & 2) == 2;
            let middle_button = (self.mouse_packet[0] & 4) == 4;

            let x;
            if (self.mouse_packet[0] & 0x40) != 0x40 && self.mouse_packet[1] != 0 {
                x = (self.mouse_packet[1] as isize -
                     (((self.mouse_packet[0] as isize) << 4) & 0x100)) as i32;
            } else {
                x = 0;
            }

            let y;
            if (self.mouse_packet[0] & 0x80) != 0x80 && self.mouse_packet[2] != 0 {
                y = ((((self.mouse_packet[0] as isize) << 3) & 0x100) -
                     self.mouse_packet[2] as isize) as i32;
            } else {
                y = 0;
            }

            if let Some(mode_info) = unsafe { VBEMODEINFO } {
                self.mouse_x = cmp::max(0, cmp::min(mode_info.xresolution as i32, self.mouse_x + x));
                self.mouse_y = cmp::max(0, cmp::min(mode_info.yresolution as i32, self.mouse_y + y));
            }

            self.mouse_i = 0;

            return Some(MouseEvent {
                x: self.mouse_x,
                y: self.mouse_y,
                left_button: left_button,
                right_button: right_button,
                middle_button: middle_button,
            });
        }

        return None;
    }

    /// Function to change the layout of the keyboard
    pub fn change_layout(&mut self, layout: usize) {
        self.layout = match layout {
            0 => layouts::Layout::English,
            1 => layouts::Layout::French,
            2 => layouts::Layout::German,
            _ => layouts::Layout::English,
        }
    }
}

impl KScheme for Ps2 {
    fn on_irq(&mut self, irq: u8) {
        if irq == 0x1 || irq == 0xC {
            loop {
                let status = self.sts.read();
                if status & 0x21 == 0x21 {
                    if let Some(mouse_event) = self.mouse_interrupt() {
                        if ::env().console.lock().draw {
                            //Ignore mouse event
                        } else {
                            ::env().events.send(mouse_event.to_event());
                        }
                    }
                } else if status & 0x21 == 1 {
                    if let Some(key_event) = self.keyboard_interrupt() {
                        if ::env().console.lock().draw {
                            ::env().console.lock().event(key_event.to_event());
                        } else {
                            ::env().events.send(key_event.to_event());
                        }
                    }
                } else {
                    break;
                }
            }
        }
    }
}
<commit_msg>Cleanup interrupt handling in ps/2, clear buffer before returning from init<commit_after>use alloc::boxed::Box;

use core::cmp;

use common::event::{KeyEvent, MouseEvent};

use drivers::io::{Io, Pio, ReadOnly, WriteOnly};

use graphics::display::VBEMODEINFO;

use fs::KScheme;

use drivers::kb_layouts::layouts;

pub struct Ps2Keyboard<'a> {
    bus: &'a mut Ps2
}

impl<'a> Ps2Keyboard<'a> {
    //TODO: Use result
    fn cmd(&mut self, command: u8) -> u8 {
        self.bus.wait_write();
        self.bus.data.write(command);
        self.bus.wait_read();
        self.bus.data.read()
    }
}

pub struct Ps2Mouse<'a> {
    bus: &'a mut Ps2
}

impl<'a> Ps2Mouse<'a> {
    //TODO: Use result
    fn cmd(&mut self, command: u8) -> u8 {
        self.bus.write(0xD4, command);
        self.bus.wait_read();
        self.bus.data.read()
    }
}

/// PS2
pub struct Ps2 {
    /// The data register
    data: Pio<u8>,
    /// The status register
    sts: ReadOnly<u8, Pio<u8>>,
    /// The command register
    cmd: WriteOnly<u8, Pio<u8>>,
    /// Left shift?
    lshift: bool,
    /// Right shift?
    rshift: bool,
    /// Caps lock?
    caps_lock: bool,
    /// Caps lock toggle
    caps_lock_toggle: bool,
    /// AltGr?
    altgr: bool,
    /// The mouse packet
    mouse_packet: [u8; 4],
    /// Mouse packet index
    mouse_i: usize,
    /// Mouse point x
    mouse_x: i32,
    /// Mouse point y
    mouse_y: i32,
    /// Layout for keyboard
    /// Default: English
    layout: layouts::Layout,
}

impl Ps2 {
    /// Create new PS2 data
    pub fn new() -> Box<Self> {
        let mut module = box Ps2 {
            data: Pio::new(0x60),
            sts: ReadOnly::new(Pio::new(0x64)),
            cmd: WriteOnly::new(Pio::new(0x64)),
            lshift: false,
            rshift: false,
            caps_lock: false,
            caps_lock_toggle: false,
            altgr: false,
            mouse_packet: [0; 4],
            mouse_i: 0,
            mouse_x: 0,
            mouse_y: 0,
            layout: layouts::Layout::English,
        };

        module.init();

        module
    }

    fn wait_read(&self) {
        while self.sts.read() & 1 == 0 {}
    }

    fn wait_write(&self) {
        while self.sts.read() & 2 == 2 {}
    }

    fn cmd(&mut self, command: u8) {
        self.wait_write();
        self.cmd.write(command);
    }

    fn read(&mut self, command: u8) -> u8 {
        self.cmd(command);
        self.wait_read();
        self.data.read()
    }

    fn write(&mut self, command: u8, data: u8) {
        self.cmd(command);
        self.wait_write();
        self.data.write(data);
    }

    fn keyboard<'a>(&'a mut self) -> Ps2Keyboard<'a> {
        Ps2Keyboard {
            bus: self
        }
    }

    fn mouse<'a>(&'a mut self) -> Ps2Mouse<'a> {
        Ps2Mouse {
            bus: self
        }
    }

    fn init(&mut self) {
        while (self.sts.read() & 0x1) == 1 {
            self.data.read();
        }

        // No interrupts, system flag set, clocks enabled, translation disabled
        self.write(0x60, 0b00000100);

        // Enable First Port
        self.cmd(0xAE);
        {
            let mut keyboard = self.keyboard();

            // Reset
            keyboard.cmd(0xFF);

            // Set defaults
            keyboard.cmd(0xF6);

            // Set LEDS
            keyboard.cmd(0xED);
            keyboard.cmd(0);

            // Set Scancode Map:
            keyboard.cmd(0xF0);
            keyboard.cmd(1);

            // Enable Streaming
            keyboard.cmd(0xF4);
        }

        // Enable Second Port
        self.cmd(0xA8);
        {
            let mut mouse = self.mouse();

            // Reset
            mouse.cmd(0xFF);

            // Set defaults
            mouse.cmd(0xF6);

            // Enable Streaming
            mouse.cmd(0xF4);
        }

        // Both interrupts, system flag set, clocks enabled, translation disabled
        self.write(0x60, 0b00000111);

        while (self.sts.read() & 0x1) == 1 {
            debugln!("Extra: {:X}", self.data.read());
        }
    }

    /// Keyboard interrupt
    pub fn keyboard_interrupt(&mut self, mut scancode: u8) -> Option<KeyEvent> {
        if scancode == 0 {
            return None;
        } else if scancode == 0x2A {
            self.lshift = true;
        } else if scancode == 0xAA {
            self.lshift = false;
        } else if scancode == 0x36 {
            self.rshift = true;
        } else if scancode == 0xB6 {
            self.rshift = false;
        } else if scancode == 0x3A {
            if !self.caps_lock {
                self.caps_lock = true;
                self.caps_lock_toggle = true;
            } else {
                self.caps_lock_toggle = false;
            }
        } else if scancode == 0xBA {
            if self.caps_lock && !self.caps_lock_toggle {
                self.caps_lock = false;
            }
        } else if scancode == 0xE0 {
            let scancode_byte_2 = self.data.read();
            if scancode_byte_2 == 0x38 {
                self.altgr = true;
            } else if scancode_byte_2 == 0xB8 {
                self.altgr = false;
            } else {
                scancode = scancode_byte_2;
            }
        }

        let shift = self.caps_lock != (self.lshift || self.rshift);

        return Some(KeyEvent {
            character: layouts::char_for_scancode(scancode & 0x7F, shift, self.altgr, &self.layout),
            scancode: scancode & 0x7F,
            pressed: scancode < 0x80,
        });
    }

    /// Mouse interrupt
    pub fn mouse_interrupt(&mut self, byte: u8) -> Option<MouseEvent> {
        if self.mouse_i == 0 {
            if byte & 0x8 == 0x8 {
                self.mouse_packet[0] = byte;
                self.mouse_i += 1;
            }
        } else if self.mouse_i == 1 {
            self.mouse_packet[1] = byte;

            self.mouse_i += 1;
        } else {
            self.mouse_packet[2] = byte;

            let left_button = (self.mouse_packet[0] & 1) == 1;
            let right_button = (self.mouse_packet[0] & 2) == 2;
            let middle_button = (self.mouse_packet[0] & 4) == 4;

            let x;
            if (self.mouse_packet[0] & 0x40) != 0x40 && self.mouse_packet[1] != 0 {
                x = (self.mouse_packet[1] as isize -
                     (((self.mouse_packet[0] as isize) << 4) & 0x100)) as i32;
            } else {
                x = 0;
            }

            let y;
            if (self.mouse_packet[0] & 0x80) != 0x80 && self.mouse_packet[2] != 0 {
                y = ((((self.mouse_packet[0] as isize) << 3) & 0x100) -
                     self.mouse_packet[2] as isize) as i32;
            } else {
                y = 0;
            }

            if let Some(mode_info) = unsafe { VBEMODEINFO } {
                self.mouse_x = cmp::max(0, cmp::min(mode_info.xresolution as i32, self.mouse_x + x));
                self.mouse_y = cmp::max(0, cmp::min(mode_info.yresolution as i32, self.mouse_y + y));
            }

            self.mouse_i = 0;

            return Some(MouseEvent {
                x: self.mouse_x,
                y: self.mouse_y,
                left_button: left_button,
                right_button: right_button,
                middle_button: middle_button,
            });
        }

        return None;
    }

    /// Function to change the layout of the keyboard
    pub fn change_layout(&mut self, layout: usize) {
        self.layout = match layout {
            0 => layouts::Layout::English,
            1 => layouts::Layout::French,
            2 => layouts::Layout::German,
            _ => layouts::Layout::English,
        }
    }
}

impl KScheme for Ps2 {
    fn on_irq(&mut self, irq: u8) {
        if irq == 0xC {
            let data = self.data.read();
            if let Some(mouse_event) = self.mouse_interrupt(data) {
                if ::env().console.lock().draw {
                    //Ignore mouse event
                } else {
                    ::env().events.send(mouse_event.to_event());
                }
            }
        } else if irq == 0x1 {
            let data = self.data.read();
            if let Some(key_event) = self.keyboard_interrupt(data) {
                if ::env().console.lock().draw {
                    ::env().console.lock().event(key_event.to_event());
                } else {
                    ::env().events.send(key_event.to_event());
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use redox::*;

#[derive(Copy, Clone)]
pub enum Mode {
    Insert,
    Normal,
}

pub struct Editor {
    url: String,
    file: Option<File>,
    string: String,
    offset: usize,
    scroll_x: isize,
    scroll_y: isize,
}

impl Editor {
    #[inline(never)]
    pub fn new() -> Self {
        Editor {
            url: String::new(),
            file: Option::None,
            string: String::new(),
            offset: 0,
            scroll_x: 0,
            scroll_y: 0,
        }
    }

    fn backspace(&mut self, window: &mut Window) {
         if self.offset > 0 {
             window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Changed"));
             self.string = self.string[0 .. self.offset - 1].to_string() +
                 &self.string[self.offset .. self.string.len()];
             self.offset -= 1;
         }
    }

    fn delete(&mut self, window: &mut Window) {
        if self.offset < self.string.len() {
            window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Changed"));
            self.string = self.string[0 .. self.offset + 1].to_string() +
                &self.string[self.offset + 1 .. self.string.len() - 1];
        }
    }

    fn up(&mut self) {
        let mut new_offset = 0;
        for i in 2..self.offset {
            match self.string.as_bytes()[self.offset - i] {
                0 => break,
                10 => {
                    new_offset = self.offset - i + 1;
                    break;
                }
                _ => (),
            }
        }
        self.offset = new_offset;
    }

    fn left(&mut self) {
        if self.offset > 0 {
            self.offset -= 1;
        }
    }

    fn right(&mut self) {
        if self.offset < self.string.len() {
            self.offset += 1;
        }
    }

    fn down(&mut self) {
        let mut new_offset = self.string.len();
        for i in self.offset..self.string.len() {
            match self.string.as_bytes()[i] {
                0 => break,
                10 => {
                    new_offset = i + 1;
                    break;
                }
                _ => (),
            }
        }
        self.offset = new_offset;
    }

    fn reload(&mut self, window: &mut Window) {
        window.set_title(&("Editor (".to_string() + &self.url + ")"));
        self.offset = 0;
        self.scroll_x = 0;
        self.scroll_y = 0;

        match self.file {
            Option::Some(ref mut file) => {
                file.seek(Seek::Start(0));
                let mut vec: Vec<u8> = Vec::new();
                file.read_to_end(&mut vec);
                self.string = unsafe { String::from_utf8_unchecked(vec) };
            },
            Option::None => self.string = String::new(),
        }
    }

    fn save(&mut self, window: &mut Window) {
        match self.file {
            Option::Some(ref mut file) => {
                window.set_title(&("Editor (".to_string() + &self.url + ") Saved"));
                file.seek(Seek::Start(0));
                file.write(&self.string.as_bytes());
                file.sync();
            }
            Option::None => {
                //TODO: Ask for file to save to
                window.set_title(&("Editor (".to_string() + &self.url + ") No Open File"));
            }
        }
    }

    fn draw_content(&mut self, window: &mut Window) {
        let mut redraw = false;

        {
            window.set([255, 255, 255, 255]);

            let scroll_x = self.scroll_x;
            let scroll_y = self.scroll_y;

            let mut offset = 0;

            let mut col = -scroll_x;
            let cols = window.width() as isize / 8;

            let mut row = -scroll_y;
            let rows = window.height() as isize / 16;

            for c in self.string.chars() {
                if offset == self.offset {
                    if col >= 0 && col < cols && row >= 0 && row < rows {
                        window.char(8 * col, 16 * row, '_', [128, 128, 128, 255]);
                    } else {
                        if col < 0 { //Too far to the left
                            self.scroll_x += col;
                        } else if col >= cols { //Too far to the right
                            self.scroll_x += cols - col + 1;
                        }
                        if row < 0 { //Too far up
                            self.scroll_y += row;
                        } else if row >= rows { //Too far down
                            self.scroll_y += rows - row + 1;
                        }

                        redraw = true;
                    }
                }

                if c == '\n' {
                    col = -scroll_x;
                    row += 1;
                } else if c == '\t' {
                    col += 8 - col % 8;
                } else {
                    if col >= 0 && col < cols && row >= 0 && row < rows {
                        window.char(8 * col, 16 * row, c, [0, 0, 0, 255]);
                    }
                    col += 1;
                }

                offset += 1;
            }

            if offset == self.offset {
                if col >= 0 && col < cols && row >= 0 && row < rows {
                    window.char(8 * col, 16 * row, '_', [128, 128, 128, 255]);
                } else {
                    if col < 0 { //Too far to the left
                        self.scroll_x += col;
                    } else if col >= cols { //Too far to the right
                        self.scroll_x += cols - col + 1;
                    }
                    if row < 0 { //Too far up
                        self.scroll_y += row;
                    } else if row >= rows { //Too far down
                        self.scroll_y += rows - row + 1;
                    }

                    redraw = true;
                }
            }

            window.sync();
        }

        if redraw {
            self.draw_content(window);
        }
    }

    fn main(&mut self, url: &str) {
        let mut window = Window::new((rand() % 400 + 50) as isize,
                                     (rand() % 300 + 50) as isize,
                                     576,
                                     400,
                                      &("Editor (".to_string() + url + ")"));

        self.url = url.to_string();
        self.file = Option::Some(File::open(&self.url));

        self.reload(&mut window);
        self.draw_content(&mut window);

        let mut mode = Mode::Normal;

        while let Option::Some(event) = window.poll() {
            match event.to_option() {
                EventOption::Key(key_event) => {
                    if key_event.pressed {
                        use self::Mode::*;
                        match (mode, key_event.scancode) {
                            (Insert, K_ESC) => mode = Normal,
                            (Insert, K_BKSP) => self.backspace(&mut window),
                            (Insert, K_DEL) => self.delete(&mut window),
                            (_, K_F5) => self.reload(&mut window),
                            (_, K_F6) => self.save(&mut window),
                            (_, K_HOME) => self.offset = 0,
                            (_, K_UP) => self.up(),
                            (_, K_LEFT) => self.left(),
                            (_, K_RIGHT) => self.right(),
                            (_, K_END) => self.offset = self.string.len(),
                            (_, K_DOWN) => self.down(),
                            (m, _) => match (m, key_event.character) {
                                (Normal, 'i') => mode = Insert,
                                (Normal, 'h') => self.left(),
                                (Normal, 'l') => self.right(),
                                (Normal, 'k') => self.up(),
                                (Normal, 'j') => self.down(),
                                (Normal, 'G') => self.offset = self.string.len(),
                                (Normal, 'a') => {
                                    self.right();
                                    mode = Insert;
                                },
                                (Normal, 'x') => self.delete(&mut window),
                                (Normal, 'X') => self.backspace(&mut window),
                                (Insert, '\0') => (),
                                (Insert, _) => {
                                    window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Changed"));
                                    self.string = self.string[0 .. self.offset].to_string() +
                                                  &key_event.character.to_string() +
                                                  &self.string[self.offset .. self.string.len()];
                                    self.offset += 1;
                                },
                                _ => {},
                            }
                        }

                        self.draw_content(&mut window);
                    }
                }
                _ => (),
            }
        }
    }
}

pub fn main() {
    match args().get(1) {
        Option::Some(arg) => Editor::new().main(&arg),
        Option::None => Editor::new().main("none://"),
    }
}
<commit_msg>Add undo functionality to the editor<commit_after>use redox::*;

#[derive(Copy, Clone)]
pub enum Mode {
    Insert,
    Normal,
}

pub struct Editor {
    url: String,
    file: Option<File>,
    string: String,
    offset: usize,
    scroll_x: isize,
    scroll_y: isize,
}

impl Editor {
    #[inline(never)]
    pub fn new() -> Self {
        Editor {
            url: String::new(),
            file: Option::None,
            string: String::new(),
            offset: 0,
            scroll_x: 0,
            scroll_y: 0,
        }
    }

    fn backspace(&mut self, window: &mut Window) {
         if self.offset > 0 {
             window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Changed"));
             self.string = self.string[0 .. self.offset - 1].to_string() +
                 &self.string[self.offset .. self.string.len()];
             self.offset -= 1;
         }
    }

    fn delete(&mut self, window: &mut Window) {
        if self.offset < self.string.len() {
            window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Changed"));
            self.string = self.string[0 .. self.offset + 1].to_string() +
                &self.string[self.offset + 1 .. self.string.len() - 1];
        }
    }

    fn up(&mut self) {
        let mut new_offset = 0;
        for i in 2..self.offset {
            match self.string.as_bytes()[self.offset - i] {
                0 => break,
                10 => {
                    new_offset = self.offset - i + 1;
                    break;
                }
                _ => (),
            }
        }
        self.offset = new_offset;
    }

    fn left(&mut self) {
        if self.offset > 0 {
            self.offset -= 1;
        }
    }

    fn right(&mut self) {
        if self.offset < self.string.len() {
            self.offset += 1;
        }
    }

    fn down(&mut self) {
        let mut new_offset = self.string.len();
        for i in self.offset..self.string.len() {
            match self.string.as_bytes()[i] {
                0 => break,
                10 => {
                    new_offset = i + 1;
                    break;
                }
                _ => (),
            }
        }
        self.offset = new_offset;
    }

    fn reload(&mut self, window: &mut Window) {
        window.set_title(&("Editor (".to_string() + &self.url + ")"));
        self.offset = 0;
        self.scroll_x = 0;
        self.scroll_y = 0;

        match self.file {
            Option::Some(ref mut file) => {
                file.seek(Seek::Start(0));
                let mut vec: Vec<u8> = Vec::new();
                file.read_to_end(&mut vec);
                self.string = unsafe { String::from_utf8_unchecked(vec) };
            },
            Option::None => self.string = String::new(),
        }
    }

    fn save(&mut self, window: &mut Window) {
        match self.file {
            Option::Some(ref mut file) => {
                window.set_title(&("Editor (".to_string() + &self.url + ") Saved"));
                file.seek(Seek::Start(0));
                file.write(&self.string.as_bytes());
                file.sync();
            }
            Option::None => {
                //TODO: Ask for file to save to
                window.set_title(&("Editor (".to_string() + &self.url + ") No Open File"));
            }
        }
    }

    fn draw_content(&mut self, window: &mut Window) {
        let mut redraw = false;

        {
            window.set([255, 255, 255, 255]);

            let scroll_x = self.scroll_x;
            let scroll_y = self.scroll_y;

            let mut offset = 0;

            let mut col = -scroll_x;
            let cols = window.width() as isize / 8;

            let mut row = -scroll_y;
            let rows = window.height() as isize / 16;

            for c in self.string.chars() {
                if offset == self.offset {
                    if col >= 0 && col < cols && row >= 0 && row < rows {
                        window.char(8 * col, 16 * row, '_', [128, 128, 128, 255]);
                    } else {
                        if col < 0 { //Too far to the left
                            self.scroll_x += col;
                        } else if col >= cols { //Too far to the right
                            self.scroll_x += cols - col + 1;
                        }
                        if row < 0 { //Too far up
                            self.scroll_y += row;
                        } else if row >= rows { //Too far down
                            self.scroll_y += rows - row + 1;
                        }

                        redraw = true;
                    }
                }

                if c == '\n' {
                    col = -scroll_x;
                    row += 1;
                } else if c == '\t' {
                    col += 8 - col % 8;
                } else {
                    if col >= 0 && col < cols && row >= 0 && row < rows {
                        window.char(8 * col, 16 * row, c, [0, 0, 0, 255]);
                    }
                    col += 1;
                }

                offset += 1;
            }

            if offset == self.offset {
                if col >= 0 && col < cols && row >= 0 && row < rows {
                    window.char(8 * col, 16 * row, '_', [128, 128, 128, 255]);
                } else {
                    if col < 0 { //Too far to the left
                        self.scroll_x += col;
                    } else if col >= cols { //Too far to the right
                        self.scroll_x += cols - col + 1;
                    }
                    if row < 0 { //Too far up
                        self.scroll_y += row;
                    } else if row >= rows { //Too far down
                        self.scroll_y += rows - row + 1;
                    }

                    redraw = true;
                }
            }

            window.sync();
        }

        if redraw {
            self.draw_content(window);
        }
    }

    fn main(&mut self, url: &str) {
        let mut window = Window::new((rand() % 400 + 50) as isize,
                                     (rand() % 300 + 50) as isize,
                                     576,
                                     400,
                                      &("Editor (".to_string() + url + ")"));

        self.url = url.to_string();
        self.file = Option::Some(File::open(&self.url));

        self.reload(&mut window);
        self.draw_content(&mut window);

        let mut mode = Mode::Normal;

        let mut last_change = String::new();

        while let Option::Some(event) = window.poll() {
            match event.to_option() {
                EventOption::Key(key_event) => {
                    if key_event.pressed {
                        use self::Mode::*;
                        match (mode, key_event.scancode) {
                            (Insert, K_ESC) => {
                                mode = Normal;
                            },
                            (Insert, K_BKSP) => self.backspace(&mut window),
                            (Insert, K_DEL) => self.delete(&mut window),
                            (_, K_F5) => self.reload(&mut window),
                            (_, K_F6) => self.save(&mut window),
                            (_, K_HOME) => self.offset = 0,
                            (_, K_UP) => self.up(),
                            (_, K_LEFT) => self.left(),
                            (_, K_RIGHT) => self.right(),
                            (_, K_END) => self.offset = self.string.len(),
                            (_, K_DOWN) => self.down(),
                            (m, _) => match (m, key_event.character) {
                                (Normal, 'i') => {
                                    mode = Insert;
                                    last_change = self.string.clone();
                                },
                                (Normal, 'h') => self.left(),
                                (Normal, 'l') => self.right(),
                                (Normal, 'k') => self.up(),
                                (Normal, 'j') => self.down(),
                                (Normal, 'G') => self.offset = self.string.len(),
                                (Normal, 'a') => {
                                    self.right();
                                    mode = Insert;
                                    last_change = self.string.clone();
                                },
                                (Normal, 'x') => self.delete(&mut window),
                                (Normal, 'X') => self.backspace(&mut window),
                                (Normal, 'u') => {
                                    ::core::mem::swap(&mut last_change, &mut self.string);
                                },
                                (Insert, '\0') => (),
                                (Insert, _) => {
                                    window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Changed"));
                                    self.string = self.string[0 .. self.offset].to_string() +
                                                  &key_event.character.to_string() +
                                                  &self.string[self.offset .. self.string.len()];
                                    self.offset += 1;
                                },
                                _ => {},
                            }
                        }

                        self.draw_content(&mut window);
                    }
                }
                _ => (),
            }
        }
    }
}

pub fn main() {
    match args().get(1) {
        Option::Some(arg) => Editor::new().main(&arg),
        Option::None => Editor::new().main("none://"),
    }
}
<|endoftext|>


<commit_before><commit_msg>gcd of all the numbers given via command line done<commit_after><|endoftext|>


<commit_before><commit_msg>Auto merge of #11011 - hi-rustin:rustin-patch-tests, r=epage<commit_after><|endoftext|>


<commit_before><commit_msg>dynamic dispatch using coercing<commit_after><|endoftext|>


<commit_before>use boxed::Box;
use core::mem;
use io::{Result, Read, Write};
use os::unix::io::{AsRawFd, FromRawFd, RawFd};
use ops::DerefMut;
use string::String;
use core_collections::borrow::ToOwned;
use vec::Vec;

use io::Error;
use system::syscall::{sys_clone, sys_close, sys_dup, sys_execve, sys_exit, sys_pipe2, sys_read, sys_write, sys_waitpid, CLONE_VM, CLONE_VFORK};
use system::error::Error as SysError;

pub struct ExitStatus {
    status: usize,
}

impl ExitStatus {
    pub fn success(&self) -> bool {
        self.status == 0
    }

    pub fn code(&self) -> Option<i32> {
        Some(self.status as i32)
    }
}

pub struct ChildStdin {
    fd: usize,
}

impl Write for ChildStdin {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        sys_write(self.fd, buf).map_err(|x| Error::from_sys(x))
    }
    fn flush(&mut self) -> Result<()> { Ok(()) }
}

impl Drop for ChildStdin {
    fn drop(&mut self) {
        let _ = sys_close(self.fd);
    }
}

pub struct ChildStdout {
    fd: usize,
}

impl AsRawFd for ChildStdout {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}

impl Read for ChildStdout {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        sys_read(self.fd, buf).map_err(|x| Error::from_sys(x))
    }
}

impl Drop for ChildStdout {
    fn drop(&mut self) {
        let _ = sys_close(self.fd);
    }
}

pub struct ChildStderr {
    fd: usize,
}

impl Read for ChildStderr {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        sys_read(self.fd, buf).map_err(|x| Error::from_sys(x))
    }
}

impl Drop for ChildStderr {
    fn drop(&mut self) {
        let _ = sys_close(self.fd);
    }
}

pub struct Child {
    pid: usize,
    pub stdin: Option<ChildStdin>,
    pub stdout: Option<ChildStdout>,
    pub stderr: Option<ChildStderr>,
}

impl Child {
    pub fn id(&self) -> u32 {
        self.pid as u32
    }

    pub fn wait(&mut self) -> Result<ExitStatus> {
        let mut status: usize = 0;
        sys_waitpid(self.pid, &mut status, 0).map(|_| ExitStatus { status: status }).map_err(|x| Error::from_sys(x))
    }
}

pub struct Command {
    pub path: String,
    pub args: Vec<String>,
    stdin: Stdio,
    stdout: Stdio,
    stderr: Stdio,
}

impl Command {
    pub fn new(path: &str) -> Command {
        Command {
            path: path.to_owned(),
            args: Vec::new(),
            stdin: Stdio::inherit(),
            stdout: Stdio::inherit(),
            stderr: Stdio::inherit(),
        }
    }

    pub fn arg(&mut self, arg: &str) -> &mut Command {
        self.args.push(arg.to_owned());
        self
    }

    pub fn stdin(&mut self, cfg: Stdio) -> &mut Command {
        self.stdin = cfg;
        self
    }

    pub fn stdout(&mut self, cfg: Stdio) -> &mut Command {
        self.stdout = cfg;
        self
    }

    pub fn stderr(&mut self, cfg: Stdio) -> &mut Command {
        self.stderr = cfg;
        self
    }

    pub fn spawn(&mut self) -> Result<Child> {
        let mut res = Box::new(0);

        let path_c = self.path.to_owned() + "\0";

        let mut args_vec: Vec<String> = Vec::new();
        for arg in self.args.iter() {
            args_vec.push(arg.to_owned() + "\0");
        }

        let mut args_c: Vec<*const u8> = Vec::new();
        for arg_vec in args_vec.iter() {
            args_c.push(arg_vec.as_ptr());
        }
        args_c.push(0 as *const u8);

        let child_res = res.deref_mut() as *mut usize;
        let child_stderr = self.stderr.inner;
        let child_stdout = self.stdout.inner;
        let child_stdin = self.stdin.inner;
        let child_code = Box::new(move || -> Result<usize> {
            match child_stderr {
                StdioType::Piped(read, write) => {
                    try!(sys_close(read).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(2).map_err(|x| Error::from_sys(x)));
                    try!(sys_dup(write).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(write).map_err(|x| Error::from_sys(x)));
                },
                StdioType::Raw(fd) => {
                    try!(sys_close(2).map_err(|x| Error::from_sys(x)));
                    try!(sys_dup(fd).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(fd).map_err(|x| Error::from_sys(x)));
                },
                StdioType::Null => {
                    try!(sys_close(2).map_err(|x| Error::from_sys(x)));
                },
                _ => ()
            }

            match child_stdout {
                StdioType::Piped(read, write) => {
                    try!(sys_close(read).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(1).map_err(|x| Error::from_sys(x)));
                    try!(sys_dup(write).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(write).map_err(|x| Error::from_sys(x)));
                },
                StdioType::Raw(fd) => {
                    try!(sys_close(1).map_err(|x| Error::from_sys(x)));
                    try!(sys_dup(fd).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(fd).map_err(|x| Error::from_sys(x)));
                },
                StdioType::Null => {
                    try!(sys_close(1).map_err(|x| Error::from_sys(x)));
                },
                _ => ()
            }

            match child_stdin {
                StdioType::Piped(read, write) => {
                    try!(sys_close(write).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(0).map_err(|x| Error::from_sys(x)));
                    try!(sys_dup(read).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(read).map_err(|x| Error::from_sys(x)));
                },
                StdioType::Raw(fd) => {
                    try!(sys_close(0).map_err(|x| Error::from_sys(x)));
                    try!(sys_dup(fd).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(fd).map_err(|x| Error::from_sys(x)));
                },
                StdioType::Null => {
                    try!(sys_close(0).map_err(|x| Error::from_sys(x)));
                },
                _ => ()
            }

            unsafe { sys_execve(path_c.as_ptr(), args_c.as_ptr()) }.map_err(|x| Error::from_sys(x))
        });

        match unsafe { sys_clone(CLONE_VM | CLONE_VFORK) } {
            Ok(0) => {
                let error = child_code();

                unsafe { *child_res = SysError::mux(error.map_err(|x| x.into_sys())); }

                loop {
                    let _ = sys_exit(127);
                }
            },
            Ok(pid) => {
                //Must forget child_code to prevent double free
                mem::forget(child_code);
                if let Err(err) = SysError::demux(*res) {
                    Err(Error::from_sys(err))
                } else {
                    Ok(Child {
                        pid: pid,
                        stdin: match self.stdin.inner {
                            StdioType::Piped(read, write) => {
                                try!(sys_close(read).map_err(|x| Error::from_sys(x)));
                                Some(ChildStdin {
                                    fd: write
                                })
                            },
                            StdioType::Raw(fd) => {
                                try!(sys_close(fd).map_err(|x| Error::from_sys(x)));
                                None
                            },
                            _ => None
                        },
                        stdout: match self.stdout.inner {
                            StdioType::Piped(read, write) => {
                                try!(sys_close(write).map_err(|x| Error::from_sys(x)));
                                Some(ChildStdout {
                                    fd: read
                                })
                            },
                            StdioType::Raw(fd) => {
                                try!(sys_close(fd).map_err(|x| Error::from_sys(x)));
                                None
                            },
                            _ => None
                        },
                        stderr: match self.stderr.inner {
                            StdioType::Piped(read, write) => {
                                try!(sys_close(write).map_err(|x| Error::from_sys(x)));
                                Some(ChildStderr {
                                    fd: read
                                })
                            },
                            StdioType::Raw(fd) => {
                                try!(sys_close(fd).map_err(|x| Error::from_sys(x)));
                                None
                            },
                            _ => None
                        }
                    })
                }
            }
            Err(err) => Err(Error::from_sys(err))
        }
    }
}

#[derive(Copy, Clone)]
enum StdioType {
    Piped(usize, usize),
    Raw(usize),
    Inherit,
    Null,
}

pub struct Stdio {
    inner: StdioType,
}

impl Stdio {
    pub fn piped() -> Stdio {
        let mut fds = [0; 2];
        if unsafe { sys_pipe2(fds.as_mut_ptr(), 0).is_ok() } {
            Stdio {
                inner: StdioType::Piped(fds[0], fds[1])
            }
        } else {
            Stdio::null()
        }
    }

    pub fn inherit() -> Stdio {
        Stdio {
            inner: StdioType::Inherit
        }
    }

    pub fn null() -> Stdio {
        Stdio {
            inner: StdioType::Null
        }
    }
}

impl FromRawFd for Stdio {
    unsafe fn from_raw_fd(fd: RawFd) -> Self {
        Stdio {
            inner: StdioType::Raw(fd)
        }
    }
}

pub fn exit(code: i32) -> ! {
    loop {
        let _ = sys_exit(code as usize);
    }
}
<commit_msg>Implement fmt::Debug for std::Command<commit_after>use boxed::Box;
use core::mem;
use fmt;
use io::{Result, Read, Write};
use os::unix::io::{AsRawFd, FromRawFd, RawFd};
use ops::DerefMut;
use string::String;
use core_collections::borrow::ToOwned;
use vec::Vec;

use io::Error;
use system::syscall::{sys_clone, sys_close, sys_dup, sys_execve, sys_exit, sys_pipe2, sys_read, sys_write, sys_waitpid, CLONE_VM, CLONE_VFORK};
use system::error::Error as SysError;

pub struct ExitStatus {
    status: usize,
}

impl ExitStatus {
    pub fn success(&self) -> bool {
        self.status == 0
    }

    pub fn code(&self) -> Option<i32> {
        Some(self.status as i32)
    }
}

pub struct ChildStdin {
    fd: usize,
}

impl Write for ChildStdin {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        sys_write(self.fd, buf).map_err(|x| Error::from_sys(x))
    }
    fn flush(&mut self) -> Result<()> { Ok(()) }
}

impl Drop for ChildStdin {
    fn drop(&mut self) {
        let _ = sys_close(self.fd);
    }
}

pub struct ChildStdout {
    fd: usize,
}

impl AsRawFd for ChildStdout {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}

impl Read for ChildStdout {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        sys_read(self.fd, buf).map_err(|x| Error::from_sys(x))
    }
}

impl Drop for ChildStdout {
    fn drop(&mut self) {
        let _ = sys_close(self.fd);
    }
}

pub struct ChildStderr {
    fd: usize,
}

impl Read for ChildStderr {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        sys_read(self.fd, buf).map_err(|x| Error::from_sys(x))
    }
}

impl Drop for ChildStderr {
    fn drop(&mut self) {
        let _ = sys_close(self.fd);
    }
}

pub struct Child {
    pid: usize,
    pub stdin: Option<ChildStdin>,
    pub stdout: Option<ChildStdout>,
    pub stderr: Option<ChildStderr>,
}

impl Child {
    pub fn id(&self) -> u32 {
        self.pid as u32
    }

    pub fn wait(&mut self) -> Result<ExitStatus> {
        let mut status: usize = 0;
        sys_waitpid(self.pid, &mut status, 0).map(|_| ExitStatus { status: status }).map_err(|x| Error::from_sys(x))
    }
}

pub struct Command {
    pub path: String,
    pub args: Vec<String>,
    stdin: Stdio,
    stdout: Stdio,
    stderr: Stdio,
}

impl fmt::Debug for Command {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{:?}", self.path));
        for arg in &self.args {
            try!(write!(f, " {:?}", arg));
        }
        Ok(())
    }
}

impl Command {
    pub fn new(path: &str) -> Command {
        Command {
            path: path.to_owned(),
            args: Vec::new(),
            stdin: Stdio::inherit(),
            stdout: Stdio::inherit(),
            stderr: Stdio::inherit(),
        }
    }

    pub fn arg(&mut self, arg: &str) -> &mut Command {
        self.args.push(arg.to_owned());
        self
    }

    pub fn stdin(&mut self, cfg: Stdio) -> &mut Command {
        self.stdin = cfg;
        self
    }

    pub fn stdout(&mut self, cfg: Stdio) -> &mut Command {
        self.stdout = cfg;
        self
    }

    pub fn stderr(&mut self, cfg: Stdio) -> &mut Command {
        self.stderr = cfg;
        self
    }

    pub fn spawn(&mut self) -> Result<Child> {
        let mut res = Box::new(0);

        let path_c = self.path.to_owned() + "\0";

        let mut args_vec: Vec<String> = Vec::new();
        for arg in self.args.iter() {
            args_vec.push(arg.to_owned() + "\0");
        }

        let mut args_c: Vec<*const u8> = Vec::new();
        for arg_vec in args_vec.iter() {
            args_c.push(arg_vec.as_ptr());
        }
        args_c.push(0 as *const u8);

        let child_res = res.deref_mut() as *mut usize;
        let child_stderr = self.stderr.inner;
        let child_stdout = self.stdout.inner;
        let child_stdin = self.stdin.inner;
        let child_code = Box::new(move || -> Result<usize> {
            match child_stderr {
                StdioType::Piped(read, write) => {
                    try!(sys_close(read).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(2).map_err(|x| Error::from_sys(x)));
                    try!(sys_dup(write).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(write).map_err(|x| Error::from_sys(x)));
                },
                StdioType::Raw(fd) => {
                    try!(sys_close(2).map_err(|x| Error::from_sys(x)));
                    try!(sys_dup(fd).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(fd).map_err(|x| Error::from_sys(x)));
                },
                StdioType::Null => {
                    try!(sys_close(2).map_err(|x| Error::from_sys(x)));
                },
                _ => ()
            }

            match child_stdout {
                StdioType::Piped(read, write) => {
                    try!(sys_close(read).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(1).map_err(|x| Error::from_sys(x)));
                    try!(sys_dup(write).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(write).map_err(|x| Error::from_sys(x)));
                },
                StdioType::Raw(fd) => {
                    try!(sys_close(1).map_err(|x| Error::from_sys(x)));
                    try!(sys_dup(fd).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(fd).map_err(|x| Error::from_sys(x)));
                },
                StdioType::Null => {
                    try!(sys_close(1).map_err(|x| Error::from_sys(x)));
                },
                _ => ()
            }

            match child_stdin {
                StdioType::Piped(read, write) => {
                    try!(sys_close(write).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(0).map_err(|x| Error::from_sys(x)));
                    try!(sys_dup(read).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(read).map_err(|x| Error::from_sys(x)));
                },
                StdioType::Raw(fd) => {
                    try!(sys_close(0).map_err(|x| Error::from_sys(x)));
                    try!(sys_dup(fd).map_err(|x| Error::from_sys(x)));
                    try!(sys_close(fd).map_err(|x| Error::from_sys(x)));
                },
                StdioType::Null => {
                    try!(sys_close(0).map_err(|x| Error::from_sys(x)));
                },
                _ => ()
            }

            unsafe { sys_execve(path_c.as_ptr(), args_c.as_ptr()) }.map_err(|x| Error::from_sys(x))
        });

        match unsafe { sys_clone(CLONE_VM | CLONE_VFORK) } {
            Ok(0) => {
                let error = child_code();

                unsafe { *child_res = SysError::mux(error.map_err(|x| x.into_sys())); }

                loop {
                    let _ = sys_exit(127);
                }
            },
            Ok(pid) => {
                //Must forget child_code to prevent double free
                mem::forget(child_code);
                if let Err(err) = SysError::demux(*res) {
                    Err(Error::from_sys(err))
                } else {
                    Ok(Child {
                        pid: pid,
                        stdin: match self.stdin.inner {
                            StdioType::Piped(read, write) => {
                                try!(sys_close(read).map_err(|x| Error::from_sys(x)));
                                Some(ChildStdin {
                                    fd: write
                                })
                            },
                            StdioType::Raw(fd) => {
                                try!(sys_close(fd).map_err(|x| Error::from_sys(x)));
                                None
                            },
                            _ => None
                        },
                        stdout: match self.stdout.inner {
                            StdioType::Piped(read, write) => {
                                try!(sys_close(write).map_err(|x| Error::from_sys(x)));
                                Some(ChildStdout {
                                    fd: read
                                })
                            },
                            StdioType::Raw(fd) => {
                                try!(sys_close(fd).map_err(|x| Error::from_sys(x)));
                                None
                            },
                            _ => None
                        },
                        stderr: match self.stderr.inner {
                            StdioType::Piped(read, write) => {
                                try!(sys_close(write).map_err(|x| Error::from_sys(x)));
                                Some(ChildStderr {
                                    fd: read
                                })
                            },
                            StdioType::Raw(fd) => {
                                try!(sys_close(fd).map_err(|x| Error::from_sys(x)));
                                None
                            },
                            _ => None
                        }
                    })
                }
            }
            Err(err) => Err(Error::from_sys(err))
        }
    }
}

#[derive(Copy, Clone)]
enum StdioType {
    Piped(usize, usize),
    Raw(usize),
    Inherit,
    Null,
}

pub struct Stdio {
    inner: StdioType,
}

impl Stdio {
    pub fn piped() -> Stdio {
        let mut fds = [0; 2];
        if unsafe { sys_pipe2(fds.as_mut_ptr(), 0).is_ok() } {
            Stdio {
                inner: StdioType::Piped(fds[0], fds[1])
            }
        } else {
            Stdio::null()
        }
    }

    pub fn inherit() -> Stdio {
        Stdio {
            inner: StdioType::Inherit
        }
    }

    pub fn null() -> Stdio {
        Stdio {
            inner: StdioType::Null
        }
    }
}

impl FromRawFd for Stdio {
    unsafe fn from_raw_fd(fd: RawFd) -> Self {
        Stdio {
            inner: StdioType::Raw(fd)
        }
    }
}

pub fn exit(code: i32) -> ! {
    loop {
        let _ = sys_exit(code as usize);
    }
}
<|endoftext|>


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

use colours::{Plain, Style, Black, Red, Green, Yellow, Blue, Purple, Cyan};
use column::{Column, Permissions, FileName, FileSize, User, Group};
use format::{formatBinaryBytes, formatDecimalBytes};
use unix::{get_user_name, get_group_name};

// Each file is definitely going to get `stat`ted at least once, if
// only to determine what kind of file it is, so carry the `stat`
// result around with the file for safe keeping.
pub struct File<'a> {
    name: &'a str,
    path: &'a Path,
    stat: io::FileStat,
}

impl<'a> File<'a> {
    pub fn from_path(path: &'a Path) -> File<'a> {
        let filename: &str = path.filename_str().unwrap();

        // We have to use lstat here instad of file.stat(), as it
        // doesn't follow symbolic links. Otherwise, the stat() call
        // will fail if it encounters a link that's target is
        // non-existent.
        let stat: io::FileStat = match fs::lstat(path) {
            Ok(stat) => stat,
            Err(e) => fail!("Couldn't stat {}: {}", filename, e),
        };

        return File { path: path, stat: stat, name: filename };
    }

    pub fn is_dotfile(&self) -> bool {
        self.name.starts_with(".")
    }

    pub fn display(&self, column: &Column) -> ~str {
        match *column {
            Permissions => self.permissions(),
            FileName => self.file_colour().paint(self.name.to_owned()),
            FileSize(si) => self.file_size(si),
            User => get_user_name(self.stat.unstable.uid as i32).expect("???"),
            Group => get_group_name(self.stat.unstable.gid as u32).expect("???"),
        }
    }

    fn file_size(&self, si: bool) -> ~str {
        let sizeStr = if si {
            formatBinaryBytes(self.stat.size)
        } else {
            formatDecimalBytes(self.stat.size)
        };

        return if self.stat.kind == io::TypeDirectory {
            Green.normal()
        } else {
            Green.bold()
        }.paint(sizeStr);
    }

    fn type_char(&self) -> ~str {
        return match self.stat.kind {
            io::TypeFile => ".".to_owned(),
            io::TypeDirectory => Blue.paint("d"),
            io::TypeNamedPipe => Yellow.paint("|"),
            io::TypeBlockSpecial => Purple.paint("s"),
            io::TypeSymlink => Cyan.paint("l"),
            _ => "?".to_owned(),
        }
    }

    fn file_colour(&self) -> Style {
        if self.stat.kind == io::TypeDirectory {
            Blue.normal()
        } else if self.stat.perm.contains(io::UserExecute) {
            Green.normal()
        } else if self.name.ends_with("~") {
            Black.bold()
        } else {
            Plain
        }
    }

    fn permissions(&self) -> ~str {
        let bits = self.stat.perm;
        return format!("{}{}{}{}{}{}{}{}{}{}",
            self.type_char(),
            bit(bits, io::UserRead, "r", Yellow.bold()),
            bit(bits, io::UserWrite, "w", Red.bold()),
            bit(bits, io::UserExecute, "x", Green.bold().underline()),
            bit(bits, io::GroupRead, "r", Yellow.normal()),
            bit(bits, io::GroupWrite, "w", Red.normal()),
            bit(bits, io::GroupExecute, "x", Green.normal()),
            bit(bits, io::OtherRead, "r", Yellow.normal()),
            bit(bits, io::OtherWrite, "w", Red.normal()),
            bit(bits, io::OtherExecute, "x", Green.normal()),
       );
    }
}

fn bit(bits: io::FilePermission, bit: io::FilePermission, other: &'static str, style: Style) -> ~str {
    if bits.contains(bit) {
        style.paint(other.to_owned())
    } else {
        Black.bold().paint("-".to_owned())
    }
}
<commit_msg>Print numeric UIDs and GIDs if they don't map to anything<commit_after>use std::io::fs;
use std::io;

use colours::{Plain, Style, Black, Red, Green, Yellow, Blue, Purple, Cyan};
use column::{Column, Permissions, FileName, FileSize, User, Group};
use format::{formatBinaryBytes, formatDecimalBytes};
use unix::{get_user_name, get_group_name};

// Each file is definitely going to get `stat`ted at least once, if
// only to determine what kind of file it is, so carry the `stat`
// result around with the file for safe keeping.
pub struct File<'a> {
    name: &'a str,
    path: &'a Path,
    stat: io::FileStat,
}

impl<'a> File<'a> {
    pub fn from_path(path: &'a Path) -> File<'a> {
        let filename: &str = path.filename_str().unwrap();

        // We have to use lstat here instad of file.stat(), as it
        // doesn't follow symbolic links. Otherwise, the stat() call
        // will fail if it encounters a link that's target is
        // non-existent.
        let stat: io::FileStat = match fs::lstat(path) {
            Ok(stat) => stat,
            Err(e) => fail!("Couldn't stat {}: {}", filename, e),
        };

        return File { path: path, stat: stat, name: filename };
    }

    pub fn is_dotfile(&self) -> bool {
        self.name.starts_with(".")
    }

    pub fn display(&self, column: &Column) -> ~str {
        match *column {
            Permissions => self.permissions(),
            FileName => self.file_colour().paint(self.name.to_owned()),
            FileSize(si) => self.file_size(si),
            User => get_user_name(self.stat.unstable.uid as i32).unwrap_or(self.stat.unstable.uid.to_str()),
            Group => get_group_name(self.stat.unstable.gid as u32).unwrap_or(self.stat.unstable.gid.to_str()),
        }
    }

    fn file_size(&self, si: bool) -> ~str {
        let sizeStr = if si {
            formatBinaryBytes(self.stat.size)
        } else {
            formatDecimalBytes(self.stat.size)
        };

        return if self.stat.kind == io::TypeDirectory {
            Green.normal()
        } else {
            Green.bold()
        }.paint(sizeStr);
    }

    fn type_char(&self) -> ~str {
        return match self.stat.kind {
            io::TypeFile => ".".to_owned(),
            io::TypeDirectory => Blue.paint("d"),
            io::TypeNamedPipe => Yellow.paint("|"),
            io::TypeBlockSpecial => Purple.paint("s"),
            io::TypeSymlink => Cyan.paint("l"),
            _ => "?".to_owned(),
        }
    }

    fn file_colour(&self) -> Style {
        if self.stat.kind == io::TypeDirectory {
            Blue.normal()
        } else if self.stat.perm.contains(io::UserExecute) {
            Green.normal()
        } else if self.name.ends_with("~") {
            Black.bold()
        } else {
            Plain
        }
    }

    fn permissions(&self) -> ~str {
        let bits = self.stat.perm;
        return format!("{}{}{}{}{}{}{}{}{}{}",
            self.type_char(),
            bit(bits, io::UserRead, "r", Yellow.bold()),
            bit(bits, io::UserWrite, "w", Red.bold()),
            bit(bits, io::UserExecute, "x", Green.bold().underline()),
            bit(bits, io::GroupRead, "r", Yellow.normal()),
            bit(bits, io::GroupWrite, "w", Red.normal()),
            bit(bits, io::GroupExecute, "x", Green.normal()),
            bit(bits, io::OtherRead, "r", Yellow.normal()),
            bit(bits, io::OtherWrite, "w", Red.normal()),
            bit(bits, io::OtherExecute, "x", Green.normal()),
       );
    }
}

fn bit(bits: io::FilePermission, bit: io::FilePermission, other: &'static str, style: Style) -> ~str {
    if bits.contains(bit) {
        style.paint(other.to_owned())
    } else {
        Black.bold().paint("-".to_owned())
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A structure for holding a set of enum variants.
//!
//! This module defines a container which uses an efficient bit mask
//! representation to hold C-like enum variants.

#![unstable(feature = "enumset",
            reason = "matches collection reform specification, \
                      waiting for dust to settle",
            issue = "0")]

use core::marker;
use core::fmt;
use core::iter::{FromIterator, FusedIterator};
use core::ops::{Sub, BitOr, BitAnd, BitXor};

// FIXME(contentions): implement union family of methods? (general design may be
// wrong here)

/// A specialized set implementation to use enum types.
///
/// It is a logic error for an item to be modified in such a way that the
/// transformation of the item to or from a `usize`, as determined by the
/// `CLike` trait, changes while the item is in the set. This is normally only
/// possible through `Cell`, `RefCell`, global state, I/O, or unsafe code.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct EnumSet<E> {
    // We must maintain the invariant that no bits are set
    // for which no variant exists
    bits: usize,
    marker: marker::PhantomData<E>,
}

impl<E> Copy for EnumSet<E> {}

impl<E> Clone for EnumSet<E> {
    fn clone(&self) -> EnumSet<E> {
        *self
    }
}

impl<E: CLike + fmt::Debug> fmt::Debug for EnumSet<E> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_set().entries(self).finish()
    }
}

/// An interface for casting C-like enum to usize and back.
/// A typically implementation is as below.
///
/// ```{rust,ignore}
/// #[repr(usize)]
/// enum Foo {
///     A, B, C
/// }
///
/// impl CLike for Foo {
///     fn to_usize(&self) -> usize {
///         *self as usize
///     }
///
///     fn from_usize(v: usize) -> Foo {
///         unsafe { mem::transmute(v) }
///     }
/// }
/// ```
pub trait CLike {
    /// Converts a C-like enum to a `usize`.
    fn to_usize(&self) -> usize;
    /// Converts a `usize` to a C-like enum.
    fn from_usize(usize) -> Self;
}

fn bit<E: CLike>(e: &E) -> usize {
    use core::mem;
    let value = e.to_usize();
    let bits = mem::size_of::<usize>() * 8;
    assert!(value < bits,
            "EnumSet only supports up to {} variants.",
            bits - 1);
    1 << value
}

impl<E: CLike> EnumSet<E> {
    /// Returns an empty `EnumSet`.
    pub fn new() -> EnumSet<E> {
        EnumSet {
            bits: 0,
            marker: marker::PhantomData,
        }
    }

    /// Returns the number of elements in the given `EnumSet`.
    pub fn len(&self) -> usize {
        self.bits.count_ones() as usize
    }

    /// Returns true if the `EnumSet` is empty.
    pub fn is_empty(&self) -> bool {
        self.bits == 0
    }

    pub fn clear(&mut self) {
        self.bits = 0;
    }

    /// Returns `false` if the `EnumSet` contains any enum of the given `EnumSet`.
    pub fn is_disjoint(&self, other: &EnumSet<E>) -> bool {
        (self.bits & other.bits) == 0
    }

    /// Returns `true` if a given `EnumSet` is included in this `EnumSet`.
    pub fn is_superset(&self, other: &EnumSet<E>) -> bool {
        (self.bits & other.bits) == other.bits
    }

    /// Returns `true` if this `EnumSet` is included in the given `EnumSet`.
    pub fn is_subset(&self, other: &EnumSet<E>) -> bool {
        other.is_superset(self)
    }

    /// Returns the union of both `EnumSets`.
    pub fn union(&self, e: EnumSet<E>) -> EnumSet<E> {
        EnumSet {
            bits: self.bits | e.bits,
            marker: marker::PhantomData,
        }
    }

    /// Returns the intersection of both `EnumSets`.
    pub fn intersection(&self, e: EnumSet<E>) -> EnumSet<E> {
        EnumSet {
            bits: self.bits & e.bits,
            marker: marker::PhantomData,
        }
    }

    /// Adds an enum to the `EnumSet`, and returns `true` if it wasn't there before
    pub fn insert(&mut self, e: E) -> bool {
        let result = !self.contains(&e);
        self.bits |= bit(&e);
        result
    }

    /// Removes an enum from the EnumSet
    pub fn remove(&mut self, e: &E) -> bool {
        let result = self.contains(e);
        self.bits &= !bit(e);
        result
    }

    /// Returns `true` if an `EnumSet` contains a given enum.
    pub fn contains(&self, e: &E) -> bool {
        (self.bits & bit(e)) != 0
    }

    /// Returns an iterator over an `EnumSet`.
    pub fn iter(&self) -> Iter<E> {
        Iter::new(self.bits)
    }
}

impl<E: CLike> Sub for EnumSet<E> {
    type Output = EnumSet<E>;

    fn sub(self, e: EnumSet<E>) -> EnumSet<E> {
        EnumSet {
            bits: self.bits & !e.bits,
            marker: marker::PhantomData,
        }
    }
}

impl<E: CLike> BitOr for EnumSet<E> {
    type Output = EnumSet<E>;

    fn bitor(self, e: EnumSet<E>) -> EnumSet<E> {
        EnumSet {
            bits: self.bits | e.bits,
            marker: marker::PhantomData,
        }
    }
}

impl<E: CLike> BitAnd for EnumSet<E> {
    type Output = EnumSet<E>;

    fn bitand(self, e: EnumSet<E>) -> EnumSet<E> {
        EnumSet {
            bits: self.bits & e.bits,
            marker: marker::PhantomData,
        }
    }
}

impl<E: CLike> BitXor for EnumSet<E> {
    type Output = EnumSet<E>;

    fn bitxor(self, e: EnumSet<E>) -> EnumSet<E> {
        EnumSet {
            bits: self.bits ^ e.bits,
            marker: marker::PhantomData,
        }
    }
}

/// An iterator over an EnumSet
pub struct Iter<E> {
    index: usize,
    bits: usize,
    marker: marker::PhantomData<E>,
}

// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
impl<E> Clone for Iter<E> {
    fn clone(&self) -> Iter<E> {
        Iter {
            index: self.index,
            bits: self.bits,
            marker: marker::PhantomData,
        }
    }
}

impl<E: CLike> Iter<E> {
    fn new(bits: usize) -> Iter<E> {
        Iter {
            index: 0,
            bits: bits,
            marker: marker::PhantomData,
        }
    }
}

impl<E: CLike> Iterator for Iter<E> {
    type Item = E;

    fn next(&mut self) -> Option<E> {
        if self.bits == 0 {
            return None;
        }

        while (self.bits & 1) == 0 {
            self.index += 1;
            self.bits >>= 1;
        }
        let elem = CLike::from_usize(self.index);
        self.index += 1;
        self.bits >>= 1;
        Some(elem)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = self.bits.count_ones() as usize;
        (exact, Some(exact))
    }
}

#[unstable(feature = "fused", issue = "35602")]
impl<E: CLike> FusedIterator for Iter<E> {}

impl<E: CLike> FromIterator<E> for EnumSet<E> {
    fn from_iter<I: IntoIterator<Item = E>>(iter: I) -> EnumSet<E> {
        let mut ret = EnumSet::new();
        ret.extend(iter);
        ret
    }
}

impl<'a, E> IntoIterator for &'a EnumSet<E> where E: CLike
{
    type Item = E;
    type IntoIter = Iter<E>;

    fn into_iter(self) -> Iter<E> {
        self.iter()
    }
}

impl<E: CLike> Extend<E> for EnumSet<E> {
    fn extend<I: IntoIterator<Item = E>>(&mut self, iter: I) {
        for element in iter {
            self.insert(element);
        }
    }
}

impl<'a, E: 'a + CLike + Copy> Extend<&'a E> for EnumSet<E> {
    fn extend<I: IntoIterator<Item = &'a E>>(&mut self, iter: I) {
        self.extend(iter.into_iter().cloned());
    }
}
<commit_msg>Rollup merge of #37967 - sfackler:enumset-issue, r=sfackler<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A structure for holding a set of enum variants.
//!
//! This module defines a container which uses an efficient bit mask
//! representation to hold C-like enum variants.

#![unstable(feature = "enumset",
            reason = "matches collection reform specification, \
                      waiting for dust to settle",
            issue = "37966")]

use core::marker;
use core::fmt;
use core::iter::{FromIterator, FusedIterator};
use core::ops::{Sub, BitOr, BitAnd, BitXor};

// FIXME(contentions): implement union family of methods? (general design may be
// wrong here)

/// A specialized set implementation to use enum types.
///
/// It is a logic error for an item to be modified in such a way that the
/// transformation of the item to or from a `usize`, as determined by the
/// `CLike` trait, changes while the item is in the set. This is normally only
/// possible through `Cell`, `RefCell`, global state, I/O, or unsafe code.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct EnumSet<E> {
    // We must maintain the invariant that no bits are set
    // for which no variant exists
    bits: usize,
    marker: marker::PhantomData<E>,
}

impl<E> Copy for EnumSet<E> {}

impl<E> Clone for EnumSet<E> {
    fn clone(&self) -> EnumSet<E> {
        *self
    }
}

impl<E: CLike + fmt::Debug> fmt::Debug for EnumSet<E> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_set().entries(self).finish()
    }
}

/// An interface for casting C-like enum to usize and back.
/// A typically implementation is as below.
///
/// ```{rust,ignore}
/// #[repr(usize)]
/// enum Foo {
///     A, B, C
/// }
///
/// impl CLike for Foo {
///     fn to_usize(&self) -> usize {
///         *self as usize
///     }
///
///     fn from_usize(v: usize) -> Foo {
///         unsafe { mem::transmute(v) }
///     }
/// }
/// ```
pub trait CLike {
    /// Converts a C-like enum to a `usize`.
    fn to_usize(&self) -> usize;
    /// Converts a `usize` to a C-like enum.
    fn from_usize(usize) -> Self;
}

fn bit<E: CLike>(e: &E) -> usize {
    use core::mem;
    let value = e.to_usize();
    let bits = mem::size_of::<usize>() * 8;
    assert!(value < bits,
            "EnumSet only supports up to {} variants.",
            bits - 1);
    1 << value
}

impl<E: CLike> EnumSet<E> {
    /// Returns an empty `EnumSet`.
    pub fn new() -> EnumSet<E> {
        EnumSet {
            bits: 0,
            marker: marker::PhantomData,
        }
    }

    /// Returns the number of elements in the given `EnumSet`.
    pub fn len(&self) -> usize {
        self.bits.count_ones() as usize
    }

    /// Returns true if the `EnumSet` is empty.
    pub fn is_empty(&self) -> bool {
        self.bits == 0
    }

    pub fn clear(&mut self) {
        self.bits = 0;
    }

    /// Returns `false` if the `EnumSet` contains any enum of the given `EnumSet`.
    pub fn is_disjoint(&self, other: &EnumSet<E>) -> bool {
        (self.bits & other.bits) == 0
    }

    /// Returns `true` if a given `EnumSet` is included in this `EnumSet`.
    pub fn is_superset(&self, other: &EnumSet<E>) -> bool {
        (self.bits & other.bits) == other.bits
    }

    /// Returns `true` if this `EnumSet` is included in the given `EnumSet`.
    pub fn is_subset(&self, other: &EnumSet<E>) -> bool {
        other.is_superset(self)
    }

    /// Returns the union of both `EnumSets`.
    pub fn union(&self, e: EnumSet<E>) -> EnumSet<E> {
        EnumSet {
            bits: self.bits | e.bits,
            marker: marker::PhantomData,
        }
    }

    /// Returns the intersection of both `EnumSets`.
    pub fn intersection(&self, e: EnumSet<E>) -> EnumSet<E> {
        EnumSet {
            bits: self.bits & e.bits,
            marker: marker::PhantomData,
        }
    }

    /// Adds an enum to the `EnumSet`, and returns `true` if it wasn't there before
    pub fn insert(&mut self, e: E) -> bool {
        let result = !self.contains(&e);
        self.bits |= bit(&e);
        result
    }

    /// Removes an enum from the EnumSet
    pub fn remove(&mut self, e: &E) -> bool {
        let result = self.contains(e);
        self.bits &= !bit(e);
        result
    }

    /// Returns `true` if an `EnumSet` contains a given enum.
    pub fn contains(&self, e: &E) -> bool {
        (self.bits & bit(e)) != 0
    }

    /// Returns an iterator over an `EnumSet`.
    pub fn iter(&self) -> Iter<E> {
        Iter::new(self.bits)
    }
}

impl<E: CLike> Sub for EnumSet<E> {
    type Output = EnumSet<E>;

    fn sub(self, e: EnumSet<E>) -> EnumSet<E> {
        EnumSet {
            bits: self.bits & !e.bits,
            marker: marker::PhantomData,
        }
    }
}

impl<E: CLike> BitOr for EnumSet<E> {
    type Output = EnumSet<E>;

    fn bitor(self, e: EnumSet<E>) -> EnumSet<E> {
        EnumSet {
            bits: self.bits | e.bits,
            marker: marker::PhantomData,
        }
    }
}

impl<E: CLike> BitAnd for EnumSet<E> {
    type Output = EnumSet<E>;

    fn bitand(self, e: EnumSet<E>) -> EnumSet<E> {
        EnumSet {
            bits: self.bits & e.bits,
            marker: marker::PhantomData,
        }
    }
}

impl<E: CLike> BitXor for EnumSet<E> {
    type Output = EnumSet<E>;

    fn bitxor(self, e: EnumSet<E>) -> EnumSet<E> {
        EnumSet {
            bits: self.bits ^ e.bits,
            marker: marker::PhantomData,
        }
    }
}

/// An iterator over an EnumSet
pub struct Iter<E> {
    index: usize,
    bits: usize,
    marker: marker::PhantomData<E>,
}

// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
impl<E> Clone for Iter<E> {
    fn clone(&self) -> Iter<E> {
        Iter {
            index: self.index,
            bits: self.bits,
            marker: marker::PhantomData,
        }
    }
}

impl<E: CLike> Iter<E> {
    fn new(bits: usize) -> Iter<E> {
        Iter {
            index: 0,
            bits: bits,
            marker: marker::PhantomData,
        }
    }
}

impl<E: CLike> Iterator for Iter<E> {
    type Item = E;

    fn next(&mut self) -> Option<E> {
        if self.bits == 0 {
            return None;
        }

        while (self.bits & 1) == 0 {
            self.index += 1;
            self.bits >>= 1;
        }
        let elem = CLike::from_usize(self.index);
        self.index += 1;
        self.bits >>= 1;
        Some(elem)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = self.bits.count_ones() as usize;
        (exact, Some(exact))
    }
}

#[unstable(feature = "fused", issue = "35602")]
impl<E: CLike> FusedIterator for Iter<E> {}

impl<E: CLike> FromIterator<E> for EnumSet<E> {
    fn from_iter<I: IntoIterator<Item = E>>(iter: I) -> EnumSet<E> {
        let mut ret = EnumSet::new();
        ret.extend(iter);
        ret
    }
}

impl<'a, E> IntoIterator for &'a EnumSet<E> where E: CLike
{
    type Item = E;
    type IntoIter = Iter<E>;

    fn into_iter(self) -> Iter<E> {
        self.iter()
    }
}

impl<E: CLike> Extend<E> for EnumSet<E> {
    fn extend<I: IntoIterator<Item = E>>(&mut self, iter: I) {
        for element in iter {
            self.insert(element);
        }
    }
}

impl<'a, E: 'a + CLike + Copy> Extend<&'a E> for EnumSet<E> {
    fn extend<I: IntoIterator<Item = &'a E>>(&mut self, iter: I) {
        self.extend(iter.into_iter().cloned());
    }
}
<|endoftext|>


<commit_before><commit_msg>Add an FXAA example<commit_after>#[macro_use]
extern crate glium;

use glium::Surface;
use glium::glutin;

mod support;

mod fxaa {
    use glium::{self, Surface};
    use glium::backend::Facade;
    use glium::backend::Context;
    use glium::framebuffer::SimpleFrameBuffer;
    use glium::Texture;

    use std::cell::RefCell;
    use std::rc::Rc;

    pub struct FxaaSystem {
        context: Rc<Context>,
        vertex_buffer: glium::VertexBuffer<SpriteVertex>,
        index_buffer: glium::IndexBuffer<u16>,
        program: glium::Program,
        target_color: RefCell<Option<glium::texture::Texture2d>>,
        target_depth: RefCell<Option<glium::framebuffer::DepthRenderBuffer>>,
    }

    #[derive(Copy, Clone)]
    struct SpriteVertex {
        position: [f32; 2],
        i_tex_coords: [f32; 2],
    }

    implement_vertex!(SpriteVertex, position, i_tex_coords);

    impl FxaaSystem {
        pub fn new<F>(facade: &F) -> FxaaSystem where F: Facade + Clone {
            FxaaSystem {
                context: facade.get_context().clone(),

                vertex_buffer: glium::VertexBuffer::new(facade,
                    vec![
                        SpriteVertex { position: [-1.0, -1.0], i_tex_coords: [0.0, 0.0] },
                        SpriteVertex { position: [-1.0,  1.0], i_tex_coords: [0.0, 1.0] },
                        SpriteVertex { position: [ 1.0,  1.0], i_tex_coords: [1.0, 1.0] },
                        SpriteVertex { position: [ 1.0, -1.0], i_tex_coords: [1.0, 0.0] }
                    ]
                ),

                index_buffer: glium::index::IndexBuffer::new(facade,
                    glium::index::PrimitiveType::TriangleStrip, vec![1 as u16, 2, 0, 3]),

                program: program!(facade,
                    100 => {
                        vertex: r"
                            #version 100

                            attribute vec2 position;
                            attribute vec2 i_tex_coords;

                            varying vec2 v_tex_coords;

                            void main() {
                                gl_Position = vec4(position, 0.0, 1.0);
                                v_tex_coords = i_tex_coords;
                            }
                        ",
                        fragment: r"
                            #version 100

                            precision mediump float;

                            uniform vec2 resolution;
                            uniform sampler2D tex;
                            uniform int enabled;

                            varying vec2 v_tex_coords;

                            #define FXAA_REDUCE_MIN   (1.0/ 128.0)
                            #define FXAA_REDUCE_MUL   (1.0 / 8.0)
                            #define FXAA_SPAN_MAX     8.0

                            vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution,
                                        vec2 v_rgbNW, vec2 v_rgbNE,
                                        vec2 v_rgbSW, vec2 v_rgbSE,
                                        vec2 v_rgbM) {
                                vec4 color;
                                mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y);
                                vec3 rgbNW = texture2D(tex, v_rgbNW).xyz;
                                vec3 rgbNE = texture2D(tex, v_rgbNE).xyz;
                                vec3 rgbSW = texture2D(tex, v_rgbSW).xyz;
                                vec3 rgbSE = texture2D(tex, v_rgbSE).xyz;
                                vec4 texColor = texture2D(tex, v_rgbM);
                                vec3 rgbM  = texColor.xyz;
                                vec3 luma = vec3(0.299, 0.587, 0.114);
                                float lumaNW = dot(rgbNW, luma);
                                float lumaNE = dot(rgbNE, luma);
                                float lumaSW = dot(rgbSW, luma);
                                float lumaSE = dot(rgbSE, luma);
                                float lumaM  = dot(rgbM,  luma);
                                float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
                                float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));

                                mediump vec2 dir;
                                dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
                                dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));

                                float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
                                                      (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);

                                float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
                                dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
                                          max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
                                          dir * rcpDirMin)) * inverseVP;

                                vec3 rgbA = 0.5 * (
                                    texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +
                                    texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);
                                vec3 rgbB = rgbA * 0.5 + 0.25 * (
                                    texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz +
                                    texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz);

                                float lumaB = dot(rgbB, luma);
                                if ((lumaB < lumaMin) || (lumaB > lumaMax))
                                    color = vec4(rgbA, texColor.a);
                                else
                                    color = vec4(rgbB, texColor.a);
                                return color;
                            }

                            void main() {
                                vec2 fragCoord = v_tex_coords * resolution;
                                vec4 color;
                                if (enabled != 0) {
                                    vec2 inverseVP = 1.0 / resolution.xy;
                                    mediump vec2 v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP;
                                    mediump vec2 v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP;
                                    mediump vec2 v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP;
                                    mediump vec2 v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP;
                                    mediump vec2 v_rgbM = vec2(fragCoord * inverseVP);
                                    color = fxaa(tex, fragCoord, resolution, v_rgbNW, v_rgbNE, v_rgbSW,
                                                 v_rgbSE, v_rgbM);
                                } else {
                                    color = texture2D(tex, v_tex_coords);
                                }
                                gl_FragColor = color;
                            }
                        "
                    }
                ).unwrap(),

                target_color: RefCell::new(None),
                target_depth: RefCell::new(None),
            }
        }
    }

    pub fn draw<T, F, R>(system: &FxaaSystem, target: &mut T, enabled: bool, mut draw: F)
                         -> R where T: Surface, F: FnMut(&mut SimpleFrameBuffer) -> R
    {
        let target_dimensions = target.get_dimensions();

        let mut target_color = system.target_color.borrow_mut();
        let mut target_depth = system.target_depth.borrow_mut();

        {
            let clear = if let &Some(ref tex) = &*target_color {
                tex.get_width() != target_dimensions.0 ||
                    tex.get_height().unwrap() != target_dimensions.1
            } else {
                false
            };
            if clear { *target_color = None; }
        }

        {
            let clear = if let &Some(ref tex) = &*target_depth {
                tex.get_dimensions() != target_dimensions
            } else {
                false
            };
            if clear { *target_depth = None; }
        }

        if target_color.is_none() {
            let texture = glium::texture::Texture2d::empty(&system.context,
                                                           target_dimensions.0 as u32,
                                                           target_dimensions.1 as u32);
            *target_color = Some(texture);
        }
        let target_color = target_color.as_ref().unwrap();

        if target_depth.is_none() {
            let texture = glium::framebuffer::DepthRenderBuffer::new(&system.context,
                                                                      glium::texture::DepthFormat::I24,
                                                                      target_dimensions.0 as u32,
                                                                      target_dimensions.1 as u32);
            *target_depth = Some(texture);
        }
        let target_depth = target_depth.as_ref().unwrap();

        let output = draw(&mut SimpleFrameBuffer::with_depth_buffer(&system.context, target_color,
                                                                                target_depth));

        let uniforms = uniform! {
            tex: &*target_color,
            enabled: if enabled { 1i32 } else { 0i32 },
            resolution: (target_dimensions.0 as f32, target_dimensions.1 as f32)
        };

        target.draw(&system.vertex_buffer, &system.index_buffer, &system.program, &uniforms,
                    &Default::default()).unwrap();

        output
    }
}

fn main() {
    use glium::DisplayBuild;

    println!("This example demonstrates FXAA. Is is an anti-aliasing technique done at the \
              post-processing stage. This example draws the teapot to a framebuffer and then \
              copies from the texture to the main framebuffer by applying a filter to it.\n\
              You can use the space bar to switch fxaa on and off.");

    // building the display, ie. the main object
    let display = glutin::WindowBuilder::new()
        .with_depth_buffer(24)
        .build_glium()
        .unwrap();

    // building the vertex and index buffers
    let vertex_buffer = support::load_wavefront(&display, include_bytes!("support/teapot.obj"));

    // the program
    let program = program!(&display,
        140 => {
            vertex: "
                #version 140

                uniform mat4 persp_matrix;
                uniform mat4 view_matrix;

                in vec3 position;
                in vec3 normal;
                out vec3 v_position;
                out vec3 v_normal;

                void main() {
                    v_position = position;
                    v_normal = normal;
                    gl_Position = persp_matrix * view_matrix * vec4(v_position * 0.005, 1.0);
                }
            ",

            fragment: "
                #version 140

                in vec3 v_normal;
                out vec4 f_color;

                const vec3 LIGHT = vec3(-0.2, 0.8, 0.1);

                void main() {
                    float lum = max(dot(normalize(v_normal), normalize(LIGHT)), 0.0);
                    vec3 color = (0.3 + 0.7 * lum) * vec3(1.0, 1.0, 1.0);
                    f_color = vec4(color, 1.0);
                }
            ",
        },

        110 => {
            vertex: "
                #version 110

                uniform mat4 persp_matrix;
                uniform mat4 view_matrix;

                attribute vec3 position;
                attribute vec3 normal;
                varying vec3 v_position;
                varying vec3 v_normal;

                void main() {
                    v_position = position;
                    v_normal = normal;
                    gl_Position = persp_matrix * view_matrix * vec4(v_position * 0.005, 1.0);
                }
            ",

            fragment: "
                #version 110

                varying vec3 v_normal;

                const vec3 LIGHT = vec3(-0.2, 0.8, 0.1);

                void main() {
                    float lum = max(dot(normalize(v_normal), normalize(LIGHT)), 0.0);
                    vec3 color = (0.3 + 0.7 * lum) * vec3(1.0, 1.0, 1.0);
                    gl_FragColor = vec4(color, 1.0);
                }
            ",
        },

        100 => {
            vertex: "
                #version 100

                uniform lowp mat4 persp_matrix;
                uniform lowp mat4 view_matrix;

                attribute lowp vec3 position;
                attribute lowp vec3 normal;
                varying lowp vec3 v_position;
                varying lowp vec3 v_normal;

                void main() {
                    v_position = position;
                    v_normal = normal;
                    gl_Position = persp_matrix * view_matrix * vec4(v_position * 0.005, 1.0);
                }
            ",

            fragment: "
                #version 100

                varying lowp vec3 v_normal;

                const lowp vec3 LIGHT = vec3(-0.2, 0.8, 0.1);

                void main() {
                    lowp float lum = max(dot(normalize(v_normal), normalize(LIGHT)), 0.0);
                    lowp vec3 color = (0.3 + 0.7 * lum) * vec3(1.0, 1.0, 1.0);
                    gl_FragColor = vec4(color, 1.0);
                }
            ",
        },
    ).unwrap();

    //
    let mut camera = support::camera::CameraState::new();
    let fxaa = fxaa::FxaaSystem::new(&display);
    let mut fxaa_enabled = true;

    // the main loop
    support::start_loop(|| {
        camera.update();

        // building the uniforms
        let uniforms = uniform! {
            persp_matrix: camera.get_perspective(),
            view_matrix: camera.get_view(),
        };

        // draw parameters
        let params = glium::DrawParameters {
            depth_test: glium::DepthTest::IfLess,
            depth_write: true,
            .. Default::default()
        };

        // drawing a frame
        let mut target = display.draw();
        fxaa::draw(&fxaa, &mut target, fxaa_enabled, |target| {
            target.clear_color_and_depth((0.0, 0.0, 0.0, 0.0), 1.0);
            target.draw(&vertex_buffer,
                        &glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList),
                        &program, &uniforms, &params).unwrap();
        });
        target.finish().unwrap();

        // polling and handling the events received by the window
        for event in display.poll_events() {
            match event {
                glutin::Event::Closed => return support::Action::Stop,
                glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::Space)) => {
                    fxaa_enabled = !fxaa_enabled;
                    println!("FXAA is now {}", if fxaa_enabled { "enabled" } else { "disabled" });
                },
                ev => camera.process_input(&ev),
            }
        }

        support::Action::Continue
    });
}
<|endoftext|>


<commit_before><commit_msg>Revert "Revert "Add a test case for #898. Closes #898.""<commit_after>fn even(&&e: int) -> bool {
    e % 2 == 0
}

fn log_if<T>(c: fn(T)->bool, e: T) {
    if c(e) { log e; }
}

fn main() {
    (bind log_if(even, _))(2);
}
<|endoftext|>