<commit_before>extern crate serde_json;
extern crate postgres;

use std::fs::File;
use std::io::{Write, BufWriter};
use std::collections::HashMap;

use self::postgres::Connection;

type CvName = String;

pub type MiscExtRange = String;

pub type GeneUniquename = String;
pub type TermUniquename = String;
pub type ReferenceUniquename = String;
pub type GeneName = String;
pub type TypeName = String;
pub type GeneProduct = String;

pub type TermName = String;
pub type TermId = String;
pub type TermDef = String;

pub type Evidence = String;
pub type Residue = String;
pub type Condition = String;
pub type Qualifier = String;

pub type TypeInteractionAnnotationMap =
    HashMap<TypeName, Vec<InteractionAnnotation>>;

pub type UniquenameGeneMap =
    HashMap<GeneUniquename, GeneDetails>;

pub type TranscriptUniquename = String;

pub type UniquenameTranscriptMap =
    HashMap<TranscriptUniquename, TranscriptDetails>;

pub type GenotypeUniquename = String;
pub type AlleleUniquename = String;

pub type UniquenameAlleleMap = HashMap<AlleleUniquename, AlleleShort>;
pub type UniquenameGenotypeMap = HashMap<GenotypeUniquename, GenotypeShort>;

pub type IdGeneMap = HashMap<GeneUniquename, GeneDetails>;
pub type IdGeneShortMap = HashMap<GeneUniquename, GeneShort>;
pub type IdTermShortMap = HashMap<TermId, Rc<TermShort>>;
pub type IdTermDetailsMap = HashMap<TermId, Rc<TermDetails>>;
pub type IdReferenceMap = HashMap<TermId, ReferenceDetails>;

include!(concat!(env!("OUT_DIR"), "/data_serde.rs"));

impl WebData {
    fn get_genes(&self) -> &IdGeneMap {
        &self.genes
    }
    fn get_terms(&self) -> &IdTermDetailsMap {
        &self.terms
    }

    fn write_reference_details(&self, output_dir: &str) {
        for (reference_uniquename, reference_details) in &self.references {
            let s = serde_json::to_string(&reference_details).unwrap();
            let file_name = String::new() + &output_dir + "/reference/" + &reference_uniquename + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write reference JSON");
        }
    }

    fn write_gene_details(&self, output_dir: &str) {
        for (gene_uniquename, gene_details) in &self.genes {
            let s = serde_json::to_string(&gene_details).unwrap();
            let file_name = String::new() + &output_dir + "/gene/" + &gene_uniquename + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write gene JSON");
        }
    }

    fn write_gene_summaries(&self, output_dir: &str, organism_genus_species: &str) {
        let filtered_gene_summaries =
            self.search_api_maps.gene_summaries.iter()
            .filter(|gene_summary| {
                let feature_org_genus_species = String::new() +
                    &gene_summary.organism.genus + "_" + &gene_summary.organism.species;
                feature_org_genus_species == organism_genus_species
            })
            .map(|gene_summary| gene_summary.clone())
            .collect::<Vec<GeneSummary>>();
        let s = serde_json::to_string(&filtered_gene_summaries).unwrap();
        let file_name = String::new() + &output_dir + "/gene_summaries.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write gene_summaries.json");
    }

    fn write_terms(&self, output_dir: &str) {
        for (termid, term_details) in &self.terms {
            let s = serde_json::to_string(&term_details).unwrap();
            let file_name = String::new() + &output_dir + "/term/" + &termid + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write term JSON");
        }
    }

    fn write_metadata(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.metadata).unwrap();
        let file_name = String::new() + &output_dir + "/metadata.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write metadata.json");
    }

    fn write_search_api_maps(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.search_api_maps).unwrap();
        let file_name = String::new() + &output_dir + "/search_api_maps.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");
    }

    pub fn write(&self, output_dir: &str, organism_genus_species: &str) {
        self.write_reference_details(output_dir);
        self.write_gene_details(output_dir);
        self.write_gene_summaries(output_dir, organism_genus_species);
        self.write_terms(output_dir);
        self.write_metadata(output_dir);
        self.write_search_api_maps(output_dir);

        println!("wrote {} genes", self.get_genes().len());
        println!("wrote {} terms", self.get_terms().len());
    }

    pub fn store_jsonb(&self, conn: &Connection) {
        let trans = conn.transaction().unwrap();

        for (uniquename, gene_details) in &self.genes {
            let serde_value = serde_json::value::to_value(&gene_details);
            trans.execute("INSERT INTO web_json.gene (uniquename, data) values ($1, $2)",
                          &[&uniquename, &serde_value]).unwrap();
        }
        for (uniquename, ref_details) in &self.references {
            let serde_value = serde_json::value::to_value(&ref_details);
            trans.execute("INSERT INTO web_json.reference (uniquename, data) values ($1, $2)",
                          &[&uniquename, &serde_value]).unwrap();
        }
        for (termid, term_details) in &self.terms {
            let serde_value = serde_json::value::to_value(&term_details);
            trans.execute("INSERT INTO web_json.term (termid, data) values ($1, $2)",
                         &[&termid, &serde_value]).unwrap();
        }

        trans.execute("CREATE INDEX gene_jsonb_idx ON web_json.gene USING gin (data jsonb_path_ops)", &[]).unwrap();
        trans.execute("CREATE INDEX gene_jsonb_name_idx ON web_json.gene USING gin ((data->>'name') gin_trgm_ops);", &[]).unwrap();
        trans.execute("CREATE INDEX term_jsonb_idx ON web_json.term USING gin (data jsonb_path_ops)", &[]).unwrap();
        trans.execute("CREATE INDEX term_jsonb_name_idx ON web_json.term USING gin ((data->>'name') gin_trgm_ops);", &[]).unwrap();
        trans.execute("CREATE INDEX reference_jsonb_idx ON web_json.reference USING gin (data jsonb_path_ops)", &[]).unwrap();
        trans.execute("CREATE INDEX reference_jsonb_title_idx ON web_json.reference USING gin ((data->>'title') gin_trgm_ops);", &[]).unwrap();

        trans.commit().unwrap();
    }
}
<commit_msg>Write number of references to stdout<commit_after>extern crate serde_json;
extern crate postgres;

use std::fs::File;
use std::io::{Write, BufWriter};
use std::collections::HashMap;

use self::postgres::Connection;

type CvName = String;

pub type MiscExtRange = String;

pub type GeneUniquename = String;
pub type TermUniquename = String;
pub type ReferenceUniquename = String;
pub type GeneName = String;
pub type TypeName = String;
pub type GeneProduct = String;

pub type TermName = String;
pub type TermId = String;
pub type TermDef = String;

pub type Evidence = String;
pub type Residue = String;
pub type Condition = String;
pub type Qualifier = String;

pub type TypeInteractionAnnotationMap =
    HashMap<TypeName, Vec<InteractionAnnotation>>;

pub type UniquenameGeneMap =
    HashMap<GeneUniquename, GeneDetails>;

pub type TranscriptUniquename = String;

pub type UniquenameTranscriptMap =
    HashMap<TranscriptUniquename, TranscriptDetails>;

pub type GenotypeUniquename = String;
pub type AlleleUniquename = String;

pub type UniquenameAlleleMap = HashMap<AlleleUniquename, AlleleShort>;
pub type UniquenameGenotypeMap = HashMap<GenotypeUniquename, GenotypeShort>;

pub type IdGeneMap = HashMap<GeneUniquename, GeneDetails>;
pub type IdGeneShortMap = HashMap<GeneUniquename, GeneShort>;
pub type IdTermShortMap = HashMap<TermId, Rc<TermShort>>;
pub type IdTermDetailsMap = HashMap<TermId, Rc<TermDetails>>;
pub type IdReferenceMap = HashMap<TermId, ReferenceDetails>;

include!(concat!(env!("OUT_DIR"), "/data_serde.rs"));

impl WebData {
    fn get_genes(&self) -> &IdGeneMap {
        &self.genes
    }
    fn get_references(&self) -> &IdReferenceMap {
        &self.references
    }
    fn get_terms(&self) -> &IdTermDetailsMap {
        &self.terms
    }

    fn write_reference_details(&self, output_dir: &str) {
        for (reference_uniquename, reference_details) in &self.references {
            let s = serde_json::to_string(&reference_details).unwrap();
            let file_name = String::new() + &output_dir + "/reference/" + &reference_uniquename + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write reference JSON");
        }
    }

    fn write_gene_details(&self, output_dir: &str) {
        for (gene_uniquename, gene_details) in &self.genes {
            let s = serde_json::to_string(&gene_details).unwrap();
            let file_name = String::new() + &output_dir + "/gene/" + &gene_uniquename + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write gene JSON");
        }
    }

