<commit_before>use std::fs::File;
use std::path::Path;
use std::io::Read;
// use std::rand;
use std::env;

use display::Display;
use keypad::Keypad;

pub struct Cpu {
    opcode: u16,
    memory: [u8; 4096],
    v: [u8; 16],
    i: usize,
    pc: usize,
    stack: [u16; 16],
    sp: usize,
    delay_timer: u8,
    sound_timer: u8,
    pub keypad: Keypad,
    pub display: Display
}

impl Cpu {
    pub fn new() -> Cpu {
        let mut cpu = Cpu {
            opcode: 0,
            memory: [0; 4096],
            v: [0; 16],
            i: 0x200,
            pc: 0x200,
            stack: [0; 16],
            sp: 0,
            delay_timer: 0,
            sound_timer: 0,
            keypad: Keypad::new(),
            display: Display::new()
        };

        for i in 0..80 {
            cpu.memory[i] = fontset[i];
        }
        cpu
    }

    pub fn emulate_cycle(&mut self) {
        self.fetch_opcode();
        self.opcode_execute();

        if self.delay_timer > 0 {
            self.delay_timer -= 1;
        }

        if self.sound_timer > 0 {
            if self.sound_timer == 1 {
                println!("BEEP!\n");
            }
            self.sound_timer -= 1;
        }

        for _ in 0..10000 {
        }
    }

    pub fn load_game(&mut self, program: String) {
        let mut path = env::current_dir().unwrap();
        path.push(program.trim());
        let mut reader = File::open(&path).unwrap();
        self.load_to_memory(&mut reader);
    }

    fn load_to_memory(&mut self, reader: &mut File) {
        match reader.bytes().next() {
            Ok(value) => {
                self.memory[self.pc] = value;
                self.pc += 1;
                self.load_to_memory(reader)
            },
            Err(_) => self.pc = 0x200,
        }
    }

    fn fetch_opcode(&mut self) {
        self.opcode = (self.memory[self.pc] as u16) << 8 | (self.memory[self.pc + 1] as u16);
    }

    fn opcode_execute(&mut self) {
        match (self.opcode & 0xf000) {
            // 0x0000 => self.op_0xxx(),
            // 0x1000 => self.op_1xxx(),
            // 0x2000 => self.op_2xxx(),
            // 0x3000 => self.op_3xxx(),
            // 0x4000 => self.op_4xxx(),
            // 0x5000 => self.op_5xxx(),
            // 0x6000 => self.op_6xxx(),
            // 0x7000 => self.op_7xxx(),
            // 0x8000 => self.op_8xxx(),
            // 0x9000 => self.op_9xxx(),
            // 0xA000 => self.op_Axxx(),
            // 0xB000 => self.op_Bxxx(),
            // 0xC000 => self.op_Cxxx(),
            // 0xD000 => self.op_Dxxx(),
            // 0xE000 => self.op_Exxx(),
            // 0xF000 => self.op_Fxxx(),
            _ => not_implemented(self.opcode as usize, self.pc),
        }
    }
}

fn not_implemented(op: usize, pc: usize) {
    println!("Not implemented:: op: {:x}, pc: {:x}", op, pc)
}

static fontset: [u8; 80] =
    [0xF0, 0x90, 0x90, 0x90, 0xF0, 0x20, 0x60, 0x20, 0x20, 0x70, 0xF0, 0x10, 0xF0, 0x80, 0xF0,
     0xF0, 0x10, 0xF0, 0x10, 0xF0, 0x90, 0x90, 0xF0, 0x10, 0x10, 0xF0, 0x80, 0xF0, 0x10, 0xF0,
     0xF0, 0x80, 0xF0, 0x90, 0xF0, 0xF0, 0x10, 0x20, 0x40, 0x40, 0xF0, 0x90, 0xF0, 0x90, 0xF0,
     0xF0, 0x90, 0xF0, 0x10, 0xF0, 0xF0, 0x90, 0xF0, 0x90, 0x90, 0xE0, 0x90, 0xE0, 0x90, 0xE0,
     0xF0, 0x80, 0x80, 0x80, 0xF0, 0xE0, 0x90, 0x90, 0x90, 0xE0, 0xF0, 0x80, 0xF0, 0x80, 0xF0,
     0xF0, 0x80, 0xF0, 0x80, 0x80];
<commit_msg>Found the error.<commit_after>use std::fs::File;
use std::path::Path;
use std::io::Read;
// use std::rand;
use std::env;

use display::Display;
use keypad::Keypad;

pub struct Cpu {
    opcode: u16,
    memory: [u8; 4096],
    v: [u8; 16],
    i: usize,
    pc: usize,
    stack: [u16; 16],
    sp: usize,
    delay_timer: u8,
    sound_timer: u8,
    pub keypad: Keypad,
    pub display: Display
}

impl Cpu {
    pub fn new() -> Cpu {
        let mut cpu = Cpu {
            opcode: 0,
            memory: [0; 4096],
            v: [0; 16],
            i: 0x200,
            pc: 0x200,
            stack: [0; 16],
            sp: 0,
            delay_timer: 0,
            sound_timer: 0,
            keypad: Keypad::new(),
            display: Display::new()
        };

        for i in 0..80 {
            cpu.memory[i] = fontset[i];
        }
        cpu
    }

    pub fn emulate_cycle(&mut self) {
        self.fetch_opcode();
        self.opcode_execute();

        if self.delay_timer > 0 {
            self.delay_timer -= 1;
        }

        if self.sound_timer > 0 {
            if self.sound_timer == 1 {
                println!("BEEP!\n");
            }
            self.sound_timer -= 1;
        }

        for _ in 0..10000 {
        }
    }

    pub fn load_game(&mut self, program: String) {
        let mut path = env::current_dir().unwrap();
        path.push(program.trim());
        let mut reader = File::open(&path).unwrap();
        // KG fixme: problem is here.
        self.load_to_memory(&mut reader);
    }

    fn load_to_memory(&mut self, reader: &mut File) {
        match reader.bytes().next() {
            Some(value) => {
                match value {
                    Ok(value) => {
                        self.memory[self.pc] = value;
                        self.pc += 1;
                        self.load_to_memory(reader)
                    },
                    Err(e) => {panic!("{:?}", e)}
                }
            },
            None => self.pc = 0x200,
        };
    }

    fn fetch_opcode(&mut self) {
        self.opcode = (self.memory[self.pc] as u16) << 8 | (self.memory[self.pc + 1] as u16);
    }

    fn opcode_execute(&mut self) {
        match (self.opcode & 0xf000) {
            // 0x0000 => self.op_0xxx(),
            // 0x1000 => self.op_1xxx(),
            // 0x2000 => self.op_2xxx(),
            // 0x3000 => self.op_3xxx(),
            // 0x4000 => self.op_4xxx(),
            // 0x5000 => self.op_5xxx(),
            // 0x6000 => self.op_6xxx(),
            // 0x7000 => self.op_7xxx(),
            // 0x8000 => self.op_8xxx(),
            // 0x9000 => self.op_9xxx(),
            // 0xA000 => self.op_Axxx(),
            // 0xB000 => self.op_Bxxx(),
            // 0xC000 => self.op_Cxxx(),
            // 0xD000 => self.op_Dxxx(),
            // 0xE000 => self.op_Exxx(),
            // 0xF000 => self.op_Fxxx(),
            _ => not_implemented(self.opcode as usize, self.pc),
        }
    }
}

fn not_implemented(op: usize, pc: usize) {
    println!("Not implemented:: op: {:x}, pc: {:x}", op, pc)
}

static fontset: [u8; 80] =
    [0xF0, 0x90, 0x90, 0x90, 0xF0, 0x20, 0x60, 0x20, 0x20, 0x70, 0xF0, 0x10, 0xF0, 0x80, 0xF0,
     0xF0, 0x10, 0xF0, 0x10, 0xF0, 0x90, 0x90, 0xF0, 0x10, 0x10, 0xF0, 0x80, 0xF0, 0x10, 0xF0,
     0xF0, 0x80, 0xF0, 0x90, 0xF0, 0xF0, 0x10, 0x20, 0x40, 0x40, 0xF0, 0x90, 0xF0, 0x90, 0xF0,
     0xF0, 0x90, 0xF0, 0x10, 0xF0, 0xF0, 0x90, 0xF0, 0x90, 0x90, 0xE0, 0x90, 0xE0, 0x90, 0xE0,
     0xF0, 0x80, 0x80, 0x80, 0xF0, 0xE0, 0x90, 0x90, 0x90, 0xE0, 0xF0, 0x80, 0xF0, 0x80, 0xF0,
     0xF0, 0x80, 0xF0, 0x80, 0x80];
<|endoftext|>


<commit_before>//! A simple parser for a tiny subset of CSS.
//!
//! To support more CSS syntax, it would probably be easiest to replace this
//! hand-rolled parser with one based on a library or parser generator.

use std::from_str::FromStr;
use std::ascii::OwnedStrAsciiExt;

// Data structures:

#[deriving(Show)]
pub struct Stylesheet {
    pub rules: Vec<Rule>,
}

#[deriving(Show)]
pub struct Rule {
    pub selectors: Vec<Selector>,
    pub declarations: Vec<Declaration>,
}

#[deriving(Show)]
pub enum Selector {
    Simple(SimpleSelector),
}

#[deriving(Show)]
pub struct SimpleSelector {
    pub tag_name: Option<String>,
    pub id: Option<String>,
    pub class: Vec<String>,
}

#[deriving(Show)]
pub struct Declaration {
    pub name: String,
    pub value: Value,
}

#[deriving(Show, Clone, PartialEq)]
pub enum Value {
    Keyword(String),
    Length(f32, Unit),
}

#[deriving(Show, Clone, PartialEq)]
pub enum Unit {
    Px,
}

pub type Specificity = (uint, uint, uint);

impl Selector {
    pub fn specificity(&self) -> Specificity {
        // http://www.w3.org/TR/selectors/#specificity
        let Simple(ref simple) = *self;
        let a = simple.id.iter().len();
        let b = simple.class.len();
        let c = simple.tag_name.iter().len();
        (a, b, c)
    }
}

// Parsing:

pub fn parse(source: String) -> Stylesheet {
    let mut parser = Parser {
        pos: 0u,
        input: source,
    };
    parser.parse_stylesheet()
}

struct Parser {
    pos: uint,
    input: String,
}

impl Parser {
    fn parse_stylesheet(&mut self) -> Stylesheet {
        let mut rules = Vec::new();
        loop {
            self.consume_whitespace();
            if self.eof() {
                break;
            }
            rules.push(self.parse_rule());
        }
        Stylesheet { rules: rules }
    }

    fn parse_rule(&mut self) -> Rule {
        Rule {
            selectors: self.parse_selectors(),
            declarations: self.parse_declarations(),
        }
    }

    fn parse_selectors(&mut self) -> Vec<Selector> {
        let mut selectors = Vec::new();
        loop {
            selectors.push(Simple(self.parse_simple_selector()));
            self.consume_whitespace();
            match self.next_char() {
                ',' => { self.consume_char(); }
                '{' => { break; }
                c   => { fail!("Unexpected character {} in selector list", c); }
            }
        }
        // Return selectors with highest specificity first, for use in matching.
        selectors.sort_by(|a,b| b.specificity().cmp(&a.specificity()));
        selectors
    }

    fn parse_simple_selector(&mut self) -> SimpleSelector {
        let mut result = SimpleSelector { tag_name: None, id: None, class: Vec::new() };
        while !self.eof() {
            match self.next_char() {
                '#' => {
                    self.consume_char();
                    result.id = Some(self.parse_identifier());
                }
                '.' => {
                    self.consume_char();
                    result.class.push(self.parse_identifier());
                }
                '*' => {
                    // universal selector
                    self.consume_char();
                }
                c if valid_identifier_char(c) => {
                    result.tag_name = Some(self.parse_identifier());
                }
                _ => break
            }
        }
        result
    }

