<commit_before>extern crate serialize;

use std::num::strconv;
use std::collections::TreeMap;
use self::serialize::json;

use {Parser, Value, Table, String, Integer, Float, Boolean, Datetime, Array};

fn to_json(toml: Value) -> json::Json {
    fn doit(s: &str, json: json::Json) -> json::Json {
        let mut map = TreeMap::new();
        map.insert("type".to_string(), json::String(s.to_string()));
        map.insert("value".to_string(), json);
        json::Object(map)
    }
    match toml {
        String(s) => doit("string", json::String(s)),
        Integer(i) => doit("integer", json::String(i.to_string())),
        Float(f) => doit("float", json::String({
            let (bytes, _) =
                strconv::float_to_str_bytes_common(f, 10, true,
                                                   strconv::SignNeg,
                                                   strconv::DigMax(15),
                                                   strconv::ExpNone,
                                                   false);
            let s = String::from_utf8(bytes).unwrap();
            if s.as_slice().contains(".") {s} else {format!("{}.0", s)}
        })),
        Boolean(b) => doit("bool", json::String(b.to_string())),
        Datetime(s) => doit("datetime", json::String(s)),
        Array(arr) => {
            let is_table = match arr.as_slice().head() {
                Some(&Table(..)) => true,
                _ => false,
            };
            let json = json::List(arr.move_iter().map(to_json).collect());
            if is_table {json} else {doit("array", json)}
        }
        Table(table) => json::Object(table.move_iter().map(|(k, v)| {
            (k, to_json(v))
        }).collect()),
    }
}

fn run(toml: &str, json: &str) {
    let mut p = Parser::new(toml);
    let table = p.parse();
    assert!(p.errors.len() == 0, "had_errors: {}",
            p.errors.iter().map(|e| {
                (e.desc.clone(), toml.slice(e.lo - 5, e.hi + 5))
            }).collect::<Vec<(String, &str)>>());
    assert!(table.is_some());
    let table = table.unwrap();

    let json = json::from_str(json).unwrap();
    let toml_json = to_json(Table(table));
    assert!(json == toml_json,
            "expected\n{}\ngot\n{}\n",
            json.to_pretty_str(),
            toml_json.to_pretty_str());
}

macro_rules! test( ($name:ident, $toml:expr, $json:expr) => (
    #[test]
    fn $name() { run($toml, $json); }
) )

test!(array_empty,
       include_str!("valid/array-empty.toml"),
       include_str!("valid/array-empty.json"))
test!(array_nospaces,
       include_str!("valid/array-nospaces.toml"),
       include_str!("valid/array-nospaces.json"))
test!(arrays_hetergeneous,
       include_str!("valid/arrays-hetergeneous.toml"),
       include_str!("valid/arrays-hetergeneous.json"))
test!(arrays,
       include_str!("valid/arrays.toml"),
       include_str!("valid/arrays.json"))
test!(arrays_nested,
       include_str!("valid/arrays-nested.toml"),
       include_str!("valid/arrays-nested.json"))
test!(empty,
       include_str!("valid/empty.toml"),
       include_str!("valid/empty.json"))
test!(bool,
       include_str!("valid/bool.toml"),
       include_str!("valid/bool.json"))
test!(datetime,
       include_str!("valid/datetime.toml"),
       include_str!("valid/datetime.json"))
test!(example,
       include_str!("valid/example.toml"),
       include_str!("valid/example.json"))
test!(float,
       include_str!("valid/float.toml"),
       include_str!("valid/float.json"))
test!(implicit_and_explicit_after,
       include_str!("valid/implicit-and-explicit-after.toml"),
       include_str!("valid/implicit-and-explicit-after.json"))
test!(implicit_and_explicit_before,
       include_str!("valid/implicit-and-explicit-before.toml"),
       include_str!("valid/implicit-and-explicit-before.json"))
test!(implicit_groups,
       include_str!("valid/implicit-groups.toml"),
       include_str!("valid/implicit-groups.json"))
test!(integer,
       include_str!("valid/integer.toml"),
       include_str!("valid/integer.json"))
test!(key_equals_nospace,
       include_str!("valid/key-equals-nospace.toml"),
       include_str!("valid/key-equals-nospace.json"))
test!(key_special_chars,
       include_str!("valid/key-special-chars.toml"),
       include_str!("valid/key-special-chars.json"))
test!(key_with_pound,
       include_str!("valid/key-with-pound.toml"),
       include_str!("valid/key-with-pound.json"))
test!(long_float,
       include_str!("valid/long-float.toml"),
       include_str!("valid/long-float.json"))
test!(long_integer,
       include_str!("valid/long-integer.toml"),
       include_str!("valid/long-integer.json"))
test!(string_empty,
       include_str!("valid/string-empty.toml"),
       include_str!("valid/string-empty.json"))
test!(string_escapes,
       include_str!("valid/string-escapes.toml"),
       include_str!("valid/string-escapes.json"))
test!(string_simple,
       include_str!("valid/string-simple.toml"),
       include_str!("valid/string-simple.json"))
test!(string_with_pound,
       include_str!("valid/string-with-pound.toml"),
       include_str!("valid/string-with-pound.json"))
test!(table_array_implicit,
       include_str!("valid/table-array-implicit.toml"),
       include_str!("valid/table-array-implicit.json"))
test!(table_array_many,
       include_str!("valid/table-array-many.toml"),
       include_str!("valid/table-array-many.json"))
test!(table_array_nest,
       include_str!("valid/table-array-nest.toml"),
       include_str!("valid/table-array-nest.json"))
test!(table_array_one,
       include_str!("valid/table-array-one.toml"),
       include_str!("valid/table-array-one.json"))
test!(table_empty,
       include_str!("valid/table-empty.toml"),
       include_str!("valid/table-empty.json"))
test!(table_sub_empty,
       include_str!("valid/table-sub-empty.toml"),
       include_str!("valid/table-sub-empty.json"))
test!(table_whitespace,
       include_str!("valid/table-whitespace.toml"),
       include_str!("valid/table-whitespace.json"))
test!(table_with_pound,
       include_str!("valid/table-with-pound.toml"),
       include_str!("valid/table-with-pound.json"))
test!(unicode_escape,
       include_str!("valid/unicode-escape.toml"),
       include_str!("valid/unicode-escape.json"))
test!(unicode_literal,
       include_str!("valid/unicode-literal.toml"),
       include_str!("valid/unicode-literal.json"))
<commit_msg>Update uses of move_iter() to into_iter()<commit_after>extern crate serialize;

use std::num::strconv;
use std::collections::TreeMap;
use self::serialize::json;

use {Parser, Value, Table, String, Integer, Float, Boolean, Datetime, Array};

fn to_json(toml: Value) -> json::Json {
    fn doit(s: &str, json: json::Json) -> json::Json {
        let mut map = TreeMap::new();
        map.insert("type".to_string(), json::String(s.to_string()));
        map.insert("value".to_string(), json);
        json::Object(map)
    }
    match toml {
        String(s) => doit("string", json::String(s)),
        Integer(i) => doit("integer", json::String(i.to_string())),
        Float(f) => doit("float", json::String({
            let (bytes, _) =
                strconv::float_to_str_bytes_common(f, 10, true,
                                                   strconv::SignNeg,
                                                   strconv::DigMax(15),
                                                   strconv::ExpNone,
                                                   false);
            let s = String::from_utf8(bytes).unwrap();
            if s.as_slice().contains(".") {s} else {format!("{}.0", s)}
        })),
        Boolean(b) => doit("bool", json::String(b.to_string())),
        Datetime(s) => doit("datetime", json::String(s)),
        Array(arr) => {
            let is_table = match arr.as_slice().head() {
                Some(&Table(..)) => true,
                _ => false,
            };
            let json = json::List(arr.into_iter().map(to_json).collect());
            if is_table {json} else {doit("array", json)}
        }
        Table(table) => json::Object(table.into_iter().map(|(k, v)| {
            (k, to_json(v))
        }).collect()),
    }
}

fn run(toml: &str, json: &str) {
    let mut p = Parser::new(toml);
    let table = p.parse();
    assert!(p.errors.len() == 0, "had_errors: {}",
            p.errors.iter().map(|e| {
                (e.desc.clone(), toml.slice(e.lo - 5, e.hi + 5))
            }).collect::<Vec<(String, &str)>>());
    assert!(table.is_some());
    let table = table.unwrap();

    let json = json::from_str(json).unwrap();
    let toml_json = to_json(Table(table));
    assert!(json == toml_json,
            "expected\n{}\ngot\n{}\n",
            json.to_pretty_str(),
            toml_json.to_pretty_str());
}

macro_rules! test( ($name:ident, $toml:expr, $json:expr) => (
    #[test]
    fn $name() { run($toml, $json); }
) )

test!(array_empty,
       include_str!("valid/array-empty.toml"),
       include_str!("valid/array-empty.json"))
test!(array_nospaces,
       include_str!("valid/array-nospaces.toml"),
       include_str!("valid/array-nospaces.json"))
test!(arrays_hetergeneous,
       include_str!("valid/arrays-hetergeneous.toml"),
       include_str!("valid/arrays-hetergeneous.json"))
test!(arrays,
       include_str!("valid/arrays.toml"),
       include_str!("valid/arrays.json"))
test!(arrays_nested,
       include_str!("valid/arrays-nested.toml"),
       include_str!("valid/arrays-nested.json"))
test!(empty,
       include_str!("valid/empty.toml"),
       include_str!("valid/empty.json"))
test!(bool,
       include_str!("valid/bool.toml"),
       include_str!("valid/bool.json"))
test!(datetime,
       include_str!("valid/datetime.toml"),
       include_str!("valid/datetime.json"))
test!(example,
       include_str!("valid/example.toml"),
       include_str!("valid/example.json"))
test!(float,
       include_str!("valid/float.toml"),
       include_str!("valid/float.json"))
test!(implicit_and_explicit_after,
       include_str!("valid/implicit-and-explicit-after.toml"),
       include_str!("valid/implicit-and-explicit-after.json"))
test!(implicit_and_explicit_before,
       include_str!("valid/implicit-and-explicit-before.toml"),
       include_str!("valid/implicit-and-explicit-before.json"))
test!(implicit_groups,
       include_str!("valid/implicit-groups.toml"),
       include_str!("valid/implicit-groups.json"))
test!(integer,
       include_str!("valid/integer.toml"),
       include_str!("valid/integer.json"))
