<commit_before>use tokenizer::Tokenizer;
use event::{Event, Rule};
use variable_mapper::VariableMapper;

pub fn nested<'a, I>(tokenizer: &mut I) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut vm = VariableMapper::new(tokenizer);
    let mut parents = Vec::new();
    nested_inner(&mut vm, &mut parents)
}

pub fn nested_inner<'a, I>(tokenizer: &mut I, parents: &mut Vec<String>) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut last = Event::End(Rule::SassRule);
    let mut current = String::new();
    let mut properties = String::new();
    let mut children = String::new();

    while let Some(token) = tokenizer.next() {
       match token.clone() {
            Event::Start(_) => {
                match children.len() {
                    0 => children = nested_inner(tokenizer, parents),
                    _ => {
                        children.push_str("\n\n");
                        children.push_str(&nested_inner(tokenizer, parents));
                    },
                };
            },
            Event::Selector(name) => {
                parents.push((*name).to_string());
                current.push_str(&format!("{} ", name));
            },
            Event::Property(name, value) => {
                match last {
                    Event::Selector(_) => properties.push_str(&format!("{{\n  {}: {};", name, value)),
                    _ => properties.push_str(&format!("\n  {}: {};", name, value)),
                }
            },
            Event::End(_) => {
                match (properties.len(), children.len()) {
                    (0, 0) => current.push_str(" }\n"),
                    (_, 0) => {
                        current.push_str(&properties);
                        current.push_str(" }");
                    },
                    (0, _) => {
                        current.push_str(&children);
                    },
                    (_, _) => {
                        current.push_str(&properties);
                        current.push_str(" }\n  ");
                        current.push_str(&parents.connect(" "));
                        current.push_str(" ");
                        current.push_str(&children.split('\n').collect::<Vec<_>>().connect("\n  "));
                    },
                }
                parents.pop();
                return current
            },
            Event::Variable(..) => unreachable!(),
            Event::Comment(body) => unimplemented!(),
        };
        last = token;
    }
    children
}

pub fn compressed<'a, I>(tokenizer: &mut I) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut vm = VariableMapper::new(tokenizer);
    let mut parents = Vec::new();
    compressed_inner(&mut vm, &mut parents)
}

fn compressed_inner<'a, I>(tokenizer: &mut I, parents: &mut Vec<String>) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut last = Event::End(Rule::SassRule);
    let mut current = String::new();
    let mut properties = String::new();
    let mut children = String::new();

    while let Some(token) = tokenizer.next() {
         match token.clone() {
             Event::Start(_) => {
                 match children.len() {
                     0 => children = compressed_inner(tokenizer, parents),
                     _ => {
                         children.push_str(&compressed_inner(tokenizer, parents));
                     },
                 };
             },
             Event::Selector(name) => {
                 parents.push((*name).to_string());
                 match last {
                     Event::Selector(_) => current.push_str(&format!(" {}", name)),
                     _ => current.push_str(&format!("{}", name)),
                 }
             },
             Event::Property(name, value) => {
                 match last {
                     Event::Selector(..) => properties.push_str(&format!("{{{}:{}", name, value)),
                     Event::Property(..) => properties.push_str(&format!(";{}:{}", name, value)),
                     _ => properties.push_str(&format!("{}:{}", name, value)),
                 }
             },
             Event::End(_) => {
                 match (properties.len(), children.len()) {
                     (0, 0) => current.push_str("}"),
                     (_, 0) => {
                         current.push_str(&properties);
                         current.push_str("}");
                     },
                     (0, _) => {
                         current.push_str(" ");
                         current.push_str(&children);
                     },
                     (_, _) => {
                         current.push_str(&properties);
                         current.push_str("}");
                         current.push_str(&parents.connect(" "));
                         current.push_str(" ");
                         current.push_str(&children);
                     },
                 }
                 parents.pop();
                 return current
             },
            Event::Variable(..) => unreachable!(),
            Event::Comment(body) => unimplemented!(),
        };
        last = token;
    }
    children
}

pub fn expanded<'a, I>(tokenizer: &mut I) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut vm = VariableMapper::new(tokenizer);
    let mut parents = Vec::new();
    expanded_inner(&mut vm, &mut parents)
}

fn expanded_inner<'a, I>(tokenizer: &mut I, parents: &mut Vec<String>) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut last = Event::End(Rule::SassRule);
    let mut current = String::new();
    let mut properties = String::new();
    let mut children = String::new();

    while let Some(token) = tokenizer.next() {
        match token.clone() {
            Event::Start(_) => {
                match children.len() {
                    0 => children = expanded_inner(tokenizer, parents),
                    _ => {
                        children.push_str("\n\n");
                        children.push_str(&expanded_inner(tokenizer, parents));
                    },
                };
            },
            Event::Selector(name) => {
                parents.push((*name).to_string());
                match last {
                    Event::Selector(_) => current.push_str(&format!(" {}", name)),
                    Event::End(_) => current.push_str(&format!("{}", name)),
                    _ => current.push_str(&format!("{}", name)),
                }
            },
            Event::Property(name, value) => {
                match last {
                    Event::Selector(_) => properties.push_str(&format!(" {{\n  {}: {};", name, value)),
                    _ => properties.push_str(&format!("\n  {}: {};", name, value)),
                }
            },
            Event::End(_) => {
                match (properties.len(), children.len()) {
                    (0, 0) => current.push_str("\n}"),
                    (_, 0) => {
                        current.push_str(&properties);
                        current.push_str("\n}");
                    },
                    (0, _) => {
                        current.push_str(" ");
                        current.push_str(&children);
                    },
                    (_, _) => {
                        current.push_str(&properties);
                        current.push_str("\n}\n");
                        current.push_str(&parents.connect(" "));
                        current.push_str(" ");
                        current.push_str(&children);
                    },
                }
                parents.pop();
                return current
            },
            Event::Variable(..) => unreachable!(),
            Event::Comment(body) => unimplemented!(),
        };

        last = token;
    }
    children
}

pub fn compact<'a, I>(tokenizer: &mut I) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut vm = VariableMapper::new(tokenizer);
    let mut parents = Vec::new();
    compact_inner(&mut vm, &mut parents)
}

fn compact_inner<'a, I>(tokenizer: &mut I, parents: &mut Vec<String>) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut last = Event::End(Rule::SassRule);
    let mut current = String::new();
    let mut properties = String::new();
    let mut children = String::new();

    while let Some(token) = tokenizer.next() {
        match token.clone() {
            Event::Start(_) => {
                match children.len() {
                    0 => children = compact_inner(tokenizer, parents),
                    _ => {
                        children.push_str("\n");
                        children.push_str(&compact_inner(tokenizer, parents));
                    },
                };
            },
            Event::Selector(name) => {
                parents.push((*name).to_string());
                match last {
                    Event::Selector(_) => current.push_str(&format!(" {}", name)),
                    Event::End(_) => current.push_str(&format!("{}", name)),
                    _ => current.push_str(&format!("{}", name)),
                }
            },
            Event::Property(name, value) => {
                match last {
                    Event::Selector(_) => properties.push_str(&format!(" {{ {}: {};", name, value)),
                    _ => properties.push_str(&format!(" {}: {};", name, value)),
                }
            },
            Event::End(_) => {
                match (properties.len(), children.len()) {
                    (0, 0) => current.push_str(" }"),
                    (_, 0) => {
                        current.push_str(&properties);
                        current.push_str(" }\n");
                    },
                    (0, _) => {
                        current.push_str(" ");
                        current.push_str(&children);
                    },
                    (_, _) => {
                        current.push_str(&properties);
                        current.push_str(" }\n");
                        current.push_str(&parents.connect(" "));
                        current.push_str(" ");
                        current.push_str(&children);
                    },
                }
                parents.pop();
                return current
            },
            Event::Variable(..) => unreachable!(),
            Event::Comment(body) => unimplemented!(),
        };
        last = token;
    }
    children
}

pub fn debug(tokenizer: &mut Tokenizer) -> String {
    let mut output = String::new();
    let mut current = String::new();

    while let Some(token) = tokenizer.next() {
        current.push_str(&format!("{:?}\n", token));
        match token {
            Event::End(_) => {
                output.push_str(&current);
                current = String::new();
            },
            _ => {},
        }
    }
    output
}
<commit_msg>Remove a redundant case<commit_after>use tokenizer::Tokenizer;
use event::{Event, Rule};
use variable_mapper::VariableMapper;

pub fn nested<'a, I>(tokenizer: &mut I) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut vm = VariableMapper::new(tokenizer);
    let mut parents = Vec::new();
    nested_inner(&mut vm, &mut parents)
}

pub fn nested_inner<'a, I>(tokenizer: &mut I, parents: &mut Vec<String>) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut last = Event::End(Rule::SassRule);
    let mut current = String::new();
    let mut properties = String::new();
    let mut children = String::new();

    while let Some(token) = tokenizer.next() {
       match token.clone() {
            Event::Start(_) => {
                match children.len() {
                    0 => children = nested_inner(tokenizer, parents),
                    _ => {
                        children.push_str("\n\n");
                        children.push_str(&nested_inner(tokenizer, parents));
                    },
                };
            },
            Event::Selector(name) => {
                parents.push((*name).to_string());
                current.push_str(&format!("{} ", name));
            },
            Event::Property(name, value) => {
                match last {
                    Event::Selector(_) => properties.push_str(&format!("{{\n  {}: {};", name, value)),
                    _ => properties.push_str(&format!("\n  {}: {};", name, value)),
                }
            },
            Event::End(_) => {
                match (properties.len(), children.len()) {
                    (0, 0) => current.push_str(" }\n"),
                    (_, 0) => {
                        current.push_str(&properties);
                        current.push_str(" }");
                    },
                    (0, _) => {
                        current.push_str(&children);
                    },
                    (_, _) => {
                        current.push_str(&properties);
                        current.push_str(" }\n  ");
                        current.push_str(&parents.connect(" "));
                        current.push_str(" ");
                        current.push_str(&children.split('\n').collect::<Vec<_>>().connect("\n  "));
                    },
                }
                parents.pop();
                return current
            },
            Event::Variable(..) => unreachable!(),
            Event::Comment(body) => unimplemented!(),
        };
        last = token;
    }
    children
}

pub fn compressed<'a, I>(tokenizer: &mut I) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut vm = VariableMapper::new(tokenizer);
    let mut parents = Vec::new();
    compressed_inner(&mut vm, &mut parents)
}

fn compressed_inner<'a, I>(tokenizer: &mut I, parents: &mut Vec<String>) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut last = Event::End(Rule::SassRule);
    let mut current = String::new();
    let mut properties = String::new();
    let mut children = String::new();

    while let Some(token) = tokenizer.next() {
         match token.clone() {
             Event::Start(_) => {
                 match children.len() {
                     0 => children = compressed_inner(tokenizer, parents),
                     _ => {
                         children.push_str(&compressed_inner(tokenizer, parents));
                     },
                 };
             },
             Event::Selector(name) => {
                 parents.push((*name).to_string());
                 match last {
                     Event::Selector(_) => current.push_str(&format!(" {}", name)),
                     _ => current.push_str(&format!("{}", name)),
                 }
             },
             Event::Property(name, value) => {
                 match last {
                     Event::Selector(..) => properties.push_str(&format!("{{{}:{}", name, value)),
                     Event::Property(..) => properties.push_str(&format!(";{}:{}", name, value)),
                     _ => properties.push_str(&format!("{}:{}", name, value)),
                 }
             },
             Event::End(_) => {
                 match (properties.len(), children.len()) {
                     (0, 0) => current.push_str("}"),
                     (_, 0) => {
                         current.push_str(&properties);
                         current.push_str("}");
                     },
                     (0, _) => {
                         current.push_str(" ");
                         current.push_str(&children);
                     },
                     (_, _) => {
                         current.push_str(&properties);
                         current.push_str("}");
                         current.push_str(&parents.connect(" "));
                         current.push_str(" ");
                         current.push_str(&children);
                     },
                 }
                 parents.pop();
                 return current
             },
            Event::Variable(..) => unreachable!(),
            Event::Comment(body) => unimplemented!(),
        };
        last = token;
    }
    children
}