    fn parse_declarations(&mut self) -> Vec<Declaration> {
        assert!(self.consume_char() == '{');
        let mut declarations = Vec::new();
        loop {
            self.consume_whitespace();
            if self.next_char() == '}' {
                self.consume_char();
                break;
            }
            declarations.push(self.parse_declaration());
        }
        declarations
    }

    fn parse_declaration(&mut self) -> Declaration {
        let property_name = self.parse_identifier();
        self.consume_whitespace();
        assert!(self.consume_char() == ':')
        self.consume_whitespace();
        let value = self.parse_value();
        self.consume_whitespace();
        assert!(self.consume_char() == ';')

        Declaration {
            name: property_name,
            value: value,
        }
    }

    fn parse_value(&mut self) -> Value {
        match self.next_char() {
            '0'..'9' => self.parse_length(),
            _ => Keyword(self.parse_identifier())
        }
    }

    fn parse_length(&mut self) -> Value {
        Length(self.parse_float(), self.parse_unit())
    }

    fn parse_identifier(&mut self) -> String {
        self.consume_while(valid_identifier_char)
    }

    fn parse_float(&mut self) -> f32 {
        let s = self.consume_while(|c| match c {
            '0'..'9' | '.' => true,
            _ => false
        });
        let f: Option<f32> = FromStr::from_str(s.as_slice());
        f.unwrap()
    }

    fn parse_unit(&mut self) -> Unit {
        match self.parse_identifier().into_ascii_lower().as_slice() {
            "px" => Px,
            _ => fail!("unrecognized unit")
        }
    }

    /// Consume and discard zero or more whitespace characters.
    fn consume_whitespace(&mut self) {
        self.consume_while(|c| c.is_whitespace());
    }

    /// Consume characters until `test` returns false.
    fn consume_while(&mut self, test: |char| -> bool) -> String {
        let mut result = String::new();
        while !self.eof() && test(self.next_char()) {
            result.push_char(self.consume_char());
        }
        result
    }

    /// Return the current character, and advance self.pos to the next character.
    fn consume_char(&mut self) -> char {
        let range = self.input.as_slice().char_range_at(self.pos);
        self.pos = range.next;
        range.ch
    }

    /// Read the current character without consuming it.
    fn next_char(&self) -> char {
        self.input.as_slice().char_at(self.pos)
    }

    /// Return true if all input is consumed.
    fn eof(&self) -> bool {
        self.pos >= self.input.len()
    }
}

fn valid_identifier_char(c: char) -> bool {
    match c {
        'a'..'z' | 'A'..'Z' | '0'..'9' | '-' | '_' => true, // TODO: Include U+00A0 and higher.
        _ => false,
    }
}
<commit_msg>Improve CSS parser organization<commit_after>//! A simple parser for a tiny subset of CSS.
//!
//! To support more CSS syntax, it would probably be easiest to replace this
//! hand-rolled parser with one based on a library or parser generator.

use std::from_str::FromStr;
use std::ascii::OwnedStrAsciiExt;

// Data structures:

#[deriving(Show)]
pub struct Stylesheet {
    pub rules: Vec<Rule>,
}

#[deriving(Show)]
pub struct Rule {
    pub selectors: Vec<Selector>,
    pub declarations: Vec<Declaration>,
}

#[deriving(Show)]
pub enum Selector {
    Simple(SimpleSelector),
}

#[deriving(Show)]
pub struct SimpleSelector {
    pub tag_name: Option<String>,
    pub id: Option<String>,
    pub class: Vec<String>,
}

#[deriving(Show)]
pub struct Declaration {
    pub name: String,
    pub value: Value,
}

#[deriving(Show, Clone, PartialEq)]
pub enum Value {
    Keyword(String),
    Length(f32, Unit),
}

#[deriving(Show, Clone, PartialEq)]
pub enum Unit {
    Px,
}

pub type Specificity = (uint, uint, uint);

impl Selector {
    pub fn specificity(&self) -> Specificity {
        // http://www.w3.org/TR/selectors/#specificity
        let Simple(ref simple) = *self;
        let a = simple.id.iter().len();
        let b = simple.class.len();
        let c = simple.tag_name.iter().len();
        (a, b, c)
    }
}

/// Parse a whole CSS stylesheet.
pub fn parse(source: String) -> Stylesheet {
    let mut parser = Parser { pos: 0u, input: source };
    Stylesheet { rules: parser.parse_rules() }
}

struct Parser {
    pos: uint,
    input: String,
}

impl Parser {
    /// Parse a list of rule sets, separated by optional whitespace.
    fn parse_rules(&mut self) -> Vec<Rule> {
        let mut rules = Vec::new();
        loop {
            self.consume_whitespace();
            if self.eof() { break }
            rules.push(self.parse_rule());
        }
        rules
    }

    /// Parse a rule set: `<selectors> { <declarations> }`.
    fn parse_rule(&mut self) -> Rule {
        Rule {
            selectors: self.parse_selectors(),
            declarations: self.parse_declarations(),
        }
    }

    /// Parse a comma-separated list of selectors.
    fn parse_selectors(&mut self) -> Vec<Selector> {
        let mut selectors = Vec::new();
        loop {
            selectors.push(Simple(self.parse_simple_selector()));
            self.consume_whitespace();
            match self.next_char() {
                ',' => { self.consume_char(); }
                '{' => break,
                c   => fail!("Unexpected character {} in selector list", c)
            }
        }
        // Return selectors with highest specificity first, for use in matching.
        selectors.sort_by(|a,b| b.specificity().cmp(&a.specificity()));
        selectors
    }

    /// Parse one simple selector, e.g.: `type#id.class1.class2.class3`
    fn parse_simple_selector(&mut self) -> SimpleSelector {
        let mut result = SimpleSelector { tag_name: None, id: None, class: Vec::new() };
        while !self.eof() {
            match self.next_char() {
                '#' => {
                    self.consume_char();
                    result.id = Some(self.parse_identifier());
                }
                '.' => {
                    self.consume_char();
                    result.class.push(self.parse_identifier());
                }
                '*' => {
                    // universal selector
                    self.consume_char();
                }
                c if valid_identifier_char(c) => {
                    result.tag_name = Some(self.parse_identifier());
                }
                _ => break
            }
        }
        result
    }

    /// Parse a list of declarations enclosed in `{ ... }`.
    fn parse_declarations(&mut self) -> Vec<Declaration> {
        assert!(self.consume_char() == '{');
        let mut declarations = Vec::new();
        loop {
            self.consume_whitespace();
            if self.next_char() == '}' {
                self.consume_char();
                break;
            }
            declarations.push(self.parse_declaration());
        }
        declarations
    }

    /// Parse one `<property>: <value>;` declaration.
    fn parse_declaration(&mut self) -> Declaration {
        let property_name = self.parse_identifier();
        self.consume_whitespace();
        assert!(self.consume_char() == ':')
        self.consume_whitespace();
        let value = self.parse_value();
        self.consume_whitespace();
        assert!(self.consume_char() == ';')

        Declaration {
            name: property_name,
            value: value,
        }
    }

    /// Parse a value (supports only lengths and keywords for now).
    fn parse_value(&mut self) -> Value {
        match self.next_char() {
            '0'..'9' => self.parse_length(),
            _ => Keyword(self.parse_identifier())
        }
    }

    // Helper functions for `parse_value`:

    fn parse_length(&mut self) -> Value {
        Length(self.parse_float(), self.parse_unit())
    }

    fn parse_float(&mut self) -> f32 {
        let s = self.consume_while(|c| match c {
            '0'..'9' | '.' => true,
            _ => false
        });
        let f: Option<f32> = FromStr::from_str(s.as_slice());
        f.unwrap()
    }

    fn parse_unit(&mut self) -> Unit {
        match self.parse_identifier().into_ascii_lower().as_slice() {
            "px" => Px,
            _ => fail!("unrecognized unit")
        }
    }

    fn parse_identifier(&mut self) -> String {
        self.consume_while(valid_identifier_char)
    }

    /// Consume and discard zero or more whitespace characters.
    fn consume_whitespace(&mut self) {
        self.consume_while(|c| c.is_whitespace());
    }

    /// Consume characters until `test` returns false.
    fn consume_while(&mut self, test: |char| -> bool) -> String {
        let mut result = String::new();
        while !self.eof() && test(self.next_char()) {
            result.push_char(self.consume_char());
        }
        result
    }

    /// Return the current character, and advance self.pos to the next character.
    fn consume_char(&mut self) -> char {
        let range = self.input.as_slice().char_range_at(self.pos);
        self.pos = range.next;
        range.ch
    }

    /// Read the current character without consuming it.
    fn next_char(&self) -> char {
        self.input.as_slice().char_at(self.pos)
    }

    /// Return true if all input is consumed.
    fn eof(&self) -> bool {
        self.pos >= self.input.len()
    }
}

fn valid_identifier_char(c: char) -> bool {
    match c {
        'a'..'z' | 'A'..'Z' | '0'..'9' | '-' | '_' => true, // TODO: Include U+00A0 and higher.
        _ => false,
    }
}
<|endoftext|>


<commit_before>//! Eigenvalue decomposition for non-symmetric square matrices

use ndarray::*;
use crate::error::*;
use crate::layout::*;
use crate::types::*;

/// Eigenvalue decomposition of general matrix reference
pub trait Eig {
    type EigVal;
    type EigVec;
    fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)>;
}

impl<A, S> Eig for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: Data<Elem = A>,
{
    type EigVal = Array1<A::Complex>;
    type EigVec = Array2<A::Complex>;

    fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)> {
        let mut a = self.to_owned();
        let layout = a.square_layout()?;
        let (s, t) = unsafe { A::eig(true, layout, a.as_allocated_mut()?)? };
        let (n, _) = layout.size();
        Ok((ArrayBase::from(s), ArrayBase::from(t).into_shape((n as usize, n as usize)).unwrap()))
    }
}

/// Calculate eigenvalues without eigenvectors
pub trait EigVals {
    type EigVal;
    fn eigvals(&self) -> Result<Self::EigVal>;
}

impl<A, S> EigVals for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
{
    type EigVal = Array1<A::Complex>;

    fn eigvals(&self) -> Result<Self::EigVal> {
        let mut a = self.to_owned();
        let (s, _) = unsafe { A::eig(true, a.square_layout()?, a.as_allocated_mut()?)? };
        Ok(ArrayBase::from(s))
    }
}<commit_msg>add comment on src/eig.rs<commit_after>//! Eigenvalue decomposition for non-symmetric square matrices

use ndarray::*;
use crate::error::*;
use crate::layout::*;
use crate::types::*;

/// Eigenvalue decomposition of general matrix reference
pub trait Eig {
    /// EigVec is the right eivenvector
    type EigVal;
    type EigVec;
    /// Calculate eigenvalues with the right eigenvector
    fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)>;
}

impl<A, S> Eig for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: Data<Elem = A>,
{
    type EigVal = Array1<A::Complex>;
    type EigVec = Array2<A::Complex>;

    fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)> {
        let mut a = self.to_owned();
        let layout = a.square_layout()?;
        let (s, t) = unsafe { A::eig(true, layout, a.as_allocated_mut()?)? };
        let (n, _) = layout.size();
        Ok((ArrayBase::from(s), ArrayBase::from(t).into_shape((n as usize, n as usize)).unwrap()))
    }
}

/// Calculate eigenvalues without eigenvectors
pub trait EigVals {
    type EigVal;
    fn eigvals(&self) -> Result<Self::EigVal>;
}