test!(key_equals_nospace,
       include_str!("valid/key-equals-nospace.toml"),
       include_str!("valid/key-equals-nospace.json"))
test!(key_special_chars,
       include_str!("valid/key-special-chars.toml"),
       include_str!("valid/key-special-chars.json"))
test!(key_with_pound,
       include_str!("valid/key-with-pound.toml"),
       include_str!("valid/key-with-pound.json"))
test!(long_float,
       include_str!("valid/long-float.toml"),
       include_str!("valid/long-float.json"))
test!(long_integer,
       include_str!("valid/long-integer.toml"),
       include_str!("valid/long-integer.json"))
test!(string_empty,
       include_str!("valid/string-empty.toml"),
       include_str!("valid/string-empty.json"))
test!(string_escapes,
       include_str!("valid/string-escapes.toml"),
       include_str!("valid/string-escapes.json"))
test!(string_simple,
       include_str!("valid/string-simple.toml"),
       include_str!("valid/string-simple.json"))
test!(string_with_pound,
       include_str!("valid/string-with-pound.toml"),
       include_str!("valid/string-with-pound.json"))
test!(table_array_implicit,
       include_str!("valid/table-array-implicit.toml"),
       include_str!("valid/table-array-implicit.json"))
test!(table_array_many,
       include_str!("valid/table-array-many.toml"),
       include_str!("valid/table-array-many.json"))
test!(table_array_nest,
       include_str!("valid/table-array-nest.toml"),
       include_str!("valid/table-array-nest.json"))
test!(table_array_one,
       include_str!("valid/table-array-one.toml"),
       include_str!("valid/table-array-one.json"))
test!(table_empty,
       include_str!("valid/table-empty.toml"),
       include_str!("valid/table-empty.json"))
test!(table_sub_empty,
       include_str!("valid/table-sub-empty.toml"),
       include_str!("valid/table-sub-empty.json"))
test!(table_whitespace,
       include_str!("valid/table-whitespace.toml"),
       include_str!("valid/table-whitespace.json"))
test!(table_with_pound,
       include_str!("valid/table-with-pound.toml"),
       include_str!("valid/table-with-pound.json"))
test!(unicode_escape,
       include_str!("valid/unicode-escape.toml"),
       include_str!("valid/unicode-escape.json"))
test!(unicode_literal,
       include_str!("valid/unicode-literal.toml"),
       include_str!("valid/unicode-literal.json"))
<|endoftext|>


<commit_before>pub const MASK_OUT_X_EA: u32 = 0b1111_0001_1100_0000; // masks out X and Y register bits, plus mode (????xxx???mmmyyy)
pub const MASK_OUT_EA: u32 = 0b1111111111000000;   // masks out Y register bits, plus mode (??????????mmmyyy)

pub const EA_DATA_REGISTER_DIRECT: u16 =      0b1000_0000_0000;
pub const EA_ADDRESS_REGISTER_DIRECT: u16 =   0b0100_0000_0000;
pub const EA_ADDRESS_REGISTER_INDIRECT: u16 = 0b0010_0000_0000;
pub const EA_ARI_POSTINCREMENT: u16 =         0b0001_0000_0000;
pub const EA_ARI_PREDECREMENT: u16 =          0b0000_1000_0000;
pub const EA_ARI_DISPLACEMENT: u16 =          0b0000_0100_0000;
pub const EA_ARI_INDEX: u16 =                 0b0000_0010_0000;
pub const EA_ABSOLUTE_SHORT: u16 =            0b0000_0001_0000;
pub const EA_ABSOLUTE_LONG: u16 =             0b0000_0000_1000;
pub const EA_IMMEDIATE: u16 =                 0b0000_0000_0100;
pub const EA_PC_DISPLACEMENT: u16 =           0b0000_0000_0010;
pub const EA_PC_INDEX: u16 =                  0b0000_0000_0001;

pub const EA_ALL: u16 = 0xfff;
pub const EA_ALL_EXCEPT_AN: u16 = EA_ALL & !EA_ADDRESS_REGISTER_DIRECT;
// despite what is claimed in MC68000PRM section 2.3 EFFECTIVE ADDRESSING MODE SUMMARY,
// Absolute Short and Long modes are in fact alterable, as is evident when looking the allowed
// addressing modes of any instruction stating only alterable (or data/memory alterable)
// such as ADDQ.
pub const EA_ALTERABLE: u16 = EA_DATA_REGISTER_DIRECT
                        | EA_ADDRESS_REGISTER_DIRECT
                        | EA_ADDRESS_REGISTER_INDIRECT
                        | EA_ARI_POSTINCREMENT
                        | EA_ARI_PREDECREMENT
                        | EA_ARI_DISPLACEMENT
                        | EA_ARI_INDEX
                        | EA_ABSOLUTE_SHORT
                        | EA_ABSOLUTE_LONG;
pub const EA_CONTROL: u16 = EA_ADDRESS_REGISTER_INDIRECT
                        | EA_ARI_DISPLACEMENT
                        | EA_ARI_INDEX
                        | EA_ABSOLUTE_SHORT
                        | EA_ABSOLUTE_LONG
                        | EA_PC_DISPLACEMENT
                        | EA_PC_INDEX;
pub const EA_CONTROL_ALTERABLE_OR_PD: u16 = EA_CONTROL & EA_ALTERABLE | EA_ARI_PREDECREMENT;
pub const EA_CONTROL_OR_PI: u16 = EA_CONTROL | EA_ARI_POSTINCREMENT;
pub const EA_DATA: u16 = EA_ALL & !EA_ADDRESS_REGISTER_DIRECT;
pub const EA_DATA_ALTERABLE: u16 = EA_DATA & EA_ALTERABLE;
pub const EA_MEMORY: u16 = EA_ALL & !(EA_DATA_REGISTER_DIRECT | EA_ADDRESS_REGISTER_DIRECT);
pub const EA_MEMORY_ALTERABLE: u16 = EA_MEMORY & EA_ALTERABLE;
#[allow(dead_code)]
pub const EA_NONE: u16 = 0x000;

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

    #[test]
    fn ea_all_except_an() {
        assert_eq!(EA_ALL_EXCEPT_AN & EA_ADDRESS_REGISTER_DIRECT, 0);
    }
    #[test]
    fn ea_alterable() {
        assert_eq!(EA_ALTERABLE & (EA_IMMEDIATE|EA_PC_DISPLACEMENT|EA_PC_INDEX), 0);
    }
    #[test]
    fn ea_control() {
        assert_eq!(EA_CONTROL, 0x27b);
    }
    #[test]
    fn ea_control_alterable_or_pd() {
        assert_eq!(EA_CONTROL_ALTERABLE_OR_PD & EA_ARI_PREDECREMENT, EA_ARI_PREDECREMENT);
    }
    #[test]
    fn ea_control_or_pi() {
        assert_eq!(EA_CONTROL_OR_PI & EA_ARI_POSTINCREMENT, EA_ARI_POSTINCREMENT);
    }
    #[test]
    fn ea_data() {
        assert_eq!(EA_DATA & (EA_ADDRESS_REGISTER_DIRECT | EA_IMMEDIATE), 0);
    }
    #[test]
    fn ea_data_alterable() {
        assert_eq!(EA_DATA_ALTERABLE, EA_DATA & EA_ALTERABLE);
    }
    #[test]
    fn ea_memory_alterable() {
        assert_eq!(EA_MEMORY_ALTERABLE & (EA_DATA_REGISTER_DIRECT | EA_ADDRESS_REGISTER_DIRECT), 0);
    }
}<commit_msg>Fix ea mode constant tests<commit_after>pub const MASK_OUT_X_EA: u32 = 0b1111_0001_1100_0000; // masks out X and Y register bits, plus mode (????xxx???mmmyyy)
pub const MASK_OUT_EA: u32 = 0b1111111111000000;   // masks out Y register bits, plus mode (??????????mmmyyy)

pub const EA_DATA_REGISTER_DIRECT: u16 =      0b1000_0000_0000;
pub const EA_ADDRESS_REGISTER_DIRECT: u16 =   0b0100_0000_0000;
pub const EA_ADDRESS_REGISTER_INDIRECT: u16 = 0b0010_0000_0000;
pub const EA_ARI_POSTINCREMENT: u16 =         0b0001_0000_0000;
pub const EA_ARI_PREDECREMENT: u16 =          0b0000_1000_0000;
pub const EA_ARI_DISPLACEMENT: u16 =          0b0000_0100_0000;
pub const EA_ARI_INDEX: u16 =                 0b0000_0010_0000;
pub const EA_ABSOLUTE_SHORT: u16 =            0b0000_0001_0000;
pub const EA_ABSOLUTE_LONG: u16 =             0b0000_0000_1000;
pub const EA_IMMEDIATE: u16 =                 0b0000_0000_0100;
pub const EA_PC_DISPLACEMENT: u16 =           0b0000_0000_0010;
pub const EA_PC_INDEX: u16 =                  0b0000_0000_0001;

pub const EA_ALL: u16 = 0xfff;
pub const EA_ALL_EXCEPT_AN: u16 = EA_ALL & !EA_ADDRESS_REGISTER_DIRECT;
// despite what is claimed in MC68000PRM section 2.3 EFFECTIVE ADDRESSING MODE SUMMARY,
// Absolute Short and Long modes are in fact alterable, as is evident when looking the allowed
// addressing modes of any instruction stating only alterable (or data/memory alterable)
// such as ADDQ.
pub const EA_ALTERABLE: u16 = EA_DATA_REGISTER_DIRECT
                        | EA_ADDRESS_REGISTER_DIRECT
                        | EA_ADDRESS_REGISTER_INDIRECT
                        | EA_ARI_POSTINCREMENT
                        | EA_ARI_PREDECREMENT
                        | EA_ARI_DISPLACEMENT
                        | EA_ARI_INDEX
                        | EA_ABSOLUTE_SHORT
                        | EA_ABSOLUTE_LONG;
pub const EA_CONTROL: u16 = EA_ADDRESS_REGISTER_INDIRECT
                        | EA_ARI_DISPLACEMENT
                        | EA_ARI_INDEX
                        | EA_ABSOLUTE_SHORT
                        | EA_ABSOLUTE_LONG
                        | EA_PC_DISPLACEMENT
                        | EA_PC_INDEX;