pub fn expanded<'a, I>(tokenizer: &mut I) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut vm = VariableMapper::new(tokenizer);
    let mut parents = Vec::new();
    expanded_inner(&mut vm, &mut parents)
}

fn expanded_inner<'a, I>(tokenizer: &mut I, parents: &mut Vec<String>) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut last = Event::End(Rule::SassRule);
    let mut current = String::new();
    let mut properties = String::new();
    let mut children = String::new();

    while let Some(token) = tokenizer.next() {
        match token.clone() {
            Event::Start(_) => {
                match children.len() {
                    0 => children = expanded_inner(tokenizer, parents),
                    _ => {
                        children.push_str("\n\n");
                        children.push_str(&expanded_inner(tokenizer, parents));
                    },
                };
            },
            Event::Selector(name) => {
                parents.push((*name).to_string());
                match last {
                    Event::Selector(_) => current.push_str(&format!(" {}", name)),
                    Event::End(_) => current.push_str(&format!("{}", name)),
                    _ => current.push_str(&format!("{}", name)),
                }
            },
            Event::Property(name, value) => {
                match last {
                    Event::Selector(_) => properties.push_str(&format!(" {{\n  {}: {};", name, value)),
                    _ => properties.push_str(&format!("\n  {}: {};", name, value)),
                }
            },
            Event::End(_) => {
                match (properties.len(), children.len()) {
                    (_, 0) => {
                        current.push_str(&properties);
                        current.push_str("\n}");
                    },
                    (0, _) => {
                        current.push_str(" ");
                        current.push_str(&children);
                    },
                    (_, _) => {
                        current.push_str(&properties);
                        current.push_str("\n}\n");
                        current.push_str(&parents.connect(" "));
                        current.push_str(" ");
                        current.push_str(&children);
                    },
                }
                parents.pop();
                return current
            },
            Event::Variable(..) => unreachable!(),
            Event::Comment(body) => unimplemented!(),
        };

        last = token;
    }
    children
}

pub fn compact<'a, I>(tokenizer: &mut I) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut vm = VariableMapper::new(tokenizer);
    let mut parents = Vec::new();
    compact_inner(&mut vm, &mut parents)
}

fn compact_inner<'a, I>(tokenizer: &mut I, parents: &mut Vec<String>) -> String
    where I: Iterator<Item = Event<'a>>
{
    let mut last = Event::End(Rule::SassRule);
    let mut current = String::new();
    let mut properties = String::new();
    let mut children = String::new();

    while let Some(token) = tokenizer.next() {
        match token.clone() {
            Event::Start(_) => {
                match children.len() {
                    0 => children = compact_inner(tokenizer, parents),
                    _ => {
                        children.push_str("\n");
                        children.push_str(&compact_inner(tokenizer, parents));
                    },
                };
            },
            Event::Selector(name) => {
                parents.push((*name).to_string());
                match last {
                    Event::Selector(_) => current.push_str(&format!(" {}", name)),
                    Event::End(_) => current.push_str(&format!("{}", name)),
                    _ => current.push_str(&format!("{}", name)),
                }
            },
            Event::Property(name, value) => {
                match last {
                    Event::Selector(_) => properties.push_str(&format!(" {{ {}: {};", name, value)),
                    _ => properties.push_str(&format!(" {}: {};", name, value)),
                }
            },
            Event::End(_) => {
                match (properties.len(), children.len()) {
                    (0, 0) => current.push_str(" }"),
                    (_, 0) => {
                        current.push_str(&properties);
                        current.push_str(" }\n");
                    },
                    (0, _) => {
                        current.push_str(" ");
                        current.push_str(&children);
                    },
                    (_, _) => {
                        current.push_str(&properties);
                        current.push_str(" }\n");
                        current.push_str(&parents.connect(" "));
                        current.push_str(" ");
                        current.push_str(&children);
                    },
                }
                parents.pop();
                return current
            },
            Event::Variable(..) => unreachable!(),
            Event::Comment(body) => unimplemented!(),
        };
        last = token;
    }
    children
}

pub fn debug(tokenizer: &mut Tokenizer) -> String {
    let mut output = String::new();
    let mut current = String::new();

    while let Some(token) = tokenizer.next() {
        current.push_str(&format!("{:?}\n", token));
        match token {
            Event::End(_) => {
                output.push_str(&current);
                current = String::new();
            },
            _ => {},
        }
    }
    output
}
<|endoftext|>


<commit_before>use clap::{ App, Arg, ArgMatches };
use std::fs::File;
use std::io::{ BufRead, BufReader };
use std::path::Path;

pub fn read_args() -> Result<(Vec<String>, String), String> {
    let matches = load_matches();

    // The only things that can cause an early return here are
    // an absent dictionary and the lack of a target prefix. Here
    // we handle the prefix:
    let prefix = match matches.value_of("prefix") {
        Some(prefix) => prefix,
        None => return Err("prefix not provided".to_string()),
    };

    // And here we handle the dictionary:
    let file = match matches.value_of("dictionary").map(|p| File::open(&Path::new(p))) {
        Some(Ok(file)) => file,
        _ => return Err("dictionary not provided".to_string()),
    };

    let sort = matches.is_present("sort");
    let ddup = matches.is_present("dedup");

    Ok((load_file(BufReader::new(file), sort, ddup), prefix.to_string()))
}

fn load_file<R: BufRead>(r: R, sort: bool, ddup: bool) -> Vec<String> {
    let mut vec: Vec<String> = r.lines()
        .filter_map(|l| l.map(|l| l.trim().to_string()).ok())
        .collect();

    if sort { vec.sort(); }
    if ddup { vec.dedup(); }

    vec
}

fn load_matches<'a>() -> ArgMatches<'a> {
    App::new("fin")
        .version("0.0.5")
        .author("J/A <archer884@gmail.com>")
        .about("Provides word completions")
        .arg(Arg::new("prefix")
             .help("Search prefix, e.g. 'app' for 'apple'")
             .required(true)
             .index(1))
        .arg(Arg::new("dictionary")
             .help("Dictionary input file(s)")
             .required(true)
             .index(2))
        .arg(Arg::new("sort")
             .short("s")
             .long("sort")
             .help("Ensure dictionary is sorted")
             .takes_value(false))
        .arg(Arg::new("dedup")
             .short("d")
             .long("dedup")
             .help("Ensure dictionary is deduplicated")
             .takes_value(false))
        .get_matches()
}
<commit_msg>Update error handling.<commit_after>use clap::{ App, Arg, ArgMatches };
use std::fs::File;
use std::io::{ BufRead, BufReader };
use std::path::Path;

pub fn read_args() -> Result<(Vec<String>, String), String> {
    let matches = load_matches();

    // The only things that can cause an early return here are
    // an absent dictionary and the lack of a target prefix. Here
    // we handle the prefix:
    let prefix = match matches.value_of("prefix") {
        Some(prefix) => prefix,
        None => return Err("Prefix not provided".to_string()),
    };

    // And here we handle the dictionary:
    let file = match matches.value_of("dictionary").map(|p| File::open(&Path::new(p))) {
        Some(Ok(file)) => file,
        Some(Err(_)) => return Err("Unable to open file".to_string()),
        None => return Err("Dictionary not provided".to_string()),
    };

    let sort = matches.is_present("sort");
    let ddup = matches.is_present("dedup");

    Ok((load_file(BufReader::new(file), sort, ddup), prefix.to_string()))
}

fn load_file<R: BufRead>(r: R, sort: bool, ddup: bool) -> Vec<String> {
    let mut vec: Vec<String> = r.lines()
        .filter_map(|l| l.map(|l| l.trim().to_string()).ok())
        .collect();

    if sort { vec.sort(); }
    if ddup { vec.dedup(); }

    vec
}

fn load_matches<'a>() -> ArgMatches<'a> {
    App::new("fin")
        .version("0.0.5")
        .author("J/A <archer884@gmail.com>")
        .about("Provides word completions")
        .arg(Arg::new("prefix")
             .help("Search prefix, e.g. 'app' for 'apple'")
             .required(true)
             .index(1))
        .arg(Arg::new("dictionary")
             .help("Dictionary input file(s)")
             .required(true)
             .index(2))
        .arg(Arg::new("sort")
             .short("s")
             .long("sort")
             .help("Ensure dictionary is sorted")
             .takes_value(false))
        .arg(Arg::new("dedup")
             .short("d")
             .long("dedup")
             .help("Ensure dictionary is deduplicated")
             .takes_value(false))
        .get_matches()
}
<|endoftext|>


<commit_before>use std::path::Path;
use ttf;

pub struct FontLoader {
  pub sans : ttf::Font,
  pub mono : ttf::Font,
}

impl FontLoader {
  pub fn new() -> FontLoader {
    FontLoader {
      sans : ttf::Font::new(&Path::new("fonts/Open_Sans/OpenSans-Regular.ttf"), 11)  ,
      mono : ttf::Font::new(&Path::new("fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf"), 11),
    }
  }
}
<commit_msg>random spacing<commit_after>use std::path::Path;
use ttf;

pub struct FontLoader {
  pub sans : ttf::Font,
  pub mono : ttf::Font,
}

impl FontLoader {
  pub fn new() -> FontLoader {
    FontLoader {
      sans : ttf::Font::new(&Path::new("fonts/Open_Sans/OpenSans-Regular.ttf"), 11),
      mono : ttf::Font::new(&Path::new("fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf"), 11),
    }
  }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use keys::*;
use event::KeyEvent;
use keyboard::KeyboardInternal;
use libusb::{Result as UsbResult, Error as UsbError};

#[derive(Debug, Clone, PartialEq)]
pub struct Packet<'a> {
    pub endpoint: u8,
    pub buf: &'a [u8],
}

impl<'a> Packet<'a> {
    pub fn new(endpoint_direction: u8, buf: &'a [u8]) -> Packet {
        Packet {
            endpoint: endpoint_direction & 0x7f,
            buf: buf
        }
    }
}

pub enum Parser {
    ParseKey(Box<ParseKey>),
    ParseControl(Box<ParseControl>),
}

pub trait ParseKey {
    fn accept(&self, packet: &Packet) -> bool;
    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<Vec<KeyEvent>>;
}

pub trait ParseControl {
    fn accept(&self, packet: &Packet) -> bool;
    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<()>;
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct KeyParser {
    pressed_keys1: HashSet<Key>,
    pressed_keys2: HashSet<Key>,
}

impl KeyParser {
    pub fn new() -> KeyParser {
        KeyParser {
            pressed_keys1: HashSet::new(),
            pressed_keys2: HashSet::new(),
        }
    }
}

impl ParseKey for KeyParser {
    fn accept(&self, packet: &Packet) -> bool {
        // normal key
        packet.buf.len() == 8 && packet.endpoint == 1 && packet.buf[1] == 0x00
        // rollover
        || packet.buf.len() == 21 && packet.endpoint == 2 && packet.buf[0] == 0x01
        //  media key
        || packet.buf.len() == 2 && packet.endpoint == 2 && packet.buf[0] == 0x02
    }