impl<A, S> EigVals for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
{
    type EigVal = Array1<A::Complex>;

    fn eigvals(&self) -> Result<Self::EigVal> {
        let mut a = self.to_owned();
        let (s, _) = unsafe { A::eig(true, a.square_layout()?, a.as_allocated_mut()?)? };
        Ok(ArrayBase::from(s))
    }
}<|endoftext|>


<commit_before>extern crate git2;

use prompt_buffer;
use prompt_buffer::{PromptLine, PromptBufferPlugin, PromptLineBuilder};
use git2::{Repository, Error, StatusOptions, STATUS_WT_NEW};
use std::{os, fmt};
use term::color;

enum StatusTypes {
    New,
    Modified,
    Deleted,
    Renamed,
    TypeChange,
    Untracked,
    Clean
}

impl fmt::Show for StatusTypes {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", match *self {
            StatusTypes::Clean => " ",
            StatusTypes::Deleted => "D",
            StatusTypes::Modified => "M",
            StatusTypes::New => "A",
            StatusTypes::Renamed => "R",
            StatusTypes::TypeChange => "T",
            StatusTypes::Untracked => "?",
        })
    }
}

struct GitStatus {
    index: StatusTypes,
    workdir: StatusTypes
}

impl GitStatus {
    fn new(f: git2::Status) -> GitStatus {
        GitStatus {
            index:
                     if f.contains(git2::STATUS_INDEX_NEW) { StatusTypes::New }
                else if f.contains(git2::STATUS_INDEX_MODIFIED) { StatusTypes::Modified }
                else if f.contains(git2::STATUS_INDEX_DELETED) { StatusTypes::Deleted }
                else if f.contains(git2::STATUS_INDEX_RENAMED) { StatusTypes::Renamed }
                else if f.contains(git2::STATUS_INDEX_TYPECHANGE) { StatusTypes::TypeChange }
                else if f.contains(git2::STATUS_WT_NEW) { StatusTypes::Untracked }
                else { StatusTypes::Clean },
            workdir:
                     if f.contains(git2::STATUS_WT_NEW) { StatusTypes::Untracked }
                else if f.contains(git2::STATUS_WT_MODIFIED) { StatusTypes::Modified }
                else if f.contains(git2::STATUS_WT_DELETED) { StatusTypes::Deleted }
                else if f.contains(git2::STATUS_WT_RENAMED) { StatusTypes::Renamed }
                else if f.contains(git2::STATUS_WT_TYPECHANGE) { StatusTypes::TypeChange }
                else { StatusTypes::Clean },
        }
    }
}

impl fmt::Show for GitStatus {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{}", self.index, self.workdir)
    }
}

fn get_git(path: &Path) -> Option<Repository> {
    match Repository::discover(path) {
        Ok(repo) => Some(repo),
        _ => None
    }
}

struct BranchInfo {
    name: Option<String>,
    upstream: Option<String>
}

fn git_branch(repo: &Repository) -> Result<BranchInfo, Error> {
    let mut branches = repo.branches(None).ok().expect("Unable to load branches");

    for (mut branch, _) in branches {
        if !branch.is_head() {
            continue;
        }

        let name = branch.name();
        return Ok(BranchInfo {
            name: match name {
                Ok(n) => match n {
                    Some(value) => Some(value.to_string()),
                    _ => None
                },
                _ => None
            },
            upstream: match branch.upstream() {
                Ok(upstream) => {
                    match upstream.name() {
                        Ok(n) => match n {
                            Some(value) => Some(value.to_string()),
                            _ => None
                        },
                        _ => None
                    }
                },
                Err(_) => None
            }
        });
    }

    match repo.head() {
        Ok(r) => match repo.find_object(r.target().unwrap(), None) {
            Ok(obj) => {
                let sid = obj.short_id().ok().unwrap();
                let s = sid.as_str();
                let short_id = s.unwrap();
                Ok(BranchInfo {
                    name: Some(format!("{}", short_id)),
                    upstream: Some("?".to_string())
                })
            },
            Err(e) => Err(e)
        },
        Err(e) => Err(e)
    }
}

pub struct GitPlugin {
    repo: Option<Repository>,
    path: Path
}

impl GitPlugin {
    pub fn new() -> GitPlugin {
        GitPlugin {
            repo: None,
            path: os::make_absolute(&Path::new(".")).unwrap()
        }
    }

    fn get_repo(&self) -> Result<&Repository, Error> {
        match self.repo {
            Some(ref repo) => Ok(repo),
            None => Err(Error::from_str("No repo"))
        }
    }

    fn status(&self, buffer: &mut Vec<PromptLine>, path: &Path) -> Result<bool, Error> {
        let repo = try!(self.get_repo());

        let st = repo.statuses(Some(StatusOptions::new()
            .include_untracked(true)
            .renames_head_to_index(true)
            .exclude_submodules(true)
        ));

        let make_path_relative = |current: Path| {
            let mut fullpath = repo.workdir().unwrap();
            fullpath.push(current);

            fullpath.path_relative_from(path).unwrap()
        };

        match st {
            Ok(statuses) => {
                if statuses.len() <= 0 { return Ok(false) }

                buffer.push(PromptLineBuilder::new()
                    .colored_block(&"Git Status", color::CYAN)
                    .build());

                for stat in statuses.iter() {
                    let mut line = PromptLineBuilder::new_free();

                    let status = GitStatus::new(stat.status());

                    let diff = match stat.head_to_index() {
                        Some(delta) => Some(delta),
                        None => match stat.index_to_workdir() {
                            Some(delta) => Some(delta),
                            None => None
                        }
                    };

                    let val = format!("{} {}", status, match diff {
                        Some(delta) => {
                            let old = make_path_relative(delta.old_file().path().unwrap());
                            let new = make_path_relative(delta.new_file().path().unwrap());

                            if old != new {
                                format!("{} -> {}", old.display(), new.display())
                            } else {
                                format!("{}", old.display())
                            }
                        },
                        None => format!("{}", Path::new(stat.path().unwrap()).display())
                    });

                    line = match status.index {
                        StatusTypes::Clean => line.colored_block(&val, file_state_color(status.workdir)),
                        _ => match status.workdir {
                            StatusTypes::Clean | StatusTypes::Untracked =>
                                line.bold_colored_block(&val, file_state_color(status.index)),
                            _ => line.bold_colored_block(&val, color::RED)
                        }
                    };

                    buffer.push(line.indent().build());
                }

                return Ok(true)
            },
            _ => { return Ok(false) }
        }

        fn file_state_color(state: StatusTypes) -> u16 {
            match state {
                StatusTypes::Clean | StatusTypes::Untracked => color::WHITE,
                StatusTypes::Deleted => color::RED,
                StatusTypes::Modified => color::BLUE,
                StatusTypes::New => color::GREEN,
                StatusTypes::Renamed => color::CYAN,
                StatusTypes::TypeChange => color::YELLOW,
            }
        }
    }

    fn outgoing(&self, buffer: &mut Vec<PromptLine>, has_status: bool) -> Result<bool, Error> {
        let repo = try!(self.get_repo());

        let branches = try!(git_branch(repo));

        let mut revwalk = try!(repo.revwalk());

        let from = try!(repo.revparse_single(branches.upstream.unwrap().as_slice())).id();
        let to = try!(repo.revparse_single(branches.name.unwrap().as_slice())).id();

        try!(revwalk.push(to));
        try!(revwalk.hide(from));

        let mut log_shown = false;

        for id in revwalk {
            let mut commit = try!(repo.find_commit(id));

            if !log_shown {
                buffer.push(PromptLineBuilder::new()
                    .colored_block(&"Git Outgoing", color::CYAN)
                    .indent_by(if has_status { 1 } else { 0 })
                    .build());
                log_shown = true;
            }

            buffer.push(PromptLineBuilder::new_free()
                .indent()
                .block(&format!("{}{} {}",
                    prompt_buffer::reset(),
                    String::from_utf8_lossy(
                        try!(try!(repo.find_object(commit.id(), None)).short_id()).get()
                    ),
                    String::from_utf8_lossy(match commit.summary_bytes() {
                        Some(b) => b,
                        None => continue
                    })))
                .build());
        }

        return Ok(log_shown);
    }

    fn end(&self, buffer: &mut Vec<PromptLine>, indented: bool) -> Result<bool, Error> {
        let repo = try!(self.get_repo());

        let branches = try!(git_branch(repo));

        buffer.push(PromptLineBuilder::new()
            .colored_block(
                &match (branches.name, branches.upstream) {
                    (None, None) => "New Repository".to_string(),
                    (Some(name), None) => name,
                    (Some(name), Some(remote)) => format!("{}{} -> {}{}",
                        name,
                        prompt_buffer::reset(),
                        prompt_buffer::col(color::MAGENTA),
                        remote),
                    _ => "Unknown branch state".to_string()
                }, color::CYAN)
            .indent_by(if indented { 1 } else { 0 })
            .build());

        Ok(true)
    }
}

impl PromptBufferPlugin for GitPlugin {
    fn run(&mut self, path: &Path, lines: &mut Vec<PromptLine>) {
        if self.path != *path || self.repo.is_none() {
            self.path = path.clone();
            self.repo = get_git(&self.path);
        }

        let st = self.status(lines, path).ok().unwrap_or(false);
        let out = self.outgoing(lines, st).ok().unwrap_or(false);
        self.end(lines, st || out).ok();
    }
}
<commit_msg>Show submodules<commit_after>extern crate git2;

use prompt_buffer;
use prompt_buffer::{PromptLine, PromptBufferPlugin, PromptLineBuilder};
use git2::{Repository, Error, StatusOptions, STATUS_WT_NEW};
use std::{os, fmt};
use term::color;

enum StatusTypes {
    New,
    Modified,
    Deleted,
    Renamed,
    TypeChange,
    Untracked,
    Clean
}

impl fmt::Show for StatusTypes {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", match *self {
            StatusTypes::Clean => " ",
            StatusTypes::Deleted => "D",
            StatusTypes::Modified => "M",
            StatusTypes::New => "A",
            StatusTypes::Renamed => "R",
            StatusTypes::TypeChange => "T",
            StatusTypes::Untracked => "?",
        })
    }
}

struct GitStatus {
    index: StatusTypes,
    workdir: StatusTypes
}

impl GitStatus {
    fn new(f: git2::Status) -> GitStatus {
        GitStatus {
            index:
                     if f.contains(git2::STATUS_INDEX_NEW) { StatusTypes::New }
                else if f.contains(git2::STATUS_INDEX_MODIFIED) { StatusTypes::Modified }
                else if f.contains(git2::STATUS_INDEX_DELETED) { StatusTypes::Deleted }
                else if f.contains(git2::STATUS_INDEX_RENAMED) { StatusTypes::Renamed }
                else if f.contains(git2::STATUS_INDEX_TYPECHANGE) { StatusTypes::TypeChange }
                else if f.contains(git2::STATUS_WT_NEW) { StatusTypes::Untracked }
                else { StatusTypes::Clean },
            workdir:
                     if f.contains(git2::STATUS_WT_NEW) { StatusTypes::Untracked }
                else if f.contains(git2::STATUS_WT_MODIFIED) { StatusTypes::Modified }
                else if f.contains(git2::STATUS_WT_DELETED) { StatusTypes::Deleted }
                else if f.contains(git2::STATUS_WT_RENAMED) { StatusTypes::Renamed }
                else if f.contains(git2::STATUS_WT_TYPECHANGE) { StatusTypes::TypeChange }
                else { StatusTypes::Clean },
        }
    }
}

impl fmt::Show for GitStatus {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{}", self.index, self.workdir)
    }
}