    fn write_gene_summaries(&self, output_dir: &str, organism_genus_species: &str) {
        let filtered_gene_summaries =
            self.search_api_maps.gene_summaries.iter()
            .filter(|gene_summary| {
                let feature_org_genus_species = String::new() +
                    &gene_summary.organism.genus + "_" + &gene_summary.organism.species;
                feature_org_genus_species == organism_genus_species
            })
            .map(|gene_summary| gene_summary.clone())
            .collect::<Vec<GeneSummary>>();
        let s = serde_json::to_string(&filtered_gene_summaries).unwrap();
        let file_name = String::new() + &output_dir + "/gene_summaries.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write gene_summaries.json");
    }

    fn write_terms(&self, output_dir: &str) {
        for (termid, term_details) in &self.terms {
            let s = serde_json::to_string(&term_details).unwrap();
            let file_name = String::new() + &output_dir + "/term/" + &termid + ".json";
            let f = File::create(file_name).expect("Unable to open file");
            let mut writer = BufWriter::new(&f);
            writer.write_all(s.as_bytes()).expect("Unable to write term JSON");
        }
    }

    fn write_metadata(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.metadata).unwrap();
        let file_name = String::new() + &output_dir + "/metadata.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write metadata.json");
    }

    fn write_search_api_maps(&self, output_dir: &str) {
        let s = serde_json::to_string(&self.search_api_maps).unwrap();
        let file_name = String::new() + &output_dir + "/search_api_maps.json";
        let f = File::create(file_name).expect("Unable to open file");
        let mut writer = BufWriter::new(&f);
        writer.write_all(s.as_bytes()).expect("Unable to write!");
    }

    pub fn write(&self, output_dir: &str, organism_genus_species: &str) {
        self.write_reference_details(output_dir);
        println!("wrote {} references", self.get_references().len());
        self.write_gene_details(output_dir);
        println!("wrote {} genes", self.get_genes().len());
        self.write_gene_summaries(output_dir, organism_genus_species);
        println!("wrote gene summaries");
        self.write_terms(output_dir);
        println!("wrote {} terms", self.get_terms().len());
        self.write_metadata(output_dir);
        println!("wrote metadata");
        self.write_search_api_maps(output_dir);
        println!("wrote search data");
    }

    pub fn store_jsonb(&self, conn: &Connection) {
        let trans = conn.transaction().unwrap();

        for (uniquename, gene_details) in &self.genes {
            let serde_value = serde_json::value::to_value(&gene_details);
            trans.execute("INSERT INTO web_json.gene (uniquename, data) values ($1, $2)",
                          &[&uniquename, &serde_value]).unwrap();
        }
        for (uniquename, ref_details) in &self.references {
            let serde_value = serde_json::value::to_value(&ref_details);
            trans.execute("INSERT INTO web_json.reference (uniquename, data) values ($1, $2)",
                          &[&uniquename, &serde_value]).unwrap();
        }
        for (termid, term_details) in &self.terms {
            let serde_value = serde_json::value::to_value(&term_details);
            trans.execute("INSERT INTO web_json.term (termid, data) values ($1, $2)",
                         &[&termid, &serde_value]).unwrap();
        }

        trans.execute("CREATE INDEX gene_jsonb_idx ON web_json.gene USING gin (data jsonb_path_ops)", &[]).unwrap();
        trans.execute("CREATE INDEX gene_jsonb_name_idx ON web_json.gene USING gin ((data->>'name') gin_trgm_ops);", &[]).unwrap();
        trans.execute("CREATE INDEX term_jsonb_idx ON web_json.term USING gin (data jsonb_path_ops)", &[]).unwrap();
        trans.execute("CREATE INDEX term_jsonb_name_idx ON web_json.term USING gin ((data->>'name') gin_trgm_ops);", &[]).unwrap();
        trans.execute("CREATE INDEX reference_jsonb_idx ON web_json.reference USING gin (data jsonb_path_ops)", &[]).unwrap();
        trans.execute("CREATE INDEX reference_jsonb_title_idx ON web_json.reference USING gin ((data->>'title') gin_trgm_ops);", &[]).unwrap();

        trans.commit().unwrap();
    }
}
<|endoftext|>


<commit_before>use std::hashmap::HashMap;
use std::num::FromPrimitive;
use std::ptr;
use std::str;
use std::vec;

use keycode::KeyCode;
use rect::Rect;
use scancode::ScanCode;
use video::Window;

pub mod ll {
    use std::libc::{c_int, c_schar, c_uint, int32_t, uint8_t, uint16_t,
                    uint32_t};
    use rect::Rect;
    use video::ll::SDL_Window;

    pub type SDL_bool = c_int;
    pub type SDL_Rect = Rect;
    pub type SDL_Keycode = int32_t;
    pub type SDL_Keymod = c_uint;
    pub type SDL_Scancode = c_uint;

    // SDL_keyboard.h
    pub struct SDL_Keysym {
        scancode: SDL_Scancode,
        sym: SDL_Keycode,
        _mod: uint16_t,
        unused: uint32_t,
    }

    externfn!(fn SDL_GetKeyboardFocus() -> *SDL_Window)
    externfn!(fn SDL_GetKeyboardState(numkeys: *c_int) -> *uint8_t)
    externfn!(fn SDL_GetModState() -> SDL_Keymod)
    externfn!(fn SDL_SetModState(modstate: SDL_Keymod))
    externfn!(fn SDL_GetKeyFromScancode(scancode: SDL_Scancode) -> SDL_Keycode)
    externfn!(fn SDL_GetScancodeFromKey(key: SDL_Keycode) -> SDL_Scancode)
    externfn!(fn SDL_GetScancodeName(scancode: SDL_Scancode) -> *c_schar)
    externfn!(fn SDL_GetScancodeFromName(name: *c_schar) -> SDL_Scancode)
    externfn!(fn SDL_GetKeyName(key: SDL_Keycode) -> *c_schar)
    externfn!(fn SDL_GetKeyFromName(name: *c_schar) -> SDL_Keycode)
    externfn!(fn SDL_StartTextInput())
    externfn!(fn SDL_IsTextInputActive() -> SDL_bool)
    externfn!(fn SDL_StopTextInput())
    externfn!(fn SDL_SetTextInputRect(rect: *SDL_Rect))
    externfn!(fn SDL_HasScreenKeyboardSupport() -> SDL_bool)
    externfn!(fn SDL_IsScreenKeyboardShown(window: *SDL_Window) -> SDL_bool)
}

#[deriving(Eq)]
pub enum Mod {
     NoMod = 0x0000,
     LShiftMod = 0x0001,
     RShiftMod = 0x0002,
     LCtrlMod = 0x0040,
     RCtrlMod = 0x0080,
     LAltMod = 0x0100,
     RAltMod = 0x0200,
     LGuiMod = 0x0400,
     RGuiMod = 0x0800,
     NumMod = 0x1000,
     CapsMod = 0x2000,
     ModeMod = 0x4000,
     ReservedMod = 0x8000
}

pub fn wrap_mod_state(bitflags: ll::SDL_Keymod) -> ~[Mod] {
    let flags = [NoMod,
        LShiftMod,
        RShiftMod,
        LCtrlMod,
        RCtrlMod,
        LAltMod,
        RAltMod,
        LGuiMod,
        RGuiMod,
        NumMod,
        CapsMod,
        ModeMod,
        ReservedMod];

    do flags.iter().filter_map |&flag| {
        if bitflags & (flag as ll::SDL_Keymod) != 0 { Some(flag) }
        else { None }
    }.collect()
}

pub fn get_keyboard_focus() -> Option<~Window> {
    let raw = unsafe { ll::SDL_GetKeyboardFocus() };
    if raw == ptr::null() {
        None
    } else {
        Some(~Window{ raw: raw, owned: false })
    }
}

pub fn get_keyboard_state() -> ~HashMap<ScanCode, bool> {
    let mut state: ~HashMap<ScanCode, bool> = ~HashMap::new();
    let count = 0;

    let raw = unsafe { vec::raw::from_buf_raw(ll::SDL_GetKeyboardState(&count),
                                              count as uint) };

    let mut current = 0;
    while current < raw.len() {
        state.insert(FromPrimitive::from_int(current as int).unwrap(),
                     raw[current] == 1);
        current += 1;
    }

    return state;
}

pub fn get_mod_state() -> ~[Mod] {
    unsafe { wrap_mod_state(ll::SDL_GetModState()) }
}

pub fn set_mod_state(flags: &[Mod]) {
    let mut state = 0;
    for flag in flags.iter() {
        state |= *flag as ll::SDL_Keymod;
    }

    unsafe { ll::SDL_SetModState(state); }
}

pub fn get_key_from_scancode(scancode: ScanCode) -> KeyCode {
    unsafe {
        FromPrimitive::from_int(ll::SDL_GetKeyFromScancode(scancode.code()
                                                            as u32) as int)
    }
}

pub fn get_scancode_from_key(key: KeyCode) -> ScanCode {
    unsafe {
        FromPrimitive::from_int(ll::SDL_GetScancodeFromKey(key.code())
                                 as int)
    }
}

pub fn get_scancode_name(scancode: ScanCode) -> ~str {
    unsafe {
        str::raw::from_c_str(ll::SDL_GetScancodeName(scancode.code() as u32))
    }
}

pub fn get_scancode_from_name(name: &str) -> ScanCode {
    unsafe {
        do name.with_c_str |name| {
            FromPrimitive::from_int(ll::SDL_GetScancodeFromName(name) as int)
        }
    }
}

pub fn get_key_name(key: KeyCode) -> ~str {
    unsafe {
        str::raw::from_c_str(ll::SDL_GetKeyName(key.code()))
    }
}

pub fn get_key_from_name(name: &str) -> KeyCode {
    unsafe {
        do name.with_c_str |name| {
            FromPrimitive::from_int(ll::SDL_GetKeyFromName(name) as int)
        }
    }
}

pub fn start_text_input() {
    unsafe { ll::SDL_StartTextInput(); }
}

pub fn is_text_input_active() -> bool {
    unsafe { ll::SDL_IsTextInputActive() == 1 }
}

pub fn stop_text_input() {
    unsafe { ll::SDL_StopTextInput(); }
}

pub fn set_text_input_rect(rect: &Rect) {
    unsafe { ll::SDL_SetTextInputRect(rect); }
}

pub fn has_screen_keyboard_support() -> bool {
    unsafe { ll::SDL_HasScreenKeyboardSupport() == 1 }
}