    #[allow(unused_variables)]
    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<Vec<KeyEvent>> {
        let mut state = HashSet::new();

        // media keys
        if packet.endpoint == 2 && packet.buf[0] == 0x02 {
            for key in MediaKey::values() {
                if packet.buf[1] & key as u8 == key as u8 {
                    state.insert(key.into());
                }
            }
        }

        // standard keys and rollover
        if packet.endpoint == 1 || packet.endpoint == 2 && packet.buf[0] == 0x01 {
            for k in &packet.buf[1..] {
                match StandardKey::from(*k) {
                    StandardKey::None => {},
                    s => { state.insert(s.into()); }
                }
            }
        }

        // modifier keys
        if packet.endpoint == 1 && packet.buf[0] != 0x00 {
            // byte 0 has modifier keys as bytemap:
            // 0b0 0 0 0 0 0 0 0
            //   R R R R L L L L
            //   W A S C W A S C
            //   I L H T I L H T
            //   N T I R N T I R
            //     G F L     F L
            //     R T       T
            if packet.buf[0] & 0x01 == 0x01 {
                state.insert(StandardKey::LeftControl.into());
            }
            if packet.buf[0] & 0x02 == 0x02 {
                state.insert(StandardKey::LeftShift.into());
            }
            if packet.buf[0] & 0x04 == 0x04 {
                state.insert(StandardKey::LeftAlt.into());
            }
            if packet.buf[0] & 0x08 == 0x08 {
                state.insert(StandardKey::LeftWindows.into());
            }
            if packet.buf[0] & 0x10 == 0x10 {
                state.insert(StandardKey::RightControl.into());
            }
            if packet.buf[0] & 0x20 == 0x20 {
                state.insert(StandardKey::RightShift.into());
            }
            if packet.buf[0] & 0x40 == 0x40 {
                state.insert(StandardKey::RightAlt.into());
            }
            if packet.buf[0] & 0x80 == 0x80 {
                state.insert(StandardKey::RightWindows.into());
            }
        }

        let mut added: Vec<_>;
        let mut removed: Vec<_>;
        if packet.endpoint == 1 {
            added = state.difference(&self.pressed_keys1).cloned().collect();
            removed = self.pressed_keys1.difference(&state).cloned().collect();
            self.pressed_keys1 = state;
        } else {
            added = state.difference(&self.pressed_keys2).cloned().collect();
            removed = self.pressed_keys2.difference(&state).cloned().collect();
            self.pressed_keys2 = state;
        }
        let res = added.drain(..).map(|e| KeyEvent::KeyPressed(e))
            .chain(removed.drain(..).map(|e| KeyEvent::KeyReleased(e)))
            .collect();
        Ok(res)
    }
}

impl From<KeyParser> for Parser {
    fn from(parser: KeyParser) -> Parser {
        Parser::ParseKey(Box::new(parser))
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ControlParser;

impl ControlParser {
    pub fn new() -> ControlParser {
        ControlParser { }
    }
}

impl ParseControl for ControlParser {
    fn accept(&self, packet: &Packet) -> bool {
        (packet.buf.len() == 20 || packet.buf.len() == 64) && packet.endpoint == 0
        || packet.buf.len() == 20 && packet.endpoint == 2 && packet.buf[0] == 0x11
    }

    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<()> {
        if packet.buf.len() == 0 {
            println!("buf empty");
            Ok(())
        } else if packet.endpoint == 0
             && !(packet.buf[0] == 0x11 || packet.buf[0] == 0x12) {
            println!("Trying to parse unknown packet from iface 0: {:?}", packet);
            Err(UsbError::NotSupported)
        } else if packet.endpoint == 2
            && !(packet.buf[0] == 0x11) {
            println!("Trying to parse unknown packet from iface 2: {:?}", packet);
            Err(UsbError::NotSupported)
        // wait for the acknoledgement of the control packet on iface 2 before
        // sending the next one
        } else if packet.endpoint == 2 {
            keyboard_internal.send_next_control()
        } else {
            Ok(())
        }
    }
}

impl From<ControlParser> for Parser {
    fn from(parser: ControlParser) -> Parser {
        Parser::ParseControl(Box::new(parser))
    }
}

<commit_msg>fix(parser): Proper caching of media keys<commit_after>use std::collections::HashSet;
use keys::*;
use event::KeyEvent;
use keyboard::KeyboardInternal;
use libusb::{Result as UsbResult, Error as UsbError};

#[derive(Debug, Clone, PartialEq)]
pub struct Packet<'a> {
    pub endpoint: u8,
    pub buf: &'a [u8],
}

impl<'a> Packet<'a> {
    pub fn new(endpoint_direction: u8, buf: &'a [u8]) -> Packet {
        Packet {
            endpoint: endpoint_direction & 0x7f,
            buf: buf
        }
    }
}

pub enum Parser {
    ParseKey(Box<ParseKey>),
    ParseControl(Box<ParseControl>),
}

pub trait ParseKey {
    fn accept(&self, packet: &Packet) -> bool;
    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<Vec<KeyEvent>>;
}

pub trait ParseControl {
    fn accept(&self, packet: &Packet) -> bool;
    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<()>;
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct KeyParser {
    pressed_keys: HashSet<Key>,
    pressed_rollover_keys: HashSet<Key>,
    pressed_media_keys: HashSet<Key>,
}

impl KeyParser {
    pub fn new() -> KeyParser {
        KeyParser {
            pressed_keys: HashSet::new(),
            pressed_rollover_keys: HashSet::new(),
            pressed_media_keys: HashSet::new(),
        }
    }
}

impl ParseKey for KeyParser {
    fn accept(&self, packet: &Packet) -> bool {
        // normal key
        packet.buf.len() == 8 && packet.endpoint == 1 && packet.buf[1] == 0x00
        // rollover
        || packet.buf.len() == 21 && packet.endpoint == 2 && packet.buf[0] == 0x01
        //  media key
        || packet.buf.len() == 2 && packet.endpoint == 2 && packet.buf[0] == 0x02
    }

    #[allow(unused_variables)]
    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<Vec<KeyEvent>> {
        let mut state = HashSet::new();

        let media = packet.endpoint == 2 && packet.buf[0] == 0x02;
        let standard = packet.endpoint == 1;
        let rollover = packet.endpoint == 2 && packet.buf[0] == 0x01;

        // media keys
        if media {
            for key in MediaKey::values() {
                if packet.buf[1] & key as u8 == key as u8 {
                    state.insert(key.into());
                }
            }
        }

        // standard keys and rollover
        if standard || rollover {
            for k in &packet.buf[1..] {
                match StandardKey::from(*k) {
                    StandardKey::None => {},
                    s => { state.insert(s.into()); }
                }
            }
        }

        // modifier keys
        if standard {
            // byte 0 has modifier keys as bytemap:
            // 0b0 0 0 0 0 0 0 0
            //   R R R R L L L L
            //   W A S C W A S C
            //   I L H T I L H T
            //   N T I R N T I R
            //     G F L     F L
            //     R T       T
            if packet.buf[0] & 0x01 == 0x01 {
                state.insert(StandardKey::LeftControl.into());
            }
            if packet.buf[0] & 0x02 == 0x02 {
                state.insert(StandardKey::LeftShift.into());
            }
            if packet.buf[0] & 0x04 == 0x04 {
                state.insert(StandardKey::LeftAlt.into());
            }
            if packet.buf[0] & 0x08 == 0x08 {
                state.insert(StandardKey::LeftWindows.into());
            }
            if packet.buf[0] & 0x10 == 0x10 {
                state.insert(StandardKey::RightControl.into());
            }
            if packet.buf[0] & 0x20 == 0x20 {
                state.insert(StandardKey::RightShift.into());
            }
            if packet.buf[0] & 0x40 == 0x40 {
                state.insert(StandardKey::RightAlt.into());
            }
            if packet.buf[0] & 0x80 == 0x80 {
                state.insert(StandardKey::RightWindows.into());
            }
        }

        let old_state = if standard {
            &mut self.pressed_keys
        } else if rollover {
            &mut self.pressed_rollover_keys
        } else if media {
            &mut self.pressed_media_keys
        } else {
            unreachable!()
        };
        let mut added: Vec<_>;
        let mut removed: Vec<_>;
        added = state.difference(old_state).cloned().collect();
        removed = old_state.difference(&state).cloned().collect();
        *old_state = state;
        let res = added.drain(..).map(|e| KeyEvent::KeyPressed(e))
            .chain(removed.drain(..).map(|e| KeyEvent::KeyReleased(e)))
            .collect();
        Ok(res)
    }
}

impl From<KeyParser> for Parser {
    fn from(parser: KeyParser) -> Parser {
        Parser::ParseKey(Box::new(parser))
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ControlParser;

impl ControlParser {
    pub fn new() -> ControlParser {
        ControlParser { }
    }
}

impl ParseControl for ControlParser {
    fn accept(&self, packet: &Packet) -> bool {
        (packet.buf.len() == 20 || packet.buf.len() == 64) && packet.endpoint == 0
        || packet.buf.len() == 20 && packet.endpoint == 2 && packet.buf[0] == 0x11
    }

    fn parse(&mut self, packet: &Packet, keyboard_internal: &mut KeyboardInternal) -> UsbResult<()> {
        if packet.buf.len() == 0 {
            println!("buf empty");
            Ok(())
        } else if packet.endpoint == 0
             && !(packet.buf[0] == 0x11 || packet.buf[0] == 0x12) {
            println!("Trying to parse unknown packet from iface 0: {:?}", packet);
            Err(UsbError::NotSupported)
        } else if packet.endpoint == 2
            && !(packet.buf[0] == 0x11) {
            println!("Trying to parse unknown packet from iface 2: {:?}", packet);
            Err(UsbError::NotSupported)
        // wait for the acknoledgement of the control packet on iface 2 before
        // sending the next one
        } else if packet.endpoint == 2 {
            keyboard_internal.send_next_control()
        } else {
            Ok(())
        }
    }
}

impl From<ControlParser> for Parser {
    fn from(parser: ControlParser) -> Parser {
        Parser::ParseControl(Box::new(parser))
    }
}

<|endoftext|>


<commit_before>use serde::de::{Deserialize, Deserializer};

use crate::http::error::DiscordJsonSingleError;
use crate::internal::prelude::*;

#[allow(clippy::missing_errors_doc)]
pub fn deserialize_errors<'de, D: Deserializer<'de>>(
    deserializer: D,
) -> StdResult<Vec<DiscordJsonSingleError>, D::Error> {
    let map: Value = Value::deserialize(deserializer)?;

    if !map.is_object() {
        return Ok(vec![]);
    }

    let mut errors: Vec<DiscordJsonSingleError> = vec![];

    loop_errors(map, &mut errors, &mut Vec::new());

    Ok(errors)
}

fn loop_errors(value: Value, errors: &mut Vec<DiscordJsonSingleError>, path: &mut Vec<String>) {
    for (key, looped) in value.as_object().expect("expected object").iter() {
        let object = looped.as_object().expect("expected object");
        if object.contains_key("_errors") {
            let found_errors = object
                .get("_errors")
                .expect("expected _errors")
                .as_array()
                .expect("expected array")
                .to_owned();
            for error in found_errors {
                let error_object = error.as_object().expect("expected object");
                let mut object_path = path.clone();

                object_path.push(key.to_string());

                errors.push(DiscordJsonSingleError {
                    code: error_object
                        .get("code")
                        .expect("expected code")
                        .as_str()
                        .expect("expected string")
                        .to_owned(),
                    message: error_object
                        .get("message")
                        .expect("expected message")
                        .as_str()
                        .expect("expected string")
                        .to_owned(),
                    path: object_path.join("."),
                });
            }
            continue;
        }
        path.push(key.to_string());

        loop_errors(looped.clone(), errors, path);
    }
}
<commit_msg>Fix paths in `DiscordJsonError` messages (#1357)<commit_after>use serde::de::{Deserialize, Deserializer};

use crate::http::error::DiscordJsonSingleError;
use crate::internal::prelude::*;

#[allow(clippy::missing_errors_doc)]
pub fn deserialize_errors<'de, D: Deserializer<'de>>(
    deserializer: D,
) -> StdResult<Vec<DiscordJsonSingleError>, D::Error> {
    let map: Value = Value::deserialize(deserializer)?;

    if !map.is_object() {
        return Ok(vec![]);
    }

    let mut errors = Vec::new();

    loop_errors(map, &mut errors, Vec::new());

    Ok(errors)
}

fn loop_errors(value: Value, errors: &mut Vec<DiscordJsonSingleError>, path: Vec<String>) {
    for (key, looped) in value.as_object().expect("expected object").iter() {
        let object = looped.as_object().expect("expected object");
        if object.contains_key("_errors") {
            let found_errors = object
                .get("_errors")
                .expect("expected _errors")
                .as_array()
                .expect("expected array")
                .to_owned();
            for error in found_errors {
                let error_object = error.as_object().expect("expected object");
                let mut object_path = path.clone();

                object_path.push(key.to_string());

                errors.push(DiscordJsonSingleError {
                    code: error_object
                        .get("code")
                        .expect("expected code")
                        .as_str()
                        .expect("expected string")
                        .to_owned(),
                    message: error_object
                        .get("message")
                        .expect("expected message")
                        .as_str()
                        .expect("expected string")
                        .to_owned(),
                    path: object_path.join("."),
                });
            }
            continue;
        }

        let mut new_path = path.clone();
        new_path.push(key.to_string());

        loop_errors(looped.clone(), errors, new_path);
    }
}
<|endoftext|>


<commit_before>//! (see [`lower_simpleast`](lower_simpleast))

use super::simple_ast as sast;
use middle::ir;
use middle::ir::MOpcode as IrOpcode;
use middle::ssa::cfg_traits::{CFGMod, CFG};
use middle::ssa::ssa_traits::{SSAExtra, SSAMod, ValueInfo, ValueType, SSA};
use middle::ssa::ssastorage::{NodeData, SSAStorage};
use std::collections::HashMap;
use std::error;
use std::fmt;
use std::mem;

pub type Result<T> = ::std::result::Result<T, LoweringError>;

/// Lowers [AST](sast) into the provided [`SSAStorage`](SSAStorage)
pub fn lower_simpleast<'a>(ssa: &'a mut SSAStorage, sfn: sast::Function) -> Result<()> {
    LowerSsa::new(ssa)?.lower_function(sfn)
}

#[derive(Debug)]
pub enum LoweringError {
    /// If an operation on the [`SSAStorage`](SSAStorage) fails
    SsaError,
    /// If the AST was invalid somehow
    InvalidAst(String),
}

type SSABlock = <SSAStorage as CFG>::ActionRef;
type SSAValue = <SSAStorage as SSA>::ValueRef;

/// from [`ssaconstructor`](::frontend::ssaconstructor)
const FALSE_EDGE: u8 = 0;
const TRUE_EDGE: u8 = 1;
const UNCOND_EDGE: u8 = 2;

struct LowerSsa<'a> {
    ssa: &'a mut SSAStorage,
    entry_node: SSABlock,
    exit_node: SSABlock,
    blocks: HashMap<ir::MAddress, SSABlock>,
    values: HashMap<sast::ValueRef, SSAValue>,
    regnames: Vec<sast::PhysReg>,
}

impl<'a> LowerSsa<'a> {
    fn new(ssa: &'a mut SSAStorage) -> Result<Self> {
        let entry_node = if let Some(en) = ssa.entry_node() {
            en
        } else {
            let entry_node = ssa.insert_block(ir::MAddress::new(0, 0))?;
            ssa.set_entry_node(entry_node);
            entry_node
        };
        let exit_node = if let Some(en) = ssa.exit_node() {
            en
        } else {
            let exit_node = ssa.insert_dynamic()?;
            ssa.set_exit_node(exit_node);
            exit_node
        };
        Ok(LowerSsa {
            ssa,
            entry_node,
            exit_node,
            blocks: HashMap::new(),
            values: HashMap::new(),
            regnames: Vec::new(),
        })
    }