pub const EA_CONTROL_ALTERABLE_OR_PD: u16 = EA_CONTROL & EA_ALTERABLE | EA_ARI_PREDECREMENT;
pub const EA_CONTROL_OR_PI: u16 = EA_CONTROL | EA_ARI_POSTINCREMENT;
pub const EA_DATA: u16 = EA_ALL & !EA_ADDRESS_REGISTER_DIRECT;
pub const EA_DATA_ALTERABLE: u16 = EA_DATA & EA_ALTERABLE;
pub const EA_MEMORY: u16 = EA_ALL & !(EA_DATA_REGISTER_DIRECT | EA_ADDRESS_REGISTER_DIRECT);
pub const EA_MEMORY_ALTERABLE: u16 = EA_MEMORY & EA_ALTERABLE;
#[allow(dead_code)]
pub const EA_NONE: u16 = 0x000;

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

    #[test]
    fn ea_all_except_an() {
        assert_eq!(EA_ALL_EXCEPT_AN & EA_ADDRESS_REGISTER_DIRECT, 0);
    }
    #[test]
    fn ea_alterable() {
        assert_eq!(EA_ALTERABLE & (EA_IMMEDIATE|EA_PC_DISPLACEMENT|EA_PC_INDEX), 0);
    }
    #[test]
    fn ea_control() {
        assert_eq!(EA_CONTROL, 0x27b);
    }
    #[test]
    fn ea_control_alterable_or_pd() {
        assert_eq!(EA_CONTROL_ALTERABLE_OR_PD & EA_ARI_PREDECREMENT, EA_ARI_PREDECREMENT);
    }
    #[test]
    fn ea_control_or_pi() {
        assert_eq!(EA_CONTROL_OR_PI & EA_ARI_POSTINCREMENT, EA_ARI_POSTINCREMENT);
    }
    #[test]
    fn ea_data() {
        assert_eq!(EA_DATA & (EA_ADDRESS_REGISTER_DIRECT), 0);
    }
    #[test]
    fn ea_data_alterable() {
        assert_eq!(EA_DATA_ALTERABLE, EA_DATA & EA_ALTERABLE);
    }
    #[test]
    fn ea_memory_alterable() {
        assert_eq!(EA_MEMORY_ALTERABLE & (EA_DATA_REGISTER_DIRECT | EA_ADDRESS_REGISTER_DIRECT), 0);
    }
}<|endoftext|>


<commit_before><commit_msg>Restrict message type of the Fleetspeak packet.<commit_after><|endoftext|>


<commit_before>use sdl2;

pub fn main() {
    sdl2::init(sdl2::InitVideo);

    let window = match sdl2::video::Window::new("rust-sdl2 demo: Video", sdl2::video::PosCentered, sdl2::video::PosCentered, 800, 600, sdl2::video::OpenGL) {
        Ok(window) => window,
        Err(err) => fail!(format!("failed to create window: {}", err))
    };

    let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::DriverAuto, sdl2::render::Accelerated) {
        Ok(renderer) => renderer,
        Err(err) => fail!(format!("failed to create renderer: {}", err))
    };

    let _ = renderer.set_draw_color(sdl2::pixels::RGB(255, 0, 0));
    let _ = renderer.clear();
    renderer.present();

    'main : loop {
        'event : loop {
            match sdl2::event::poll_event() {
                sdl2::event::QuitEvent(_) => break 'main,
                sdl2::event::KeyDownEvent(_, _, key, _, _) => {
                    if key == sdl2::keycode::EscapeKey {
                        break 'main
                    }
                }
                _ => {}
            }
        }
    }

    sdl2::quit();
}
<commit_msg>Added inner loop break to the demo.<commit_after>use sdl2;

pub fn main() {
    sdl2::init(sdl2::InitVideo);

    let window = match sdl2::video::Window::new("rust-sdl2 demo: Video", sdl2::video::PosCentered, sdl2::video::PosCentered, 800, 600, sdl2::video::OpenGL) {
        Ok(window) => window,
        Err(err) => fail!(format!("failed to create window: {}", err))
    };

    let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::DriverAuto, sdl2::render::Accelerated) {
        Ok(renderer) => renderer,
        Err(err) => fail!(format!("failed to create renderer: {}", err))
    };

    let _ = renderer.set_draw_color(sdl2::pixels::RGB(255, 0, 0));
    let _ = renderer.clear();
    renderer.present();

    'main : loop {
        'event : loop {
            match sdl2::event::poll_event() {
                sdl2::event::QuitEvent(_) => break 'main,
                sdl2::event::KeyDownEvent(_, _, key, _, _) => {
                    if key == sdl2::keycode::EscapeKey {
                        break 'main
                    }
                },
                sdl2::event::NoEvent => break 'event,
                _ => {}
            }
        }
    }

    sdl2::quit();
}
<|endoftext|>


<commit_before>use self::DispatchType::{ChangeCurrentChannel, OutgoingMessage, IncomingMessage};
use std::collections::HashMap;
use std::sync::mpsc;

enum DispatchType {
    ChangeCurrentChannel,
    OutgoingMessage,
    IncomingMessage
}

struct Dispatcher {
    // Internally store as string for faster access
    subscribers: HashMap<&'static str, Vec<mpsc::Sender<String>>>,
    broadcasters: Vec<mpsc::Receiver<String>>
}

impl Dispatcher {
    pub fn new() -> Dispatcher {
        Dispatcher { subscribers: HashMap::new(), broadcasters: vec![] }
    }

    pub fn register_broadcaster(&mut self, broadcaster: &Broadcast) {
       self.broadcasters.push(broadcaster.broadcast());
    }

    pub fn register_subscriber(&mut self, subscriber: &Subscribe) {
       let sender = subscriber.subscribe();
       let type_key = type_to_str(subscriber.what_subscribe());
       let new = match self.subscribers.get_mut(type_key) {
          Some(others) => {
             others.push(sender);
             None
          },
          None => {
             Some(vec![sender])
          }
       };
       // Improve me. Can chain because double mut borrow not allowed
       new.and_then(|new_senders| self.subscribers.insert(type_key, new_senders));
    }

    fn num_broadcasters(&self) -> usize {
       self.broadcasters.len()
    }

    fn num_subscribers(&self, dispatch_type: DispatchType) -> usize {
       match self.subscribers.get(type_to_str(dispatch_type)) {
          Some(subscribers) => subscribers.len(),
          None => 0
       }
    }
}

// Convert to hashable for dispatchtype?
fn type_to_str(dispatch_type: DispatchType) -> &'static str {
   match dispatch_type {
       OutgoingMessage => "OutgoingMessage",
       ChangeCurrentChannel => "ChangeCurrentChannel",
       IncomingMessage => "IncomingMessage"
   }
}

trait Broadcast {
   fn broadcast(&self) -> mpsc::Receiver<String>;
}

trait Subscribe {
   fn subscribe(&self) -> mpsc::Sender<String>;
   fn what_subscribe(&self) -> DispatchType;
}

#[cfg(test)]
mod test {
    use std::sync::mpsc;
    use super::{ Dispatcher, Broadcast, Subscribe};
    use super::DispatchType::{self, OutgoingMessage};

    #[test]
    fn test_register_broadcaster() {
        let mut dispatcher = Dispatcher::new();
        let brd = TestBroadcaster;
        assert_eq!(dispatcher.num_broadcasters(), 0);
        dispatcher.register_broadcaster(&brd);
        assert_eq!(dispatcher.num_broadcasters(), 1);
    }

    #[test]
    fn test_register_subscriber() {
        let mut dispatcher = Dispatcher::new();
        let brd = TestSubscriber;
        assert_eq!(dispatcher.num_subscribers(OutgoingMessage), 0);
        dispatcher.register_subscriber(&brd);
        assert_eq!(dispatcher.num_subscribers(OutgoingMessage), 1);
    }

    struct TestBroadcaster;

    impl Broadcast for TestBroadcaster {
      fn broadcast(&self) -> mpsc::Receiver<String> {
         let (_, rx) = mpsc::channel::<String>();
         rx
      }
    }

    struct TestSubscriber;

    impl Subscribe for TestSubscriber {
       fn subscribe(&self) -> mpsc::Sender<String> {
          let(tx, _) = mpsc::channel::<String>();
          tx
       }

       fn what_subscribe(&self) -> DispatchType {
          OutgoingMessage
       }
    }
}
<commit_msg>Implement dispatcher start()<commit_after>use self::DispatchType::{ChangeCurrentChannel, OutgoingMessage, IncomingMessage};
use std::collections::HashMap;
use std::sync::{mpsc, Arc, Mutex};
use std::thread;

#[derive(PartialEq, Debug, Clone)]
enum DispatchType {
    ChangeCurrentChannel,
    OutgoingMessage,
    IncomingMessage
}

#[derive(Clone)]
struct DispatchMessage {
   dispatch_type: DispatchType,
   payload: String
}

struct Dispatcher {
    // I heard you like types
    subscribers: HashMap<&'static str, Vec<mpsc::Sender<DispatchMessage>>>,
    broadcasters: Vec<Arc<Mutex<mpsc::Receiver<DispatchMessage>>>>
}

impl Dispatcher {
    pub fn new() -> Dispatcher {
        Dispatcher { subscribers: HashMap::new(), broadcasters: vec![] }
    }

    pub fn register_broadcaster(&mut self, broadcaster: &mut Broadcast) {
       let handle = Arc::new(Mutex::new(broadcaster.broadcast_handle()));
       self.broadcasters.push(handle);
    }

    pub fn register_subscriber(&mut self, subscriber: &Subscribe) {
       let sender = subscriber.subscribe();
       let type_key = type_to_str(&subscriber.what_subscribe());
       let new = match self.subscribers.get_mut(type_key) {
          Some(others) => {
             others.push(sender);
             None
          },
          None => {
             Some(vec![sender])
          }
       };
       // Improve me. Cant chain because double mut borrow not allowed
       new.and_then(|new_senders| self.subscribers.insert(type_key, new_senders));
    }

    pub fn start(&self) {
       for broadcaster in self.broadcasters.clone() {
          let subscribers = self.subscribers.clone();
          thread::spawn(move || {
             loop {
                let message = broadcaster.lock().unwrap().recv().ok().expect("Couldn't receive message in broadcaster or channel hung up");
                match subscribers.get(type_to_str(&message.dispatch_type)) {
                  Some(ref subs) => {
                      for sub in subs.iter() { sub.send(message.clone()).unwrap(); }
                  },
                  None => ()
                }

             }
          });
       }
    }

    // fn shared_subscribers(&self) -> HashMap<&str, Arc<Mutex<mpsc::Sender<DispatchMessage>>>> {
    //    self.subscribers.iter().map(|v| Arc::new(Mutex::new(v.clone()))).collect()
    // }