pub fn is_screen_keyboard_shown(window: &Window) -> bool {
    unsafe { ll::SDL_IsScreenKeyboardShown(window.raw) == 1 }
}
<commit_msg>Added some Unwrap statements for Keyboard<commit_after>use std::hashmap::HashMap;
use std::num::FromPrimitive;
use std::ptr;
use std::str;
use std::vec;

use keycode::KeyCode;
use rect::Rect;
use scancode::ScanCode;
use video::Window;

pub mod ll {
    use std::libc::{c_int, c_schar, c_uint, int32_t, uint8_t, uint16_t,
                    uint32_t};
    use rect::Rect;
    use video::ll::SDL_Window;

    pub type SDL_bool = c_int;
    pub type SDL_Rect = Rect;
    pub type SDL_Keycode = int32_t;
    pub type SDL_Keymod = c_uint;
    pub type SDL_Scancode = c_uint;

    // SDL_keyboard.h
    pub struct SDL_Keysym {
        scancode: SDL_Scancode,
        sym: SDL_Keycode,
        _mod: uint16_t,
        unused: uint32_t,
    }

    externfn!(fn SDL_GetKeyboardFocus() -> *SDL_Window)
    externfn!(fn SDL_GetKeyboardState(numkeys: *c_int) -> *uint8_t)
    externfn!(fn SDL_GetModState() -> SDL_Keymod)
    externfn!(fn SDL_SetModState(modstate: SDL_Keymod))
    externfn!(fn SDL_GetKeyFromScancode(scancode: SDL_Scancode) -> SDL_Keycode)
    externfn!(fn SDL_GetScancodeFromKey(key: SDL_Keycode) -> SDL_Scancode)
    externfn!(fn SDL_GetScancodeName(scancode: SDL_Scancode) -> *c_schar)
    externfn!(fn SDL_GetScancodeFromName(name: *c_schar) -> SDL_Scancode)
    externfn!(fn SDL_GetKeyName(key: SDL_Keycode) -> *c_schar)
    externfn!(fn SDL_GetKeyFromName(name: *c_schar) -> SDL_Keycode)
    externfn!(fn SDL_StartTextInput())
    externfn!(fn SDL_IsTextInputActive() -> SDL_bool)
    externfn!(fn SDL_StopTextInput())
    externfn!(fn SDL_SetTextInputRect(rect: *SDL_Rect))
    externfn!(fn SDL_HasScreenKeyboardSupport() -> SDL_bool)
    externfn!(fn SDL_IsScreenKeyboardShown(window: *SDL_Window) -> SDL_bool)
}

#[deriving(Eq)]
pub enum Mod {
     NoMod = 0x0000,
     LShiftMod = 0x0001,
     RShiftMod = 0x0002,
     LCtrlMod = 0x0040,
     RCtrlMod = 0x0080,
     LAltMod = 0x0100,
     RAltMod = 0x0200,
     LGuiMod = 0x0400,
     RGuiMod = 0x0800,
     NumMod = 0x1000,
     CapsMod = 0x2000,
     ModeMod = 0x4000,
     ReservedMod = 0x8000
}

pub fn wrap_mod_state(bitflags: ll::SDL_Keymod) -> ~[Mod] {
    let flags = [NoMod,
        LShiftMod,
        RShiftMod,
        LCtrlMod,
        RCtrlMod,
        LAltMod,
        RAltMod,
        LGuiMod,
        RGuiMod,
        NumMod,
        CapsMod,
        ModeMod,
        ReservedMod];

    do flags.iter().filter_map |&flag| {
        if bitflags & (flag as ll::SDL_Keymod) != 0 { Some(flag) }
        else { None }
    }.collect()
}

pub fn get_keyboard_focus() -> Option<~Window> {
    let raw = unsafe { ll::SDL_GetKeyboardFocus() };
    if raw == ptr::null() {
        None
    } else {
        Some(~Window{ raw: raw, owned: false })
    }
}

pub fn get_keyboard_state() -> ~HashMap<ScanCode, bool> {
    let mut state: ~HashMap<ScanCode, bool> = ~HashMap::new();
    let count = 0;

    let raw = unsafe { vec::raw::from_buf_raw(ll::SDL_GetKeyboardState(&count),
                                              count as uint) };

    let mut current = 0;
    while current < raw.len() {
        state.insert(FromPrimitive::from_int(current as int).unwrap(),
                     raw[current] == 1);
        current += 1;
    }

    return state;
}

pub fn get_mod_state() -> ~[Mod] {
    unsafe { wrap_mod_state(ll::SDL_GetModState()) }
}

pub fn set_mod_state(flags: &[Mod]) {
    let mut state = 0;
    for flag in flags.iter() {
        state |= *flag as ll::SDL_Keymod;
    }

    unsafe { ll::SDL_SetModState(state); }
}

pub fn get_key_from_scancode(scancode: ScanCode) -> KeyCode {
    unsafe {
        FromPrimitive::from_int(ll::SDL_GetKeyFromScancode(scancode.code()
                                                            as u32) as int).unwrap()
    }
}

pub fn get_scancode_from_key(key: KeyCode) -> ScanCode {
    unsafe {
        FromPrimitive::from_int(ll::SDL_GetScancodeFromKey(key.code())
                                 as int).unwrap()
    }
}

pub fn get_scancode_name(scancode: ScanCode) -> ~str {
    unsafe {
        str::raw::from_c_str(ll::SDL_GetScancodeName(scancode.code() as u32))
    }
}

pub fn get_scancode_from_name(name: &str) -> ScanCode {
    unsafe {
        do name.with_c_str |name| {
            FromPrimitive::from_int(ll::SDL_GetScancodeFromName(name) as int).unwrap()
        }
    }
}

pub fn get_key_name(key: KeyCode) -> ~str {
    unsafe {
        str::raw::from_c_str(ll::SDL_GetKeyName(key.code()))
    }
}

pub fn get_key_from_name(name: &str) -> KeyCode {
    unsafe {
        do name.with_c_str |name| {
            FromPrimitive::from_int(ll::SDL_GetKeyFromName(name) as int).unwrap()
        }
    }
}

pub fn start_text_input() {
    unsafe { ll::SDL_StartTextInput(); }
}

pub fn is_text_input_active() -> bool {
    unsafe { ll::SDL_IsTextInputActive() == 1 }
}

pub fn stop_text_input() {
    unsafe { ll::SDL_StopTextInput(); }
}

pub fn set_text_input_rect(rect: &Rect) {
    unsafe { ll::SDL_SetTextInputRect(rect); }
}

pub fn has_screen_keyboard_support() -> bool {
    unsafe { ll::SDL_HasScreenKeyboardSupport() == 1 }
}

pub fn is_screen_keyboard_shown(window: &Window) -> bool {
    unsafe { ll::SDL_IsScreenKeyboardShown(window.raw) == 1 }
}
<|endoftext|>


<commit_before>//! Contains information for keybindings.

use std::collections::HashMap;
use std::sync::RwLock;

use rustwlc::types::*; // Need * for bitflags...

mod keypress;
pub use self::keypress::KeyPress;

mod event;
pub use self::event::KeyEvent;

lazy_static! {
    static ref BINDINGS: RwLock<HashMap<KeyPress, KeyEvent>> =
        RwLock::new(HashMap::new());

    static ref NAME_MAPPING: HashMap<&'static str, &'static str> = {
        let mut map = HashMap::new();
        map.insert("enter", "return");
        map.insert("\n", "return");
        map.insert("\t", "tab");
        map
    };
}

/// Parses a KeyMod from key names.
pub fn keymod_from_names(keys: &[&str]) -> Result<KeyMod, String> {
    let mut result = KeyMod::empty();
    for key in keys {
        match key.to_lowercase().as_str() {
            "shift"            => result = result | MOD_SHIFT,
            "control" | "ctrl" => result = result | MOD_CTRL,
            "alt"              => result = result | MOD_ALT,
            "mod2"             => result = result | MOD_MOD2,
            "mod3"             => result = result | MOD_MOD3,
            "mod4" | "super" | "logo" => result = result | MOD_MOD4,
            "mod5" | "5mod5me" => result = result | MOD_MOD5,
            err => return Err(format!("Invalid modifier: {}", err))
        }
    }
    return Ok(result)
}

pub fn init() {
    use rustwlc::xkb::keysyms;
    use commands;
    register(KeyPress::new(MOD_ALT | MOD_SHIFT, keysyms::KEY_Escape),
             KeyEvent::Command(commands::get("quit")
                               .expect("Error reading commands::quit")));
}

/// Get a key mapping from the list.
pub fn get(key: &KeyPress) -> Option<KeyEvent> {
    let bindings = BINDINGS.read()
        .expect("Keybindings/get: unable to lock keybindings");
    bindings.get(key).map(KeyEvent::clone)
}

/// Register a new set of key mappings
pub fn register(key: KeyPress, event: KeyEvent) -> Option<KeyEvent> {
    let mut bindings = BINDINGS.write()
        .expect("Keybindings/register: unable to lock keybindings");
    bindings.insert(key, event)
}

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

    fn test_cmd() {
        assert!(true);
    }

    fn keypress() -> KeyPress {
        keypress!("Ctrl", "t")
    }

    #[test]
    fn add_key() {
        require_rustwlc!();
        register(keypress(), KeyEvent::Command(Arc::new(test_cmd)));
        assert!(get(&keypress()).is_some(), "Key not registered");
    }
}
<commit_msg>Re-added hard-coded alt+shift+esc<commit_after>//! Contains information for keybindings.

use std::collections::HashMap;
use std::sync::RwLock;

use rustwlc::types::*; // Need * for bitflags...
use rustwlc::xkb::keysyms;