    fn lower_function(mut self, sfn: sast::Function) -> Result<()> {
        self.regnames = sfn.register_list;
        if self.regnames.len() >= u8::max_value() as usize {
            return Err(LoweringError::InvalidAst(format!(
                "too many registers: {}",
                self.regnames.len()
            )));
        }

        // when we're lowering a block, we need to know what block comes afterwards;
        // so when we iterate over the blocks, we lower the *previous* block we saw,
        // so then that block's next block is just the current block
        let mut opt_prev_sbb: Option<sast::BasicBlock> = None;
        for sbb in sfn.basic_blocks {
            let sbb_addr = sbb.addr;
            if let Some(prev_sbb) = mem::replace(&mut opt_prev_sbb, Some(sbb)) {
                // lower `prev`; `sbb` is `prev`'s next
                self.lower_basicblock(prev_sbb, Some(sbb_addr))?;
            } else {
                // `sbb` is the first block
                let bb = self.block_at(sbb_addr)?;
                self.ssa
                    .insert_control_edge(self.entry_node, bb, UNCOND_EDGE);
            }
        }
        if let Some(last_sbb) = opt_prev_sbb {
            // lower the last block
            self.lower_basicblock(last_sbb, None)?;
        } else {
            // there were 0 blocks
            // I think this is a sane thing to do in this case :P
            self.ssa
                .insert_control_edge(self.entry_node, self.exit_node, UNCOND_EDGE);
        }

        if let Some(sen) = sfn.exit_node {
            self.lower_exit_node(sen)?;
        }

        let mut sfinal_state: Vec<Option<SSAValue>> = vec![None; self.regnames.len() + 1];
        for (sreg, sop) in sfn.final_reg_state {
            // a bit of a hack...
            let reg_idx = if sreg.0 != "mem" {
                self.index_of_reg(&sreg)? as usize
            } else {
                self.regnames.len()
            };
            let op = self.lower_operand(sop)?;
            sfinal_state[reg_idx] = Some(op);
        }
        let final_state = self.ssa.registers_in(self.exit_node)?;
        for (reg_i, opt_op) in sfinal_state.into_iter().enumerate() {
            let op = if let Some(op) = opt_op {
                op
            } else {
                let cmnt = if reg_i != self.regnames.len() {
                    self.regnames[reg_i].0.clone()
                } else {
                    "mem".to_owned()
                };
                self.lower_operand(sast::Operand::Comment(cmnt))?
            };
            self.ssa.op_use(final_state, reg_i as u8, op);
        }

        self.ssa
            .map_registers(self.regnames.into_iter().map(|x| x.0).collect());

        Ok(())
    }

    fn lower_basicblock(
        &mut self,
        sbb: sast::BasicBlock,
        opt_next_addr: Option<ir::MAddress>,
    ) -> Result<()> {
        let bb = self.block_at(sbb.addr)?;

        for sop in sbb.ops {
            let (res, opt_op_addr) = self.lower_operation(sop)?;
            let op_addr = opt_op_addr.unwrap_or(sbb.addr);
            self.ssa.insert_into_block(res, bb, op_addr);
        }

        let next_node = opt_next_addr.map_or(Ok(self.exit_node), |a| self.block_at(a))?;
        match sbb.jump {
            Some(sast::Terminator::JmpUncond(tgt)) => {
                let tgt_bb = self.block_at(tgt)?;
                self.ssa.insert_control_edge(bb, tgt_bb, UNCOND_EDGE);
            }
            Some(sast::Terminator::JmpCond(sel_sop, if_tgt, opt_else_tgt)) => {
                let sel_op = self.lower_operand(sel_sop)?;
                let if_bb = self.block_at(if_tgt)?;
                let else_bb = opt_else_tgt.map_or(Ok(next_node), |a| self.block_at(a))?;
                self.ssa.set_selector(sel_op, bb);
                self.ssa.insert_control_edge(bb, if_bb, TRUE_EDGE);
                self.ssa.insert_control_edge(bb, else_bb, FALSE_EDGE);
            }
            Some(sast::Terminator::JmpIndirect(sel_sop)) => {
                let sel_op = self.lower_operand(sel_sop)?;
                self.ssa.set_selector(sel_op, bb);
                self.ssa
                    .insert_control_edge(bb, self.exit_node, UNCOND_EDGE);
            }
            Some(sast::Terminator::Unreachable) => {
                // nothing to do
            }
            None => {
                // fallthrough to `next`
                self.ssa.insert_control_edge(bb, next_node, UNCOND_EDGE);
            }
        }

        Ok(())
    }

    fn lower_exit_node(&mut self, sen: sast::ExitNode) -> Result<()> {
        let node_addr = self.ssa.starting_address(self.exit_node)?;
        for sop in sen.ops {
            let (res, opt_op_addr) = self.lower_operation(sop)?;
            let op_addr = opt_op_addr.unwrap_or(node_addr);
            self.ssa.insert_into_block(res, self.exit_node, op_addr);
        }

        Ok(())
    }

    fn lower_operation(
        &mut self,
        sopn: sast::Operation,
    ) -> Result<(SSAValue, Option<ir::MAddress>)> {
        Ok(match sopn {
            sast::Operation::Phi(vr, ty, sops) => {
                let vi = lower_valueinfo(ty);
                let res = self.ssa.insert_phi(vi)?;
                for sop in sops.into_iter().rev() {
                    let op = self.lower_operand(sop)?;
                    self.ssa.phi_use(res, op);
                }
                self.values.insert(vr, res);
                (res, None)
            }

            sast::Operation::Assign(opt_addr, vr, ty, sexpr) => {
                let vi = lower_valueinfo(ty);
                let (opcode, sops) = match sexpr {
                    sast::Expr::Infix(sop0, sopcode, sop1) => {
                        (lower_infix_op(sopcode), vec![sop0, sop1])
                    }
                    sast::Expr::Prefix(sopcode, sop0) => (lower_prefix_op(sopcode), vec![sop0]),
                    sast::Expr::Load(sop0, sop1) => (IrOpcode::OpLoad, vec![sop0, sop1]),
                    sast::Expr::Store(sop0, sop1, sop2) => {
                        (IrOpcode::OpStore, vec![sop0, sop1, sop2])
                    }
                    sast::Expr::Resize(rst, ws, sop0) => (lower_resize_op(rst, ws), vec![sop0]),
                };
                let res = self.ssa.insert_op(opcode, vi, None)?;
                for (i, sop) in sops.into_iter().enumerate() {
                    let op = self.lower_operand(sop)?;
                    self.ssa.op_use(res, i as u8, op);
                }
                self.values.insert(vr, res);
                (res, opt_addr)
            }

            sast::Operation::Call(opt_addr, tgt, sargs) => {
                // TODO: round-trip call `ValueInfo`
                let vi = ValueInfo::new_unresolved(ir::WidthSpec::Unknown);
                let res = self.ssa.insert_op(IrOpcode::OpCall, vi, None)?;
                let tgt_op = self.lower_operand(tgt)?;
                self.ssa.op_use(res, 0, tgt_op);
                for sarg in sargs {
                    let reg_idx = self.index_of_reg(&sarg.formal)?;
                    let op = self.lower_operand(sarg.actual)?;
                    self.ssa.op_use(res, reg_idx + 1, op);
                }
                (res, opt_addr)
            }
        })
    }