    fn num_broadcasters(&self) -> usize {
       self.broadcasters.len()
    }

    fn num_subscribers(&self, dispatch_type: DispatchType) -> usize {
       match self.subscribers.get(type_to_str(&dispatch_type)) {
          Some(subscribers) => subscribers.len(),
          None => 0
       }
    }
}

// Convert to hashable for dispatchtype?
fn type_to_str(dispatch_type: &DispatchType) -> &'static str {
   match *dispatch_type {
       OutgoingMessage => "OutgoingMessage",
       ChangeCurrentChannel => "ChangeCurrentChannel",
       IncomingMessage => "IncomingMessage"
   }
}

trait Broadcast {
   fn broadcast(&self, dispatch_type: DispatchType, payload: String);
   fn broadcast_handle(&mut self) -> mpsc::Receiver<DispatchMessage>;
}

trait Subscribe {
   fn subscribe(&self) -> mpsc::Sender<DispatchMessage>;
   fn what_subscribe(&self) -> DispatchType;
}

#[cfg(test)]
mod test {
    use std::sync::mpsc;
    use super::{ Dispatcher, Broadcast, Subscribe, DispatchMessage};
    use super::DispatchType::{self, OutgoingMessage};

    #[test]
    fn test_register_broadcaster() {
        let mut dispatcher = Dispatcher::new();
        let mut brd = TestBroadcaster::new();
        assert_eq!(dispatcher.num_broadcasters(), 0);
        dispatcher.register_broadcaster(&mut brd);
        assert_eq!(dispatcher.num_broadcasters(), 1);
    }

    #[test]
    fn test_register_subscriber() {
        let mut dispatcher = Dispatcher::new();
        let sub = TestSubscriber::new();
        assert_eq!(dispatcher.num_subscribers(OutgoingMessage), 0);
        dispatcher.register_subscriber(&sub);
        assert_eq!(dispatcher.num_subscribers(OutgoingMessage), 1);
    }

    #[test]
    fn test_register_multiple_subscribers() {
        let mut dispatcher = Dispatcher::new();
        let sub = TestSubscriber::new();
        let sub2 = TestSubscriber::new();

        assert_eq!(dispatcher.num_subscribers(OutgoingMessage), 0);
        dispatcher.register_subscriber(&sub);
        dispatcher.register_subscriber(&sub2);
        assert_eq!(dispatcher.num_subscribers(OutgoingMessage), 2);
    }

    #[test]
    fn test_broadcast_simple_message() {
        let mut dispatcher = Dispatcher::new();
        let sub = TestSubscriber::new();
        let mut brd = TestBroadcaster::new();
        dispatcher.register_broadcaster(&mut brd);
        dispatcher.register_subscriber(&sub);

        dispatcher.start();

        brd.broadcast(OutgoingMessage, "Hello world!".to_string());
        let message = sub.receiver.recv().unwrap();
        assert_eq!(message.dispatch_type, OutgoingMessage);
        assert_eq!(message.payload, "Hello world!");
    }

    struct TestBroadcaster {
       sender: Option<mpsc::Sender<DispatchMessage>>
    }

    impl TestBroadcaster {
       fn new() -> TestBroadcaster {
         TestBroadcaster { sender: None }
      }
    }
    impl Broadcast for TestBroadcaster {
      fn broadcast_handle(&mut self) -> mpsc::Receiver<DispatchMessage> {
         let (tx, rx) = mpsc::channel::<DispatchMessage>();
         self.sender = Some(tx);
         rx
      }

      fn broadcast(&self, dispatch_type: DispatchType, payload: String) {
         let message = DispatchMessage { dispatch_type: dispatch_type, payload: payload };
         match self.sender {
            Some(ref s) => { s.send(message); },
            None => ()
         };
      }
    }

    struct TestSubscriber {
      receiver: mpsc::Receiver<DispatchMessage>,
      sender: mpsc::Sender<DispatchMessage>
    }

    impl TestSubscriber {
       fn new() -> TestSubscriber {
          let(tx, rx) = mpsc::channel::<DispatchMessage>();
          TestSubscriber { receiver: rx, sender: tx }
       }
    }

    impl Subscribe for TestSubscriber {
       fn subscribe(&self) -> mpsc::Sender<DispatchMessage> {
          self.sender.clone()
       }

       fn what_subscribe(&self) -> DispatchType {
          OutgoingMessage
       }
    }
}
<|endoftext|>


<commit_before>//! The main event loop which performs I/O on the pseudoterminal
use std::borrow::Cow;
use std::collections::VecDeque;
use std::io::{self, ErrorKind, Write};
use std::fs::File;
use std::os::unix::io::AsRawFd;
use std::sync::Arc;

use mio::{self, Events, PollOpt, Ready};
use mio::unix::EventedFd;

use ansi;
use display;
use event;
use term::Term;
use util::thread;
use sync::FairMutex;

/// Messages that may be sent to the `EventLoop`
#[derive(Debug)]
pub enum Msg {
    /// Data that should be written to the pty
    Input(Cow<'static, [u8]>),
}

/// The main event!.. loop.
///
/// Handles all the pty I/O and runs the pty parser which updates terminal
/// state.
pub struct EventLoop<Io> {
    poll: mio::Poll,
    pty: Io,
    rx: mio::channel::Receiver<Msg>,
    tx: mio::channel::Sender<Msg>,
    terminal: Arc<FairMutex<Term>>,
    display: display::Notifier,
    ref_test: bool,
}

/// Helper type which tracks how much of a buffer has been written.
struct Writing {
    source: Cow<'static, [u8]>,
    written: usize,
}

/// All of the mutable state needed to run the event loop
///
/// Contains list of items to write, current write state, etc. Anything that
/// would otherwise be mutated on the `EventLoop` goes here.
pub struct State {
    write_list: VecDeque<Cow<'static, [u8]>>,
    writing: Option<Writing>,
    parser: ansi::Processor,
}

pub struct Notifier(pub ::mio::channel::Sender<Msg>);

impl event::Notify for Notifier {
    fn notify<B>(&mut self, bytes: B)
        where B: Into<Cow<'static, [u8]>>
    {
        let bytes = bytes.into();
        match self.0.send(Msg::Input(bytes)) {
            Ok(_) => (),
            Err(_) => panic!("expected send event loop msg"),
        }
    }
}

impl Default for State {
    fn default() -> State {
        State {
            write_list: VecDeque::new(),
            parser: ansi::Processor::new(),
            writing: None,
        }
    }
}

impl State {
    #[inline]
    fn ensure_next(&mut self) {
        if self.writing.is_none() {
            self.goto_next();
        }
    }

    #[inline]
    fn goto_next(&mut self) {
        self.writing = self.write_list
            .pop_front()
            .map(Writing::new);
    }

    #[inline]
    fn take_current(&mut self) -> Option<Writing> {
        self.writing.take()
    }

    #[inline]
    fn needs_write(&self) -> bool {
        self.writing.is_some() || !self.write_list.is_empty()
    }

    #[inline]
    fn set_current(&mut self, new: Option<Writing>) {
        self.writing = new;
    }
}

impl Writing {
    #[inline]
    fn new(c: Cow<'static, [u8]>) -> Writing {
        Writing { source: c, written: 0 }
    }

    #[inline]
    fn advance(&mut self, n: usize) {
        self.written += n;
    }

    #[inline]
    fn remaining_bytes(&self) -> &[u8] {
        &self.source[self.written..]
    }