mod keypress;
pub use self::keypress::KeyPress;

use super::commands;

mod event;
pub use self::event::KeyEvent;

lazy_static! {
    static ref BINDINGS: RwLock<HashMap<KeyPress, KeyEvent>> = {
        let mut mapping = HashMap::new();
        mapping.insert(KeyPress::new(KeyMod::from_bits(19).unwrap(),
                                     keysyms::KEY_Escape),
                       KeyEvent::Command(commands::read_lock().get("quit").unwrap().clone()));

        RwLock::new(mapping)
    };

    static ref NAME_MAPPING: HashMap<&'static str, &'static str> = {
        let mut map = HashMap::new();
        map.insert("enter", "return");
        map.insert("\n", "return");
        map.insert("\t", "tab");
        map
    };
}

/// Parses a KeyMod from key names.
pub fn keymod_from_names(keys: &[&str]) -> Result<KeyMod, String> {
    let mut result = KeyMod::empty();
    for key in keys {
        match key.to_lowercase().as_str() {
            "shift"            => result = result | MOD_SHIFT,
            "control" | "ctrl" => result = result | MOD_CTRL,
            "alt"              => result = result | MOD_ALT,
            "mod2"             => result = result | MOD_MOD2,
            "mod3"             => result = result | MOD_MOD3,
            "mod4" | "super" | "logo" => result = result | MOD_MOD4,
            "mod5" | "5mod5me" => result = result | MOD_MOD5,
            err => return Err(format!("Invalid modifier: {}", err))
        }
    }
    return Ok(result)
}

pub fn init() {
    use rustwlc::xkb::keysyms;
    use commands;
    register(KeyPress::new(MOD_ALT | MOD_SHIFT, keysyms::KEY_Escape),
             KeyEvent::Command(commands::get("quit")
                               .expect("Error reading commands::quit")));
}

/// Get a key mapping from the list.
pub fn get(key: &KeyPress) -> Option<KeyEvent> {
    let bindings = BINDINGS.read()
        .expect("Keybindings/get: unable to lock keybindings");
    bindings.get(key).map(KeyEvent::clone)
}

/// Register a new set of key mappings
pub fn register(key: KeyPress, event: KeyEvent) -> Option<KeyEvent> {
    let mut bindings = BINDINGS.write()
        .expect("Keybindings/register: unable to lock keybindings");
    bindings.insert(key, event)
}

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

    fn test_cmd() {
        assert!(true);
    }

    fn keypress() -> KeyPress {
        keypress!("Ctrl", "t")
    }

    #[test]
    fn add_key() {
        require_rustwlc!();
        register(keypress(), KeyEvent::Command(Arc::new(test_cmd)));
        assert!(get(&keypress()).is_some(), "Key not registered");
    }
}
<|endoftext|>


<commit_before>/// Used if an error from a popular crate is better being fully seralized, or if it is in std and has fields that should be preserved.
///
/// This enum may be expanded in the future. For this reason, you should not exaustively match aganst it.
#[derive(Serialize, Deserialize, RustcEncodable, RustcDecodable, Debug)]
pub enum RealError {
    /// This ensures that you cannot match the whole enum, and must always consiter for more feilds in the furure.
    #[doc(hidden)]
    __Nonexhaustive,
}
<commit_msg>impl Error for RealError<commit_after>use std::convert::From;
use std::error::Error;
use std::fmt;
use std::fmt::{Display, Formatter};

/// Used if an error from a popular crate is better being fully seralized, or if it is in std and has fields that should be preserved.
///
/// This enum may be expanded in the future. For this reason, you should not exaustively match aganst it.
#[derive(Serialize, Deserialize, RustcEncodable, RustcDecodable, Debug)]
pub enum RealError {
    /// This ensures that you cannot match the whole enum, and must always consiter for more feilds in the furure.
    ///
    /// This should also never exist in usage, and if it is, consuming it will return some error.
    #[doc(hidden)]
    __Nonexhaustive,
}

impl RealError {
    /// Returns true if the error value can be represented as a RealError.
    #[allow(dead_code)]
    pub fn can_represent(_err: &Error) -> bool {
        unimplemented!()
    }
}

impl Display for RealError {
    fn fmt(&self, _fmt: &mut Formatter) -> Result<(), fmt::Error> {
        use self::RealError::*;
        match *self {
            __Nonexhaustive => Err(fmt::Error), // __Nonexhaustive should never exist in a RealError. If I could return a real error, I would.
        }
    }
}

impl<'a> From<&'a Error> for RealError {
    fn from(_err: &Error) -> RealError {
        unimplemented!()
    }
}

impl Error for RealError {
    fn description(&self) -> &str {
        use self::RealError::*;
        match *self {
            __Nonexhaustive => "__Nonexhaustive: This value should never exist. If you are seeing this, it may be a result of corrupt data, or an attempt to crash the program with bad data.",
        }
    }

    #[allow(trivial_casts)]
    fn cause(&self) -> Option<&Error> {
        use self::RealError::*;
        match *self {
            __Nonexhaustive => None,
        }
    }
}
<|endoftext|>


<commit_before>use std::vec::Vec;
use std::io::IoError;
use serialize::Encodable;
use serialize::Decodable;
use std::io::{Acceptor, Listener, TcpListener, TcpStream, IoResult, BufferedReader};
use std::io::net::tcp::TcpAcceptor;
use std::comm::Select;
use collections::HashMap;
use sync::{Mutex, Arc};
use serialize::json::{Encoder,Error};

pub use self::peer::NetPeer;
use super::events::*;
use self::types::*;
pub mod peer;

// Private stuff, shouldn't be used elsewhere.
pub mod parsers;
mod types;

// TODO: put entry functions in here, like:
// - start_peer_helper (which returns a Peer struct, including fields
// with channels to message with)
// TODO: Peer will contain identity info and channels for
// communicating with this peer task

/*
 * Contains all the information on what peers we have, and manages Schooner's interactions
 * with them.
 */
struct NetListener {
    peer_select_map: HashMap<uint, uint>,
    peer_id_map: HashMap<uint, NetPeer>,
}

impl NetListener {
    fn new() -> NetListener {
        NetListener {
            peer_select_map: HashMap::new(),
            peer_id_map: HashMap::new()
        }
    }

    /*
     * Start the listener for this server. This needs to open a TCP listening port
     * at whatever its configured listening address is, and it needs to have a way
     * to send commands that it has received from peers back out to the main loop.
     *
     * conf: the config for this server
     * peer_configs: vector of configs for peers
     * from_peers_send: sends messages from peers back to the main loop.
     *
     */
    fn spawn_peer_listener(mut self, conf: NetPeerConfig, peer_configs: ~Vec<NetPeerConfig>, from_peers_send: Sender<RaftMsg>) {
        // unwrapping because our server is dead in the water if it can't listen on its assigned port
        let selector = Select::new();
        for conf in peer_configs.iter() {
            let (send, recv) = channel();
            let netpeer = NetPeer::new(~conf.clone(), ~send);
            let mut peer_handle = selector.handle(&recv);
            unsafe { peer_handle.add(); }
            self.peer_select_map.insert(peer_handle.id(), netpeer.conf.id);
            self.peer_id_map.insert(conf.id, netpeer);
        }
    }

    /*
     * Start the client listener.
     *
     * conf: the config for this server, containing *client* listen address.
     * from_clients_send: sends messages from peers back to the main loop.
     *
     */
    fn spawn_client_listener(& mut self, conf: NetPeerConfig, from_client_send: Sender<(ClientCmdReq, Sender<ClientCmdRes>)>) {
        // unwrapping because our server is dead in the water if it can't listen on its assigned port
        let listener: TcpListener = TcpListener::bind(conf.address).unwrap();
        let mut acceptor: TcpAcceptor = listener.listen().unwrap();
        for stream in acceptor.incoming() {

        }
    }

    /*
     * Get the configurations of the known peers for this network listener. Maybe
     * only used by the leader to get the potential peers that it can send messages
     * to. Probably should send even peers that NetListener thinks are down, since
     * in case they come back up the leader might like to send requests to them.
     */
    fn get_peer_ids(& self) -> Vec<uint> {
        let mut confs = Vec::new();
        for conf in self.peer_id_map.keys() {
            confs.push(conf.clone());
        }
        confs
    }

    /*
     * Leader only
     */
    fn send_append_req(& mut self, peer: uint, cmd: AppendEntriesReq) -> Option<Receiver<AppendEntriesRes>> {
        // if we were able to send the data over the TCP connection, then we will send it
        // back out on the returned Receiver.
        let netpeer = self.peer_id_map.get(&peer);
        /*
        match netpeer.send(RpcARQ(cmd)) {
            Some(reschan) => {
                // TODO
                None
            }
            None => {
                None
            }
        }
         */
        None
    }

    fn send_vote_req(peer: NetPeerConfig, cmd: VoteReq) -> Option<Receiver<VoteRes>> {
        None
    }

}

#[cfg(test)]
mod test {
    use std::vec::Vec;
    use std::io::net::ip::{SocketAddr, Ipv4Addr};
    use std::io::net::tcp::TcpStream;
    use super::types::*;
    use super::NetListener;