    fn lower_operand(&mut self, sop: sast::Operand) -> Result<SSAValue> {
        match sop {
            sast::Operand::Comment(s) => {
                // TODO: round-trip comment `ValueInfo`
                let vi = ValueInfo::new_unresolved(ir::WidthSpec::Unknown);
                Ok(self.ssa.insert_comment(vi, s)?)
            }
            sast::Operand::ValueRef(r) => {
                if let Some(x) = self.values.get(&r).cloned() {
                    Ok(x)
                } else {
                    Err(LoweringError::InvalidAst(format!(
                        "no value reference: %{}",
                        r.0
                    )))
                }
            }
            sast::Operand::Const(v) => Ok(self.ssa.insert_const(v)?),
        }
    }

    fn block_at(&mut self, at: ir::MAddress) -> Result<SSABlock> {
        use std::collections::hash_map::Entry;
        // can't use `or_insert_with` because `ssa.insert_block` may fail
        Ok(*match self.blocks.entry(at) {
            Entry::Occupied(o) => o.into_mut(),
            Entry::Vacant(v) => v.insert(self.ssa.insert_block(at)?),
        })
    }

    fn index_of_reg(&self, sreg: &sast::PhysReg) -> Result<u8> {
        // TODO: more efficient as a HashMap<Reg, u8>?
        if let Some(x) = self.regnames.iter().position(|r| r == sreg) {
            // we already checked that `regnames.len() < u8::max_value()`
            Ok(x as u8)
        } else {
            Err(LoweringError::InvalidAst(format!(
                "no physical register: {}",
                sreg.0
            )))
        }
    }
}

fn lower_infix_op(siop: sast::InfixOp) -> IrOpcode {
    match siop {
        sast::InfixOp::Add => IrOpcode::OpAdd,
        sast::InfixOp::Sub => IrOpcode::OpSub,
        sast::InfixOp::Mul => IrOpcode::OpMul,
        sast::InfixOp::Div => IrOpcode::OpDiv,
        sast::InfixOp::Mod => IrOpcode::OpMod,
        sast::InfixOp::And => IrOpcode::OpAnd,
        sast::InfixOp::Or => IrOpcode::OpOr,
        sast::InfixOp::Xor => IrOpcode::OpXor,
        sast::InfixOp::Eq => IrOpcode::OpEq,
        sast::InfixOp::Gt => IrOpcode::OpGt,
        sast::InfixOp::Lt => IrOpcode::OpLt,
        sast::InfixOp::Lsl => IrOpcode::OpLsl,
        sast::InfixOp::Lsr => IrOpcode::OpLsr,
    }
}

fn lower_prefix_op(spop: sast::PrefixOp) -> IrOpcode {
    match spop {
        sast::PrefixOp::Not => IrOpcode::OpNot,
    }
}

fn lower_resize_op(srst: sast::ResizeType, sws: sast::WidthSpec) -> IrOpcode {
    match srst {
        sast::ResizeType::Narrow => IrOpcode::OpNarrow(sws.0),
        sast::ResizeType::SignExt => IrOpcode::OpSignExt(sws.0),
        sast::ResizeType::ZeroExt => IrOpcode::OpZeroExt(sws.0),
    }
}

fn lower_valueinfo(sty: sast::Type) -> ValueInfo {
    let ws = ir::WidthSpec::Known((sty.0).0);
    match sty.1 {
        sast::RefSpec::Scalar => ValueInfo::new_scalar(ws),
        sast::RefSpec::Reference => ValueInfo::new_reference(ws),
        sast::RefSpec::Unknown => ValueInfo::new_unresolved(ws),
    }
}

/// [`SSAStorage`][SSAStorage] methods return `Option`,
/// so we convert `None`s into [`SsaError`][LoweringError::SsaError]
impl From<::std::option::NoneError> for LoweringError {
    fn from(_: ::std::option::NoneError) -> Self {
        LoweringError::SsaError
    }
}

impl error::Error for LoweringError {
    fn description(&self) -> &str {
        match *self {
            LoweringError::SsaError => "could not perform an `SSAStorage` operation",
            LoweringError::InvalidAst(_) => "invalid ast",
        }
    }
}

impl fmt::Display for LoweringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            LoweringError::SsaError => write!(f, "could not perform an `SSAStorage` operation"),
            LoweringError::InvalidAst(ref s) => write!(f, "invalid ast: {}", s),
        }
    }
}
<commit_msg>Fix `ir_reader` handling of `mem` "register"<commit_after>//! (see [`lower_simpleast`](lower_simpleast))

use super::simple_ast as sast;
use middle::ir;
use middle::ir::MOpcode as IrOpcode;
use middle::ssa::cfg_traits::{CFGMod, CFG};
use middle::ssa::ssa_traits::{SSAExtra, SSAMod, ValueInfo, ValueType, SSA};
use middle::ssa::ssastorage::{NodeData, SSAStorage};
use std::collections::HashMap;
use std::error;
use std::fmt;
use std::mem;

pub type Result<T> = ::std::result::Result<T, LoweringError>;

/// Lowers [AST](sast) into the provided [`SSAStorage`](SSAStorage)
pub fn lower_simpleast<'a>(ssa: &'a mut SSAStorage, sfn: sast::Function) -> Result<()> {
    LowerSsa::new(ssa)?.lower_function(sfn)
}

#[derive(Debug)]
pub enum LoweringError {
    /// If an operation on the [`SSAStorage`](SSAStorage) fails
    SsaError,
    /// If the AST was invalid somehow
    InvalidAst(String),
}

type SSABlock = <SSAStorage as CFG>::ActionRef;
type SSAValue = <SSAStorage as SSA>::ValueRef;

/// from [`ssaconstructor`](::frontend::ssaconstructor)
const FALSE_EDGE: u8 = 0;
const TRUE_EDGE: u8 = 1;
const UNCOND_EDGE: u8 = 2;

struct LowerSsa<'a> {
    ssa: &'a mut SSAStorage,
    entry_node: SSABlock,
    exit_node: SSABlock,
    blocks: HashMap<ir::MAddress, SSABlock>,
    values: HashMap<sast::ValueRef, SSAValue>,
    regnames: Vec<sast::PhysReg>,
}

impl<'a> LowerSsa<'a> {
    fn new(ssa: &'a mut SSAStorage) -> Result<Self> {
        let entry_node = if let Some(en) = ssa.entry_node() {
            en
        } else {
            let entry_node = ssa.insert_block(ir::MAddress::new(0, 0))?;
            ssa.set_entry_node(entry_node);
            entry_node
        };
        let exit_node = if let Some(en) = ssa.exit_node() {
            en
        } else {
            let exit_node = ssa.insert_dynamic()?;
            ssa.set_exit_node(exit_node);
            exit_node
        };
        Ok(LowerSsa {
            ssa,
            entry_node,
            exit_node,
            blocks: HashMap::new(),
            values: HashMap::new(),
            regnames: Vec::new(),
        })
    }

    fn lower_function(mut self, sfn: sast::Function) -> Result<()> {
        self.regnames = sfn.register_list;
        if self.regnames.len() >= u8::max_value() as usize {
            return Err(LoweringError::InvalidAst(format!(
                "too many registers: {}",
                self.regnames.len()
            )));
        }

        // when we're lowering a block, we need to know what block comes afterwards;
        // so when we iterate over the blocks, we lower the *previous* block we saw,
        // so then that block's next block is just the current block
        let mut opt_prev_sbb: Option<sast::BasicBlock> = None;
        for sbb in sfn.basic_blocks {
            let sbb_addr = sbb.addr;
            if let Some(prev_sbb) = mem::replace(&mut opt_prev_sbb, Some(sbb)) {
                // lower `prev`; `sbb` is `prev`'s next
                self.lower_basicblock(prev_sbb, Some(sbb_addr))?;
            } else {
                // `sbb` is the first block
                let bb = self.block_at(sbb_addr)?;
                self.ssa
                    .insert_control_edge(self.entry_node, bb, UNCOND_EDGE);
            }
        }
        if let Some(last_sbb) = opt_prev_sbb {
            // lower the last block
            self.lower_basicblock(last_sbb, None)?;
        } else {
            // there were 0 blocks
            // I think this is a sane thing to do in this case :P
            self.ssa
                .insert_control_edge(self.entry_node, self.exit_node, UNCOND_EDGE);
        }

        if let Some(sen) = sfn.exit_node {
            self.lower_exit_node(sen)?;
        }

        let mut sfinal_state: Vec<Option<SSAValue>> = vec![None; self.regnames.len() + 1];
        for (sreg, sop) in sfn.final_reg_state {
            // a bit of a hack...
            let reg_idx = if sreg.0 != "mem" {
                self.index_of_reg(&sreg)? as usize
            } else {
                self.regnames.len()
            };
            let op = self.lower_operand(sop)?;
            sfinal_state[reg_idx] = Some(op);
        }
        let final_state = self.ssa.registers_in(self.exit_node)?;
        for (reg_i, opt_op) in sfinal_state.into_iter().enumerate() {
            let op = if let Some(op) = opt_op {
                op
            } else {
                let cmnt = if reg_i != self.regnames.len() {
                    self.regnames[reg_i].0.clone()
                } else {
                    "mem".to_owned()
                };
                self.lower_operand(sast::Operand::Comment(cmnt))?
            };
            self.ssa.op_use(final_state, reg_i as u8, op);
        }

        self.ssa
            .map_registers(self.regnames.into_iter().map(|x| x.0).collect());

        Ok(())
    }

    fn lower_basicblock(
        &mut self,
        sbb: sast::BasicBlock,
        opt_next_addr: Option<ir::MAddress>,
    ) -> Result<()> {
        let bb = self.block_at(sbb.addr)?;

        for sop in sbb.ops {
            let (res, opt_op_addr) = self.lower_operation(sop)?;
            let op_addr = opt_op_addr.unwrap_or(sbb.addr);
            self.ssa.insert_into_block(res, bb, op_addr);
        }

        let next_node = opt_next_addr.map_or(Ok(self.exit_node), |a| self.block_at(a))?;
        match sbb.jump {
            Some(sast::Terminator::JmpUncond(tgt)) => {
                let tgt_bb = self.block_at(tgt)?;
                self.ssa.insert_control_edge(bb, tgt_bb, UNCOND_EDGE);
            }
            Some(sast::Terminator::JmpCond(sel_sop, if_tgt, opt_else_tgt)) => {
                let sel_op = self.lower_operand(sel_sop)?;
                let if_bb = self.block_at(if_tgt)?;
                let else_bb = opt_else_tgt.map_or(Ok(next_node), |a| self.block_at(a))?;
                self.ssa.set_selector(sel_op, bb);
                self.ssa.insert_control_edge(bb, if_bb, TRUE_EDGE);
                self.ssa.insert_control_edge(bb, else_bb, FALSE_EDGE);
            }
            Some(sast::Terminator::JmpIndirect(sel_sop)) => {
                let sel_op = self.lower_operand(sel_sop)?;
                self.ssa.set_selector(sel_op, bb);
                self.ssa
                    .insert_control_edge(bb, self.exit_node, UNCOND_EDGE);
            }
            Some(sast::Terminator::Unreachable) => {
                // nothing to do
            }
            None => {
                // fallthrough to `next`
                self.ssa.insert_control_edge(bb, next_node, UNCOND_EDGE);
            }
        }

        Ok(())
    }

    fn lower_exit_node(&mut self, sen: sast::ExitNode) -> Result<()> {
        let node_addr = self.ssa.starting_address(self.exit_node)?;
        for sop in sen.ops {
            let (res, opt_op_addr) = self.lower_operation(sop)?;
            let op_addr = opt_op_addr.unwrap_or(node_addr);
            self.ssa.insert_into_block(res, self.exit_node, op_addr);
        }

        Ok(())
    }