    #[inline]
    fn finished(&self) -> bool {
        self.written >= self.source.len()
    }
}

/// `mio::Token` for the event loop channel
const CHANNEL: mio::Token = mio::Token(0);

/// `mio::Token` for the pty file descriptor
const PTY: mio::Token = mio::Token(1);

impl<Io> EventLoop<Io>
    where Io: io::Read + io::Write + Send + AsRawFd + 'static
{
    /// Create a new event loop
    pub fn new(
        terminal: Arc<FairMutex<Term>>,
        display: display::Notifier,
        pty: Io,
        ref_test: bool,
    ) -> EventLoop<Io> {
        let (tx, rx) = ::mio::channel::channel();
        EventLoop {
            poll: mio::Poll::new().expect("create mio Poll"),
            pty: pty,
            tx: tx,
            rx: rx,
            terminal: terminal,
            display: display,
            ref_test: ref_test,
        }
    }

    pub fn channel(&self) -> mio::channel::Sender<Msg> {
        self.tx.clone()
    }

    // Drain the channel
    //
    // Returns true if items were received
    fn drain_recv_channel(&self, state: &mut State) -> bool {
        let mut received_item = false;
        while let Ok(msg) = self.rx.try_recv() {
            received_item = true;
            match msg {
                Msg::Input(input) => {
                    state.write_list.push_back(input);
                }
            }
        }

        received_item
    }

    #[inline]
    fn channel_event(&mut self, state: &mut State) {
        self.drain_recv_channel(state);

        self.poll.reregister(
            &self.rx, CHANNEL,
            Ready::readable(),
            PollOpt::edge() | PollOpt::oneshot()
        ).expect("reregister channel");

        if state.needs_write() {
            self.poll.reregister(
                &EventedFd(&self.pty.as_raw_fd()),
                PTY,
                Ready::readable() | Ready::writable(),
                PollOpt::edge() | PollOpt::oneshot()
            ).expect("reregister fd after channel recv");
        }
    }

    #[inline]
    fn pty_read<W>(
        &mut self,
        state: &mut State,
        buf: &mut [u8],
        mut writer: Option<&mut W>
    )
        where W: Write
    {
        loop {
            match self.pty.read(&mut buf[..]) {
                Ok(0) => break,
                Ok(got) => {
                    writer = writer.map(|w| {
                        w.write_all(&buf[..got]).unwrap(); w
                    });

                    let mut terminal = self.terminal.lock();
                    for byte in &buf[..got] {
                        state.parser.advance(&mut *terminal, *byte, &mut self.pty);
                    }

                    // Only request a draw if one hasn't already been requested.
                    //
                    // This is a performance optimization even if only for X11
                    // which is very expensive to hammer on the even loop wakeup
                    if !terminal.dirty {
                        self.display.notify();
                        terminal.dirty = true;

                        // Break for writing
                        //
                        // Want to prevent case where reading always returns
                        // data and sequences like `C-c` cannot be sent.
                        //
                        // Doing this check in !terminal.dirty will prevent the
                        // condition from being checked overzealously.
                        if state.writing.is_some()
                            || !state.write_list.is_empty()
                            || self.drain_recv_channel(state)
                        {
                            break;
                        }
                    }
                },
                Err(err) => {
                    match err.kind() {
                        ErrorKind::Interrupted |
                        ErrorKind::WouldBlock => break,
                        _ => panic!("unexpected read err: {:?}", err),
                    }
                }
            }
        }
    }

    #[inline]
    fn pty_write(&mut self, state: &mut State) {
        state.ensure_next();

        'write_many: while let Some(mut current) = state.take_current() {
            'write_one: loop {
                match self.pty.write(current.remaining_bytes()) {
                    Ok(0) => {
                        state.set_current(Some(current));
                        break 'write_many;
                    },
                    Ok(n) => {
                        current.advance(n);
                        if current.finished() {
                            state.goto_next();
                            break 'write_one;
                        }
                    },
                    Err(err) => {
                        state.set_current(Some(current));
                        match err.kind() {
                            ErrorKind::Interrupted |
                            ErrorKind::WouldBlock => break 'write_many,
                            // TODO
                            _ => panic!("unexpected err: {:?}", err),
                        }
                    }
                }

            }
        }
    }

    pub fn spawn(
        mut self,
        state: Option<State>
    ) -> thread::JoinHandle<(EventLoop<Io>, State)> {
        thread::spawn_named("pty reader", move || {
            let mut state = state.unwrap_or_else(Default::default);
            let mut buf = [0u8; 4096];

            let fd = self.pty.as_raw_fd();
            let fd = EventedFd(&fd);

            let poll_opts = PollOpt::edge() | PollOpt::oneshot();

            self.poll.register(&self.rx, CHANNEL, Ready::readable(), poll_opts).unwrap();
            self.poll.register(&fd, PTY, Ready::readable(), poll_opts).unwrap();

            let mut events = Events::with_capacity(1024);

            let mut pipe = if self.ref_test {
                let file = File::create("./alacritty.recording")
                    .expect("create alacritty recording");
                Some(file)
            } else {
                None
            };

            'event_loop: loop {
                if let Err(err) = self.poll.poll(&mut events, None) {
                    match err.kind() {
                        ErrorKind::Interrupted => continue,
                        _ => panic!("EventLoop polling error: {:?}", err)
                    }
                }

                for event in events.iter() {
                    match event.token() {
                        CHANNEL => self.channel_event(&mut state),
                        PTY => {
                            let kind = event.kind();

                            if kind.is_readable() {
                                self.pty_read(&mut state, &mut buf, pipe.as_mut());
                                if ::tty::process_should_exit() {
                                    break 'event_loop;
                                }
                            }

                            if kind.is_writable() {
                                self.pty_write(&mut state);
                            }

                            if kind.is_hup() {
                                break 'event_loop;
                            }

                            // Figure out pty interest
                            let mut interest = Ready::readable();
                            if state.needs_write() {
                                interest.insert(Ready::writable());
                            }

                            // Reregister pty
                            self.poll
                                .reregister(&fd, PTY, interest, poll_opts)
                                .expect("register fd after read/write");
                        },
                        _ => (),
                    }
                }
            }

            let _ = self.poll.deregister(&self.rx);
            let _ = self.poll.deregister(&fd);

            (self, state)
        })
    }
}
<commit_msg>Better error handling in event loop<commit_after>//! The main event loop which performs I/O on the pseudoterminal
use std::borrow::Cow;
use std::collections::VecDeque;
use std::io::{self, ErrorKind, Write};
use std::fs::File;
use std::os::unix::io::AsRawFd;
use std::sync::Arc;

use mio::{self, Events, PollOpt, Ready};
use mio::unix::EventedFd;

use ansi;
use display;
use event;
use term::Term;
use util::thread;
use sync::FairMutex;

/// Messages that may be sent to the `EventLoop`
#[derive(Debug)]
pub enum Msg {
    /// Data that should be written to the pty
    Input(Cow<'static, [u8]>),
}

/// The main event!.. loop.
///
/// Handles all the pty I/O and runs the pty parser which updates terminal
/// state.
pub struct EventLoop<Io> {
    poll: mio::Poll,
    pty: Io,
    rx: mio::channel::Receiver<Msg>,
    tx: mio::channel::Sender<Msg>,
    terminal: Arc<FairMutex<Term>>,
    display: display::Notifier,
    ref_test: bool,
}

/// Helper type which tracks how much of a buffer has been written.
struct Writing {
    source: Cow<'static, [u8]>,
    written: usize,
}

/// All of the mutable state needed to run the event loop
///
/// Contains list of items to write, current write state, etc. Anything that
/// would otherwise be mutated on the `EventLoop` goes here.
pub struct State {
    write_list: VecDeque<Cow<'static, [u8]>>,
    writing: Option<Writing>,
    parser: ansi::Processor,
}

pub struct Notifier(pub ::mio::channel::Sender<Msg>);

impl event::Notify for Notifier {
    fn notify<B>(&mut self, bytes: B)
        where B: Into<Cow<'static, [u8]>>
    {
        let bytes = bytes.into();
        match self.0.send(Msg::Input(bytes)) {
            Ok(_) => (),
            Err(_) => panic!("expected send event loop msg"),
        }
    }
}

impl Default for State {
    fn default() -> State {
        State {
            write_list: VecDeque::new(),
            parser: ansi::Processor::new(),
            writing: None,
        }
    }
}

impl State {
    #[inline]
    fn ensure_next(&mut self) {
        if self.writing.is_none() {
            self.goto_next();
        }
    }

    #[inline]
    fn goto_next(&mut self) {
        self.writing = self.write_list
            .pop_front()
            .map(Writing::new);
    }

    #[inline]
    fn take_current(&mut self) -> Option<Writing> {
        self.writing.take()
    }

    #[inline]
    fn needs_write(&self) -> bool {
        self.writing.is_some() || !self.write_list.is_empty()
    }

    #[inline]
    fn set_current(&mut self, new: Option<Writing>) {
        self.writing = new;
    }
}

impl Writing {
    #[inline]
    fn new(c: Cow<'static, [u8]>) -> Writing {
        Writing { source: c, written: 0 }
    }

    #[inline]
    fn advance(&mut self, n: usize) {
        self.written += n;
    }

    #[inline]
    fn remaining_bytes(&self) -> &[u8] {
        &self.source[self.written..]
    }

    #[inline]
    fn finished(&self) -> bool {
        self.written >= self.source.len()
    }
}

/// `mio::Token` for the event loop channel
const CHANNEL: mio::Token = mio::Token(0);

/// `mio::Token` for the pty file descriptor
const PTY: mio::Token = mio::Token(1);

impl<Io> EventLoop<Io>
    where Io: io::Read + io::Write + Send + AsRawFd + 'static
{
    /// Create a new event loop
    pub fn new(
        terminal: Arc<FairMutex<Term>>,
        display: display::Notifier,
        pty: Io,
        ref_test: bool,
    ) -> EventLoop<Io> {
        let (tx, rx) = ::mio::channel::channel();
        EventLoop {
            poll: mio::Poll::new().expect("create mio Poll"),
            pty: pty,
            tx: tx,
            rx: rx,
            terminal: terminal,
            display: display,
            ref_test: ref_test,
        }
    }

    pub fn channel(&self) -> mio::channel::Sender<Msg> {
        self.tx.clone()
    }

    // Drain the channel
    //
    // Returns true if items were received
    fn drain_recv_channel(&self, state: &mut State) -> bool {
        let mut received_item = false;
        while let Ok(msg) = self.rx.try_recv() {
            received_item = true;
            match msg {
                Msg::Input(input) => {
                    state.write_list.push_back(input);
                }
            }
        }

        received_item
    }

    #[inline]
    fn channel_event(&mut self, state: &mut State) {
        self.drain_recv_channel(state);

        self.poll.reregister(
            &self.rx, CHANNEL,
            Ready::readable(),
            PollOpt::edge() | PollOpt::oneshot()
        ).expect("reregister channel");

        if state.needs_write() {
            self.poll.reregister(
                &EventedFd(&self.pty.as_raw_fd()),
                PTY,
                Ready::readable() | Ready::writable(),
                PollOpt::edge() | PollOpt::oneshot()
            ).expect("reregister fd after channel recv");
        }
    }

    #[inline]
    fn pty_read<W>(
        &mut self,
        state: &mut State,
        buf: &mut [u8],
        mut writer: Option<&mut W>
    ) -> io::Result<()>
        where W: Write
    {
        loop {
            match self.pty.read(&mut buf[..]) {
                Ok(0) => break,
                Ok(got) => {
                    writer = writer.map(|w| {
                        w.write_all(&buf[..got]).unwrap(); w
                    });

                    let mut terminal = self.terminal.lock();
                    for byte in &buf[..got] {
                        state.parser.advance(&mut *terminal, *byte, &mut self.pty);
                    }

                    // Only request a draw if one hasn't already been requested.
                    //
                    // This is a performance optimization even if only for X11
                    // which is very expensive to hammer on the even loop wakeup
                    if !terminal.dirty {
                        self.display.notify();
                        terminal.dirty = true;

                        // Break for writing
                        //
                        // Want to prevent case where reading always returns
                        // data and sequences like `C-c` cannot be sent.
                        //
                        // Doing this check in !terminal.dirty will prevent the
                        // condition from being checked overzealously.
                        if state.writing.is_some()
                            || !state.write_list.is_empty()
                            || self.drain_recv_channel(state)
                        {
                            break;
                        }
                    }
                },
                Err(err) => {
                    match err.kind() {
                        ErrorKind::Interrupted |
                        ErrorKind::WouldBlock => break,
                        _ => return Err(err),
                    }
                }
            }
        }

        Ok(())
    }

    #[inline]
    fn pty_write(&mut self, state: &mut State) -> io::Result<()> {
        state.ensure_next();

        'write_many: while let Some(mut current) = state.take_current() {
            'write_one: loop {
                match self.pty.write(current.remaining_bytes()) {
                    Ok(0) => {
                        state.set_current(Some(current));
                        break 'write_many;
                    },
                    Ok(n) => {
                        current.advance(n);
                        if current.finished() {
                            state.goto_next();
                            break 'write_one;
                        }
                    },
                    Err(err) => {
                        state.set_current(Some(current));
                        match err.kind() {
                            ErrorKind::Interrupted |
                            ErrorKind::WouldBlock => break 'write_many,
                            _ => return Err(err),
                        }
                    }
                }

            }
        }