    #[test]
    fn test_warmup() {
        let pc = NetPeerConfig {
            id: 1,
            address: SocketAddr {
                ip: Ipv4Addr(127, 0, 0, 1),
                port: 8844,
            },
            client_addr: SocketAddr {
                ip: Ipv4Addr(127, 0, 0, 1),
                port: 8840,
            },
        };
        let mut pc_vec = ~Vec::new();
        pc_vec.push(NetPeerConfig {
            id: 1,
            address: SocketAddr {
                ip: Ipv4Addr(127, 0, 0, 1),
                port: 8888,
            },
            client_addr: SocketAddr {
                ip: Ipv4Addr(127, 0, 0, 1),
                port: 8840,
            },
        });
        let mut nl = NetListener::new();
        let (from_peers_send, from_peers) = channel();
        nl.spawn_peer_listener(pc, pc_vec, from_peers_send);
    }
}
<commit_msg>connection handshake basics<commit_after>use std::vec::Vec;
use std::io::IoError;
use serialize::Encodable;
use serialize::Decodable;
use std::io::{Acceptor, Listener, TcpListener, TcpStream, IoResult, BufferedReader};
use std::io::net::tcp::TcpAcceptor;
use std::io::net::ip::SocketAddr;
use std::comm::Select;
use collections::HashMap;
use sync::{RWLock, Arc};
use serialize::json::{Encoder,Error};

pub use self::peer::NetPeer;
use super::events::*;
use self::types::*;
pub mod peer;

// Private stuff, shouldn't be used elsewhere.
pub mod parsers;
mod types;

static CONNECT_TIMEOUT: u64 = 3000;

macro_rules! may_shutdown(
    ($p: ident) => {
        match $p.try_recv() {
            Ok(exitcode) => {
                break;
            }
            Err(_) => {},
        }
    }
)

// TODO: put entry functions in here, like:
// - start_peer_helper (which returns a Peer struct, including fields
// with channels to message with)
// TODO: Peer will contain identity info and channels for
// communicating with this peer task

/*
 * Contains all the information on what peers we have, and manages Schooner's interactions
 * with them.
 */
pub struct NetListener {
    // Maps peer IDs to their associated TCP streams.
    // Since these streams might fail, we need to reestablish them sometimes.
    peer_id_map: HashMap<uint, TcpStream>,
    // Peer configurations, stored in a concurrency construct.
    peer_configs: Vec<NetPeerConfig>,
}

impl NetListener {
    pub fn new() -> NetListener {
        NetListener {
            peer_id_map: HashMap::new(),
            peer_configs: Vec::new(),
        }
    }

    /*
     * Start the listener for this server. This needs to open a TCP listening port
     * at whatever its configured listening address is, and it needs to have a way
     * to send commands that it has received from peers back out to the main loop.
     *
     * conf: the config for this server
     * peer_configs: vector of configs for peers
     * from_peers_send: sends messages from peers back to the main loop.
     *
     */
    pub fn startup_peers(mut self, conf: NetPeerConfig, peer_configs: ~Vec<NetPeerConfig>, from_peers_send: Sender<RaftMsg>) {
        for conf in peer_configs.iter() {
            self.peer_configs.push(conf.clone());
        }
        let (peer_connect_send, peer_connect_recv) = channel();
        let (peer_shutdown_send, peer_shutdown_recv) = channel();
        NetListener::listen_peers(conf.address, peer_connect_send, peer_shutdown_recv);
        /*
        let selector = Select::new();
        for conf in peer_configs.iter() {
            let (send, recv) = channel();
            let netpeer = NetPeer::new(~conf.clone(), ~send);
            let mut peer_handle = selector.handle(&recv);
            unsafe { peer_handle.add(); }
            self.peer_select_map.insert(peer_handle.id(), netpeer.conf.id);
            self.peer_id_map.insert(conf.id, netpeer);
        }
        let listener = TcpListener::new();
        a.set_timeout(Some(100));
        match a.accept() {
            Ok(..) => println!("accepted a socket"),
            Err(ref e) if e.kind == TimedOut => { println!("timed out!"); }
            Err(e) => println!("err: {}", e),
        }
        */
    }

    fn listen_peers(addr: SocketAddr, peer_send: Sender<(uint, TcpStream)>, shutdown: Receiver<uint>) {
        spawn(proc() {
            let listener: TcpListener = TcpListener::bind(addr).unwrap();
            let mut acceptor: TcpAcceptor = listener.listen().unwrap();
            debug!("Started listening on {}", addr);
            loop {
                acceptor.set_timeout(Some(5000));
                for maybe_stream in acceptor.incoming() {
                    match maybe_stream {
                        Ok(stream) => {
                            let mut reader = ~BufferedReader::new(stream);
                            let line = reader.read_line();
                            let id: Option<uint> = line.ok().and_then(|l| from_str(l));
                            if id.is_some() {
                                debug!("Handshake with peer {} completed.", id.unwrap());
                                peer_send.send((id.unwrap(), reader.unwrap()));
                            }
                            else {
                                let mut stream = reader.unwrap();
                                debug!("Dropping peer at {} never got an id.", stream.peer_name());
                                drop(stream);
                            }
                        }
                        Err(e) => {
                            break;
                        }
                    }
                }
                may_shutdown!(shutdown);
            }
        });
    }

    fn try_connect(&mut self, peer_id: uint) -> Option<TcpStream> {
        let ref peer_configs = self.peer_configs;
        let mut peer: Option<&NetPeerConfig> = None;
        for conf in peer_configs.iter() {
            if conf.id == peer_id {
                peer = Some(conf);
            }
        }
        if peer.is_none() {
            return None;
        }
        match TcpStream::connect_timeout(peer.unwrap().address, CONNECT_TIMEOUT) {
            Ok(mut stream) => {
                stream.write_uint(peer.unwrap().id);
                stream.write_line("");
                Some(stream.clone())
            }
            err => {
                None
            }
        }
    }

    /*
     * Start the client listener.
     *
     * conf: the config for this server, containing *client* listen address.
     * from_clients_send: sends messages from peers back to the main loop.
     *
     */
    fn spawn_client_listener(& mut self, conf: NetPeerConfig, from_client_send: Sender<(ClientCmdReq, Sender<ClientCmdRes>)>) {
        // unwrapping because our server is dead in the water if it can't listen on its assigned port
        let listener: TcpListener = TcpListener::bind(conf.address).unwrap();
        let mut acceptor: TcpAcceptor = listener.listen().unwrap();
        for maybe_stream in acceptor.incoming() {
            match maybe_stream {
                Ok(stream) => {
                    // TODO
                }
                Err(e) => {
                    debug!("{}", e);
                    continue;
                }
            }
        }
    }

    /*
     * Get the configurations of the known peers for this network listener. Maybe
     * only used by the leader to get the potential peers that it can send messages
     * to. Probably should send even peers that NetListener thinks are down, since
     * in case they come back up the leader might like to send requests to them.
     */
    fn get_peer_ids(& self) -> Vec<uint> {
        /*
        let mut confs = Vec::new();
        for conf in self.peer_id_map.keys() {
            confs.push(conf.clone());
        }
        confs
         */
        Vec::new()
    }

    /*
     * Leader only
     */
    fn send_append_req(& mut self, peer: uint, cmd: AppendEntriesReq) -> Option<Receiver<AppendEntriesRes>> {
        // if we were able to send the data over the TCP connection, then we will send it
        // back out on the returned Receiver.
        /*
        let netpeer = self.peer_id_map.get(&peer);
        match netpeer.send(RpcARQ(cmd)) {
            Some(reschan) => {
                // TODO
                None
            }
            None => {
                None
            }
        }
         */
        None
    }

    fn send_vote_req(peer: NetPeerConfig, cmd: VoteReq) -> Option<Receiver<VoteRes>> {
        None
    }

}

#[cfg(test)]
mod test {
    use std::vec::Vec;
    use std::io::net::ip::{SocketAddr, Ipv4Addr};
    use std::io::net::tcp::TcpStream;
    use std::io::timer::sleep;
    use std::io::BufferedWriter;
    use std::container::MutableSet;
    use super::types::*;
    use super::NetListener;

    #[test]
    fn test_warmup() {
        let pc = NetPeerConfig {
            id: 1,
            address: SocketAddr {
                ip: Ipv4Addr(127, 0, 0, 1),
                port: 8844,
            },
            client_addr: SocketAddr {
                ip: Ipv4Addr(127, 0, 0, 1),
                port: 8840,
            },
        };
        let mut pc_vec = ~Vec::new();
        pc_vec.push(NetPeerConfig {
            id: 1,
            address: SocketAddr {
                ip: Ipv4Addr(127, 0, 0, 1),
                port: 8888,
            },
            client_addr: SocketAddr {
                ip: Ipv4Addr(127, 0, 0, 1),
                port: 8840,
            },
        });
        /*
        let mut nl = NetListener::new();
        let (from_peers_send, from_peers) = channel();
        nl.spawn_peer_listener(pc, pc_vec, from_peers_send);
        */
    }

    fn connect_handshake(id: uint, addr: SocketAddr) {
        match TcpStream::connect(addr) {
            Ok(mut stream) => {
                let mut writer = BufferedWriter::new(stream);
                writer.write_uint(id);
                drop(writer.unwrap());
            }
            Err(e) => {
                fail!("{}", e);
            }
        }
    }

    #[test]
    fn test_listen_peers() {
        let (peer_connect_send, peer_connect_recv) = channel();
        let (shutdown_send, shutdown_recv) = channel();
        let listen_addr = SocketAddr {
            ip: Ipv4Addr(127, 0, 0, 1),
            port: 9999,
        };
        NetListener::listen_peers(listen_addr, peer_connect_send, shutdown_recv);
        sleep(1000);
        connect_handshake(14, listen_addr);
        let (res_id, _) = peer_connect_recv.recv();
        assert_eq!(res_id, 14);
        connect_handshake(10, listen_addr);
        let (res_id, _) = peer_connect_recv.recv();
        assert_eq!(res_id, 10);
        connect_handshake(1, listen_addr);
        let (res_id, _) = peer_connect_recv.recv();
        assert_eq!(res_id, 1);
        shutdown_send.send(0);
    }
}
<|endoftext|>