    fn lower_operation(
        &mut self,
        sopn: sast::Operation,
    ) -> Result<(SSAValue, Option<ir::MAddress>)> {
        Ok(match sopn {
            sast::Operation::Phi(vr, ty, sops) => {
                let vi = lower_valueinfo(ty);
                let res = self.ssa.insert_phi(vi)?;
                for sop in sops.into_iter().rev() {
                    let op = self.lower_operand(sop)?;
                    self.ssa.phi_use(res, op);
                }
                self.values.insert(vr, res);
                (res, None)
            }

            sast::Operation::Assign(opt_addr, vr, ty, sexpr) => {
                let vi = lower_valueinfo(ty);
                let (opcode, sops) = match sexpr {
                    sast::Expr::Infix(sop0, sopcode, sop1) => {
                        (lower_infix_op(sopcode), vec![sop0, sop1])
                    }
                    sast::Expr::Prefix(sopcode, sop0) => (lower_prefix_op(sopcode), vec![sop0]),
                    sast::Expr::Load(sop0, sop1) => (IrOpcode::OpLoad, vec![sop0, sop1]),
                    sast::Expr::Store(sop0, sop1, sop2) => {
                        (IrOpcode::OpStore, vec![sop0, sop1, sop2])
                    }
                    sast::Expr::Resize(rst, ws, sop0) => (lower_resize_op(rst, ws), vec![sop0]),
                };
                let res = self.ssa.insert_op(opcode, vi, None)?;
                for (i, sop) in sops.into_iter().enumerate() {
                    let op = self.lower_operand(sop)?;
                    self.ssa.op_use(res, i as u8, op);
                }
                self.values.insert(vr, res);
                (res, opt_addr)
            }

            sast::Operation::Call(opt_addr, tgt, sargs) => {
                // TODO: round-trip call `ValueInfo`
                let vi = ValueInfo::new_unresolved(ir::WidthSpec::Unknown);
                let res = self.ssa.insert_op(IrOpcode::OpCall, vi, None)?;
                let tgt_op = self.lower_operand(tgt)?;
                self.ssa.op_use(res, 0, tgt_op);
                for sarg in sargs {
                    let reg_idx = self.index_of_reg(&sarg.formal)?;
                    let op = self.lower_operand(sarg.actual)?;
                    self.ssa.op_use(res, reg_idx + 1, op);
                }
                (res, opt_addr)
            }
        })
    }

    fn lower_operand(&mut self, sop: sast::Operand) -> Result<SSAValue> {
        match sop {
            sast::Operand::Comment(s) => {
                // TODO: round-trip comment `ValueInfo`
                let vi = ValueInfo::new_unresolved(ir::WidthSpec::Unknown);
                Ok(self.ssa.insert_comment(vi, s)?)
            }
            sast::Operand::ValueRef(r) => {
                if let Some(x) = self.values.get(&r).cloned() {
                    Ok(x)
                } else {
                    Err(LoweringError::InvalidAst(format!(
                        "no value reference: %{}",
                        r.0
                    )))
                }
            }
            sast::Operand::Const(v) => Ok(self.ssa.insert_const(v)?),
        }
    }

    fn block_at(&mut self, at: ir::MAddress) -> Result<SSABlock> {
        use std::collections::hash_map::Entry;
        // can't use `or_insert_with` because `ssa.insert_block` may fail
        Ok(*match self.blocks.entry(at) {
            Entry::Occupied(o) => o.into_mut(),
            Entry::Vacant(v) => v.insert(self.ssa.insert_block(at)?),
        })
    }

    fn index_of_reg(&self, sreg: &sast::PhysReg) -> Result<u8> {
        if sreg.0 == "mem" {
            // we already checked that `regnames.len() < u8::max_value()`
            Ok(self.regnames.len() as u8)
        } else {
            // TODO: more efficient as a HashMap<Reg, u8>?
            if let Some(x) = self.regnames.iter().position(|r| r == sreg) {
                // we already checked that `regnames.len() < u8::max_value()`
                Ok(x as u8)
            } else {
                Err(LoweringError::InvalidAst(format!(
                    "no physical register: {}",
                    sreg.0
                )))
            }
        }
    }
}

fn lower_infix_op(siop: sast::InfixOp) -> IrOpcode {
    match siop {
        sast::InfixOp::Add => IrOpcode::OpAdd,
        sast::InfixOp::Sub => IrOpcode::OpSub,
        sast::InfixOp::Mul => IrOpcode::OpMul,
        sast::InfixOp::Div => IrOpcode::OpDiv,
        sast::InfixOp::Mod => IrOpcode::OpMod,
        sast::InfixOp::And => IrOpcode::OpAnd,
        sast::InfixOp::Or => IrOpcode::OpOr,
        sast::InfixOp::Xor => IrOpcode::OpXor,
        sast::InfixOp::Eq => IrOpcode::OpEq,
        sast::InfixOp::Gt => IrOpcode::OpGt,
        sast::InfixOp::Lt => IrOpcode::OpLt,
        sast::InfixOp::Lsl => IrOpcode::OpLsl,
        sast::InfixOp::Lsr => IrOpcode::OpLsr,
    }
}

fn lower_prefix_op(spop: sast::PrefixOp) -> IrOpcode {
    match spop {
        sast::PrefixOp::Not => IrOpcode::OpNot,
    }
}

fn lower_resize_op(srst: sast::ResizeType, sws: sast::WidthSpec) -> IrOpcode {
    match srst {
        sast::ResizeType::Narrow => IrOpcode::OpNarrow(sws.0),
        sast::ResizeType::SignExt => IrOpcode::OpSignExt(sws.0),
        sast::ResizeType::ZeroExt => IrOpcode::OpZeroExt(sws.0),
    }
}

fn lower_valueinfo(sty: sast::Type) -> ValueInfo {
    let ws = ir::WidthSpec::Known((sty.0).0);
    match sty.1 {
        sast::RefSpec::Scalar => ValueInfo::new_scalar(ws),
        sast::RefSpec::Reference => ValueInfo::new_reference(ws),
        sast::RefSpec::Unknown => ValueInfo::new_unresolved(ws),
    }
}

/// [`SSAStorage`][SSAStorage] methods return `Option`,
/// so we convert `None`s into [`SsaError`][LoweringError::SsaError]
impl From<::std::option::NoneError> for LoweringError {
    fn from(_: ::std::option::NoneError) -> Self {
        LoweringError::SsaError
    }
}

impl error::Error for LoweringError {
    fn description(&self) -> &str {
        match *self {
            LoweringError::SsaError => "could not perform an `SSAStorage` operation",
            LoweringError::InvalidAst(_) => "invalid ast",
        }
    }
}

impl fmt::Display for LoweringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            LoweringError::SsaError => write!(f, "could not perform an `SSAStorage` operation"),
            LoweringError::InvalidAst(ref s) => write!(f, "invalid ast: {}", s),
        }
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::path::Path;
use std::fmt::{self, Display, Formatter};

#[derive(Debug)]
pub struct ParsedFile<'a> {
	pub path: &'a Path,
	pub file: File,
	pub method: IncludeMethod,
	pub included_files: Vec<ParsedFile<'a>>,
}

#[derive(Debug)]
pub enum IncludeMethod {
	DTS,
	CPP(Vec<FileMapping>),
}

#[derive(Debug, Clone, Copy)]
pub struct FileMapping {
	pub parent_start: usize,
	pub child_start: usize,
	pub len: usize,
}

impl<'a> ParsedFile<'a> {
	pub fn new(path: &'a Path, method: IncludeMethod) -> ParsedFile<'a> {
		ParsedFile {
			path: path,
			file: File::open(path).unwrap(),
			method: method,
			included_files: vec![],
		}
	}

	pub fn assign_mapping(&mut self, path: &Path, mapping: FileMapping) -> Result<(), String> { //TODO: error propogation
		if self.path == path {
			match self.method {
				IncludeMethod::CPP(ref mut mappings) => mappings.push(mapping),
				IncludeMethod::DTS => unreachable!(),
			};
			Ok(())
		} else {
			for file in self.included_files.iter_mut() {
				if file.assign_mapping(path, mapping).is_ok() {
					return Ok(());
				}
			}
			Err(format!("Did not find file: {:?}", path))
		}
	}

	fn write(&self, f: &mut Formatter, prefix: &str) -> fmt::Result {
		let mut next_prefix = prefix.to_string();
		next_prefix.push_str(" |-");
		writeln!(f, "{} {:?}: {}", prefix, self.path, self.method)
			.and(self.included_files.iter().fold(Ok(()), |res, x| res.and(x.write(f, &next_prefix))))
	}
}

impl<'a> Display for ParsedFile<'a> {
	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
		self.write(f, "")
	}
}

impl Display for IncludeMethod {
	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
		match *self {
			IncludeMethod::DTS => write!(f, "DTS"),
			IncludeMethod::CPP(_) => write!(f, "CPP"),
		}
	}
}
<commit_msg>Self is a thing<commit_after>use std::fs::File;
use std::path::Path;
use std::fmt::{self, Display, Formatter};

#[derive(Debug)]
pub struct ParsedFile<'a> {
	pub path: &'a Path,
	pub file: File,
	pub method: IncludeMethod,
	pub included_files: Vec<ParsedFile<'a>>,
}

#[derive(Debug)]
pub enum IncludeMethod {
	DTS,
	CPP(Vec<FileMapping>),
}

#[derive(Debug, Clone, Copy)]
pub struct FileMapping {
	pub parent_start: usize,
	pub child_start: usize,
	pub len: usize,
}

impl<'a> ParsedFile<'a> {
	pub fn new(path: &'a Path, method: IncludeMethod) -> Self {
		ParsedFile {
			path: path,
			file: File::open(path).unwrap(),
			method: method,
			included_files: vec![],
		}
	}

	pub fn assign_mapping(&mut self, path: &Path, mapping: FileMapping) -> Result<(), String> { //TODO: error propogation
		if self.path == path {
			match self.method {
				IncludeMethod::CPP(ref mut mappings) => mappings.push(mapping),
				IncludeMethod::DTS => unreachable!(),
			};
			Ok(())
		} else {
			for file in self.included_files.iter_mut() {
				if file.assign_mapping(path, mapping).is_ok() {
					return Ok(());
				}
			}
			Err(format!("Did not find file: {:?}", path))
		}
	}

	fn write(&self, f: &mut Formatter, prefix: &str) -> fmt::Result {
		let mut next_prefix = prefix.to_string();
		next_prefix.push_str(" |-");
		writeln!(f, "{} {:?}: {}", prefix, self.path, self.method)
			.and(self.included_files.iter().fold(Ok(()), |res, x| res.and(x.write(f, &next_prefix))))
	}
}

impl<'a> Display for ParsedFile<'a> {
	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
		self.write(f, "")
	}
}

impl Display for IncludeMethod {
	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
		match *self {
			IncludeMethod::DTS => write!(f, "DTS"),
			IncludeMethod::CPP(_) => write!(f, "CPP"),
		}
	}
}
<|endoftext|>


<commit_before>use std::fs;
use std::fs::File;
use std::io;
use std::path::{Path, PathBuf};
use std::path::MAIN_SEPARATOR;

use directories::BaseDirs;
use flate2::read::GzDecoder;
use regex::Regex;
use tar::Archive;
use zip::ZipArchive;

use crate::manager::OS::WINDOWS;

const CACHE_FOLDER: &str = ".cache/selenium";
const ZIP: &str = "zip";
const GZ: &str = "gz";

pub fn clear_cache() {
    let cache_path = compose_cache_folder();
    if cache_path.exists() {
        log::debug!("Clearing cache at: {}", cache_path.display());
        fs::remove_dir_all(&cache_path).unwrap();
    }
}