        Ok(())
    }

    pub fn spawn(
        mut self,
        state: Option<State>
    ) -> thread::JoinHandle<(EventLoop<Io>, State)> {
        thread::spawn_named("pty reader", move || {
            let mut state = state.unwrap_or_else(Default::default);
            let mut buf = [0u8; 4096];

            let fd = self.pty.as_raw_fd();
            let fd = EventedFd(&fd);

            let poll_opts = PollOpt::edge() | PollOpt::oneshot();

            self.poll.register(&self.rx, CHANNEL, Ready::readable(), poll_opts).unwrap();
            self.poll.register(&fd, PTY, Ready::readable(), poll_opts).unwrap();

            let mut events = Events::with_capacity(1024);

            let mut pipe = if self.ref_test {
                let file = File::create("./alacritty.recording")
                    .expect("create alacritty recording");
                Some(file)
            } else {
                None
            };

            'event_loop: loop {
                if let Err(err) = self.poll.poll(&mut events, None) {
                    match err.kind() {
                        ErrorKind::Interrupted => continue,
                        _ => panic!("EventLoop polling error: {:?}", err)
                    }
                }

                for event in events.iter() {
                    match event.token() {
                        CHANNEL => self.channel_event(&mut state),
                        PTY => {
                            let kind = event.kind();

                            if kind.is_hup() {
                                break 'event_loop;
                            }

                            if kind.is_readable() {
                                if let Err(err) = self.pty_read(&mut state, &mut buf, pipe.as_mut()) {
                                    error!("Event loop exitting due to error: {} [{}:{}]",
                                           err, file!(), line!());
                                    break 'event_loop;
                                }

                                if ::tty::process_should_exit() {
                                    break 'event_loop;
                                }
                            }

                            if kind.is_writable() {
                                if let Err(err) = self.pty_write(&mut state) {
                                    error!("Event loop exitting due to error: {} [{}:{}]",
                                           err, file!(), line!());
                                    break 'event_loop;
                                }
                            }

                            // Figure out pty interest
                            let mut interest = Ready::readable();
                            if state.needs_write() {
                                interest.insert(Ready::writable());
                            }

                            // Reregister pty
                            self.poll
                                .reregister(&fd, PTY, interest, poll_opts)
                                .expect("register fd after read/write");
                        },
                        _ => (),
                    }
                }
            }

            let _ = self.poll.deregister(&self.rx);
            let _ = self.poll.deregister(&fd);

            (self, state)
        })
    }
}
<|endoftext|>


<commit_before>pub enum Expression {
    Int(int),
    Float(float),
    Symbol(~str),
    List(~[Expression]),
    Proc(~fn(~[Expression],@Environment) -> Expression)
}

pub impl Expression {
    fn to_bool(&self) -> bool {
        match *self {
            Int( number ) => 0 != number,
            Float( number ) => 0.0 != number,
            _ => true
        }
    }

    fn to_str(&self) -> ~str {
        match copy *self {
            Int(number) => { fmt!("%d", number) }
            Float(number) => {
                if number == (number as int) as float {
                    fmt!("%.1f", number)
                } else {
                    fmt!("%f", number)
                }
            }
            Symbol(string) => { copy string }
            List(expressions) => {
                let strings = expressions.map( | &expr | {expr.to_str()} );
                ~"(" + strings.foldl(~"", |&x, &y| { x + ~" " + y } ).trim() + ~")"
            }
            Proc(_) => { ~"procedure" }
        }
    }
}

#[test]
fn test_to_bool_returns_true_for_non_zero_numbers() {
    assert Int(1).to_bool();
    assert Int(-1).to_bool();
    assert Float(1.0).to_bool();
    assert Float(-1.0).to_bool();
}

#[test]
fn test_to_bool_returns_false_for_zero_numbers() {
    assert !Int(0).to_bool();
    assert !Float(0.0).to_bool();
}
<commit_msg>Make expressions (except procs) comparable<commit_after>pub enum Expression {
    Int(int),
    Float(float),
    Symbol(~str),
    List(~[Expression]),
    Proc(~fn(~[Expression],@Environment) -> Expression)
}

pub impl Expression {
    fn to_bool(&self) -> bool {
        match *self {
            Int( number ) => 0 != number,
            Float( number ) => 0.0 != number,
            _ => true
        }
    }

    fn to_str(&self) -> ~str {
        match copy *self {
            Int(number) => { fmt!("%d", number) }
            Float(number) => {
                if number == (number as int) as float {
                    fmt!("%.1f", number)
                } else {
                    fmt!("%f", number)
                }
            }
            Symbol(string) => { copy string }
            List(expressions) => {
                let strings = expressions.map( | &expr | {expr.to_str()} );
                ~"(" + strings.foldl(~"", |&x, &y| { x + ~" " + y } ).trim() + ~")"
            }
            Proc(_) => { ~"procedure" }
        }
    }
}

impl Expression : cmp::Eq {
    pure fn eq(&self, other:&Expression) -> bool {
        match copy *self {
            Int(x) => match *other { Int(y) => x == y, _ => false },
            Float(x) => match *other { Float(y) => x == y, _ => false },
            Symbol(x) => match copy *other { Symbol(y) => x == y, _ => false },
            List(x) => match copy *other { List(y) => x == y, _ => false },
            _ => false
        }
    }

    pure fn ne(&self, other:&Expression) -> bool {
        return !(*self).eq(other);
    }
}

#[test]
fn test_to_bool_returns_true_for_non_zero_numbers() {
    assert Int(1).to_bool();
    assert Int(-1).to_bool();
    assert Float(1.0).to_bool();
    assert Float(-1.0).to_bool();
}

#[test]
fn test_to_bool_returns_false_for_zero_numbers() {
    assert !Int(0).to_bool();
    assert !Float(0.0).to_bool();
}

#[test]
fn test_that_integers_are_comparable() {
    assert Int(1) == Int(1);
    assert Int(1) != Int(2);
}

#[test]
fn test_that_floats_are_comparable() {
    assert Float(1.0) == Float(1.0);
    assert Float(1.0) != Float(2.0);
}

#[test]
fn test_that_symbols_are_comparable() {
    assert Symbol(~"1") == Symbol(~"1");
    assert Symbol(~"1") != Symbol(~"2");
}

#[test]
fn test_that_vectors_are_comparable() {
    assert List(~[Int(1)]) == List(~[Int(1)]);
    assert List(~[Int(1)]) != List(~[Int(2)]);
}
<|endoftext|>


<commit_before>use std::convert::{From, TryFrom, TryInto};
use std::ops::{Deref, DerefMut};
use std::str::FromStr;
use std::fmt;
use stack::Stack;
use operate::Operate;

/// Used to specify an `Operand` or an `Operator`.
#[derive(Debug, Copy, Clone)]
pub enum Arithm<T, O: Operate<T>> {
    Operand(T),
    Operator(O),
}

/// Interpret a [`Reverse Polish notated`] expression (cf. `3 4 +`).
///
/// `Operate` method returns the valid result or an [`Operate::Err`] if an operation fails.
///
/// `Expressions` are constructed from [`str`] the most of the time.
/// Use the [`try_into()`] method to create an `Expression` type,
/// the result contain informations about the possible error at conversion time.
///
/// [`Reverse Polish notated`]: https://en.wikipedia.org/wiki/Reverse_Polish_notation
/// [`Operate::Err`]: ../operate/trait.Operate.html#associatedtype.Err
/// [`str`]: https://doc.rust-lang.org/std/str/index.html
/// [`try_into()`]: https://doc.rust-lang.org/std/convert/trait.TryInto.html#tymethod.try_into
#[derive(Debug)]
pub struct Expression<T, O: Operate<T>> {
    stack_max: usize,
    expr: Vec<Arithm<T, O>>,
}

impl<T: Copy, O: Operate<T> + Copy> Expression<T, O> {
    /// Evaluate the `RPN` expression. Returns the result or the [`operate Error`].
    ///
    /// [`operate Error`]: ../operate/trait.Operate.html#associatedtype.Err
    pub fn operate(&self) -> Result<T, O::Err> {
        let mut stack = Stack::with_capacity(self.stack_max);
        for arithm in &self.expr {
            match *arithm {
                Arithm::Operand(operand) => stack.push(operand),
                Arithm::Operator(operator) => operator.operate(&mut stack)?,
            }
        }
        Ok(stack.pop().unwrap())
    }
}

/// Used to specify the error during the convertion.
#[derive(Debug, PartialEq)]
pub enum ExprResult<A, B> {
    TooManyOperands,
    NotEnoughOperand,
    InvalidToken(A, B),
}

impl<'a, T, O> Expression<T, O>
    where T: FromStr,
          O: Operate<T> + TryFrom<&'a str>
{
    fn check_validity(expr: &[Arithm<T, O>])
        -> Result<(), ExprResult<<T as FromStr>::Err, <O as TryFrom<&'a str>>::Err>> {
        use self::ExprResult::*;
        let mut num_operands: usize = 0;
        for arithm in expr {
            match *arithm {
                Arithm::Operand(_) => num_operands += 1,
                Arithm::Operator(ref operator) => {
                    let needed = operator.operands_needed();
                    num_operands = num_operands.checked_sub(needed).ok_or(NotEnoughOperand)?;
                    num_operands += operator.operands_generated();
                },
            }
        }
        match num_operands {
            0 => Err(NotEnoughOperand),
            1 => Ok(()),
            _ => Err(TooManyOperands),
        }
    }
}

impl<T, O: Operate<T>> Expression<T, O> {
    fn compute_stack_max(expr: &[Arithm<T, O>]) -> usize {
        expr.iter().map(|arithm| {
            match *arithm {
                Arithm::Operand(_) => 1,
                Arithm::Operator(ref op) => {
                    op.operands_generated() as isize - op.operands_needed() as isize
                }
            }
        }).fold((0, 0isize), |(max, acc_count), count| {
            let acc = (acc_count + count) as usize;
            if acc > max { (acc, acc as isize) } else { (max, acc as isize) }
        }).0
    }
}

impl<'a, T, O> TryFrom<&'a str> for Expression<T, O>
    where T: FromStr,
          O: Operate<T> + TryFrom<&'a str>
{
    type Err = ExprResult<<T as FromStr>::Err, <O as TryFrom<&'a str>>::Err>;
    fn try_from(expr: &'a str) -> Result<Self, Self::Err> {
        use self::ExprResult::*;
        let mut final_expr = Vec::new();
        for token in expr.split_whitespace() {
            let arithm = match token.parse() {
                Ok(operand) => Arithm::Operand(operand),
                Err(operand_err) => {
                    match TryInto::<O>::try_into(token) {
                        Ok(operator) => Arithm::Operator(operator),
                        Err(operator_err) => return Err(InvalidToken(operand_err, operator_err)),
                    }
                }
            };
            final_expr.push(arithm);
        }
        Expression::check_validity(&final_expr)
            .map(|_| {
                Expression {
                    stack_max: Expression::compute_stack_max(&final_expr),
                    expr: final_expr
                }
            })
    }
}