fn get_git(path: &Path) -> Option<Repository> {
    match Repository::discover(path) {
        Ok(repo) => Some(repo),
        _ => None
    }
}

struct BranchInfo {
    name: Option<String>,
    upstream: Option<String>
}

fn git_branch(repo: &Repository) -> Result<BranchInfo, Error> {
    let mut branches = repo.branches(None).ok().expect("Unable to load branches");

    for (mut branch, _) in branches {
        if !branch.is_head() {
            continue;
        }

        let name = branch.name();
        return Ok(BranchInfo {
            name: match name {
                Ok(n) => match n {
                    Some(value) => Some(value.to_string()),
                    _ => None
                },
                _ => None
            },
            upstream: match branch.upstream() {
                Ok(upstream) => {
                    match upstream.name() {
                        Ok(n) => match n {
                            Some(value) => Some(value.to_string()),
                            _ => None
                        },
                        _ => None
                    }
                },
                Err(_) => None
            }
        });
    }

    match repo.head() {
        Ok(r) => match repo.find_object(r.target().unwrap(), None) {
            Ok(obj) => {
                let sid = obj.short_id().ok().unwrap();
                let s = sid.as_str();
                let short_id = s.unwrap();
                Ok(BranchInfo {
                    name: Some(format!("{}", short_id)),
                    upstream: Some("?".to_string())
                })
            },
            Err(e) => Err(e)
        },
        Err(e) => Err(e)
    }
}

pub struct GitPlugin {
    repo: Option<Repository>,
    path: Path
}

impl GitPlugin {
    pub fn new() -> GitPlugin {
        GitPlugin {
            repo: None,
            path: os::make_absolute(&Path::new(".")).unwrap()
        }
    }

    fn get_repo(&self) -> Result<&Repository, Error> {
        match self.repo {
            Some(ref repo) => Ok(repo),
            None => Err(Error::from_str("No repo"))
        }
    }

    fn status(&self, buffer: &mut Vec<PromptLine>, path: &Path) -> Result<bool, Error> {
        let repo = try!(self.get_repo());

        let st = repo.statuses(Some(StatusOptions::new()
            .include_untracked(true)
            .renames_head_to_index(true)
        ));

        let make_path_relative = |current: Path| {
            let mut fullpath = repo.workdir().unwrap();
            fullpath.push(current);

            fullpath.path_relative_from(path).unwrap()
        };

        match st {
            Ok(statuses) => {
                if statuses.len() <= 0 { return Ok(false) }

                buffer.push(PromptLineBuilder::new()
                    .colored_block(&"Git Status", color::CYAN)
                    .build());

                for stat in statuses.iter() {
                    let mut line = PromptLineBuilder::new_free();

                    let status = GitStatus::new(stat.status());

                    let diff = match stat.head_to_index() {
                        Some(delta) => Some(delta),
                        None => match stat.index_to_workdir() {
                            Some(delta) => Some(delta),
                            None => None
                        }
                    };

                    let val = format!("{} {}", status, match diff {
                        Some(delta) => {
                            let old = make_path_relative(delta.old_file().path().unwrap());
                            let new = make_path_relative(delta.new_file().path().unwrap());

                            if old != new {
                                format!("{} -> {}", old.display(), new.display())
                            } else {
                                format!("{}", old.display())
                            }
                        },
                        None => format!("{}", Path::new(stat.path().unwrap()).display())
                    });

                    line = match status.index {
                        StatusTypes::Clean => line.colored_block(&val, file_state_color(status.workdir)),
                        _ => match status.workdir {
                            StatusTypes::Clean | StatusTypes::Untracked =>
                                line.bold_colored_block(&val, file_state_color(status.index)),
                            _ => line.bold_colored_block(&val, color::RED)
                        }
                    };

                    buffer.push(line.indent().build());
                }

                return Ok(true)
            },
            _ => { return Ok(false) }
        }

        fn file_state_color(state: StatusTypes) -> u16 {
            match state {
                StatusTypes::Clean | StatusTypes::Untracked => color::WHITE,
                StatusTypes::Deleted => color::RED,
                StatusTypes::Modified => color::BLUE,
                StatusTypes::New => color::GREEN,
                StatusTypes::Renamed => color::CYAN,
                StatusTypes::TypeChange => color::YELLOW,
            }
        }
    }

    fn outgoing(&self, buffer: &mut Vec<PromptLine>, has_status: bool) -> Result<bool, Error> {
        let repo = try!(self.get_repo());

        let branches = try!(git_branch(repo));

        let mut revwalk = try!(repo.revwalk());

        let from = try!(repo.revparse_single(branches.upstream.unwrap().as_slice())).id();
        let to = try!(repo.revparse_single(branches.name.unwrap().as_slice())).id();

        try!(revwalk.push(to));
        try!(revwalk.hide(from));

        let mut log_shown = false;

        for id in revwalk {
            let mut commit = try!(repo.find_commit(id));

            if !log_shown {
                buffer.push(PromptLineBuilder::new()
                    .colored_block(&"Git Outgoing", color::CYAN)
                    .indent_by(if has_status { 1 } else { 0 })
                    .build());
                log_shown = true;
            }

            buffer.push(PromptLineBuilder::new_free()
                .indent()
                .block(&format!("{}{} {}",
                    prompt_buffer::reset(),
                    String::from_utf8_lossy(
                        try!(try!(repo.find_object(commit.id(), None)).short_id()).get()
                    ),
                    String::from_utf8_lossy(match commit.summary_bytes() {
                        Some(b) => b,
                        None => continue
                    })))
                .build());
        }

        return Ok(log_shown);
    }

    fn end(&self, buffer: &mut Vec<PromptLine>, indented: bool) -> Result<bool, Error> {
        let repo = try!(self.get_repo());

        let branches = try!(git_branch(repo));

        buffer.push(PromptLineBuilder::new()
            .colored_block(
                &match (branches.name, branches.upstream) {
                    (None, None) => "New Repository".to_string(),
                    (Some(name), None) => name,
                    (Some(name), Some(remote)) => format!("{}{} -> {}{}",
                        name,
                        prompt_buffer::reset(),
                        prompt_buffer::col(color::MAGENTA),
                        remote),
                    _ => "Unknown branch state".to_string()
                }, color::CYAN)
            .indent_by(if indented { 1 } else { 0 })
            .build());

        Ok(true)
    }
}

impl PromptBufferPlugin for GitPlugin {
    fn run(&mut self, path: &Path, lines: &mut Vec<PromptLine>) {
        if self.path != *path || self.repo.is_none() {
            self.path = path.clone();
            self.repo = get_git(&self.path);
        }

        let st = self.status(lines, path).ok().unwrap_or(false);
        let out = self.outgoing(lines, st).ok().unwrap_or(false);
        self.end(lines, st || out).ok();
    }
}
<|endoftext|>


<commit_before>
// Copyright 2017 The gltf Library Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use byteorder::{LE, ReadBytesExt};

use Error;

use std::{fmt, io};

/// Represents a Glb loader error.
#[derive(Debug)]
pub enum GlbError {
    /// Io error occured.
    IoError(::std::io::Error),
    /// Unsupported version.
    Version(u32),
    /// Magic says that file is not glTF.
    Magic([u8; 4]),
    /// Length specified in GLB header exceeeds that of slice.
    Length {
        /// length specified in GLB header.
        length: u32,
        /// Actual length of data read.
        length_read: usize,
    },
    /// Stream ended before we could read the chunk.
    ChunkLength {
        /// chunkType error happened at.
        ty: ChunkType,
        /// chunkLength.
        length: u32,
        /// Actual length of data read.
        length_read: usize,
    },
    /// Chunk of this chunkType was not expected.
    ChunkType(ChunkType),
    /// Unknown chunk type.
    UnknownChunkType([u8; 4]),
}

/// The contents of a .glb file.
#[derive(Clone, Debug)]
pub struct Glb<'a> {
    /// The header section of the `.glb` file.
    pub header: Header,
    /// The JSON section of the `.glb` file.
    pub json: &'a [u8],
    /// The optional BIN section of the `.glb` file.
    pub bin: Option<&'a [u8]>,
}

/// The header section of a .glb file.
#[derive(Copy, Clone, Debug)]
pub struct Header {
    /// Must be `b"glTF"`.
    pub magic: [u8; 4],
    /// Must be `2`.
    pub version: u32,
    /// Must match the length of the parent .glb file.
    pub length: u32,
}

/// GLB chunk type.
#[derive(Copy, Clone, Debug)]
pub enum ChunkType {
    /// JSON chunk.
    Json,
    /// BIN\0 chunk.
    Bin,
}

/// Chunk header with no data read yet.
#[derive(Copy, Clone, Debug)]
struct ChunkHeader {
    /// The length of the chunk data in byte excluding the header.
    length: u32,
    /// Chunk type.
    ty: ChunkType,
}

impl Header {
    fn from_reader<R: io::Read>(mut reader: R) -> Result<Self, GlbError> {
        use self::GlbError::IoError;
        let mut magic = [0; 4];
        reader.read_exact(&mut magic).map_err(IoError)?;
        // We only validate magic as we don't care for version and length of
        // contents, the caller does.  Let them decide what to do next with
        // regard to version and length.
        if &magic == b"glTF" {
            Ok(Self {
                magic,
                version: reader.read_u32::<LE>().map_err(IoError)?,
                length: reader.read_u32::<LE>().map_err(IoError)?,
            })
        } else {
            Err(GlbError::Magic(magic))
        }
    }

    fn size_of() -> usize { 12 }
}

impl ChunkHeader {
    fn from_reader<R: io::Read>(mut reader: R) -> Result<Self, GlbError> {
        use self::GlbError::IoError;
        let length = reader.read_u32::<LE>().map_err(IoError)?;
        let mut ty = [0; 4];
        reader.read_exact(&mut ty).map_err(IoError)?;
        let ty = match &ty {
            b"JSON" => Ok(ChunkType::Json),
            b"BIN\0" => Ok(ChunkType::Bin),
            _ => Err(GlbError::UnknownChunkType(ty)),
        }?;
        Ok(Self { length, ty })
    }
}

impl<'a> Glb<'a> {
    /// Splits loaded GLB into its three chunks.
    ///
    /// * Mandatory GLB header.
    /// * Mandatory JSON chunk.
    /// * Optional BIN chunk.
    pub fn from_slice(mut data: &'a [u8]) -> Result<Self, Error> {
        let header = Header::from_reader(&mut data)
            .and_then(|header| {
                let contents_length = header.length as usize - Header::size_of();
                if contents_length <= data.len() {
                    Ok(header)
                } else {
                    Err(GlbError::Length {
                        length: contents_length,
                        length_read: data.len(),
                    })
                }
            })
            .map_err(Error::Glb)?;
        match header.version {
            2 => Self::from_v2(data)
                .map(|(json, bin)| Glb { header, json, bin })
                .map_err(Error::Glb),
            x => Err(Error::Glb(GlbError::Version(x)))
        }
    }

    /// Does the loading job for you.  Provided buf will be cleared before new
    /// data will be written.  When error happens, if only header was read, buf
    /// will not be mutated, otherwise, buf will be empty.
    pub fn from_reader<R: io::Read>(mut reader: R,
                                    buf: &'a mut Vec<u8>) -> Result<Self, Error> {
        let header = Header::from_reader(&mut reader).map_err(Error::Glb)?;
        match header.version {
            2 => {
                let glb_len = header.length - Header::size_of() as u32;
                buf.clear();
                buf.reserve(glb_len as usize);
                // SAFETY: We are doing unsafe operation on a user-supplied
                // container!  Make sure not to expose user to uninitialized
                // data if an error happens during reading.
                //
                // It is guaranteed by reserve's implementation that the reserve
                // call will make buf's capacity _at least_ buf_len.
                //
                // We do not read contents of the Vec unless it is fully
                // initialized.
                unsafe { buf.set_len(glb_len as usize) };
                if let Err(e) = reader.read_exact(buf).map_err(GlbError::IoError) {
                    // SAFETY: It is safe to not run destructors because u8 has
                    // none.
                    unsafe { buf.set_len(0) };
                    Err(Error::Glb(e))
                } else {
                    Self::from_v2(buf)
                       .map(|(json, bin)| Glb { header, json, bin })
                       .map_err(Error::Glb)
                }
            }
            x => Err(Error::Glb(GlbError::Version(x)))
        }
    }