pub fn create_path_if_not_exists(path: &Path) {
    if !path.exists() {
        fs::create_dir_all(&path).unwrap();
    }
}

pub fn uncompress(compressed_file: &String, target: PathBuf) {
    let file = File::open(compressed_file).unwrap();
    let kind = infer::get_from_path(compressed_file).unwrap().unwrap();
    let extension = kind.extension();
    log::trace!("The detected extension of the compressed file is {}", extension);

    if extension.eq_ignore_ascii_case(ZIP) {
        unzip(file, target);
    } else if extension.eq_ignore_ascii_case(GZ) {
        untargz(file, target);
    } else {
        let error_msg = format!("Downloaded file cannot be uncompressed ({} extension)", extension);
        log::error!("{}", error_msg);
        panic!("{}", error_msg);
    }
}

pub fn untargz(file: File, target: PathBuf) {
    log::trace!("Untargz file to {}", target.display());
    let tar = GzDecoder::new(file);
    let mut archive = Archive::new(tar);
    archive.unpack(target.parent().unwrap()).unwrap();
}

pub fn unzip(file: File, target: PathBuf) {
    log::trace!("Unzipping file to {}", target.display());
    let mut archive = ZipArchive::new(file).unwrap();

    for i in 0..archive.len() {
        let mut file = archive.by_index(i).unwrap();
        if (file.name()).ends_with('/') {
            continue;
        } else {
            log::debug!("File extracted to {} ({} bytes)", target.display(), file.size());
            if let Some(p) = target.parent() {
                create_path_if_not_exists(p);
            }
            let mut outfile = File::create(&target).unwrap();

            // Set permissions in Unix-like systems
            #[cfg(unix)]
            {
                use std::os::unix::fs::PermissionsExt;

                fs::set_permissions(&target, fs::Permissions::from_mode(0o755)).unwrap();
            }

            io::copy(&mut file, &mut outfile).unwrap();
            break;
        }
    }
}

pub fn compose_cache_folder() -> PathBuf {
    Path::new(BaseDirs::new().unwrap().home_dir())
        .join(String::from(CACHE_FOLDER).replace('/', &MAIN_SEPARATOR.to_string()))
}

pub fn get_cache_folder() -> PathBuf {
    let cache_path = compose_cache_folder();
    create_path_if_not_exists(&cache_path);
    cache_path
}

pub fn compose_driver_path_in_cache(driver_name: &str, os: &str, arch_folder: &str, driver_version: &str) -> PathBuf {
    get_cache_folder()
        .join(driver_name)
        .join(arch_folder)
        .join(driver_version)
        .join(get_driver_filename(driver_name, os))
}

pub fn get_driver_filename(driver_name: &str, os: &str) -> String {
    format!("{}{}", driver_name, get_binary_extension(os))
}

pub fn get_binary_extension(os: &str) -> &str {
    if WINDOWS.is(os) {
        ".exe"
    } else {
        ""
    }
}