<commit_before>use subframe::{self, Subframe, MAX_FIXED_ORDER, MAX_LPC_ORDER};

use std::ptr;

// Restore the original signal from a fixed linear prediction.
//
// Signal restoration is accomplished by summing up the residual and the
// predictor. With the linear prediction being "fixed", the polynomials will
// remain the same depending on the order value. And the max order is
// `MAX_FIXED_ORDER`, which is 4.
//
// This function also assumes that `output` already has the warm up values
// from the `Fixed` subframe in it.
pub fn fixed_restore_signal(order: usize,
                            residual: &[i32],
                            output: &mut [i32]) {
  debug_assert!(order <= MAX_FIXED_ORDER);

  let polynomial = [ &[][..]
                   , &[1][..]
                   , &[-1, 2][..]
                   , &[1, -3, 3][..]
                   , &[-1, 4, -6, 4][..]
                   ];

  let coefficients = polynomial[order];

  for i in 0..residual.len() {
    let offset     = i + order;
    let prediction = coefficients.iter()
                      .zip(&output[i..offset])
                      .fold(0, |result, (coefficient, signal)|
                            result + coefficient * signal);

    output[offset] = residual[i] + prediction;
  }
}

// Restore the original signal from a FIR linear prediction.
//
// Signal restoration is accomplished by summing up the residual and the
// predictor. Figuring out the linear prediction for finite impulse response
// is a bit more involved because you have more to deal with, but the
// concept is very similar to the fixed version. Coefficients are passed in
// and reversed within function and the result of these reverse order
// coefficients and warm up values are summed and the quantization level
// will determine how much the bits gets shifted in order to figure the
// current predictor for it's corresponding residual value.
//
// The order doesn't get passed in explicitly because the coefficients
// length is assumed to be the value of order. And the max order is
// `MAX_LPC_ORDER`, which is 32. This function also assumes that `output`
// already has the warm up values from the `LPC` subframe in it.
pub fn lpc_restore_signal(quantization_level: i8,
                          coefficients: &[i32],
                          residual: &[i32],
                          output: &mut [i32]) {
  let order = coefficients.len();

  debug_assert!(order <= MAX_LPC_ORDER);

  for i in 0..residual.len() {
    let offset     = i + order;
    let prediction = coefficients.iter().rev()
                       .zip(&output[i..offset])
                       .fold(0, |result, (coefficient, signal)|
                             result + coefficient * signal);

    output[offset] = residual[i] + (prediction >> quantization_level);
  }
}

/// Decodes the current subframe.
///
/// * `Constant` - fills the length of `output` with the constant value
///   within the subframe.
/// * `Verbatim` - copies the data within the verbatim subframe over to
///   `output`.
/// * `Fixed` - restore the signal of the fixed linear prediction and put
///   the result into `output`.
/// * `LPC` - restore the signal of the finite impulse response linear
///   prediction and put the result into `output`.
pub fn decode(subframe: &Subframe, output: &mut [i32]) {
  match subframe.data {
    subframe::Data::Constant(constant)     => {
      for i in 0..output.len() {
        output[i] = constant
      }
    }
    subframe::Data::Verbatim(ref verbatim) => {
      let length = verbatim.len();

      unsafe {
        ptr::copy(verbatim.as_ptr(), output.as_mut_ptr(), length)
      }
    }
    subframe::Data::Fixed(ref fixed)       => {
      let order = fixed.order as usize;

      for i in 0..order {
        output[i] = fixed.warmup[i];
      }

      fixed_restore_signal(order, &fixed.residual, output);
    }
    subframe::Data::LPC(ref lpc)           => {
      let order        = lpc.order as usize;
      let coefficients = &lpc.qlp_coefficients[0..order];

      for i in 0..order {
        output[i] = lpc.warmup[i];
      }

      lpc_restore_signal(lpc.quantization_level, coefficients, &lpc.residual,
                         output);
    }
  }

  if subframe.wasted_bits > 0 {
    for value in output {
      *value <<= subframe.wasted_bits;
    }
  }
}

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

  use subframe;
  use subframe::{
    Subframe, Fixed, LPC,
    EntropyCodingMethod, CodingMethod, PartitionedRice,
    PartitionedRiceContents,
  };

  #[test]
  fn test_fixed_restore_signal() {
    let residuals   = [ &[-19, -16, 17, -23, -7, 16, -16, -5, 3
                         , -8, -13, -15, -1][..]
                      , &[-6513][..]
                      ];
    let mut outputs = [ &mut [-729, -722, -667, 0, 0, 0, 0, 0, 0
                             , 0, 0, 0, 0, 0, 0, 0][..]
                      , &mut [21877, 27482, 0][..]
                      ];

    fixed_restore_signal(3, &residuals[0], &mut outputs[0]);
    fixed_restore_signal(2, &residuals[1], &mut outputs[1]);

    assert_eq!(&outputs[0], &[-729, -722, -667, -583, -486, -359, -225, -91
                             , 59, 209, 354, 497, 630, 740, 812, 845]);
    assert_eq!(&outputs[1], &[21877, 27482, 26574]);
  }

  #[test]
  fn test_lpc_restore_signal() {
    let residuals    = [ &[-2, -23, 14, 6, 3, -4, 12, -2, 10][..]
                       , &[3157][..]
                       ];
    let coefficients = [ &[1042, -399, -75, -269, 121, 166, -75][..]
                       , &[1757, -1199, 879, -836, 555, -255, 119][..]
                       ];
    let mut outputs = [ &mut [-796, -547, -285, -32, 199, 443, 670
                             , 0, 0, 0, 0, 0, 0, 0, 0, 0][..]
                      , &mut [-21363, -21951, -22649, -24364, -27297, -26870
                             ,-30017, 0][..]
                      ];

    lpc_restore_signal(9, &coefficients[0], &residuals[0], &mut outputs[0]);
    lpc_restore_signal(10, &coefficients[1], &residuals[1], &mut outputs[1]);

    assert_eq!(&outputs[0], &[-796, -547, -285, -32, 199, 443, 670, 875
                             , 1046, 1208, 1343, 1454, 1541, 1616, 1663
                             , 1701]);
    assert_eq!(&outputs[1], &[-21363, -21951, -22649, -24364, -27297, -26870
                             , -30017, -29718]);
  }

  #[test]
  fn test_decode() {
    let mut output = [0; 16];

    let constant = Subframe {
      data: subframe::Data::Constant(4),
      wasted_bits: 0,
    };

    let verbatim = Subframe {
      data: subframe::Data::Verbatim(vec![16, -3, 55, 49, -32, 6, 40, -90, 1
                                         ,0, 77, -12, 84, 10, -112, 136]),
      wasted_bits: 0,
    };

    let fixed = Subframe {
      data: subframe::Data::Fixed(Fixed {
        entropy_coding_method: EntropyCodingMethod {
          method_type: CodingMethod::PartitionedRice,
          data: PartitionedRice {
            order: 0,
            contents: PartitionedRiceContents {
              parameters: vec![],
              raw_bits: vec![],
            },
          },
        },
        order: 3,
        warmup: [-729, -722, -667, 0],
        residual: vec![-19, -16, 17, -23, -7, 16, -16, -5, 3 , -8, -13, -15
                      ,-1],
      }),
      wasted_bits: 0,
    };

    let lpc = Subframe {
      data: subframe::Data::LPC(LPC {
        entropy_coding_method: EntropyCodingMethod {
          method_type: CodingMethod::PartitionedRice,
          data: PartitionedRice {
            order: 0,
            contents: PartitionedRiceContents {
              parameters: vec![],
              raw_bits: vec![],
            },
          },
        },
        order: 7,
        qlp_coeff_precision: 0,
        quantization_level: 9,
        qlp_coefficients: [1042, -399, -75, -269, 121, 166, -75, 0, 0, 0, 0
                          ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                          ,0, 0, 0, 0],
        warmup: [-796, -547, -285, -32, 199, 443, 670, 0, 0, 0, 0, 0, 0, 0, 0
                ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        residual: vec![-2, -23, 14, 6, 3, -4, 12, -2, 10],
      }),
      wasted_bits: 0,
    };

    decode(&constant, &mut output);
    assert_eq!(&output, &[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]);

    decode(&verbatim, &mut output);
    assert_eq!(&output, &[16, -3, 55, 49, -32, 6, 40 , -90, 1, 0, 77, -12, 84
                         ,10 , -112, 136]);

    decode(&fixed, &mut output);
    assert_eq!(&output, &[-729, -722, -667, -583, -486, -359, -225, -91, 59
                         ,209, 354, 497, 630, 740, 812, 845]);

    decode(&lpc, &mut output);
    assert_eq!(&output, &[-796, -547, -285, -32, 199, 443, 670, 875, 1046
                         ,1208, 1343, 1454, 1541, 1616, 1663, 1701]);
  }

  #[test]
  fn test_wasted_bit_decode() {
    let mut output = [0; 4];

    let constant = Subframe {
      data: subframe::Data::Constant(1),
      wasted_bits: 10,
    };

    decode(&constant, &mut output);
    assert_eq!(&output, &[1024, 1024, 1024, 1024]);
  }
}
<commit_msg>Change algorithm for `fixed_restore_signal`<commit_after>use subframe::{self, Subframe, MAX_FIXED_ORDER, MAX_LPC_ORDER};

use std::ptr;