    fn from_v2(mut data: &'a [u8]) -> Result<(&'a [u8], Option<&'a [u8]>), GlbError> {
        let (json, mut data) = ChunkHeader::from_reader(&mut data)
            .and_then(|json_h| if let ChunkType::Json = json_h.ty {
                Ok(json_h)
            } else {
                Err(GlbError::ChunkType(json_h.ty))
            })
            .and_then(|json_h| if json_h.length as usize <= data.len() {
                Ok(json_h)
            } else {
                Err(GlbError::ChunkLength {
                    ty: json_h.ty,
                    length: json_h.length,
                    length_read: data.len(),
                })
            })
            // PANIC: We have verified that json_h.length is no greater than
            // that of data.len().
            .map(|json_h| data.split_at(json_h.length as usize))?;

        let bin = if data.len() > 0 {
            ChunkHeader::from_reader(&mut data)
                .and_then(|bin_h| if let ChunkType::Bin = bin_h.ty {
                    Ok(bin_h)
                } else {
                    Err(GlbError::ChunkType(bin_h.ty))
                })
                .and_then(|bin_h| if bin_h.length as usize <= data.len() {
                    Ok(bin_h)
                } else {
                    Err(GlbError::ChunkLength {
                        ty: bin_h.ty,
                        length: bin_h.length,
                        length_read: data.len(),
                    })
                })
                // PANIC: we have verified that bin_h.length is no greater than
                // that of data.len().
                .map(|bin_h| data.split_at(bin_h.length as usize))
                .map(|(x, _)| Some(x))?
        } else {
            None
        };
        Ok((json, bin))
    }
}

impl fmt::Display for GlbError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use std::error::Error;
        write!(f, "{}", self.description())
    }
}

impl ::std::error::Error for GlbError {
    fn description(&self) -> &str {
         match *self {
             GlbError::IoError(ref e) => e.description(),
             GlbError::Version(_) => "unsupported version",
             GlbError::Magic(_) => "not glTF magic",
             GlbError::Length { .. } => "could not completely read the object",
             GlbError::ChunkLength { ty, .. } => match ty {
                 ChunkType::Json => "JSON chunk length exceeds that of slice",
                 ChunkType::Bin => "BIN\\0 chunk length exceeds that of slice",
             },
             GlbError::ChunkType(ty) => match ty {
                 ChunkType::Json => "was not expecting JSON chunk",
                 ChunkType::Bin => "was not expecting BIN\\0 chunk",
             },
             GlbError::UnknownChunkType(_) => "unknown chunk type",
        }
    }
}
<commit_msg>Cast contents_length appropriately<commit_after>
// Copyright 2017 The gltf Library Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use byteorder::{LE, ReadBytesExt};

use Error;

use std::{fmt, io};

/// Represents a Glb loader error.
#[derive(Debug)]
pub enum GlbError {
    /// Io error occured.
    IoError(::std::io::Error),
    /// Unsupported version.
    Version(u32),
    /// Magic says that file is not glTF.
    Magic([u8; 4]),
    /// Length specified in GLB header exceeeds that of slice.
    Length {
        /// length specified in GLB header.
        length: u32,
        /// Actual length of data read.
        length_read: usize,
    },
    /// Stream ended before we could read the chunk.
    ChunkLength {
        /// chunkType error happened at.
        ty: ChunkType,
        /// chunkLength.
        length: u32,
        /// Actual length of data read.
        length_read: usize,
    },
    /// Chunk of this chunkType was not expected.
    ChunkType(ChunkType),
    /// Unknown chunk type.
    UnknownChunkType([u8; 4]),
}

/// The contents of a .glb file.
#[derive(Clone, Debug)]
pub struct Glb<'a> {
    /// The header section of the `.glb` file.
    pub header: Header,
    /// The JSON section of the `.glb` file.
    pub json: &'a [u8],
    /// The optional BIN section of the `.glb` file.
    pub bin: Option<&'a [u8]>,
}

/// The header section of a .glb file.
#[derive(Copy, Clone, Debug)]
pub struct Header {
    /// Must be `b"glTF"`.
    pub magic: [u8; 4],
    /// Must be `2`.
    pub version: u32,
    /// Must match the length of the parent .glb file.
    pub length: u32,
}

/// GLB chunk type.
#[derive(Copy, Clone, Debug)]
pub enum ChunkType {
    /// JSON chunk.
    Json,
    /// BIN\0 chunk.
    Bin,
}

/// Chunk header with no data read yet.
#[derive(Copy, Clone, Debug)]
struct ChunkHeader {
    /// The length of the chunk data in byte excluding the header.
    length: u32,
    /// Chunk type.
    ty: ChunkType,
}

impl Header {
    fn from_reader<R: io::Read>(mut reader: R) -> Result<Self, GlbError> {
        use self::GlbError::IoError;
        let mut magic = [0; 4];
        reader.read_exact(&mut magic).map_err(IoError)?;
        // We only validate magic as we don't care for version and length of
        // contents, the caller does.  Let them decide what to do next with
        // regard to version and length.
        if &magic == b"glTF" {
            Ok(Self {
                magic,
                version: reader.read_u32::<LE>().map_err(IoError)?,
                length: reader.read_u32::<LE>().map_err(IoError)?,
            })
        } else {
            Err(GlbError::Magic(magic))
        }
    }

    fn size_of() -> usize { 12 }
}

impl ChunkHeader {
    fn from_reader<R: io::Read>(mut reader: R) -> Result<Self, GlbError> {
        use self::GlbError::IoError;
        let length = reader.read_u32::<LE>().map_err(IoError)?;
        let mut ty = [0; 4];
        reader.read_exact(&mut ty).map_err(IoError)?;
        let ty = match &ty {
            b"JSON" => Ok(ChunkType::Json),
            b"BIN\0" => Ok(ChunkType::Bin),
            _ => Err(GlbError::UnknownChunkType(ty)),
        }?;
        Ok(Self { length, ty })
    }
}

impl<'a> Glb<'a> {
    /// Splits loaded GLB into its three chunks.
    ///
    /// * Mandatory GLB header.
    /// * Mandatory JSON chunk.
    /// * Optional BIN chunk.
    pub fn from_slice(mut data: &'a [u8]) -> Result<Self, Error> {
        let header = Header::from_reader(&mut data)
            .and_then(|header| {
                let contents_length = header.length as usize - Header::size_of();
                if contents_length <= data.len() {
                    Ok(header)
                } else {
                    Err(GlbError::Length {
                        length: contents_length as u32,
                        length_read: data.len(),
                    })
                }
            })
            .map_err(Error::Glb)?;
        match header.version {
            2 => Self::from_v2(data)
                .map(|(json, bin)| Glb { header, json, bin })
                .map_err(Error::Glb),
            x => Err(Error::Glb(GlbError::Version(x)))
        }
    }

    /// Does the loading job for you.  Provided buf will be cleared before new
    /// data will be written.  When error happens, if only header was read, buf
    /// will not be mutated, otherwise, buf will be empty.
    pub fn from_reader<R: io::Read>(mut reader: R,
                                    buf: &'a mut Vec<u8>) -> Result<Self, Error> {
        let header = Header::from_reader(&mut reader).map_err(Error::Glb)?;
        match header.version {
            2 => {
                let glb_len = header.length - Header::size_of() as u32;
                buf.clear();
                buf.reserve(glb_len as usize);
                // SAFETY: We are doing unsafe operation on a user-supplied
                // container!  Make sure not to expose user to uninitialized
                // data if an error happens during reading.
                //
                // It is guaranteed by reserve's implementation that the reserve
                // call will make buf's capacity _at least_ buf_len.
                //
                // We do not read contents of the Vec unless it is fully
                // initialized.
                unsafe { buf.set_len(glb_len as usize) };
                if let Err(e) = reader.read_exact(buf).map_err(GlbError::IoError) {
                    // SAFETY: It is safe to not run destructors because u8 has
                    // none.
                    unsafe { buf.set_len(0) };
                    Err(Error::Glb(e))
                } else {
                    Self::from_v2(buf)
                       .map(|(json, bin)| Glb { header, json, bin })
                       .map_err(Error::Glb)
                }
            }
            x => Err(Error::Glb(GlbError::Version(x)))
        }
    }

    fn from_v2(mut data: &'a [u8]) -> Result<(&'a [u8], Option<&'a [u8]>), GlbError> {
        let (json, mut data) = ChunkHeader::from_reader(&mut data)
            .and_then(|json_h| if let ChunkType::Json = json_h.ty {
                Ok(json_h)
            } else {
                Err(GlbError::ChunkType(json_h.ty))
            })
            .and_then(|json_h| if json_h.length as usize <= data.len() {
                Ok(json_h)
            } else {
                Err(GlbError::ChunkLength {
                    ty: json_h.ty,
                    length: json_h.length,
                    length_read: data.len(),
                })
            })
            // PANIC: We have verified that json_h.length is no greater than
            // that of data.len().
            .map(|json_h| data.split_at(json_h.length as usize))?;

        let bin = if data.len() > 0 {
            ChunkHeader::from_reader(&mut data)
                .and_then(|bin_h| if let ChunkType::Bin = bin_h.ty {
                    Ok(bin_h)
                } else {
                    Err(GlbError::ChunkType(bin_h.ty))
                })
                .and_then(|bin_h| if bin_h.length as usize <= data.len() {
                    Ok(bin_h)
                } else {
                    Err(GlbError::ChunkLength {
                        ty: bin_h.ty,
                        length: bin_h.length,
                        length_read: data.len(),
                    })
                })
                // PANIC: we have verified that bin_h.length is no greater than
                // that of data.len().
                .map(|bin_h| data.split_at(bin_h.length as usize))
                .map(|(x, _)| Some(x))?
        } else {
            None
        };
        Ok((json, bin))
    }
}

impl fmt::Display for GlbError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use std::error::Error;
        write!(f, "{}", self.description())
    }
}

impl ::std::error::Error for GlbError {
    fn description(&self) -> &str {
         match *self {
             GlbError::IoError(ref e) => e.description(),
             GlbError::Version(_) => "unsupported version",
             GlbError::Magic(_) => "not glTF magic",
             GlbError::Length { .. } => "could not completely read the object",
             GlbError::ChunkLength { ty, .. } => match ty {
                 ChunkType::Json => "JSON chunk length exceeds that of slice",
                 ChunkType::Bin => "BIN\\0 chunk length exceeds that of slice",
             },
             GlbError::ChunkType(ty) => match ty {
                 ChunkType::Json => "was not expecting JSON chunk",
                 ChunkType::Bin => "was not expecting BIN\\0 chunk",
             },
             GlbError::UnknownChunkType(_) => "unknown chunk type",
        }
    }
}
<|endoftext|>


<commit_before>//! Rustic bindings to [libnotify](https://developer.gnome.org/libnotify/)
//!
//! ```rust
//!extern crate libnotify;
//!
//!fn main() {
//!    let notify = libnotify::Context::new("hello").unwrap_or_else(|e| {
//!        panic!("{}", e);
//!    });
//!    let body_text = Some("This is the optional body text.");
//!    let n = notify.new_notification("This is the summary.", body_text, None)
//!                  .unwrap_or_else(|e| panic!("{}", e));
//!    n.show().unwrap_or_else(|e| panic!("{}", e));
//!}
//!
//! ```