pub fn parse_version(version_text: String) -> String {
    let re = Regex::new(r"[^\d^.]").unwrap();
    re.replace_all(&*version_text, "").to_string()
}<commit_msg>[rust] Fix msedgedriver uncompression in Selenium Manager (#11180)<commit_after>use std::fs;
use std::fs::File;
use std::io;
use std::path::{Path, PathBuf};
use std::path::MAIN_SEPARATOR;

use directories::BaseDirs;
use flate2::read::GzDecoder;
use regex::Regex;
use tar::Archive;
use zip::ZipArchive;

use crate::manager::OS::WINDOWS;

const CACHE_FOLDER: &str = ".cache/selenium";
const ZIP: &str = "zip";
const GZ: &str = "gz";

pub fn clear_cache() {
    let cache_path = compose_cache_folder();
    if cache_path.exists() {
        log::debug!("Clearing cache at: {}", cache_path.display());
        fs::remove_dir_all(&cache_path).unwrap();
    }
}

pub fn create_path_if_not_exists(path: &Path) {
    if !path.exists() {
        fs::create_dir_all(&path).unwrap();
    }
}

pub fn uncompress(compressed_file: &String, target: PathBuf) {
    let file = File::open(compressed_file).unwrap();
    let kind = infer::get_from_path(compressed_file).unwrap().unwrap();
    let extension = kind.extension();
    log::trace!("The detected extension of the compressed file is {}", extension);

    if extension.eq_ignore_ascii_case(ZIP) {
        unzip(file, target);
    } else if extension.eq_ignore_ascii_case(GZ) {
        untargz(file, target);
    } else {
        let error_msg = format!("Downloaded file cannot be uncompressed ({} extension)", extension);
        log::error!("{}", error_msg);
        panic!("{}", error_msg);
    }
}

pub fn untargz(file: File, target: PathBuf) {
    log::trace!("Untargz file to {}", target.display());
    let tar = GzDecoder::new(file);
    let mut archive = Archive::new(tar);
    archive.unpack(target.parent().unwrap()).unwrap();
}

pub fn unzip(file: File, target: PathBuf) {
    log::trace!("Unzipping file to {}", target.display());
    let mut archive = ZipArchive::new(file).unwrap();

    for i in 0..archive.len() {
        let mut file = archive.by_index(i).unwrap();
        if (file.name()).ends_with('/') || target.file_name().unwrap().to_str().unwrap() != file.name() {
            continue;
        } else {
            log::debug!("File extracted to {} ({} bytes)", target.display(), file.size());
            if let Some(p) = target.parent() {
                create_path_if_not_exists(p);
            }
            let mut outfile = File::create(&target).unwrap();

            // Set permissions in Unix-like systems
            #[cfg(unix)]
            {
                use std::os::unix::fs::PermissionsExt;

                fs::set_permissions(&target, fs::Permissions::from_mode(0o755)).unwrap();
            }

            io::copy(&mut file, &mut outfile).unwrap();
            break;
        }
    }
}

pub fn compose_cache_folder() -> PathBuf {
    Path::new(BaseDirs::new().unwrap().home_dir())
        .join(String::from(CACHE_FOLDER).replace('/', &MAIN_SEPARATOR.to_string()))
}

pub fn get_cache_folder() -> PathBuf {
    let cache_path = compose_cache_folder();
    create_path_if_not_exists(&cache_path);
    cache_path
}

pub fn compose_driver_path_in_cache(driver_name: &str, os: &str, arch_folder: &str, driver_version: &str) -> PathBuf {
    get_cache_folder()
        .join(driver_name)
        .join(arch_folder)
        .join(driver_version)
        .join(get_driver_filename(driver_name, os))
}

pub fn get_driver_filename(driver_name: &str, os: &str) -> String {
    format!("{}{}", driver_name, get_binary_extension(os))
}

pub fn get_binary_extension(os: &str) -> &str {
    if WINDOWS.is(os) {
        ".exe"
    } else {
        ""
    }
}

pub fn parse_version(version_text: String) -> String {
    let re = Regex::new(r"[^\d^.]").unwrap();
    re.replace_all(&*version_text, "").to_string()
}<|endoftext|>


<commit_before>#![feature(test)]

extern crate beagle;
extern crate test;

use self::test::Bencher;

use beagle::vec::Vec3;
use beagle::mat::Mat3x3;

#[bench]
fn bench_add_mat3s(b: &mut Bencher) {
    b.iter(|| {
        let mut a: Mat3x3<f64> = Mat3x3::from([
            [1.0, 2.0, 3.0],
            [4.0, 5.0, 6.0],
            [7.0, 8.0, 9.0],
        ]);

        let n = test::black_box(1_000_000);
        for _ in 0..n {
            a = a+a;
        }
        a
    });
}

#[bench]
fn bench_mul_mat3s(b: &mut Bencher) {
    b.iter(|| {
        let mut a: Mat3x3<f64> = Mat3x3::from([
            [1.0, 2.0, 3.0],
            [4.0, 5.0, 6.0],
            [7.0, 8.0, 9.0],
        ]);

        let n = test::black_box(1_000_000);
        for _ in 0..n {
            a = a*a;
        }
        a
    });
}

#[bench]
fn bench_mul_vec_mat3s(b: &mut Bencher) {
    b.iter(|| {
        let a: Mat3x3<f64> = Mat3x3::from([
            [1.0, 2.0, 3.0],
            [4.0, 5.0, 6.0],
            [7.0, 8.0, 9.0],
        ]);
        let mut b: Vec3<f64> = Vec3::from([1.0, 2.0, 3.0]);

        let n = test::black_box(1_000_000);
        for _ in 0..n {
            b = a*b;
        }
        b
    });
}

#[bench]
fn bench_add_f64(b: &mut Bencher) {
    b.iter(|| {
        let mut a: f64 = 1.0;

        let n = test::black_box(1_000_000);
        for _ in 0..n {
            a = a+a;
        }
        a
    });
}
<commit_msg>Reduced benchmarks scale.<commit_after>#![feature(test)]

extern crate beagle;
extern crate test;

use self::test::Bencher;

use beagle::vec::Vec3;
use beagle::mat::Mat3x3;

#[bench]
fn bench_add_mat3s(b: &mut Bencher) {
    b.iter(|| {
        let mut a: Mat3x3<f64> = Mat3x3::from([
            [1.0, 2.0, 3.0],
            [4.0, 5.0, 6.0],
            [7.0, 8.0, 9.0],
        ]);

        let n = test::black_box(10_000);
        for _ in 0..n {
            a = a+a;
        }
        a
    });
}

#[bench]
fn bench_mul_mat3s(b: &mut Bencher) {
    b.iter(|| {
        let mut a: Mat3x3<f64> = Mat3x3::from([
            [1.0, 2.0, 3.0],
            [4.0, 5.0, 6.0],
            [7.0, 8.0, 9.0],
        ]);

        let n = test::black_box(10_000);
        for _ in 0..n {
            a = a*a;
        }
        a
    });
}

#[bench]
fn bench_mul_vec_mat3s(b: &mut Bencher) {
    b.iter(|| {
        let a: Mat3x3<f64> = Mat3x3::from([
            [1.0, 2.0, 3.0],
            [4.0, 5.0, 6.0],
            [7.0, 8.0, 9.0],
        ]);
        let mut b: Vec3<f64> = Vec3::from([1.0, 2.0, 3.0]);

        let n = test::black_box(10_000);
        for _ in 0..n {
            b = a*b;
        }
        b
    });
}

#[bench]
fn bench_add_f64(b: &mut Bencher) {
    b.iter(|| {
        let mut a: f64 = 1.0;

        let n = test::black_box(10_000);
        for _ in 0..n {
            a = a+a;
        }
        a
    });
}
<|endoftext|>


<commit_before>use js::function::{NativeFunction, NativeFunc};
use js::value::{Value, ResultValue, VFunction, VUndefined, VObject, to_value};
use collections::treemap::TreeMap;
use std::gc::Gc;
use std::cell::RefCell;
use time::{now, strftime};
/// Print a javascript value to stdout
pub fn log(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	println!("{}: {}", strftime("%X", &now()), args.get(0).borrow());
	return Ok(Gc::new(VUndefined));
}
/// Create a new 'console' object
pub fn _create() -> Value {
	let mut console = TreeMap::new();
	console.insert(~"log", to_value(log));
	to_value(console)
}<commit_msg>Console.log accepts multiple arguments<commit_after>use js::function::{NativeFunction, NativeFunc};
use js::value::{Value, ResultValue, VFunction, VUndefined, VObject, to_value, from_value};
use collections::treemap::TreeMap;
use std::gc::Gc;
use std::cell::RefCell;
use std::iter::FromIterator;
use time::{now, strftime};
/// Print a javascript value to stdout
pub fn log(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	let args : Vec<~str> = FromIterator::from_iter(args.iter().map(|x|from_value::<~str>(*x).unwrap()));
	println!("{}: {}", strftime("%X", &now()), args.connect(" "));
	return Ok(Gc::new(VUndefined));
}
/// Create a new 'console' object
pub fn _create() -> Value {
	let mut console = TreeMap::new();
	console.insert(~"log", to_value(log));
	to_value(console)
}<|endoftext|>


<commit_before>/// Type size assertion. The first argument is a type and the second argument is its expected size.
#[macro_export]
macro_rules! static_assert_size {
    ($ty:ty, $size:expr) => {
        const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
    };
}

#[macro_export]
macro_rules! enum_from_u32 {
    ($(#[$attr:meta])* pub enum $name:ident {
        $($variant:ident = $e:expr,)*
    }) => {
        $(#[$attr])*
        pub enum $name {
            $($variant = $e),*
        }

        impl $name {
            pub fn from_u32(u: u32) -> Option<$name> {
                $(if u == $name::$variant as u32 {
                    return Some($name::$variant)
                })*
                None
            }
        }
    };
    ($(#[$attr:meta])* pub enum $name:ident {
        $($variant:ident,)*
    }) => {
        $(#[$attr])*
        pub enum $name {
            $($variant,)*
        }

        impl $name {
            pub fn from_u32(u: u32) -> Option<$name> {
                $(if u == $name::$variant as u32 {
                    return Some($name::$variant)
                })*
                None
            }
        }
    }
}
<commit_msg>Allow variant attributes in `enum_from_u32!`<commit_after>/// Type size assertion. The first argument is a type and the second argument is its expected size.
#[macro_export]
macro_rules! static_assert_size {
    ($ty:ty, $size:expr) => {
        const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
    };
}

#[macro_export]
macro_rules! enum_from_u32 {
    ($(#[$attr:meta])* pub enum $name:ident {
        $($(#[$var_attr:meta])* $variant:ident = $e:expr,)*
    }) => {
        $(#[$attr])*
        pub enum $name {
            $($(#[$var_attr])* $variant = $e),*
        }

        impl $name {
            pub fn from_u32(u: u32) -> Option<$name> {
                $(if u == $name::$variant as u32 {
                    return Some($name::$variant)
                })*
                None
            }
        }
    };
    ($(#[$attr:meta])* pub enum $name:ident {
        $($(#[$var_attr:meta])* $variant:ident,)*
    }) => {
        $(#[$attr])*
        pub enum $name {
            $($(#[$var_attr])* $variant,)*
        }

        impl $name {
            pub fn from_u32(u: u32) -> Option<$name> {
                $(if u == $name::$variant as u32 {
                    return Some($name::$variant)
                })*
                None
            }
        }
    }
}
<|endoftext|>


<commit_before>use gfx;
use glutin;
use nalgebra::{Isometry3, PerspectiveMatrix3, ToHomogeneous};
use rand;
use std::convert::AsRef;

use cube::{CubeRef, Spatial};
use math::{IntoSpace, FMatrix4, FPoint3, FScalar, FVector3, FVector4};
use mesh::{Conjoint, DecomposePolygon, DecomposePrimitive, Indexed, UCube};
use super::OptionExt;

pub type Index = u32;

gfx_pipeline!{
    pipeline {
        vertex_buffer: gfx::VertexBuffer<RawVertex> = (),
        transform: gfx::Global<[[f32; 4]; 4]> = "u_transform",
        output: gfx::RenderTarget<gfx::format::Rgba8> = "f_target0",
    }
}

gfx_vertex_struct!{
    RawVertex {
        position: [f32; 3] = "a_position",
        color: [f32; 4] = "a_color",
    }
}

impl From<Vertex> for RawVertex {
    fn from(vertex: Vertex) -> Self {
        RawVertex {
            position: *vertex.position.as_ref(),
            color: *vertex.color.as_ref(),
        }
    }
}

pub struct Vertex {
    pub position: FPoint3,
    pub color: FVector4,
}

impl Vertex {
    pub fn new(position: FPoint3, color: FVector4) -> Self {
        Vertex {
            position: position,
            color: color,
        }
    }
}

pub struct MeshBuffer {
    pub vertices: Vec<RawVertex>,
    pub indeces: Vec<Index>,
}

impl MeshBuffer {
    pub fn new() -> Self {
        MeshBuffer {
            vertices: vec![],
            indeces: vec![],
        }
    }

    pub fn extend(&mut self, buffer: &Self) {
        let offset = self.vertices.len();
        self.vertices.extend(buffer.vertices.iter());
        self.indeces.extend(buffer.indeces
            .iter()
            .map(|index| index + offset as Index));
    }
}

pub trait Mesh {
    fn mesh_buffer(&self) -> MeshBuffer;
}

impl<'a> Mesh for CubeRef<'a> {
    fn mesh_buffer(&self) -> MeshBuffer {
        let mut buffer = MeshBuffer::new();
        if let Some(leaf) = self.try_as_leaf().and_if(|leaf| !leaf.geometry.is_empty()) {
            let origin: FVector3 = self.partition().origin().to_vector().into_space();
            let width = self.partition().width().exp() as FScalar;
            let color = random_color();

            let cube = UCube::with_unit_width();
            buffer.vertices.extend(cube.conjoint_points()
                .map(|point| leaf.geometry.map_unit_cube_point(&point))
                .map(|point| (point * width) + origin)
                .map(|point| RawVertex::from(Vertex::new(point, color))));
            buffer.indeces.extend(cube.indexed_polygons()
                .triangulate()
                .points()
                .map(|index| index as Index));
        }
        buffer
    }
}

pub fn vertex_buffer_from_cube<R, F>(cube: &CubeRef,
                                     factory: &mut F)
                                     -> (gfx::handle::Buffer<R, RawVertex>, gfx::Slice<R>)
    where R: gfx::Resources,
          F: gfx::traits::FactoryExt<R>
{
    let mut buffer = MeshBuffer::new();
    for cube in cube.iter().filter(|cube| cube.is_leaf()) {
        buffer.extend(&cube.mesh_buffer());
    }
    factory.create_vertex_buffer_with_slice(buffer.vertices.as_slice(), buffer.indeces.as_slice())
}

pub fn projection_from_window(window: &glutin::Window) -> FMatrix4 {
    let aspect = {
        let (width, height) = window.get_inner_size_pixels().unwrap();
        width as f32 / height as f32
    };
    PerspectiveMatrix3::new(aspect, 1.0, -1.0, 1.0).to_matrix()
}

pub fn look_at_cube<C>(cube: &C, from: &FPoint3) -> FMatrix4
    where C: Spatial
{
    Isometry3::look_at_rh(from,
                          &cube.partition().midpoint().into_space(),
                          &FVector3::new(0.0, 0.0, 1.0))
        .to_homogeneous()
}

fn random_color() -> FVector4 {
    FVector4::new(rand::random::<FScalar>(),
                  rand::random::<FScalar>(),
                  rand::random::<FScalar>(),
                  1.0)
}

#[cfg(test)]
mod tests {
    use super::*;
}
<commit_msg>Color cubes per triangle.<commit_after>use gfx;
use glutin;
use nalgebra::{Isometry3, PerspectiveMatrix3, ToHomogeneous};
use rand;
use std::convert::AsRef;

use cube::{CubeRef, Spatial};
use math::{IntoSpace, FMatrix4, FPoint3, FScalar, FVector3, FVector4};
use mesh::{DecomposePolygon, DecomposePrimitive, Triangle, UCube};
use super::OptionExt;

pub type Index = u32;

gfx_pipeline!{
    pipeline {
        vertex_buffer: gfx::VertexBuffer<RawVertex> = (),
        transform: gfx::Global<[[f32; 4]; 4]> = "u_transform",
        output: gfx::RenderTarget<gfx::format::Rgba8> = "f_target0",
    }
}

gfx_vertex_struct!{
    RawVertex {
        position: [f32; 3] = "a_position",
        color: [f32; 4] = "a_color",
    }
}

impl From<Vertex> for RawVertex {
    fn from(vertex: Vertex) -> Self {
        RawVertex {
            position: *vertex.position.as_ref(),
            color: *vertex.color.as_ref(),
        }
    }
}

pub struct Vertex {
    pub position: FPoint3,
    pub color: FVector4,
}

impl Vertex {
    pub fn new(position: FPoint3, color: FVector4) -> Self {
        Vertex {
            position: position,
            color: color,
        }
    }
}

pub struct MeshBuffer {
    pub vertices: Vec<RawVertex>,
    pub indeces: Vec<Index>,
}

impl MeshBuffer {
    pub fn new() -> Self {
        MeshBuffer {
            vertices: vec![],
            indeces: vec![],
        }
    }

    pub fn extend(&mut self, buffer: &Self) {
        let offset = self.vertices.len();
        self.vertices.extend(buffer.vertices.iter());
        self.indeces.extend(buffer.indeces
            .iter()
            .map(|index| index + offset as Index));
    }
}

pub trait Mesh {
    fn mesh_buffer(&self) -> MeshBuffer;
}

impl<'a> Mesh for CubeRef<'a> {
    fn mesh_buffer(&self) -> MeshBuffer {
        let mut buffer = MeshBuffer::new();
        if let Some(leaf) = self.try_as_leaf().and_if(|leaf| !leaf.geometry.is_empty()) {
            let origin: FVector3 = self.partition().origin().to_vector().into_space();
            let width = self.partition().width().exp() as FScalar;

            buffer.vertices.extend(UCube::with_unit_width()
                .triangulate()
                .map(|triangle| {
                    let color = random_color();
                    Triangle::new((triangle.a, color), (triangle.b, color), (triangle.c, color))
                })
                .points()
                .map(|(point, color)| {
                    (leaf.geometry.map_unit_cube_point(&point), color)
                })
                .map(|(point, color)| ((point * width) + origin, color))
                .map(|(point, color)| RawVertex::from(Vertex::new(point, color))));
            buffer.indeces.extend(UCube::with_unit_width()
                .triangulate()
                .points()
                .enumerate()
                .map(|(index, _)| index as Index));
        }
        buffer
    }
}

pub fn vertex_buffer_from_cube<R, F>(cube: &CubeRef,
                                     factory: &mut F)
                                     -> (gfx::handle::Buffer<R, RawVertex>, gfx::Slice<R>)
    where R: gfx::Resources,
          F: gfx::traits::FactoryExt<R>
{
    let mut buffer = MeshBuffer::new();
    for cube in cube.iter().filter(|cube| cube.is_leaf()) {
        buffer.extend(&cube.mesh_buffer());
    }
    factory.create_vertex_buffer_with_slice(buffer.vertices.as_slice(), buffer.indeces.as_slice())
}

pub fn projection_from_window(window: &glutin::Window) -> FMatrix4 {
    let aspect = {
        let (width, height) = window.get_inner_size_pixels().unwrap();
        width as f32 / height as f32
    };
    PerspectiveMatrix3::new(aspect, 1.0, -1.0, 1.0).to_matrix()
}

pub fn look_at_cube<C>(cube: &C, from: &FPoint3) -> FMatrix4
    where C: Spatial
{
    Isometry3::look_at_rh(from,
                          &cube.partition().midpoint().into_space(),
                          &FVector3::new(0.0, 0.0, 1.0))
        .to_homogeneous()
}

fn random_color() -> FVector4 {
    FVector4::new(rand::random::<FScalar>(),
                  rand::random::<FScalar>(),
                  rand::random::<FScalar>(),
                  1.0)
}

#[cfg(test)]
mod tests {
    use super::*;
}
<|endoftext|>