impl<T, O: Operate<T>> From<Vec<Arithm<T, O>>> for Expression<T, O> {
    fn from(expr: Vec<Arithm<T, O>>) -> Self {
        Expression {
            stack_max: Expression::compute_stack_max(&expr),
            expr: expr
        }
    }
}

impl<T, O: Operate<T>> Into<Vec<Arithm<T, O>>> for Expression<T, O> {
    fn into(self) -> Vec<Arithm<T, O>> {
        self.expr
    }
}

impl<T, O: Operate<T>> Deref for Expression<T, O> {
    type Target = Vec<Arithm<T, O>>;
    fn deref(&self) -> &Self::Target {
        &self.expr
    }
}

impl<T, O: Operate<T>> DerefMut for Expression<T, O> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.expr
    }
}

impl<T, O> fmt::Display for Expression<T, O>
    where T: fmt::Display,
          O: Operate<T> + fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let len = self.expr.len();
        for (i, arithm) in self.expr.iter().enumerate() {
            match *arithm {
                Arithm::Operand(ref operand) => operand.fmt(f)?,
                Arithm::Operator(ref operator) => operator.fmt(f)?,
            }
            if i != len - 1 {
                f.write_str(" ")?
            }
        }
        Ok(())
    }
}
<commit_msg>expression: Remove Deref/Mut Trait impl<commit_after>use std::convert::{From, TryFrom, TryInto};
use std::str::FromStr;
use std::fmt;
use stack::Stack;
use operate::Operate;

/// Used to specify an `Operand` or an `Operator`.
#[derive(Debug, Copy, Clone)]
pub enum Arithm<T, O: Operate<T>> {
    Operand(T),
    Operator(O),
}

/// Interpret a [`Reverse Polish notated`] expression (cf. `3 4 +`).
///
/// `Operate` method returns the valid result or an [`Operate::Err`] if an operation fails.
///
/// `Expressions` are constructed from [`str`] the most of the time.
/// Use the [`try_into()`] method to create an `Expression` type,
/// the result contain informations about the possible error at conversion time.
///
/// [`Reverse Polish notated`]: https://en.wikipedia.org/wiki/Reverse_Polish_notation
/// [`Operate::Err`]: ../operate/trait.Operate.html#associatedtype.Err
/// [`str`]: https://doc.rust-lang.org/std/str/index.html
/// [`try_into()`]: https://doc.rust-lang.org/std/convert/trait.TryInto.html#tymethod.try_into
#[derive(Debug)]
pub struct Expression<T, O: Operate<T>> {
    stack_max: usize,
    expr: Vec<Arithm<T, O>>,
}

impl<T: Copy, O: Operate<T> + Copy> Expression<T, O> {
    /// Evaluate the `RPN` expression. Returns the result or the [`operate Error`].
    ///
    /// [`operate Error`]: ../operate/trait.Operate.html#associatedtype.Err
    pub fn operate(&self) -> Result<T, O::Err> {
        let mut stack = Stack::with_capacity(self.stack_max);
        for arithm in &self.expr {
            match *arithm {
                Arithm::Operand(operand) => stack.push(operand),
                Arithm::Operator(operator) => operator.operate(&mut stack)?,
            }
        }
        Ok(stack.pop().unwrap())
    }
}

/// Used to specify the error during the convertion.
#[derive(Debug, PartialEq)]
pub enum ExprResult<A, B> {
    TooManyOperands,
    NotEnoughOperand,
    InvalidToken(A, B),
}

impl<'a, T, O> Expression<T, O>
    where T: FromStr,
          O: Operate<T> + TryFrom<&'a str>
{
    fn check_validity(expr: &[Arithm<T, O>])
        -> Result<(), ExprResult<<T as FromStr>::Err, <O as TryFrom<&'a str>>::Err>> {
        use self::ExprResult::*;
        let mut num_operands: usize = 0;
        for arithm in expr {
            match *arithm {
                Arithm::Operand(_) => num_operands += 1,
                Arithm::Operator(ref operator) => {
                    let needed = operator.operands_needed();
                    num_operands = num_operands.checked_sub(needed).ok_or(NotEnoughOperand)?;
                    num_operands += operator.operands_generated();
                },
            }
        }
        match num_operands {
            0 => Err(NotEnoughOperand),
            1 => Ok(()),
            _ => Err(TooManyOperands),
        }
    }
}

impl<T, O: Operate<T>> Expression<T, O> {
    fn compute_stack_max(expr: &[Arithm<T, O>]) -> usize {
        expr.iter().map(|arithm| {
            match *arithm {
                Arithm::Operand(_) => 1,
                Arithm::Operator(ref op) => {
                    op.operands_generated() as isize - op.operands_needed() as isize
                }
            }
        }).fold((0, 0isize), |(max, acc_count), count| {
            let acc = (acc_count + count) as usize;
            if acc > max { (acc, acc as isize) } else { (max, acc as isize) }
        }).0
    }
}

impl<'a, T, O> TryFrom<&'a str> for Expression<T, O>
    where T: FromStr,
          O: Operate<T> + TryFrom<&'a str>
{
    type Err = ExprResult<<T as FromStr>::Err, <O as TryFrom<&'a str>>::Err>;
    fn try_from(expr: &'a str) -> Result<Self, Self::Err> {
        use self::ExprResult::*;
        let mut final_expr = Vec::new();
        for token in expr.split_whitespace() {
            let arithm = match token.parse() {
                Ok(operand) => Arithm::Operand(operand),
                Err(operand_err) => {
                    match TryInto::<O>::try_into(token) {
                        Ok(operator) => Arithm::Operator(operator),
                        Err(operator_err) => return Err(InvalidToken(operand_err, operator_err)),
                    }
                }
            };
            final_expr.push(arithm);
        }
        Expression::check_validity(&final_expr)
            .map(|_| {
                Expression {
                    stack_max: Expression::compute_stack_max(&final_expr),
                    expr: final_expr
                }
            })
    }
}

impl<T, O: Operate<T>> From<Vec<Arithm<T, O>>> for Expression<T, O> {
    fn from(expr: Vec<Arithm<T, O>>) -> Self {
        Expression {
            stack_max: Expression::compute_stack_max(&expr),
            expr: expr
        }
    }
}

impl<T, O: Operate<T>> Into<Vec<Arithm<T, O>>> for Expression<T, O> {
    fn into(self) -> Vec<Arithm<T, O>> {
        self.expr
    }
}

impl<T, O> fmt::Display for Expression<T, O>
    where T: fmt::Display,
          O: Operate<T> + fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let len = self.expr.len();
        for (i, arithm) in self.expr.iter().enumerate() {
            match *arithm {
                Arithm::Operand(ref operand) => operand.fmt(f)?,
                Arithm::Operator(ref operator) => operator.fmt(f)?,
            }
            if i != len - 1 {
                f.write_str(" ")?
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use crate::syntax::instantiate::NamedImplKey;
use crate::syntax::{Lifetimes, NamedType, Pair, Types};
use proc_macro2::Ident;

#[derive(Copy, Clone)]
pub struct Resolution<'a> {
    pub name: &'a Pair,
    pub generics: &'a Lifetimes,
}

impl<'a> Types<'a> {
    pub fn resolve(&self, ident: &impl UnresolvedName) -> Resolution<'a> {
        *self
            .resolutions
            .get(ident.ident())
            .expect("Unable to resolve type")
    }
}

pub trait UnresolvedName {
    fn ident(&self) -> &Ident;
}

impl UnresolvedName for Ident {
    fn ident(&self) -> &Ident {
        self
    }
}

impl UnresolvedName for NamedType {
    fn ident(&self) -> &Ident {
        &self.rust
    }
}

impl<'a> UnresolvedName for NamedImplKey<'a> {
    fn ident(&self) -> &Ident {
        self.rust
    }
}
<commit_msg>Print type name in type resolver error<commit_after>use crate::syntax::instantiate::NamedImplKey;
use crate::syntax::{Lifetimes, NamedType, Pair, Types};
use proc_macro2::Ident;

#[derive(Copy, Clone)]
pub struct Resolution<'a> {
    pub name: &'a Pair,
    pub generics: &'a Lifetimes,
}

impl<'a> Types<'a> {
    pub fn resolve(&self, ident: &impl UnresolvedName) -> Resolution<'a> {
        let ident = ident.ident();
        match self.resolutions.get(ident) {
            Some(resolution) => *resolution,
            None => panic!("Unable to resolve type `{}`", ident),
        }
    }
}

pub trait UnresolvedName {
    fn ident(&self) -> &Ident;
}

impl UnresolvedName for Ident {
    fn ident(&self) -> &Ident {
        self
    }
}

impl UnresolvedName for NamedType {
    fn ident(&self) -> &Ident {
        &self.rust
    }
}

impl<'a> UnresolvedName for NamedImplKey<'a> {
    fn ident(&self) -> &Ident {
        self.rust
    }
}
<|endoftext|>


<commit_before>#[crate_id(name="mkdir", vers="1.0.0", author="Nicholas Juszczak")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Nicholas Juszczak <juszczakn@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#[feature(macro_rules)];

extern crate extra;
extern crate getopts;

use std::os;
use std::io::fs;
use std::num::strconv;

#[path = "../common/util.rs"]
mod util;

static NAME: &'static str = "mkdir";
static VERSION: &'static str = "1.0.0";

/**
 * Handles option parsing
 */