#![warn(missing_docs)]

extern crate libnotify_sys as sys;
extern crate glib_2_0_sys as glib;
extern crate gtypes;

use std::ffi::{self, CStr, CString};
use std::marker::PhantomData;
use std::fmt;
use std::error::Error;

use gtypes::{TRUE, FALSE};

/// Error that can happen on context creation
#[derive(Debug)]
pub enum ContextCreationError {
    /// Context already exists.
    AlreadyExists,
    /// Failed to initialize libnotify.
    InitError,
    /// A nul byte was found in the provided string.
    NulError(ffi::NulError),
}

impl fmt::Display for ContextCreationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use ContextCreationError::*;
        match *self {
            AlreadyExists => write!(f, "A Libnotify context already exists."),
            InitError => write!(f, "Failed to initialize libnotify."),
            NulError(ref e) => write!(f, "{}", e),
        }
    }
}

#[derive(Debug)]
pub enum NotificationCreationError {
    /// A nul byte was found in the provided string.
    NulError(ffi::NulError),
    /// An unknown error happened.
    Unknown,
}

impl fmt::Display for NotificationCreationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use NotificationCreationError::*;
        match *self {
            NulError(ref e) => write!(f, "{}", e),
            Unknown => write!(f, "Unknown error"),
        }
    }
}

/// The context which within libnotify operates.
///
/// Only one context can exist at a time.
pub struct Context;

impl Context {
    /// Create a new context
    ///
    /// Arguments:
    ///
    /// - app_name: The name of the application using the context
    pub fn new(app_name: &str) -> Result<Context, ContextCreationError> {
        unsafe {
            if sys::notify_is_initted() == TRUE {
                return Err(ContextCreationError::AlreadyExists);
            }
            let app_name = match CString::new(app_name) {
                Ok(name) => name,
                Err(e) => return Err(ContextCreationError::NulError(e)),
            };
            if sys::notify_init(app_name.as_ptr()) == FALSE {
                return Err(ContextCreationError::InitError);
            }
        }
        Ok(Context)
    }
    /// Creates a new Notification.
    ///
    /// Arguments:
    ///
    /// - summary: Required summary text
    /// - body: Optional body text
    /// - icon: Optional icon theme icon name or filename
    pub fn new_notification(&self,
                            summary: &str,
                            body: Option<&str>,
                            icon: Option<&str>)
                            -> Result<Notification, NotificationCreationError> {
        let summary = match CString::new(summary) {
            Ok(cstr) => cstr,
            Err(e) => return Err(NotificationCreationError::NulError(e)),
        };
        let body = match body {
            Some(body) => match CString::new(body) {
                Ok(cstr) => Some(cstr),
                Err(e) => return Err(NotificationCreationError::NulError(e)),
            },
            None => None,
        };
        let body_ptr = match body {
            Some(body) => body.as_ptr(),
            None => std::ptr::null(),
        };
        let icon = match icon {
            Some(icon) => match CString::new(icon) {
                Ok(cstr) => Some(cstr),
                Err(e) => return Err(NotificationCreationError::NulError(e)),
            },
            None => None,
        };
        let icon_ptr = match icon {
            Some(icon) => icon.as_ptr(),
            None => std::ptr::null(),
        };
        unsafe {
            let n = sys::notify_notification_new(summary.as_ptr(), body_ptr, icon_ptr);
            if n.is_null() {
                return Err(NotificationCreationError::Unknown);
            }

            Ok(Notification {
                handle: n,
                _phantom: PhantomData,
            })
        }
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            sys::notify_uninit();
        }
    }
}

/// A passive pop-up notification
pub struct Notification<'a> {
    handle: *mut sys::NotifyNotification,
    _phantom: PhantomData<&'a Context>,
}

impl<'a> Notification<'a> {
    /// Tells the notification server to display the notification
    /// on the screen.
    pub fn show(&'a self) -> Result<(), NotificationShowError> {
        unsafe {
            let mut err: *mut glib::GError = std::ptr::null_mut();
            sys::notify_notification_show(self.handle, &mut err);
            if !err.is_null() {
                let result = Err(NotificationShowError {
                    message: CStr::from_ptr((*err).message).to_string_lossy().into_owned(),
                });
                glib::g_error_free(err);
                return result;
            }
            return Ok(());
        }
    }
}

#[derive(Debug)]
pub struct NotificationShowError {
    message: String,
}

impl fmt::Display for NotificationShowError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Error showing notification: {}", self.message)
    }
}

impl Error for NotificationShowError {
    fn description(&self) -> &str {
        "Notification show error"
    }
}
<commit_msg>Add remaining missing documentation<commit_after>//! Rustic bindings to [libnotify](https://developer.gnome.org/libnotify/)
//!
//! ```rust
//!extern crate libnotify;
//!
//!fn main() {
//!    let notify = libnotify::Context::new("hello").unwrap_or_else(|e| {
//!        panic!("{}", e);
//!    });
//!    let body_text = Some("This is the optional body text.");
//!    let n = notify.new_notification("This is the summary.", body_text, None)
//!                  .unwrap_or_else(|e| panic!("{}", e));
//!    n.show().unwrap_or_else(|e| panic!("{}", e));
//!}
//!
//! ```

#![warn(missing_docs)]

extern crate libnotify_sys as sys;
extern crate glib_2_0_sys as glib;
extern crate gtypes;

use std::ffi::{self, CStr, CString};
use std::marker::PhantomData;
use std::fmt;
use std::error::Error;

use gtypes::{TRUE, FALSE};

/// Error that can happen on context creation
#[derive(Debug)]
pub enum ContextCreationError {
    /// Context already exists.
    AlreadyExists,
    /// Failed to initialize libnotify.
    InitError,
    /// A nul byte was found in the provided string.
    NulError(ffi::NulError),
}

impl fmt::Display for ContextCreationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use ContextCreationError::*;
        match *self {
            AlreadyExists => write!(f, "A Libnotify context already exists."),
            InitError => write!(f, "Failed to initialize libnotify."),
            NulError(ref e) => write!(f, "{}", e),
        }
    }
}

#[derive(Debug)]
/// An error that can happen when attempting to create a notification.
pub enum NotificationCreationError {
    /// A nul byte was found in the provided string.
    NulError(ffi::NulError),
    /// An unknown error happened.
    Unknown,
}

impl fmt::Display for NotificationCreationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use NotificationCreationError::*;
        match *self {
            NulError(ref e) => write!(f, "{}", e),
            Unknown => write!(f, "Unknown error"),
        }
    }
}

/// The context which within libnotify operates.
///
/// Only one context can exist at a time.
pub struct Context;

impl Context {
    /// Create a new context
    ///
    /// Arguments:
    ///
    /// - app_name: The name of the application using the context
    pub fn new(app_name: &str) -> Result<Context, ContextCreationError> {
        unsafe {
            if sys::notify_is_initted() == TRUE {
                return Err(ContextCreationError::AlreadyExists);
            }
            let app_name = match CString::new(app_name) {
                Ok(name) => name,
                Err(e) => return Err(ContextCreationError::NulError(e)),
            };
            if sys::notify_init(app_name.as_ptr()) == FALSE {
                return Err(ContextCreationError::InitError);
            }
        }
        Ok(Context)
    }
    /// Creates a new Notification.
    ///
    /// Arguments:
    ///
    /// - summary: Required summary text
    /// - body: Optional body text
    /// - icon: Optional icon theme icon name or filename
    pub fn new_notification(&self,
                            summary: &str,
                            body: Option<&str>,
                            icon: Option<&str>)
                            -> Result<Notification, NotificationCreationError> {
        let summary = match CString::new(summary) {
            Ok(cstr) => cstr,
            Err(e) => return Err(NotificationCreationError::NulError(e)),
        };
        let body = match body {
            Some(body) => match CString::new(body) {
                Ok(cstr) => Some(cstr),
                Err(e) => return Err(NotificationCreationError::NulError(e)),
            },
            None => None,
        };
        let body_ptr = match body {
            Some(body) => body.as_ptr(),
            None => std::ptr::null(),
        };
        let icon = match icon {
            Some(icon) => match CString::new(icon) {
                Ok(cstr) => Some(cstr),
                Err(e) => return Err(NotificationCreationError::NulError(e)),
            },
            None => None,
        };
        let icon_ptr = match icon {
            Some(icon) => icon.as_ptr(),
            None => std::ptr::null(),
        };
        unsafe {
            let n = sys::notify_notification_new(summary.as_ptr(), body_ptr, icon_ptr);
            if n.is_null() {
                return Err(NotificationCreationError::Unknown);
            }

            Ok(Notification {
                handle: n,
                _phantom: PhantomData,
            })
        }
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            sys::notify_uninit();
        }
    }
}

/// A passive pop-up notification
pub struct Notification<'a> {
    handle: *mut sys::NotifyNotification,
    _phantom: PhantomData<&'a Context>,
}

impl<'a> Notification<'a> {
    /// Tells the notification server to display the notification
    /// on the screen.
    pub fn show(&'a self) -> Result<(), NotificationShowError> {
        unsafe {
            let mut err: *mut glib::GError = std::ptr::null_mut();
            sys::notify_notification_show(self.handle, &mut err);
            if !err.is_null() {
                let result = Err(NotificationShowError {
                    message: CStr::from_ptr((*err).message).to_string_lossy().into_owned(),
                });
                glib::g_error_free(err);
                return result;
            }
            return Ok(());
        }
    }
}

/// An error that can happen when attempting to show a notification.
#[derive(Debug)]
pub struct NotificationShowError {
    message: String,
}

impl fmt::Display for NotificationShowError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Error showing notification: {}", self.message)
    }
}

impl Error for NotificationShowError {
    fn description(&self) -> &str {
        "Notification show error"
    }
}
<|endoftext|>


<commit_before>extern crate regex;

use std::process::Command;
mod lsb_release;
mod windows_ver;
mod rhel_release;
mod utils;

///A list of supported operating system types
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Clone)]
pub enum OSType {
    Unknown,
    Redhat,
    OSX,
    Ubuntu,
    Debian,
    Windows,
    Arch,
    CentOS
}

fn is_windows() -> bool {
    if cfg!(target_os="windows") {
        return true;
    } else {
        return false;
    }
}

fn is_os_x() -> bool {
    match Command::new("sw_vers").output() {
        Ok(output) => output.status.success(),
        Err(_) => false
    }
}

fn lsb_release() -> OSType {
    match lsb_release::retrieve() {
        Some(release) => {
            if release.distro == Some("Ubuntu".to_string()) {
                OSType::Ubuntu
            }
            else if release.distro == Some("Debian".to_string()) {
                OSType::Debian
            } else if release.distro == Some("Arch".to_string()) {
                OSType::Arch
            }
            else if release.distro == Some("CentOS".to_string()){
                OSType::CentOS
            }
            else {
                OSType::Unknown
            }
        },
        None => OSType::Unknown
    }
}

fn rhel_release() -> OSType {
    match rhel_release::retrieve() {
        Some(release) => {
            if release.distro == Some("CentOS".to_string()) {
                OSType::CentOS
            } else {
                OSType::Redhat
            }
        },
        None => OSType::Unknown
    }
}

///Returns the current operating system type
///
///#Example
///
///```
///use os_type;
///let os = os_type::current_platform();
///```
pub fn current_platform() -> OSType {
    if is_os_x() {
        OSType::OSX
    }
    else if is_windows() {
        OSType::Windows
    }
    else if lsb_release::is_available() {
        lsb_release()
    }
    else if utils::file_exists("/etc/redhat-release") || utils::file_exists("/etc/centos-release") {
        rhel_release()
    }
    else {
        OSType::Unknown
    }
}
<commit_msg>feat: Return version with os type<commit_after>extern crate regex;