// Restore the original signal from a fixed linear prediction.
//
// Signal restoration is accomplished by summing up the residual and the
// predictor. With the linear prediction being "fixed", the polynomials will
// remain the same depending on the order value. And the max order is
// `MAX_FIXED_ORDER`, which is 4.
//
// This function also assumes that `output` already has the warm up values
// from the `Fixed` subframe in it.
pub fn fixed_restore_signal(order: usize,
                            block_size: usize,
                            output: &mut [i32]) {
  debug_assert!(order <= MAX_FIXED_ORDER);

  let polynomial = [ &[][..]
                   , &[1][..]
                   , &[-1, 2][..]
                   , &[1, -3, 3][..]
                   , &[-1, 4, -6, 4][..]
                   ];

  let coefficients = polynomial[order];
  let length       = block_size - order;

  for i in 0..length {
    let offset     = i + order;
    let prediction = coefficients.iter()
                      .zip(&output[i..offset])
                      .fold(0, |result, (coefficient, signal)|
                            result + coefficient * signal);

    output[offset] += prediction;
  }
}

// Restore the original signal from a FIR linear prediction.
//
// Signal restoration is accomplished by summing up the residual and the
// predictor. Figuring out the linear prediction for finite impulse response
// is a bit more involved because you have more to deal with, but the
// concept is very similar to the fixed version. Coefficients are passed in
// and reversed within function and the result of these reverse order
// coefficients and warm up values are summed and the quantization level
// will determine how much the bits gets shifted in order to figure the
// current predictor for it's corresponding residual value.
//
// The order doesn't get passed in explicitly because the coefficients
// length is assumed to be the value of order. And the max order is
// `MAX_LPC_ORDER`, which is 32. This function also assumes that `output`
// already has the warm up values from the `LPC` subframe in it.
pub fn lpc_restore_signal(quantization_level: i8,
                          coefficients: &[i32],
                          residual: &[i32],
                          output: &mut [i32]) {
  let order = coefficients.len();

  debug_assert!(order <= MAX_LPC_ORDER);

  for i in 0..residual.len() {
    let offset     = i + order;
    let prediction = coefficients.iter().rev()
                       .zip(&output[i..offset])
                       .fold(0, |result, (coefficient, signal)|
                             result + coefficient * signal);

    output[offset] = residual[i] + (prediction >> quantization_level);
  }
}

/// Decodes the current subframe.
///
/// * `Constant` - fills the length of `output` with the constant value
///   within the subframe.
/// * `Verbatim` - copies the data within the verbatim subframe over to
///   `output`.
/// * `Fixed` - restore the signal of the fixed linear prediction and put
///   the result into `output`.
/// * `LPC` - restore the signal of the finite impulse response linear
///   prediction and put the result into `output`.
pub fn decode(subframe: &Subframe, output: &mut [i32]) {
  match subframe.data {
    subframe::Data::Constant(constant)     => {
      for i in 0..output.len() {
        output[i] = constant
      }
    }
    subframe::Data::Verbatim(ref verbatim) => {
      let length = verbatim.len();

      unsafe {
        ptr::copy(verbatim.as_ptr(), output.as_mut_ptr(), length)
      }
    }
    subframe::Data::Fixed(ref fixed)       => {
      let order = fixed.order as usize;

      for i in 0..order {
        output[i] = fixed.warmup[i];
      }

      fixed_restore_signal(order, &fixed.residual, output);
    }
    subframe::Data::LPC(ref lpc)           => {
      let order        = lpc.order as usize;
      let coefficients = &lpc.qlp_coefficients[0..order];

      for i in 0..order {
        output[i] = lpc.warmup[i];
      }

      lpc_restore_signal(lpc.quantization_level, coefficients, &lpc.residual,
                         output);
    }
  }

  if subframe.wasted_bits > 0 {
    for value in output {
      *value <<= subframe.wasted_bits;
    }
  }
}

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

  use subframe;
  use subframe::{
    Subframe, Fixed, LPC,
    EntropyCodingMethod, CodingMethod, PartitionedRice,
    PartitionedRiceContents,
  };

  #[test]
  fn test_fixed_restore_signal() {
    let residuals   = [ &[-19, -16, 17, -23, -7, 16, -16, -5, 3
                         , -8, -13, -15, -1][..]
                      , &[-6513][..]
                      ];
    let mut outputs = [ &mut [-729, -722, -667, 0, 0, 0, 0, 0, 0
                             , 0, 0, 0, 0, 0, 0, 0][..]
                      , &mut [21877, 27482, 0][..]
                      ];

    fixed_restore_signal(3, &residuals[0], &mut outputs[0]);
    fixed_restore_signal(2, &residuals[1], &mut outputs[1]);

    assert_eq!(&outputs[0], &[-729, -722, -667, -583, -486, -359, -225, -91
                             , 59, 209, 354, 497, 630, 740, 812, 845]);
    assert_eq!(&outputs[1], &[21877, 27482, 26574]);
  }

  #[test]
  fn test_lpc_restore_signal() {
    let residuals    = [ &[-2, -23, 14, 6, 3, -4, 12, -2, 10][..]
                       , &[3157][..]
                       ];
    let coefficients = [ &[1042, -399, -75, -269, 121, 166, -75][..]
                       , &[1757, -1199, 879, -836, 555, -255, 119][..]
                       ];
    let mut outputs = [ &mut [-796, -547, -285, -32, 199, 443, 670
                             , 0, 0, 0, 0, 0, 0, 0, 0, 0][..]
                      , &mut [-21363, -21951, -22649, -24364, -27297, -26870
                             ,-30017, 0][..]
                      ];

    lpc_restore_signal(9, &coefficients[0], &residuals[0], &mut outputs[0]);
    lpc_restore_signal(10, &coefficients[1], &residuals[1], &mut outputs[1]);

    assert_eq!(&outputs[0], &[-796, -547, -285, -32, 199, 443, 670, 875
                             , 1046, 1208, 1343, 1454, 1541, 1616, 1663
                             , 1701]);
    assert_eq!(&outputs[1], &[-21363, -21951, -22649, -24364, -27297, -26870
                             , -30017, -29718]);
  }

  #[test]
  fn test_decode() {
    let mut output = [0; 16];

    let constant = Subframe {
      data: subframe::Data::Constant(4),
      wasted_bits: 0,
    };

    let verbatim = Subframe {
      data: subframe::Data::Verbatim(vec![16, -3, 55, 49, -32, 6, 40, -90, 1
                                         ,0, 77, -12, 84, 10, -112, 136]),
      wasted_bits: 0,
    };

    let fixed = Subframe {
      data: subframe::Data::Fixed(Fixed {
        entropy_coding_method: EntropyCodingMethod {
          method_type: CodingMethod::PartitionedRice,
          data: PartitionedRice {
            order: 0,
            contents: PartitionedRiceContents {
              parameters: vec![],
              raw_bits: vec![],
            },
          },
        },
        order: 3,
        warmup: [-729, -722, -667, 0],
        residual: vec![-19, -16, 17, -23, -7, 16, -16, -5, 3 , -8, -13, -15
                      ,-1],
      }),
      wasted_bits: 0,
    };

    let lpc = Subframe {
      data: subframe::Data::LPC(LPC {
        entropy_coding_method: EntropyCodingMethod {
          method_type: CodingMethod::PartitionedRice,
          data: PartitionedRice {
            order: 0,
            contents: PartitionedRiceContents {
              parameters: vec![],
              raw_bits: vec![],
            },
          },
        },
        order: 7,
        qlp_coeff_precision: 0,
        quantization_level: 9,
        qlp_coefficients: [1042, -399, -75, -269, 121, 166, -75, 0, 0, 0, 0
                          ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                          ,0, 0, 0, 0],
        warmup: [-796, -547, -285, -32, 199, 443, 670, 0, 0, 0, 0, 0, 0, 0, 0
                ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        residual: vec![-2, -23, 14, 6, 3, -4, 12, -2, 10],
      }),
      wasted_bits: 0,
    };

    decode(&constant, &mut output);
    assert_eq!(&output, &[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]);

    decode(&verbatim, &mut output);
    assert_eq!(&output, &[16, -3, 55, 49, -32, 6, 40 , -90, 1, 0, 77, -12, 84
                         ,10 , -112, 136]);

    decode(&fixed, &mut output);
    assert_eq!(&output, &[-729, -722, -667, -583, -486, -359, -225, -91, 59
                         ,209, 354, 497, 630, 740, 812, 845]);

    decode(&lpc, &mut output);
    assert_eq!(&output, &[-796, -547, -285, -32, 199, 443, 670, 875, 1046
                         ,1208, 1343, 1454, 1541, 1616, 1663, 1701]);
  }

  #[test]
  fn test_wasted_bit_decode() {
    let mut output = [0; 4];

    let constant = Subframe {
      data: subframe::Data::Constant(1),
      wasted_bits: 10,
    };

    decode(&constant, &mut output);
    assert_eq!(&output, &[1024, 1024, 1024, 1024]);
  }
}
<|endoftext|>


<commit_before>extern crate debug;
use std::io;
use std::io::process::Command;
use std::io::process;

struct JobEntry{
	process : process::Process,
	name : String
}

#[deriving(Clone)]
struct HistoryEntry{
	args : Vec<String>,
	background : bool
}