fn main() {
    let args = os::args();

    let opts = ~[
        // Linux-specific options, not implemented
        // getopts::optflag("Z", "context", "set SELinux secutiry context" +
        // " of each created directory to CTX"),
        getopts::optopt("m", "mode", "set file mode", "755"),
        getopts::optflag("p", "parents", "make parent directories as needed"),
        getopts::optflag("v", "verbose",
                        "print a message for each printed directory"),
        getopts::optflag("h", "help", "display this help"),
        getopts::optflag("V", "version", "display this version")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            crash!(1, "Invalid options\n{}", f.to_err_msg());
        }
    };

    if args.len() == 1 || matches.opt_present("help") {
        print_help(opts);
        return;
    }
    if matches.opt_present("version") {
        println!("mkdir v{}", VERSION);
        return;
    }
    let verbose_flag = matches.opt_present("verbose");
    let mk_parents = matches.opt_present("parents");

    // Translate a ~str in octal form to u32, default to 755
    // Not tested on Windows
    let mode_match = matches.opts_str(&[~"mode"]);
    let mode: u32 = if mode_match.is_some() {
        let m = mode_match.unwrap();
        let res = strconv::from_str_common(m, 8, false, false, false,
                                           strconv::ExpNone,
                                           false, false);
        if res.is_some() {
            res.unwrap()
        } else {
            crash!(1, "no mode given");
        }
    } else {
        0o755
    };

    let dirs = matches.free;
    exec(dirs, mk_parents, mode, verbose_flag);
}

fn print_help(opts: &[getopts::OptGroup]) {
    println!("mkdir v{} - make a new directory with the given path", VERSION);
    println!("");
    println!("Usage:");
    print!("{}", getopts::usage("Create the given DIRECTORY(ies)" +
                               " if they do not exist", opts));
}

/**
 * Create the list of new directories
 */
fn exec(dirs: ~[~str], mk_parents: bool, mode: u32, verbose: bool) {
    let mut parent_dirs: ~[~str] = ~[];
    if mk_parents {
        for dir in dirs.iter() {
            let path = Path::new((*dir).clone());
            // Build list of parent dirs which need to be created
            let parent = path.dirname_str();
            match parent {
                Some(p) => {
                    if !Path::new(p).exists() {
                        parent_dirs.push(p.into_owned())
                    }
                },
                None => ()
            }
        }
    }
    // Recursively build parent dirs that are needed
    if !parent_dirs.is_empty() {
        exec(parent_dirs, mk_parents, mode, verbose);
    }

    for dir in dirs.iter() {
        let path = Path::new((*dir).clone());
        // Determine if parent directory to the one to
        // be created exists
        let parent = match path.dirname_str() {
            Some(p) => p,
            None => ""
        };
        let parent_exists = Path::new(parent).exists();
        if parent_exists && !path.exists() {
            mkdir(&path, mode);
            if verbose {println!("{}", *dir);}
        } else {
            let mut error_msg = ~"";
            if !parent_exists {
                error_msg.push_str("Error: parent directory '");
                error_msg.push_str(parent);
                error_msg.push_str("' does not exist");
            } else {
                error_msg.push_str("Error: directory '");
                error_msg.push_str(*dir);
                error_msg.push_str("' already exists");
            }
            show_error!(1, "{}", error_msg);
        }
    }
}

/**
 * Wrapper to catch errors, return false if failed
 */
fn mkdir(path: &Path, mode: u32) {
    match fs::mkdir(path, mode) {
        Ok(_) => {},
        Err(e) => {
            crash!(1, "test {}", e.to_str());
        }
    }
}
<commit_msg>mkdir: improve error handling (closes #121)<commit_after>#[crate_id(name="mkdir", vers="1.0.0", author="Nicholas Juszczak")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Nicholas Juszczak <juszczakn@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#[feature(macro_rules)];

extern crate extra;
extern crate getopts;

use std::os;
use std::io::fs;
use std::num::strconv;

#[path = "../common/util.rs"]
mod util;

static NAME: &'static str = "mkdir";
static VERSION: &'static str = "1.0.0";

/**
 * Handles option parsing
 */
fn main() {
    let args = os::args();

    let opts = ~[
        // Linux-specific options, not implemented
        // getopts::optflag("Z", "context", "set SELinux secutiry context" +
        // " of each created directory to CTX"),
        getopts::optopt("m", "mode", "set file mode", "755"),
        getopts::optflag("p", "parents", "make parent directories as needed"),
        getopts::optflag("v", "verbose",
                        "print a message for each printed directory"),
        getopts::optflag("h", "help", "display this help"),
        getopts::optflag("V", "version", "display this version")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            crash!(1, "Invalid options\n{}", f.to_err_msg());
        }
    };

    if args.len() == 1 || matches.opt_present("help") {
        print_help(opts);
        return;
    }
    if matches.opt_present("version") {
        println!("mkdir v{}", VERSION);
        return;
    }
    let verbose_flag = matches.opt_present("verbose");
    let mk_parents = matches.opt_present("parents");

    // Translate a ~str in octal form to u32, default to 755
    // Not tested on Windows
    let mode_match = matches.opts_str(&[~"mode"]);
    let mode: u32 = if mode_match.is_some() {
        let m = mode_match.unwrap();
        let res = strconv::from_str_common(m, 8, false, false, false,
                                           strconv::ExpNone,
                                           false, false);
        if res.is_some() {
            res.unwrap()
        } else {
            crash!(1, "no mode given");
        }
    } else {
        0o755
    };

    let dirs = matches.free;
    exec(dirs, mk_parents, mode, verbose_flag);
}

fn print_help(opts: &[getopts::OptGroup]) {
    println!("mkdir v{} - make a new directory with the given path", VERSION);
    println!("");
    println!("Usage:");
    print!("{}", getopts::usage("Create the given DIRECTORY(ies)" +
                               " if they do not exist", opts));
}

/**
 * Create the list of new directories
 */
fn exec(dirs: ~[~str], mk_parents: bool, mode: u32, verbose: bool) {
    let mut parent_dirs: ~[~str] = ~[];
    if mk_parents {
        for dir in dirs.iter() {
            let path = Path::new((*dir).clone());
            // Build list of parent dirs which need to be created
            let parent = path.dirname_str();
            match parent {
                Some(p) => {
                    if !Path::new(p).exists() {
                        parent_dirs.push(p.into_owned())
                    }
                },
                None => ()
            }
        }
    }
    // Recursively build parent dirs that are needed
    if !parent_dirs.is_empty() {
        exec(parent_dirs, mk_parents, mode, verbose);
    }

    for dir in dirs.iter() {
        let path = Path::new((*dir).clone());
        // Determine if parent directory to the one to
        // be created exists
        let parent = match path.dirname_str() {
            Some(p) => p,
            None => ""
        };
        let parent_exists = Path::new(parent).exists();
        if parent_exists && !path.exists() {
            mkdir(&path, mode);
            if verbose {println!("{}", *dir);}
        } else if !mk_parents {
            let mut error_msg = ~"";
            if !parent_exists {
                error_msg.push_str("parent directory '");
                error_msg.push_str(parent);
                error_msg.push_str("' does not exist");
            } else {
                error_msg.push_str("directory '");
                error_msg.push_str(*dir);
                error_msg.push_str("' already exists");
            }
            show_error!(1, "{}", error_msg);
        }
    }
}

/**
 * Wrapper to catch errors, return false if failed
 */
fn mkdir(path: &Path, mode: u32) {
    match fs::mkdir(path, mode) {
        Ok(_) => {},
        Err(e) => {
            crash!(1, "test {}", e.to_str());
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code, non_camel_case_types)]
#[macro_use]
extern crate derive_more;

#[derive(
    From,
    FromStr,
    Display,
    Index,
    Not,
    Add,
    Mul,
    Sum,
    IndexMut,
    AddAssign,
    Deref,
    DerefMut,
    IntoIterator,
    Constructor
)]
#[deref(forward)]
#[deref_mut(forward)]
#[into_iterator(owned, ref, ref_mut)]
struct Wrapped<T: Clone>(T);

#[derive(Deref, DerefMut)]
struct Wrapped2<T: Clone>(T);

#[derive(From, Not, Add, Mul, AddAssign, Constructor, Sum)]
struct WrappedDouble<T: Clone, U: Clone>(T, U);

#[derive(
    From,
    FromStr,
    Display,
    Index,
    Not,
    Add,
    Mul,
    IndexMut,
    AddAssign,
    Deref,
    DerefMut,
    IntoIterator,
    Constructor,
    Sum
)]
#[deref(forward)]
#[deref_mut(forward)]
#[into_iterator(owned, ref, ref_mut)]
struct Struct<T: Clone> {
    t: T,
}

#[derive(Deref, DerefMut)]
struct Struct2<T: Clone> {
    t: T,
}

#[derive(From, Not, Add, Mul, AddAssign, Constructor, Sum)]
struct DoubleStruct<T: Clone, U: Clone> {
    t: T,
    u: U,
}

#[derive(From, Not, Add)]
enum TupleEnum<T: Clone, U: Clone> {
    Tuple(T),
    DoubleTuple(T, U),
}

#[derive(From, Not, Add)]
enum StructEnum<T: Clone, U: Clone> {
    Struct { t: T },
    DoubleStruct { t: T, u: U },
}
<commit_msg>Add generics tests for MulAssign<commit_after>#![allow(dead_code, non_camel_case_types)]
#[macro_use]
extern crate derive_more;

#[derive(
    From,
    FromStr,
    Display,
    Index,
    Not,
    Add,
    Mul,
    Sum,
    IndexMut,
    AddAssign,
    MulAssign,
    Deref,
    DerefMut,
    IntoIterator,
    Constructor
)]
#[deref(forward)]
#[deref_mut(forward)]
#[into_iterator(owned, ref, ref_mut)]
struct Wrapped<T: Clone>(T);

#[derive(Deref, DerefMut)]
struct Wrapped2<T: Clone>(T);

#[derive(From, Not, Add, Mul, AddAssign, MulAssign, Constructor, Sum)]
struct WrappedDouble<T: Clone, U: Clone>(T, U);

#[derive(
    From,
    FromStr,
    Display,
    Index,
    Not,
    Add,
    Mul,
    IndexMut,
    AddAssign,
    MulAssign,
    Deref,
    DerefMut,
    IntoIterator,
    Constructor,
    Sum
)]
#[deref(forward)]
#[deref_mut(forward)]
#[into_iterator(owned, ref, ref_mut)]
struct Struct<T: Clone> {
    t: T,
}

#[derive(Deref, DerefMut)]
struct Struct2<T: Clone> {
    t: T,
}

#[derive(From, Not, Add, Mul, AddAssign, MulAssign, Constructor, Sum)]
struct DoubleStruct<T: Clone, U: Clone> {
    t: T,
    u: U,
}

#[derive(From, Not, Add)]
enum TupleEnum<T: Clone, U: Clone> {
    Tuple(T),
    DoubleTuple(T, U),
}

#[derive(From, Not, Add)]
enum StructEnum<T: Clone, U: Clone> {
    Struct { t: T },
    DoubleStruct { t: T, u: U },
}
<|endoftext|>