use std::process::Command;
mod lsb_release;
mod windows_ver;
mod rhel_release;
mod utils;

///A list of supported operating system types
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Clone)]
pub enum OSType {
    Unknown,
    Redhat,
    OSX,
    Ubuntu,
    Debian,
    Windows,
    Arch,
    CentOS
}

pub struct OSInformation {
    pub os_type: self::OSType,
    pub version: String
}

fn default_version() -> String {
    "0.0.0".into()
}

fn unknown_os() -> OSInformation {
    OSInformation {
        os_type: OSType::Unknown,
        version: default_version()
    }
}

fn is_windows() -> bool {
    if cfg!(target_os="windows") {
        return true;
    } else {
        return false;
    }
}

fn is_os_x() -> bool {
    match Command::new("sw_vers").output() {
        Ok(output) => output.status.success(),
        Err(_) => false
    }
}

fn lsb_release() -> OSInformation {
    match lsb_release::retrieve() {
        Some(release) => {
            if release.distro == Some("Ubuntu".to_string()) {
                OSInformation {
                    os_type: OSType::Ubuntu,
                    version: release.version.unwrap_or(default_version())
                }
            }
            else if release.distro == Some("Debian".to_string()) {
                OSInformation {
                    os_type: OSType::Debian,
                    version: release.version.unwrap_or(default_version())
                }
            } else if release.distro == Some("Arch".to_string()) {
                OSInformation {
                    os_type: OSType::Arch,
                    version: release.version.unwrap_or(default_version())
                }
            }
            else if release.distro == Some("CentOS".to_string()){
                OSInformation {
                    os_type: OSType::CentOS,
                    version: release.version.unwrap_or(default_version())
                }
            }
            else {
                unknown_os()
            }
        },
        None => unknown_os()
    }
}

fn rhel_release() -> OSInformation {
    match rhel_release::retrieve() {
        Some(release) => {
            if release.distro == Some("CentOS".to_string()) {
                OSInformation {
                    os_type: OSType::CentOS,
                    version: release.version.unwrap_or(default_version())
                }
            } else {
                OSInformation {
                    os_type: OSType::Redhat,
                    version: release.version.unwrap_or(default_version())
                }
            }
        },
        None => unknown_os()
    }
}

///Returns the current operating system type
///
///#Example
///
///```
///use os_type;
///let os = os_type::current_platform();
///```
pub fn current_platform() -> OSInformation {
    // if is_os_x() {
    //     OSType::OSX
    // }
    // else if is_windows() {
    //     OSType::Windows
    // }
    if lsb_release::is_available() {
        lsb_release()
    }
    else if utils::file_exists("/etc/redhat-release") || utils::file_exists("/etc/centos-release") {
        rhel_release()
    }
    else {
        unknown_os()
    }
}
<|endoftext|>


<commit_before>//! Open URLs in the web browsers available on a platform.
//!
//! Inspired by the [webbrowser](https://docs.python.org/2/library/webbrowser.html) python library.
//!
//! ## Examples
//!
//! ```no_run
//! use webbrowser;
//!
//! if webbrowser::open("http://github.com").is_ok() {
//!     // ...
//! }
//! ```
//!
//! ## Platform Support Status
//!
//! | Platform | Supported | Browsers | Test status |
//! |----------|-----------|----------|-------------|
//! | macos    | ✅        | default + [others](https://docs.rs/webbrowser/latest/webbrowser/enum.Browser.html) | ✅ |
//! | windows  | ✅        | default only | ✅ |
//! | linux/*bsd  | ✅     | default only (respects $BROWSER env var, so can be used with other browsers) | ✅ |
//! | android  | ✅        | default only | ✅ |
//! | wasm     | ✅        | default only | ✅ |
//! | haiku    | ✅ (experimental) | default only | ❌ |
//! | ios      | ❌        | unsupported | ❌ |
//!
//! ## Consistent Behaviour
//! `webbrowser` defines consistent behaviour on all platforms as follows:
//! * **Non-Blocking** for GUI based browsers (e.g. Firefox, Chrome etc.), while **Blocking** for text based browser (e.g. lynx etc.)
//! * **Suppressed output** by default for GUI based browsers, so that their stdout/stderr don't pollute the main program's output. This can be overridden by `webbrowser::open_browser_with_options`.

#[cfg_attr(target_os = "macos", path = "macos.rs")]
#[cfg_attr(target_os = "android", path = "android.rs")]
#[cfg_attr(target_arch = "wasm32", path = "wasm.rs")]
#[cfg_attr(windows, path = "windows.rs")]
#[cfg_attr(
    any(
        target_os = "linux",
        target_os = "freebsd",
        target_os = "netbsd",
        target_os = "openbsd",
        target_os = "haiku"
    ),
    path = "unix.rs"
)]
mod os;

#[cfg(not(any(
    target_os = "android",
    target_os = "windows",
    target_os = "macos",
    target_os = "linux",
    target_os = "freebsd",
    target_os = "netbsd",
    target_os = "openbsd",
    target_os = "haiku",
    target_arch = "wasm32"
)))]
compile_error!("Only Windows, Mac OS, Linux, *BSD and Haiku and Wasm32 are currently supported");

use std::default::Default;
use std::io::{Error, ErrorKind, Result};
use std::str::FromStr;
use std::{error, fmt};

#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
/// Browser types available
pub enum Browser {
    ///Operating system's default browser
    Default,

    ///Mozilla Firefox
    Firefox,

    ///Microsoft's Internet Explorer
    InternetExplorer,

    ///Google Chrome
    Chrome,

    ///Opera
    Opera,

    ///Mac OS Safari
    Safari,

    ///Haiku's WebPositive
    WebPositive,
}

///The Error type for parsing a string into a Browser.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
pub struct ParseBrowserError;

impl fmt::Display for ParseBrowserError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("Invalid browser given")
    }
}

impl error::Error for ParseBrowserError {
    fn description(&self) -> &str {
        "invalid browser"
    }
}

impl Default for Browser {
    fn default() -> Self {
        Browser::Default
    }
}

impl fmt::Display for Browser {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Browser::Default => f.write_str("Default"),
            Browser::Firefox => f.write_str("Firefox"),
            Browser::InternetExplorer => f.write_str("Internet Explorer"),
            Browser::Chrome => f.write_str("Chrome"),
            Browser::Opera => f.write_str("Opera"),
            Browser::Safari => f.write_str("Safari"),
            Browser::WebPositive => f.write_str("WebPositive"),
        }
    }
}

impl FromStr for Browser {
    type Err = ParseBrowserError;

    fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
        match s {
            "firefox" => Ok(Browser::Firefox),
            "default" => Ok(Browser::Default),
            "ie" | "internet explorer" | "internetexplorer" => Ok(Browser::InternetExplorer),
            "chrome" => Ok(Browser::Chrome),
            "opera" => Ok(Browser::Opera),
            "safari" => Ok(Browser::Safari),
            "webpositive" => Ok(Browser::WebPositive),
            _ => Err(ParseBrowserError),
        }
    }
}

#[derive(Debug, Eq, PartialEq, Clone, Hash)]
/// BrowserOptions to override certain default behaviour
///
/// e.g. by default, we suppress stdout/stderr, but that behaviour can be overridden here
pub struct BrowserOptions {
    pub suppress_output: bool,
    pub target_hint: String,
}

impl fmt::Display for BrowserOptions {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_fmt(format_args!(
            "BrowserOptions(supress_output={}, target_hint={})",
            self.suppress_output, self.target_hint,
        ))
    }
}

impl std::default::Default for BrowserOptions {
    fn default() -> Self {
        let target_hint = String::from(option_env!("WEBBROWSER_WASM_TARGET").unwrap_or("_blank"));
        BrowserOptions {
            suppress_output: true,
            target_hint,
        }
    }
}

impl BrowserOptions {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn with_suppress_output<'a>(&'a mut self, suppress_output: bool) -> &'a mut Self {
        self.suppress_output = suppress_output;
        self
    }

    pub fn with_target_hint<'a>(&'a mut self, target_hint: &str) -> &'a mut Self {
        self.target_hint = target_hint.to_owned();
        self
    }
}

/// Opens the URL on the default browser of this platform
///
/// Returns Ok(..) so long as the browser invocation was successful. An Err(..) is returned only if
/// there was an error in running the command, or if the browser was not found.
///
/// Equivalent to:
/// ```no_run
/// # use webbrowser::{Browser, open_browser};
/// # let url = "http://example.com";
/// open_browser(Browser::Default, url);
/// ```
///
/// # Examples
/// ```no_run
/// use webbrowser;
///
/// if webbrowser::open("http://github.com").is_ok() {
///     // ...
/// }
/// ```
pub fn open(url: &str) -> Result<()> {
    open_browser(Browser::Default, url)
}

/// Opens the specified URL on the specific browser (if available) requested. Return semantics are
/// the same as for [open](fn.open.html).
///
/// # Examples
/// ```no_run
/// use webbrowser::{open_browser, Browser};
///
/// if open_browser(Browser::Firefox, "http://github.com").is_ok() {
///     // ...
/// }
/// ```
pub fn open_browser(browser: Browser, url: &str) -> Result<()> {
    open_browser_with_options(browser, url, &BrowserOptions::default())
}

/// Opens the specified URL on the specific browser (if available) requested, while overriding the
/// default options.
///
/// Return semantics are
/// the same as for [open](fn.open.html).
///
/// # Examples
/// ```no_run
/// use webbrowser::{open_browser_with_options, Browser, BrowserOptions};
///
/// if open_browser_with_options(Browser::Default, "http://github.com", BrowserOptions::new().with_suppress_output(false)).is_ok() {
///     // ...
/// }
/// ```
pub fn open_browser_with_options(
    browser: Browser,
    url: &str,
    options: &BrowserOptions,
) -> Result<()> {
    let url_s: String = match url::Url::parse(url) {
        Ok(u) => u.as_str().into(),
        Err(_) => url.into(),
    };
    os::open_browser_internal(browser, &url_s, options)
}

#[test]
#[ignore]
fn test_open_firefox() {
    assert!(open_browser(Browser::Firefox, "http://github.com").is_ok());
}

#[test]
#[ignore]
fn test_open_chrome() {
    assert!(open_browser(Browser::Chrome, "http://github.com").is_ok());
}

#[test]
#[ignore]
fn test_open_safari() {
    assert!(open_browser(Browser::Safari, "http://github.com").is_ok());
}

#[test]
#[ignore]
fn test_open_webpositive() {
    assert!(open_browser(Browser::WebPositive, "http://github.com").is_ok());
}
<commit_msg>fix linter error<commit_after>//! Open URLs in the web browsers available on a platform.
//!
//! Inspired by the [webbrowser](https://docs.python.org/2/library/webbrowser.html) python library.
//!
//! ## Examples
//!
//! ```no_run
//! use webbrowser;
//!
//! if webbrowser::open("http://github.com").is_ok() {
//!     // ...
//! }
//! ```
//!
//! ## Platform Support Status
//!
//! | Platform | Supported | Browsers | Test status |
//! |----------|-----------|----------|-------------|
//! | macos    | ✅        | default + [others](https://docs.rs/webbrowser/latest/webbrowser/enum.Browser.html) | ✅ |
//! | windows  | ✅        | default only | ✅ |
//! | linux/*bsd  | ✅     | default only (respects $BROWSER env var, so can be used with other browsers) | ✅ |
//! | android  | ✅        | default only | ✅ |
//! | wasm     | ✅        | default only | ✅ |
//! | haiku    | ✅ (experimental) | default only | ❌ |
//! | ios      | ❌        | unsupported | ❌ |
//!
//! ## Consistent Behaviour
//! `webbrowser` defines consistent behaviour on all platforms as follows:
//! * **Non-Blocking** for GUI based browsers (e.g. Firefox, Chrome etc.), while **Blocking** for text based browser (e.g. lynx etc.)
//! * **Suppressed output** by default for GUI based browsers, so that their stdout/stderr don't pollute the main program's output. This can be overridden by `webbrowser::open_browser_with_options`.