fn main(){
	let mut jobs : Vec<JobEntry> = Vec::new();
	let mut history : Vec<HistoryEntry> = Vec::new();

	fn execute(args : &Vec<&str>, background : bool, history : &mut Vec<HistoryEntry>, jobs : &mut Vec<JobEntry>) -> Result<(), ()> {
		assert!(args.len() > 0);
		match args[0] {
			"exit" => {Err(())}
			"history" =>{
				if history.is_empty(){
					println!("Nothing entered yet");
				} else{
					let y : Vec<&HistoryEntry> = history.iter().rev().take(10u).collect();
					for (i, x) in  y.iter().enumerate().rev(){
						let name = x.args.iter().fold(String::new(), |acc, x|{acc.add(x).append(" ")});
						let name = if x.background {name} else {name.append("&")};
						println!("{}: {}", history.len() - i, name)
					}
				};
				Ok(())}
			"r" => {
				if args.len() == 1 {
					match history.clone().last(){
						Some(entry) => {
							let args = entry.args.iter().map(|x|{x.as_slice()}).collect();
							execute(&args, entry.background, history, jobs)}
						None => {println!("Nothing entered yet"); Ok(())}}
				} else {
					let mut found = false;
					let mut res = Ok(());
					for x in history.clone().iter().rev() {
						if x.args[0].as_slice().char_at(0) == args[1].char_at(0){
							found = true;
							res = execute(&(x.args.iter().map(|x|{x.as_slice()}).collect()), x.background, history, jobs);
							break;
						}
					}
					if !found {println!("No arguments starting with {}", args[1]); Ok(())} else{res}
				}
			}
			"jobs" => {
				if jobs.is_empty(){println!("No jobs currently running")}
				else{
					for (i, x) in jobs.iter().enumerate(){
						println!("[{}] {}", i+1, x.name)}}
				Ok(())
			}
			"fg" => {
				if args.len() > 1 {
					let x : Option<uint> = from_str(args[1]);
					match x {
						Some(x) =>{
							if (x > jobs.len() || x <= 0){println!("No job [{}]", x)}
							else{
								jobs.get_mut(x-1).process.wait();
								jobs.remove(x-1);
							};
							Ok(())
						}
						None => {println!("Not a valid number"); Ok(())}
					}
				} else if jobs.len() == 1 {
					jobs.get_mut(0).process.wait();
					jobs.remove(0);
					Ok(())
				}else {
					println!("No number specified for 'fg'"); Ok(())
				}
			}
			"kill" => {
				if args.len() > 1 {
					let x : Option<uint> = from_str(args[1]);
					match x {
						Some(x) =>{
							if (x > jobs.len() || x <= 0){println!("No job [{}]", x)}
							else{
								let _ = jobs.get_mut(x-1).process.signal_exit();
								jobs.remove(x-1);
							};
							Ok(())
						}
						None => {println!("Not a valid number"); Ok(())}
					}
				} else if jobs.len() == 1 {
					let _ = jobs.get_mut(0).process.signal_exit();
					jobs.remove(0);
					Ok(())
				}else {
					println!("No number specified for 'kill'"); Ok(())
				}
			}
			_ => {
				let mut prog = Command::new(args[0]);
				prog.args(args.tail().as_slice());
				prog.stdin(process::InheritFd(0));
				prog.stdout(process::InheritFd(1));
				prog.stderr(process::InheritFd(2));

				if background {
					let (tx, rx): (Sender<process::Process>, Receiver<process::Process>) = channel();
					spawn(proc() {
						match prog.spawn() {
							Ok(p) => tx.send(p),
							Err(e) => println!("Invalid command: {}", e.kind)}});
					let p = rx.recv();
					jobs.push(JobEntry{process : p, name : args.iter().fold(String::new(), |acc, x|{acc.append(*x).append(" ")})})}
				else {
					match prog.spawn(){
						Ok(p) => (),
						Err(e) => println!("Invalid command: {}", e.kind)
					}}

				history.push(HistoryEntry{args : args.iter().map(|x|{String::from_str(*x)}).collect(), background : background});

				Ok(())
			}
		}
	};

	fn setup<'r>(input : &'r String) -> (Vec<&'r str>, bool){
		let mut ret = Vec::new();
		let mut background = false;
		for c in input.as_slice().split(' '){
			match c {
			"&" => {background = true},
			_ => ret.push(c)}}
		(ret, background)}

	loop{
		print!("COMMAND -> ");
		let input : String = io::stdin().read_line().unwrap_or(String::new()).replace("\n", "");
//		println!("Input: \"{}\"", input);
		if input.is_empty() {break};
		let (setup_res, background) = setup(&input);
		// println!("args: {}\nBackground: {}\n", setup_res, background);
		if execute(&setup_res, background, &mut history, &mut jobs).is_err(){break}

		// println!("{}", exec_res);
	}

	for x in jobs.iter(){
		let _ = process::Process::kill(x.process.id(), process::PleaseExitSignal);}

	println!("exit")

}
<commit_msg>Basic cleanup<commit_after>extern crate debug;
use std::io;
use std::io::process::Command;
use std::io::process;

struct JobEntry{
	process : process::Process,
	name : String
}

#[deriving(Clone)]
struct HistoryEntry{
	args : Vec<String>,
	background : bool
}

fn main(){
	let mut jobs : Vec<JobEntry> = Vec::new();
	let mut history : Vec<HistoryEntry> = Vec::new();

	fn execute(args : &Vec<&str>, background : bool, history : &mut Vec<HistoryEntry>, jobs : &mut Vec<JobEntry>) -> Result<(), ()> {
		assert!(args.len() > 0);
		match args[0] {
			"exit" => {Err(())}
			"history" =>{
				if history.is_empty(){
					println!("Nothing entered yet");
				} else{
					let y : Vec<&HistoryEntry> = history.iter().rev().take(10u).collect();
					for (i, x) in  y.iter().enumerate().rev(){
						let name = x.args.iter().fold(String::new(), |acc, x|{acc.add(x).append(" ")});
						let name = if x.background {name} else {name.append("&")};
						println!("{}: {}", history.len() - i, name)
					}
				};
				Ok(())}
			"r" => {
				if args.len() == 1 {
					match history.clone().last(){
						Some(entry) => {
							let args = entry.args.iter().map(|x|{x.as_slice()}).collect();
							execute(&args, entry.background, history, jobs)}
						None => {println!("Nothing entered yet"); Ok(())}}
				} else {
					let mut found = false;
					let mut res = Ok(());
					for x in history.clone().iter().rev() {
						if x.args[0].as_slice().char_at(0) == args[1].char_at(0){
							found = true;
							res = execute(&(x.args.iter().map(|x|{x.as_slice()}).collect()), x.background, history, jobs);
							break;
						}
					}
					if !found {println!("No arguments starting with {}", args[1]); Ok(())} else{res}
				}
			}
			"jobs" => {
				if jobs.is_empty(){println!("No jobs currently running")}
				else{
					for (i, x) in jobs.iter().enumerate(){
						println!("[{}] {}", i+1, x.name)}}
				Ok(())
			}
			"fg" => {
				if args.len() > 1 {
					let x : Option<uint> = from_str(args[1]);
					match x {
						Some(x) =>{
							if (x > jobs.len() || x <= 0){println!("No job [{}]", x)}
							else{
								jobs.get_mut(x-1).process.wait();
								jobs.remove(x-1);
							};
							Ok(())
						}
						None => {println!("Not a valid number"); Ok(())}
					}
				} else if jobs.len() == 1 {
					jobs.get_mut(0).process.wait();
					jobs.remove(0);
					Ok(())
				}else {
					println!("No number specified for 'fg'"); Ok(())
				}
			}
			"kill" => {
				if args.len() > 1 {
					let x : Option<uint> = from_str(args[1]);
					match x {
						Some(x) =>{
							if (x > jobs.len() || x <= 0){println!("No job [{}]", x)}
							else{
								let _ = jobs.get_mut(x-1).process.signal_exit();
								jobs.remove(x-1);
							};
							Ok(())
						}
						None => {println!("Not a valid number"); Ok(())}
					}
				} else if jobs.len() == 1 {
					let _ = jobs.get_mut(0).process.signal_exit();
					jobs.remove(0);
					Ok(())
				}else {
					println!("No number specified for 'kill'"); Ok(())
				}
			}
			_ => {
				let mut prog = Command::new(args[0]);
				prog.args(args.tail().as_slice());
				prog.stdin(process::InheritFd(0));
				prog.stdout(process::InheritFd(1));
				prog.stderr(process::InheritFd(2));

				if background {
					let (tx, rx): (Sender<process::Process>, Receiver<process::Process>) = channel();
					spawn(proc() {
						match prog.spawn() {
							Ok(p) => tx.send(p),
							Err(e) => println!("Invalid command: {}", e.kind)}});
					let p = rx.recv();
					jobs.push(JobEntry{process : p, name : args.iter().fold(String::new(), |acc, x|{acc.append(*x).append(" ")})})}
				else {
					match prog.spawn(){
						Ok(p) => (),
						Err(e) => println!("Invalid command: {}", e.kind)
					}}

				history.push(HistoryEntry{args : args.iter().map(|x|{String::from_str(*x)}).collect(), background : background});

				Ok(())
			}
		}
	};

	fn setup<'r>(input : &'r String) -> (Vec<&'r str>, bool){
		let mut ret = Vec::new();
		let mut background = false;
		for c in input.as_slice().split(' '){
			match c {
			"&" => {background = true},
			_ => ret.push(c)}}
		(ret, background)}

	loop{
		print!("COMMAND -> ");
		let input : String = io::stdin().read_line().unwrap_or(String::new());
		// If they just entered a newline, continue, if its empty, means ^-D, so exit
		if input.is_empty() {break}
		else if input == String::from_str("\n"){continue};
		let input : String = input.replace("\n", "");// Remove trailing newline
		let (setup_res, background) = setup(&input);
		if execute(&setup_res, background, &mut history, &mut jobs).is_err(){break}
	}

	for x in jobs.iter(){
		let _ = process::Process::kill(x.process.id(), process::PleaseExitSignal);}

	println!("exit")

}
<|endoftext|>