#[cfg_attr(target_os = "macos", path = "macos.rs")]
#[cfg_attr(target_os = "android", path = "android.rs")]
#[cfg_attr(target_arch = "wasm32", path = "wasm.rs")]
#[cfg_attr(windows, path = "windows.rs")]
#[cfg_attr(
    any(
        target_os = "linux",
        target_os = "freebsd",
        target_os = "netbsd",
        target_os = "openbsd",
        target_os = "haiku"
    ),
    path = "unix.rs"
)]
mod os;

#[cfg(not(any(
    target_os = "android",
    target_os = "windows",
    target_os = "macos",
    target_os = "linux",
    target_os = "freebsd",
    target_os = "netbsd",
    target_os = "openbsd",
    target_os = "haiku",
    target_arch = "wasm32"
)))]
compile_error!("Only Windows, Mac OS, Linux, *BSD and Haiku and Wasm32 are currently supported");

use std::default::Default;
use std::io::{Error, ErrorKind, Result};
use std::str::FromStr;
use std::{error, fmt};

#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
/// Browser types available
pub enum Browser {
    ///Operating system's default browser
    Default,

    ///Mozilla Firefox
    Firefox,

    ///Microsoft's Internet Explorer
    InternetExplorer,

    ///Google Chrome
    Chrome,

    ///Opera
    Opera,

    ///Mac OS Safari
    Safari,

    ///Haiku's WebPositive
    WebPositive,
}

///The Error type for parsing a string into a Browser.
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
pub struct ParseBrowserError;

impl fmt::Display for ParseBrowserError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("Invalid browser given")
    }
}

impl error::Error for ParseBrowserError {
    fn description(&self) -> &str {
        "invalid browser"
    }
}

impl Default for Browser {
    fn default() -> Self {
        Browser::Default
    }
}

impl fmt::Display for Browser {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Browser::Default => f.write_str("Default"),
            Browser::Firefox => f.write_str("Firefox"),
            Browser::InternetExplorer => f.write_str("Internet Explorer"),
            Browser::Chrome => f.write_str("Chrome"),
            Browser::Opera => f.write_str("Opera"),
            Browser::Safari => f.write_str("Safari"),
            Browser::WebPositive => f.write_str("WebPositive"),
        }
    }
}

impl FromStr for Browser {
    type Err = ParseBrowserError;

    fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
        match s {
            "firefox" => Ok(Browser::Firefox),
            "default" => Ok(Browser::Default),
            "ie" | "internet explorer" | "internetexplorer" => Ok(Browser::InternetExplorer),
            "chrome" => Ok(Browser::Chrome),
            "opera" => Ok(Browser::Opera),
            "safari" => Ok(Browser::Safari),
            "webpositive" => Ok(Browser::WebPositive),
            _ => Err(ParseBrowserError),
        }
    }
}

#[derive(Debug, Eq, PartialEq, Clone, Hash)]
/// BrowserOptions to override certain default behaviour
///
/// e.g. by default, we suppress stdout/stderr, but that behaviour can be overridden here
pub struct BrowserOptions {
    pub suppress_output: bool,
    pub target_hint: String,
}

impl fmt::Display for BrowserOptions {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_fmt(format_args!(
            "BrowserOptions(supress_output={}, target_hint={})",
            self.suppress_output, self.target_hint,
        ))
    }
}

impl std::default::Default for BrowserOptions {
    fn default() -> Self {
        let target_hint = String::from(option_env!("WEBBROWSER_WASM_TARGET").unwrap_or("_blank"));
        BrowserOptions {
            suppress_output: true,
            target_hint,
        }
    }
}

impl BrowserOptions {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn with_suppress_output(&mut self, suppress_output: bool) -> &mut Self {
        self.suppress_output = suppress_output;
        self
    }

    pub fn with_target_hint(&mut self, target_hint: &str) -> &mut Self {
        self.target_hint = target_hint.to_owned();
        self
    }
}

/// Opens the URL on the default browser of this platform
///
/// Returns Ok(..) so long as the browser invocation was successful. An Err(..) is returned only if
/// there was an error in running the command, or if the browser was not found.
///
/// Equivalent to:
/// ```no_run
/// # use webbrowser::{Browser, open_browser};
/// # let url = "http://example.com";
/// open_browser(Browser::Default, url);
/// ```
///
/// # Examples
/// ```no_run
/// use webbrowser;
///
/// if webbrowser::open("http://github.com").is_ok() {
///     // ...
/// }
/// ```
pub fn open(url: &str) -> Result<()> {
    open_browser(Browser::Default, url)
}

/// Opens the specified URL on the specific browser (if available) requested. Return semantics are
/// the same as for [open](fn.open.html).
///
/// # Examples
/// ```no_run
/// use webbrowser::{open_browser, Browser};
///
/// if open_browser(Browser::Firefox, "http://github.com").is_ok() {
///     // ...
/// }
/// ```
pub fn open_browser(browser: Browser, url: &str) -> Result<()> {
    open_browser_with_options(browser, url, &BrowserOptions::default())
}

/// Opens the specified URL on the specific browser (if available) requested, while overriding the
/// default options.
///
/// Return semantics are
/// the same as for [open](fn.open.html).
///
/// # Examples
/// ```no_run
/// use webbrowser::{open_browser_with_options, Browser, BrowserOptions};
///
/// if open_browser_with_options(Browser::Default, "http://github.com", BrowserOptions::new().with_suppress_output(false)).is_ok() {
///     // ...
/// }
/// ```
pub fn open_browser_with_options(
    browser: Browser,
    url: &str,
    options: &BrowserOptions,
) -> Result<()> {
    let url_s: String = match url::Url::parse(url) {
        Ok(u) => u.as_str().into(),
        Err(_) => url.into(),
    };
    os::open_browser_internal(browser, &url_s, options)
}

#[test]
#[ignore]
fn test_open_firefox() {
    assert!(open_browser(Browser::Firefox, "http://github.com").is_ok());
}

#[test]
#[ignore]
fn test_open_chrome() {
    assert!(open_browser(Browser::Chrome, "http://github.com").is_ok());
}

#[test]
#[ignore]
fn test_open_safari() {
    assert!(open_browser(Browser::Safari, "http://github.com").is_ok());
}

#[test]
#[ignore]
fn test_open_webpositive() {
    assert!(open_browser(Browser::WebPositive, "http://github.com").is_ok());
}
<|endoftext|>


<commit_before>#![feature(zero_one)]
#![feature(const_fn)]
#![no_std]

#[cfg(test)]
mod tests;

use core::mem::size_of;

#[derive(Debug, Clone, Copy)]
pub struct BitField<T: Number>(T);

impl<T> BitField<T>
    where T: Number
{
    pub const fn new(value: T) -> BitField<T> {
        BitField(value)
    }

    pub fn get_bit(&self, bit: u8) -> bool {
        assert!(bit < self.length());
        self.get_range(bit..(bit + 1)) == T::one()
    }

    pub fn get_range(&self, range: Range<u8>) -> T {
        assert!(range.start < self.length());
        assert!(range.end <= self.length());
        assert!(range.start < range.end);

        // shift away high bits
        let bits = self.0 << (self.length() - range.end) >> (self.length() - range.end);

        // shift away low bits
        bits >> range.start
    }

    pub fn set_bit(&mut self, bit: u8, value: bool) {
        assert!(bit < self.length());
        if value {
            self.0 |= T::one() << bit;
        } else {
            self.0 &= !(T::one() << bit);
        }
    }

    pub fn set_range(&mut self, range: Range<u8>, value: T) {
        assert!(range.start < self.length());
        assert!(range.end <= self.length());
        assert!(range.start < range.end);
        assert!(value << (self.length() - (range.end - range.start)) >>
                (self.length() - (range.end - range.start)) == value,
                "value too big");

        let bitmask: T = !(!T::zero() << (self.length() - range.end) >>
                           (self.length() - range.end) >>
                           range.start << range.start);

        let bits = self.0 & bitmask;
        // set bits
        self.0 = bits | (value << range.start);
    }

    fn length(&self) -> u8 {
        size_of::<T>() as u8 * 8
    }
}

use core::ops::{Range, Shl, Shr, BitAnd, BitOr, BitOrAssign, BitAndAssign, Not};
use core::num::{Zero, One};
use core::fmt::Debug;

pub trait Number: Debug + Copy + Eq + Zero + One +
    Not<Output=Self> + Shl<u8, Output=Self> + Shr<u8, Output=Self> +
    BitAnd<Self, Output=Self> + BitOr<Self, Output=Self>  + BitAndAssign + BitOrAssign {}

impl Number for u8 {}
impl Number for u16 {}
impl Number for u32 {}
impl Number for u64 {}
impl Number for usize {}
<commit_msg>Return Self on set_bit and set_range for method chaining<commit_after>#![feature(zero_one)]
#![feature(const_fn)]
#![no_std]

#[cfg(test)]
mod tests;

use core::mem::size_of;

#[derive(Debug, Clone, Copy)]
pub struct BitField<T: Number>(T);

impl<T> BitField<T>
    where T: Number
{
    pub const fn new(value: T) -> BitField<T> {
        BitField(value)
    }

    pub fn get_bit(&self, bit: u8) -> bool {
        assert!(bit < self.length());
        self.get_range(bit..(bit + 1)) == T::one()
    }

    pub fn get_range(&self, range: Range<u8>) -> T {
        assert!(range.start < self.length());
        assert!(range.end <= self.length());
        assert!(range.start < range.end);

        // shift away high bits
        let bits = self.0 << (self.length() - range.end) >> (self.length() - range.end);

        // shift away low bits
        bits >> range.start
    }

    pub fn set_bit(&mut self, bit: u8, value: bool) -> Self {
        assert!(bit < self.length());
        if value {
            self.0 |= T::one() << bit;
        } else {
            self.0 &= !(T::one() << bit);
        }
        *self
    }

    pub fn set_range(&mut self, range: Range<u8>, value: T) -> Self {
        assert!(range.start < self.length());
        assert!(range.end <= self.length());
        assert!(range.start < range.end);
        assert!(value << (self.length() - (range.end - range.start)) >>
                (self.length() - (range.end - range.start)) == value,
                "value too big");

        let bitmask: T = !(!T::zero() << (self.length() - range.end) >>
                           (self.length() - range.end) >>
                           range.start << range.start);

        let bits = self.0 & bitmask;
        // set bits
        self.0 = bits | (value << range.start);

        *self
    }

    fn length(&self) -> u8 {
        size_of::<T>() as u8 * 8
    }
}

use core::ops::{Range, Shl, Shr, BitAnd, BitOr, BitOrAssign, BitAndAssign, Not};
use core::num::{Zero, One};
use core::fmt::Debug;

pub trait Number: Debug + Copy + Eq + Zero + One +
    Not<Output=Self> + Shl<u8, Output=Self> + Shr<u8, Output=Self> +
    BitAnd<Self, Output=Self> + BitOr<Self, Output=Self>  + BitAndAssign + BitOrAssign {}

impl Number for u8 {}
impl Number for u16 {}
impl Number for u32 {}
impl Number for u64 {}
impl Number for usize {}
<|endoftext|>