<commit_before>use std::collections::LinkedList;
use std::borrow::Borrow;

use token::Token;

use std::cell::Cell;
use std::rc::Rc;
use regex::Regex;
use context::Context;
use token::Posn;

pub trait ESCharExt {
    fn is_es_newline(self) -> bool;
    fn is_es_whitespace(self) -> bool;
    fn is_es_identifier(self) -> bool;
    fn is_es_identifier_start(self) -> bool;
    fn is_es_identifier_continue(self) -> bool;
}

/*
// https://github.com/ariya/esprima/blob/master/tools/generate-identifier-regex.js
// https://gist.github.com/mathiasbynens/6334847
// http://unicode.org/reports/tr31/

pub trait UnicodeCharExt {
    fn is_L(self) -> bool;
    fn is_Lu(self) -> bool;
    fn is_Ll(self) -> bool;
    fn is_Lt(self) -> bool;
    fn is_Lm(self) -> bool;
    fn is_Lo(self) -> bool;
    fn is_Nl(self) -> bool;
    fn is_OtherID_Start(self) -> bool;
}

impl UnicodeCharExt for char {
    fn is_L(self) -> bool {
        self.is_Lu() ||
        self.is_Ll() ||
        self.is_Lt() ||
        self.is_Lm() ||
        self.is_Lo()
    }

    fn is_Lu(self) -> bool {
        false
    }

    fn is_Ll(self) -> bool {
        false
    }

    fn is_Lt(self) -> bool {
        false
    }

    fn is_Lm(self) -> bool {
        false
    }

    fn is_Lo(self) -> bool {
        false
    }

    fn is_Nl(self) -> bool {
        false
    }

    fn is_OtherID_Start(self) -> bool {
        false
    }
}
*/

impl ESCharExt for char {
    fn is_es_newline(self) -> bool {
        match self {
            '\u{000a}' | '\u{000d}' | '\u{2028}' | '\u{2029}' => true,
            _ => false
        }
    }

    fn is_es_whitespace(self) -> bool {
        match self {
              '\u{0009}' | '\u{000b}' | '\u{000c}' | '\u{0020}' | '\u{00a0}'
            | '\u{1680}' | '\u{2000}' | '\u{2001}' | '\u{2002}' | '\u{2003}' | '\u{2004}'
            | '\u{2005}' | '\u{2006}' | '\u{2009}' | '\u{200a}' | '\u{202f}' | '\u{205f}'
            | '\u{3000}' | '\u{feff}' => true,
            _ => false
        }
    }

    fn is_es_identifier(self) -> bool {
        self.is_es_identifier_continue()
    }

    fn is_es_identifier_start(self) -> bool {
        self == '$' ||
        self == '_' ||
        self.is_alphabetic()
    }

    fn is_es_identifier_continue(self) -> bool {
        self.is_es_identifier_start() ||
        self.is_numeric()
    }
}

struct LineOrientedReader<I> {
    chars: I,
    curr_char: Option<char>,
    next_char: Option<char>,
    curr_posn: Posn
}

impl<I> LineOrientedReader<I> where I: Iterator<Item=char> {
    pub fn new(mut chars: I) -> LineOrientedReader<I> {
        let curr_char = chars.next();
        let next_char = if curr_char.is_some() { chars.next() } else { None };
        LineOrientedReader {
            chars: chars,
            curr_char: curr_char,
            next_char: next_char,
            curr_posn: Posn {
                offset: 0,
                line: 0,
                column: 0
            }
        }
    }

    pub fn curr_char(&mut self) -> Option<char> { self.curr_char }
    pub fn curr_posn(&mut self) -> Posn { self.curr_posn }
    pub fn next_char(&mut self) -> Option<char> { self.next_char }

    pub fn bump(&mut self) {
        let curr_char = self.next_char;
        let next_char = if curr_char.is_some() { self.chars.next() } else { None };

        self.curr_char = curr_char;
        self.next_char = next_char;

        if (curr_char == Some('\r') && next_char != Some('\n')) ||
           curr_char == Some('\n') ||
           curr_char == Some('\u{2028}') ||
           curr_char == Some('\u{2029}') {
            self.curr_posn.line += 1;
            self.curr_posn.column = 0;
        } else {
            self.curr_posn.column += 1;
        }

        self.curr_posn.offset += 1;
    }
}

// test case: x=0;y=g=1;alert(eval("while(x)break\n/y/g.exec('y')"))
//       see: https://groups.google.com/d/msg/mozilla.dev.tech.js-engine.internals/2JLH5jRcr7E/Mxc7ZKc5r6sJ

struct TokenBuffer {
    tokens: LinkedList<Token>
}

impl TokenBuffer {
    fn new() -> TokenBuffer {
        TokenBuffer {
            tokens: LinkedList::new()
        }
    }

    fn is_empty(&mut self) -> bool {
        self.tokens.len() == 0
    }

    fn push_token(&mut self, token: Token) {
        assert!(self.tokens.len() == 0);
        self.tokens.push_back(token);
    }

    fn read_token(&mut self) -> Token {
        assert!(self.tokens.len() > 0);
        self.tokens.pop_front().unwrap()
    }

    fn peek_token(&mut self) -> &Token {
        assert!(self.tokens.len() > 0);
        self.tokens.front().unwrap()
    }

    fn unread_token(&mut self, token: Token) {
        assert!(self.tokens.len() >= 0);
        assert!(self.tokens.len() < 3);
        self.tokens.push_front(token);
    }
}

pub struct Lexer<I> {
    reader: LineOrientedReader<I>,
    cx: Rc<Cell<Context>>,
    lookahead: TokenBuffer
}

impl<I> Lexer<I> where I: Iterator<Item=char> {
    // constructor

    pub fn new(chars: I, cx: Rc<Cell<Context>>) -> Lexer<I> {
        Lexer {
            reader: LineOrientedReader::new(chars),
            cx: cx,
            lookahead: TokenBuffer::new()
        }
    }

    // public methods

    pub fn peek_token(&mut self) -> &Token {
        if self.lookahead.is_empty() {
            let token = self.read_next_token();
            self.lookahead.push_token(token);
        }
        self.lookahead.peek_token()
    }

    pub fn read_token(&mut self) -> Token {
        if self.lookahead.is_empty() {
            self.read_next_token()
        } else {
            self.lookahead.read_token()
        }
    }

    pub fn unread_token(&mut self, token: Token) {
        self.lookahead.unread_token(token);
    }

    // private methods

    fn skip_line_comment(&mut self) {
    }

    fn skip_block_comment(&mut self) {
    }

    fn div_or_regexp(&mut self) -> Token {
        if self.cx.get().is_operator() {
            self.reader.bump();
            Token::Slash
        } else {
            unimplemented!()
        }
    }

    fn if_assign(&mut self, cons: Token, alt: Token) -> Token {
        self.reader.bump();
        if self.reader.curr_char() == Some('=') { self.reader.bump(); cons } else { alt }
    }

    fn lt(&mut self) -> Token { unimplemented!() }
    fn gt(&mut self) -> Token { unimplemented!() }
    fn eq(&mut self) -> Token { unimplemented!() }

    fn plus(&mut self) -> Token {
        self.bump();
        match self.reader.curr_char() {
            Some('+') => { self.bump(); Token::Inc },
            Some('=') => { self.bump(); Token::PlusAssign },
            _ => Token::Plus
        }
    }

    fn minus(&mut self) -> Token { unimplemented!() }
    fn bang(&mut self) -> Token { unimplemented!() }

    fn number(&mut self) -> Token {
        if self.reader.curr_char() == Some('1') {
            self.bump();
            return Token::DecimalInt(String::from_str("1"));
        }
        unimplemented!()
    }

    fn string(&mut self) -> Token { unimplemented!() }
    fn word(&mut self) -> Token { unimplemented!() }

    fn read_next_token(&mut self) -> Token {
        self.skip_whitespace();
        println!("inspecting {:?}", self.reader.curr_char());
        loop {
            match self.reader.curr_char() {
                Some('/') => {
                    match self.reader.next_char() {
                        Some('/') => self.skip_line_comment(),
                        Some('*') => self.skip_block_comment(),
                        _ => return self.div_or_regexp()
                    }
                },
                Some('.') => {
                    match self.reader.next_char() {
                        Some(ch) if ch.is_digit(10) => { return self.number() },
                        _ => { self.reader.bump(); return Token::Dot }
                    }
                }
                Some('{') => { self.bump(); return Token::LBrace },
                Some('}') => { self.bump(); return Token::RBrace },
                Some('[') => { self.bump(); return Token::LBrack },
                Some(']') => { self.bump(); return Token::RBrack },
                Some('(') => { self.bump(); return Token::LParen },
                Some(')') => { self.bump(); return Token::RParen },
                Some(';') => { self.bump(); return Token::Semi },
                Some(':') => { self.bump(); return Token::Colon },
                Some(',') => { self.bump(); return Token::Comma },
                Some('<') => return self.lt(),
                Some('>') => return self.gt(),
                Some('=') => return self.eq(),
                Some('+') => return self.plus(),
                Some('-') => return self.minus(),
                Some('*') => return self.if_assign(Token::StarAssign, Token::Star),
                Some('%') => return self.if_assign(Token::ModAssign, Token::Mod),
                Some('^') => return self.if_assign(Token::BitXorAssign, Token::BitXor),
                Some('&') => {
                    self.bump();
                    match self.reader.curr_char() {
                        Some('&') => { self.bump(); return Token::LogicalAnd },
                        _ => return Token::BitAnd
                    }
                },
                Some('|') => {
                    self.bump();
                    match self.reader.curr_char() {
                        Some('|') => { self.bump(); return Token::LogicalOr },
                        _ => return Token::BitOr
                    }
                },
                Some('~') => { self.bump(); return Token::Tilde },
                Some('!') => return self.bang(),
                Some('?') => { self.bump(); return Token::Question },
                Some('"') => return self.string(),
                Some('\'') => return self.string(),
                Some('\r') => {
                    self.bump();
                    if self.reader.curr_char() == Some('\n') {
                        self.bump();
                    }
                    if self.cx.get().is_asi_possible() {
                        return Token::Newline;
                    }
                },
                Some(ch) if ch.is_es_newline() => {
                    self.bump();
                    if self.cx.get().is_asi_possible() {
                        return Token::Newline;
                    }
                }
                Some(ch) if ch.is_digit(10) => return self.number(),
                Some(ch) if ch.is_es_identifier() => return self.word(),
                Some(ch) => return Token::Error(ch),
                None => return Token::EOF
            }
        }
    }

    fn is_whitespace(&mut self) -> bool {
        match self.reader.curr_char() {
            Some(ch) => ch.is_es_whitespace(),
            None => false
        }
    }

    fn bump(&mut self) {
        self.reader.bump();
    }

    fn eat(&mut self) -> Option<char> {
        let ch = self.reader.curr_char();
        self.bump();
        ch
    }

    fn skip_whitespace(&mut self) {
        while self.is_whitespace() {
            self.reader.bump();
        }
    }
}

impl<I> Iterator for Lexer<I> where I: Iterator<Item=char> {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        match self.read_token() {
            Token::EOF => None,
            t => Some(t)
        }
    }
}
<commit_msg>implementing easy cases in lexer, bug in line comments -- need to deal with Option src/lexer.rs:241:39: 241:54 error: type `core::option::Option<char>` does not implement any method in scope named `is_es_newline` src/lexer.rs:241         while self.reader.curr_char().is_es_newline() {                                                        ^~~~~~~~~~~~~~~ src/lexer.rs:241:54: 241:54 help: methods from traits can only be called if the trait is implemented and in scope; the following trait defines a method `is_es_newline`, perhaps you need to implement it: src/lexer.rs:241:54: 241:54 help: candidate #1: `lexer::ESCharExt`<commit_after>use std::collections::LinkedList;
use std::borrow::Borrow;

use token::Token;

use std::cell::Cell;
use std::rc::Rc;
use regex::Regex;
use context::Context;
use token::Posn;

pub trait ESCharExt {
    fn is_es_newline(self) -> bool;
    fn is_es_whitespace(self) -> bool;
    fn is_es_identifier(self) -> bool;
    fn is_es_identifier_start(self) -> bool;
    fn is_es_identifier_continue(self) -> bool;
}

/*
// https://github.com/ariya/esprima/blob/master/tools/generate-identifier-regex.js
// https://gist.github.com/mathiasbynens/6334847
// http://unicode.org/reports/tr31/

pub trait UnicodeCharExt {
    fn is_L(self) -> bool;
    fn is_Lu(self) -> bool;
    fn is_Ll(self) -> bool;
    fn is_Lt(self) -> bool;
    fn is_Lm(self) -> bool;
    fn is_Lo(self) -> bool;
    fn is_Nl(self) -> bool;
    fn is_OtherID_Start(self) -> bool;
}

impl UnicodeCharExt for char {
    fn is_L(self) -> bool {
        self.is_Lu() ||
        self.is_Ll() ||
        self.is_Lt() ||
        self.is_Lm() ||
        self.is_Lo()
    }

    fn is_Lu(self) -> bool {
        false
    }

    fn is_Ll(self) -> bool {
        false
    }

    fn is_Lt(self) -> bool {
        false
    }

    fn is_Lm(self) -> bool {
        false
    }

    fn is_Lo(self) -> bool {
        false
    }

    fn is_Nl(self) -> bool {
        false
    }

    fn is_OtherID_Start(self) -> bool {
        false
    }
}
*/

impl ESCharExt for char {
    fn is_es_newline(self) -> bool {
        match self {
            '\u{000a}' | '\u{000d}' | '\u{2028}' | '\u{2029}' => true,
            _ => false
        }
    }

    fn is_es_whitespace(self) -> bool {
        match self {
              '\u{0009}' | '\u{000b}' | '\u{000c}' | '\u{0020}' | '\u{00a0}'
            | '\u{1680}' | '\u{2000}' | '\u{2001}' | '\u{2002}' | '\u{2003}' | '\u{2004}'
            | '\u{2005}' | '\u{2006}' | '\u{2009}' | '\u{200a}' | '\u{202f}' | '\u{205f}'
            | '\u{3000}' | '\u{feff}' => true,
            _ => false
        }
    }

    fn is_es_identifier(self) -> bool {
        self.is_es_identifier_continue()
    }

    fn is_es_identifier_start(self) -> bool {
        self == '$' ||
        self == '_' ||
        self.is_alphabetic()
    }

    fn is_es_identifier_continue(self) -> bool {
        self.is_es_identifier_start() ||
        self.is_numeric()
    }
}

struct LineOrientedReader<I> {
    chars: I,
    curr_char: Option<char>,
    next_char: Option<char>,
    curr_posn: Posn
}

impl<I> LineOrientedReader<I> where I: Iterator<Item=char> {
    pub fn new(mut chars: I) -> LineOrientedReader<I> {
        let curr_char = chars.next();
        let next_char = if curr_char.is_some() { chars.next() } else { None };
        LineOrientedReader {
            chars: chars,
            curr_char: curr_char,
            next_char: next_char,
            curr_posn: Posn {
                offset: 0,
                line: 0,
                column: 0
            }
        }
    }

    pub fn curr_char(&mut self) -> Option<char> { self.curr_char }
    pub fn curr_posn(&mut self) -> Posn { self.curr_posn }
    pub fn next_char(&mut self) -> Option<char> { self.next_char }

    pub fn bump(&mut self) {
        let curr_char = self.next_char;
        let next_char = if curr_char.is_some() { self.chars.next() } else { None };

        self.curr_char = curr_char;
        self.next_char = next_char;

        if (curr_char == Some('\r') && next_char != Some('\n')) ||
           curr_char == Some('\n') ||
           curr_char == Some('\u{2028}') ||
           curr_char == Some('\u{2029}') {
            self.curr_posn.line += 1;
            self.curr_posn.column = 0;
        } else {
            self.curr_posn.column += 1;
        }

        self.curr_posn.offset += 1;
    }
}

// test case: x=0;y=g=1;alert(eval("while(x)break\n/y/g.exec('y')"))
//       see: https://groups.google.com/d/msg/mozilla.dev.tech.js-engine.internals/2JLH5jRcr7E/Mxc7ZKc5r6sJ

struct TokenBuffer {
    tokens: LinkedList<Token>
}

impl TokenBuffer {
    fn new() -> TokenBuffer {
        TokenBuffer {
            tokens: LinkedList::new()
        }
    }

    fn is_empty(&mut self) -> bool {
        self.tokens.len() == 0
    }

    fn push_token(&mut self, token: Token) {
        assert!(self.tokens.len() == 0);
        self.tokens.push_back(token);
    }

    fn read_token(&mut self) -> Token {
        assert!(self.tokens.len() > 0);
        self.tokens.pop_front().unwrap()
    }

    fn peek_token(&mut self) -> &Token {
        assert!(self.tokens.len() > 0);
        self.tokens.front().unwrap()
    }

    fn unread_token(&mut self, token: Token) {
        assert!(self.tokens.len() >= 0);
        assert!(self.tokens.len() < 3);
        self.tokens.push_front(token);
    }
}

pub struct Lexer<I> {
    reader: LineOrientedReader<I>,
    cx: Rc<Cell<Context>>,
    lookahead: TokenBuffer
}

impl<I> Lexer<I> where I: Iterator<Item=char> {
    // constructor

    pub fn new(chars: I, cx: Rc<Cell<Context>>) -> Lexer<I> {
        Lexer {
            reader: LineOrientedReader::new(chars),
            cx: cx,
            lookahead: TokenBuffer::new()
        }
    }

    // public methods

    pub fn peek_token(&mut self) -> &Token {
        if self.lookahead.is_empty() {
            let token = self.read_next_token();
            self.lookahead.push_token(token);
        }
        self.lookahead.peek_token()
    }

    pub fn read_token(&mut self) -> Token {
        if self.lookahead.is_empty() {
            self.read_next_token()
        } else {
            self.lookahead.read_token()
        }
    }

    pub fn unread_token(&mut self, token: Token) {
        self.lookahead.unread_token(token);
    }

    // private methods

    fn skip_line_comment(&mut self) {
        self.bump();
        self.bump();
        while self.reader.curr_char().is_es_newline() {
            self.bump();
        }
    }

    fn skip_block_comment(&mut self) {
    }

    fn div_or_regexp(&mut self) -> Token {
        if self.cx.get().is_operator() {
            self.reader.bump();
            Token::Slash
        } else {
            unimplemented!()
        }
    }

    fn if_assign(&mut self, cons: Token, alt: Token) -> Token {
        self.reader.bump();
        if self.reader.curr_char() == Some('=') { self.reader.bump(); cons } else { alt }
    }

    fn if_equality(&mut self, zero: Token, one: Token, two: Token) -> Token {
        self.bump();
        if self.reader.curr_char() == Some('=') {
            self.bump();
            if self.reader.curr_char() == Some('=') {
                self.bump();
                two
            } else {
                one
            }
        } else {
            zero
        }
    }

    fn lt(&mut self) -> Token {
        self.bump();
        match self.reader.curr_char() {
            Some('<') => {
                self.bump();
                if self.reader.curr_char() == Some('=') {
                    self.bump();
                    Token::LShiftAssign
                } else {
                    Token::LShift
                }
            },
            Some('=') => { self.bump(); Token::LEq }
            _ => Token::LAngle
        }
    }

    fn gt(&mut self) -> Token {
        self.bump();
        match self.reader.curr_char() {
            Some('>') => {
                self.bump();
                match self.reader.curr_char() {
                    Some('>') => {
                        self.bump();
                        if self.reader.curr_char() == Some('=') {
                            self.bump();
                            Token::URShiftAssign
                        } else {
                            Token::URShift
                        }
                    },
                    Some('=') => { self.bump(); Token::RShiftAssign },
                    _ => Token::RShift
                }
            },
            Some('=') => { self.bump(); Token::GEq },
            _ => Token::RAngle
        }
    }

    fn plus(&mut self) -> Token {
        self.bump();
        match self.reader.curr_char() {
            Some('+') => { self.bump(); Token::Inc },
            Some('=') => { self.bump(); Token::PlusAssign },
            _ => Token::Plus
        }
    }

    fn minus(&mut self) -> Token {
        self.bump();
        match self.reader.curr_char() {
            Some('-') => { self.bump(); Token::Dec },
            Some('=') => { self.bump(); Token::MinusAssign },
            _ => Token::Minus
        }
    }

    fn number(&mut self) -> Token {
        if self.reader.curr_char() == Some('1') {
            self.bump();
            return Token::DecimalInt(String::from_str("1"));
        }
        unimplemented!()
    }

    fn string(&mut self) -> Token { unimplemented!() }
    fn word(&mut self) -> Token { unimplemented!() }

    fn read_next_token(&mut self) -> Token {
        self.skip_whitespace();
        println!("inspecting {:?}", self.reader.curr_char());
        loop {
            match self.reader.curr_char() {
                Some('/') => {
                    match self.reader.next_char() {
                        Some('/') => self.skip_line_comment(),
                        Some('*') => self.skip_block_comment(),
                        _ => return self.div_or_regexp()
                    }
                },
                Some('.') => {
                    match self.reader.next_char() {
                        Some(ch) if ch.is_digit(10) => { return self.number() },
                        _ => { self.reader.bump(); return Token::Dot }
                    }
                }
                Some('{') => { self.bump(); return Token::LBrace },
                Some('}') => { self.bump(); return Token::RBrace },
                Some('[') => { self.bump(); return Token::LBrack },
                Some(']') => { self.bump(); return Token::RBrack },
                Some('(') => { self.bump(); return Token::LParen },
                Some(')') => { self.bump(); return Token::RParen },
                Some(';') => { self.bump(); return Token::Semi },
                Some(':') => { self.bump(); return Token::Colon },
                Some(',') => { self.bump(); return Token::Comma },
                Some('<') => return self.lt(),
                Some('>') => return self.gt(),
                Some('=') => return self.if_equality(Token::Assign, Token::Eq, Token::StrictEq),
                Some('+') => return self.plus(),
                Some('-') => return self.minus(),
                Some('*') => return self.if_assign(Token::StarAssign, Token::Star),
                Some('%') => return self.if_assign(Token::ModAssign, Token::Mod),
                Some('^') => return self.if_assign(Token::BitXorAssign, Token::BitXor),
                Some('&') => {
                    self.bump();
                    match self.reader.curr_char() {
                        Some('&') => { self.bump(); return Token::LogicalAnd },
                        _ => return Token::BitAnd
                    }
                },
                Some('|') => {
                    self.bump();
                    match self.reader.curr_char() {
                        Some('|') => { self.bump(); return Token::LogicalOr },
                        _ => return Token::BitOr
                    }
                },
                Some('~') => { self.bump(); return Token::Tilde },
                Some('!') => return self.if_equality(Token::Bang, Token::NEq, Token::StrictNEq),
                Some('?') => { self.bump(); return Token::Question },
                Some('"') => return self.string(),
                Some('\'') => return self.string(),
                Some('\r') => {
                    self.bump();
                    if self.reader.curr_char() == Some('\n') {
                        self.bump();
                    }
                    if self.cx.get().is_asi_possible() {
                        return Token::Newline;
                    }
                },
                Some(ch) if ch.is_es_newline() => {
                    self.bump();
                    if self.cx.get().is_asi_possible() {
                        return Token::Newline;
                    }
                }
                Some(ch) if ch.is_digit(10) => return self.number(),
                Some(ch) if ch.is_es_identifier() => return self.word(),
                Some(ch) => return Token::Error(ch),
                None => return Token::EOF
            }
        }
    }

    fn is_whitespace(&mut self) -> bool {
        match self.reader.curr_char() {
            Some(ch) => ch.is_es_whitespace(),
            None => false
        }
    }

    fn bump(&mut self) {
        self.reader.bump();
    }

    fn eat(&mut self) -> Option<char> {
        let ch = self.reader.curr_char();
        self.bump();
        ch
    }

    fn skip_whitespace(&mut self) {
        while self.is_whitespace() {
            self.reader.bump();
        }
    }
}

impl<I> Iterator for Lexer<I> where I: Iterator<Item=char> {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        match self.read_token() {
            Token::EOF => None,
            t => Some(t)
        }
    }
}
<|endoftext|>


<commit_before>use color::RGB;
use linear::{Direction, Position};
use std::default::Default;

pub struct LightProp {
  pub diff: RGB,
  _pad_0: f32,
  pub spec: RGB,
  _pad_1: f32,
  pub gloss: f32,
  _pad_2: [f32; 3]
}

impl LightProp {
  pub fn new(diff: RGB, spec: RGB, gloss: f32) -> Self {
    LightProp {
      diff: diff,
      _pad_0: 0.,
      spec: spec,
      _pad_1: 0.,
      gloss: gloss,
      _pad_2: [0., 0., 0.]
    }
  }
}

impl Default for LightProp {
  fn default() -> Self {
    LightProp::new(
      RGB::new(0.6, 0.6, 0.7),
      RGB::new(0.6, 0.6, 0.7),
      10.
    )
  }
}

pub struct Light<L> {
  pub prop: LightProp,
  pub feature: L
}

impl<L> Light<L> {
  pub fn new(prop: LightProp, feature: L) -> Self {
    Light {
      prop: prop,
      feature: feature
    }
  }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct LightDir {
  dir: Direction,
  _pad: f32
}

impl From<Direction> for LightDir {
  fn from(dir: Direction) -> Self {
    LightDir {
      dir: dir,
      _pad: 0.
    }
  }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct LightPos {
  pos: Position,
  _pad: f32
}

impl From<Position> for LightPos {
  fn from(pos: Position) -> Self {
    LightPos {
      pos: pos,
      _pad: 0.
    }
  }
}

pub type Dir = Light<LightDir>;
pub type Omni = Light<LightPos>;

<commit_msg>Default implementation for most of lights.<commit_after>use color::RGB;
use linear::{Direction, Position};
use std::default::Default;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct LightProp {
  pub diff: RGB,
  _pad_0: f32,
  pub spec: RGB,
  _pad_1: f32,
  pub gloss: f32,
  _pad_2: [f32; 3]
}

impl LightProp {
  pub fn new(diff: RGB, spec: RGB, gloss: f32) -> Self {
    LightProp {
      diff: diff,
      _pad_0: 0.,
      spec: spec,
      _pad_1: 0.,
      gloss: gloss,
      _pad_2: [0., 0., 0.]
    }
  }
}

impl Default for LightProp {
  fn default() -> Self {
    LightProp::new(
      RGB::new(0.6, 0.6, 0.7),
      RGB::new(0.6, 0.6, 0.7),
      10.
    )
  }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Light<L> {
  pub prop: LightProp,
  pub feature: L
}

impl<L> Light<L> {
  pub fn new(prop: LightProp, feature: L) -> Self {
    Light {
      prop: prop,
      feature: feature
    }
  }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct LightDir {
  dir: Direction,
  _pad: f32
}

impl From<Direction> for LightDir {
  fn from(dir: Direction) -> Self {
    LightDir {
      dir: dir,
      _pad: 0.
    }
  }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct LightPos {
  pos: Position,
  _pad: f32
}

impl From<Position> for LightPos {
  fn from(pos: Position) -> Self {
    LightPos {
      pos: pos,
      _pad: 0.
    }
  }
}

pub type Dir = Light<LightDir>;
pub type Omni = Light<LightPos>;
<|endoftext|>


<commit_before>//! Tests for the `cargo rustdoc` command.

use cargo_test_support::{basic_manifest, cross_compile, project};

#[cargo_test]
fn rustdoc_simple() {
    let p = project().file("src/lib.rs", "").build();

    p.cargo("rustdoc -v")
        .with_stderr(
            "\
[DOCUMENTING] foo v0.0.1 ([CWD])
[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs [..]\
        -o [CWD]/target/doc \
        [..] \
        -L dependency=[CWD]/target/debug/deps [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn rustdoc_args() {
    let p = project().file("src/lib.rs", "").build();

    p.cargo("rustdoc -v -- --cfg=foo")
        .with_stderr(
            "\
[DOCUMENTING] foo v0.0.1 ([CWD])
[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs [..]\
        -o [CWD]/target/doc \
        [..] \
        --cfg=foo \
        -L dependency=[CWD]/target/debug/deps [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn rustdoc_binary_args_passed() {
    let p = project().file("src/main.rs", "").build();

    p.cargo("rustdoc -v")
        .arg("--")
        .arg("--markdown-no-toc")
        .with_stderr_contains("[RUNNING] `rustdoc [..] --markdown-no-toc[..]`")
        .run();
}

#[cargo_test]
fn rustdoc_foo_with_bar_dependency() {
    let foo = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.0.1"
                authors = []

                [dependencies.bar]
                path = "../bar"
            "#,
        )
        .file("src/lib.rs", "extern crate bar; pub fn foo() {}")
        .build();
    let _bar = project()
        .at("bar")
        .file("Cargo.toml", &basic_manifest("bar", "0.0.1"))
        .file("src/lib.rs", "pub fn baz() {}")
        .build();

    foo.cargo("rustdoc -v -- --cfg=foo")
        .with_stderr(
            "\
[CHECKING] bar v0.0.1 ([..])
[RUNNING] `rustc [..]bar/src/lib.rs [..]`
[DOCUMENTING] foo v0.0.1 ([CWD])
[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs [..]\
        -o [CWD]/target/doc \
        [..] \
        --cfg=foo \
        -L dependency=[CWD]/target/debug/deps \
        --extern [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn rustdoc_only_bar_dependency() {
    let foo = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.0.1"
                authors = []

                [dependencies.bar]
                path = "../bar"
            "#,
        )
        .file("src/main.rs", "extern crate bar; fn main() { bar::baz() }")
        .build();
    let _bar = project()
        .at("bar")
        .file("Cargo.toml", &basic_manifest("bar", "0.0.1"))
        .file("src/lib.rs", "pub fn baz() {}")
        .build();

    foo.cargo("rustdoc -v -p bar -- --cfg=foo")
        .with_stderr(
            "\
[DOCUMENTING] bar v0.0.1 ([..])
[RUNNING] `rustdoc [..]--crate-name bar [..]bar/src/lib.rs [..]\
        -o [CWD]/target/doc \
        [..] \
        --cfg=foo \
        -L dependency=[CWD]/target/debug/deps [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn rustdoc_same_name_documents_lib() {
    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file("src/lib.rs", r#" "#)
        .build();

    p.cargo("rustdoc -v -- --cfg=foo")
        .with_stderr(
            "\
[DOCUMENTING] foo v0.0.1 ([..])
[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs [..]\
        -o [CWD]/target/doc \
        [..] \
        --cfg=foo \
        -L dependency=[CWD]/target/debug/deps [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn features() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.0.1"
                authors = []

                [features]
                quux = []
            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("rustdoc --verbose --features quux")
        .with_stderr_contains("[..]feature=[..]quux[..]")
        .run();
}

#[cargo_test]
fn proc_macro_crate_type() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.0.1"
                authors = []

                [lib]
                proc-macro = true

            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("rustdoc --verbose")
        .with_stderr_contains(
            "\
[RUNNING] `rustdoc --crate-type proc-macro [..]`
",
        )
        .run();
}

#[cargo_test]
fn rustdoc_target() {
    if cross_compile::disabled() {
        return;
    }

    let p = project().file("src/lib.rs", "").build();

    p.cargo("rustdoc --verbose --target")
        .arg(cross_compile::alternate())
        .with_stderr(format!(
            "\
[DOCUMENTING] foo v0.0.1 ([..])
[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs [..]\
    --target {target} \
    -o [CWD]/target/{target}/doc \
    [..] \
    -L dependency=[CWD]/target/{target}/debug/deps \
    -L dependency=[CWD]/target/debug/deps[..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
            target = cross_compile::alternate()
        ))
        .run();
}

#[cargo_test]
fn fail_with_glob() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [workspace]
                members = ["bar"]
            "#,
        )
        .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
        .file("bar/src/lib.rs", "pub fn bar() {  break_the_build(); }")
        .build();

    p.cargo("rustdoc -p '*z'")
        .with_status(101)
        .with_stderr("[ERROR] Glob patterns on package selection are not supported.")
        .run();
}
<commit_msg>Update rustdoc tests with -Cmetadata flag<commit_after>//! Tests for the `cargo rustdoc` command.

use cargo_test_support::{basic_manifest, cross_compile, project};

#[cargo_test]
fn rustdoc_simple() {
    let p = project().file("src/lib.rs", "").build();

    p.cargo("rustdoc -v")
        .with_stderr(
            "\
[DOCUMENTING] foo v0.0.1 ([CWD])
[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs [..]\
        -o [CWD]/target/doc \
        [..] \
        -L dependency=[CWD]/target/debug/deps [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn rustdoc_args() {
    let p = project().file("src/lib.rs", "").build();

    p.cargo("rustdoc -v -- --cfg=foo")
        .with_stderr(
            "\
[DOCUMENTING] foo v0.0.1 ([CWD])
[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs [..]\
        -o [CWD]/target/doc \
        [..] \
        --cfg=foo \
        -C metadata=[..] \
        -L dependency=[CWD]/target/debug/deps [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn rustdoc_binary_args_passed() {
    let p = project().file("src/main.rs", "").build();

    p.cargo("rustdoc -v")
        .arg("--")
        .arg("--markdown-no-toc")
        .with_stderr_contains("[RUNNING] `rustdoc [..] --markdown-no-toc[..]`")
        .run();
}

#[cargo_test]
fn rustdoc_foo_with_bar_dependency() {
    let foo = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.0.1"
                authors = []

                [dependencies.bar]
                path = "../bar"
            "#,
        )
        .file("src/lib.rs", "extern crate bar; pub fn foo() {}")
        .build();
    let _bar = project()
        .at("bar")
        .file("Cargo.toml", &basic_manifest("bar", "0.0.1"))
        .file("src/lib.rs", "pub fn baz() {}")
        .build();

    foo.cargo("rustdoc -v -- --cfg=foo")
        .with_stderr(
            "\
[CHECKING] bar v0.0.1 ([..])
[RUNNING] `rustc [..]bar/src/lib.rs [..]`
[DOCUMENTING] foo v0.0.1 ([CWD])
[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs [..]\
        -o [CWD]/target/doc \
        [..] \
        --cfg=foo \
        -C metadata=[..] \
        -L dependency=[CWD]/target/debug/deps \
        --extern [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn rustdoc_only_bar_dependency() {
    let foo = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.0.1"
                authors = []

                [dependencies.bar]
                path = "../bar"
            "#,
        )
        .file("src/main.rs", "extern crate bar; fn main() { bar::baz() }")
        .build();
    let _bar = project()
        .at("bar")
        .file("Cargo.toml", &basic_manifest("bar", "0.0.1"))
        .file("src/lib.rs", "pub fn baz() {}")
        .build();

    foo.cargo("rustdoc -v -p bar -- --cfg=foo")
        .with_stderr(
            "\
[DOCUMENTING] bar v0.0.1 ([..])
[RUNNING] `rustdoc [..]--crate-name bar [..]bar/src/lib.rs [..]\
        -o [CWD]/target/doc \
        [..] \
        --cfg=foo \
        -C metadata=[..] \
        -L dependency=[CWD]/target/debug/deps [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn rustdoc_same_name_documents_lib() {
    let p = project()
        .file("src/main.rs", "fn main() {}")
        .file("src/lib.rs", r#" "#)
        .build();

    p.cargo("rustdoc -v -- --cfg=foo")
        .with_stderr(
            "\
[DOCUMENTING] foo v0.0.1 ([..])
[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs [..]\
        -o [CWD]/target/doc \
        [..] \
        --cfg=foo \
        -C metadata=[..] \
        -L dependency=[CWD]/target/debug/deps [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn features() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.0.1"
                authors = []

                [features]
                quux = []
            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("rustdoc --verbose --features quux")
        .with_stderr_contains("[..]feature=[..]quux[..]")
        .run();
}

#[cargo_test]
fn proc_macro_crate_type() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.0.1"
                authors = []

                [lib]
                proc-macro = true

            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("rustdoc --verbose")
        .with_stderr_contains(
            "\
[RUNNING] `rustdoc --crate-type proc-macro [..]`
",
        )
        .run();
}

#[cargo_test]
fn rustdoc_target() {
    if cross_compile::disabled() {
        return;
    }

    let p = project().file("src/lib.rs", "").build();

    p.cargo("rustdoc --verbose --target")
        .arg(cross_compile::alternate())
        .with_stderr(format!(
            "\
[DOCUMENTING] foo v0.0.1 ([..])
[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs [..]\
    --target {target} \
    -o [CWD]/target/{target}/doc \
    [..] \
    -L dependency=[CWD]/target/{target}/debug/deps \
    -L dependency=[CWD]/target/debug/deps[..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
            target = cross_compile::alternate()
        ))
        .run();
}

#[cargo_test]
fn fail_with_glob() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [workspace]
                members = ["bar"]
            "#,
        )
        .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
        .file("bar/src/lib.rs", "pub fn bar() {  break_the_build(); }")
        .build();

    p.cargo("rustdoc -p '*z'")
        .with_status(101)
        .with_stderr("[ERROR] Glob patterns on package selection are not supported.")
        .run();
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods;
use dom::bindings::codegen::Bindings::HTMLFormControlsCollectionBinding;
use dom::bindings::codegen::Bindings::HTMLFormControlsCollectionBinding::HTMLFormControlsCollectionMethods;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
use dom::element::Element;
use dom::htmlcollection::{CollectionFilter, HTMLCollection};
use dom::node::Node;
use dom::window::Window;
use util::str::DOMString;

#[dom_struct]
pub struct HTMLFormControlsCollection {
    collection: HTMLCollection,
}

impl HTMLFormControlsCollection {
    fn new_inherited(root: &Node, filter: Box<CollectionFilter + 'static>) -> HTMLFormControlsCollection {
        HTMLFormControlsCollection {
            collection: HTMLCollection::new_inherited(root, filter)
        }
    }

    pub fn new(window: &Window, root: &Node, filter: Box<CollectionFilter + 'static>)
        -> Root<HTMLFormControlsCollection>
    {
        reflect_dom_object(box HTMLFormControlsCollection::new_inherited(root, filter),
                           GlobalRef::Window(window),
                           HTMLFormControlsCollectionBinding::Wrap)
    }

    // FIXME: This shouldn't need to be implemented here since HTMLCollection (the parent of
    // HTMLFormControlsCollection) implements Length
    pub fn Length(&self) -> u32 {
        self.collection.Length()
    }
}

impl HTMLFormControlsCollectionMethods for HTMLFormControlsCollection {
    // https://html.spec.whatwg.org/multipage/#dom-htmlformcontrolscollection-nameditem
    fn NamedGetter(&self, name: DOMString, found: &mut bool) -> Option<Root<Element>> {
        self.collection.NamedGetter(name, found)
    }

    // https://html.spec.whatwg.org/multipage/#the-htmlformcontrolscollection-interface:supported-property-names
    fn SupportedPropertyNames(&self) -> Vec<DOMString> {
        self.collection.SupportedPropertyNames()
    }

    // FIXME: This shouldn't need to be implemented here since HTMLCollection (the parent of
    // HTMLFormControlsCollection) implements IndexedGetter
    //
    // https://dom.spec.whatwg.org/#dom-htmlcollection-item
    fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Element>> {
        self.collection.IndexedGetter(index, found)
    }
}
<commit_msg>Link to tracking issue for redundant codegen getter<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods;
use dom::bindings::codegen::Bindings::HTMLFormControlsCollectionBinding;
use dom::bindings::codegen::Bindings::HTMLFormControlsCollectionBinding::HTMLFormControlsCollectionMethods;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
use dom::element::Element;
use dom::htmlcollection::{CollectionFilter, HTMLCollection};
use dom::node::Node;
use dom::window::Window;
use util::str::DOMString;

#[dom_struct]
pub struct HTMLFormControlsCollection {
    collection: HTMLCollection,
}

impl HTMLFormControlsCollection {
    fn new_inherited(root: &Node, filter: Box<CollectionFilter + 'static>) -> HTMLFormControlsCollection {
        HTMLFormControlsCollection {
            collection: HTMLCollection::new_inherited(root, filter)
        }
    }

    pub fn new(window: &Window, root: &Node, filter: Box<CollectionFilter + 'static>)
        -> Root<HTMLFormControlsCollection>
    {
        reflect_dom_object(box HTMLFormControlsCollection::new_inherited(root, filter),
                           GlobalRef::Window(window),
                           HTMLFormControlsCollectionBinding::Wrap)
    }

    // FIXME: This shouldn't need to be implemented here since HTMLCollection (the parent of
    // HTMLFormControlsCollection) implements Length
    pub fn Length(&self) -> u32 {
        self.collection.Length()
    }
}

impl HTMLFormControlsCollectionMethods for HTMLFormControlsCollection {
    // https://html.spec.whatwg.org/multipage/#dom-htmlformcontrolscollection-nameditem
    fn NamedGetter(&self, name: DOMString, found: &mut bool) -> Option<Root<Element>> {
        self.collection.NamedGetter(name, found)
    }

    // https://html.spec.whatwg.org/multipage/#the-htmlformcontrolscollection-interface:supported-property-names
    fn SupportedPropertyNames(&self) -> Vec<DOMString> {
        self.collection.SupportedPropertyNames()
    }

    // FIXME: This shouldn't need to be implemented here since HTMLCollection (the parent of
    // HTMLFormControlsCollection) implements IndexedGetter.
    // https://github.com/servo/servo/issues/5875
    //
    // https://dom.spec.whatwg.org/#dom-htmlcollection-item
    fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Element>> {
        self.collection.IndexedGetter(index, found)
    }
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Panic handling and stack unwinding

use core::fmt;
use core::fmt::Write;
use super::io::term;

#[lang = "panic_fmt"]
#[no_mangle] #[inline(never)] #[cold]
pub extern fn panic_fmt( args: fmt::Arguments
                   , file: &'static str
                   , line: usize ) -> !
{
    write!( term::CONSOLE.lock()
          , "{}: {} {}"
          , file, line, args
          );
    loop { }
}

/// Required for Rust stack unwinding
#[lang = "eh_personality"]
#[no_mangle] #[inline(never)] #[cold]
pub extern fn eh_personality() {
    // TODO: add support for stack unwinding
}

#[lang="stack_exhausted"]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn __morestack() -> ! {
    loop { }
}

#[allow(non_snake_case)]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn _Unwind_Resume() -> ! {
    loop { }
}
<commit_msg>Add the begin_unwind function (this SHOULD fix panics)<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Panic handling and stack unwinding

use core::fmt;
use core::fmt::{Arguments, Write};
use super::io::term;

#[lang = "panic_fmt"]
#[no_mangle] #[inline(never)] #[cold]
pub extern fn panic_fmt( args: Arguments
                       , file: &'static str
                       , line: usize ) -> !
{
    write!( term::CONSOLE.lock()
          , "{}: {} {}"
          , file, line, args
          );
    loop { }
}

/// Required for Rust stack unwinding
#[lang = "eh_personality"]
#[no_mangle] #[inline(never)] #[cold]
pub extern fn eh_personality() {
    // TODO: add support for stack unwinding
}

#[lang = "stack_exhausted"]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn __morestack() -> ! {
    loop { }
}

#[allow(non_snake_case)]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn _Unwind_Resume() -> ! {
    loop { }
}

#[lang = "begin_unwind"]
#[no_mangle] #[inline(never)] #[cold]
pub fn begin_unwind<M: Send>(msg: M
                            , file_line: &(&'static str, usize))  -> !
{ loop { } }
<|endoftext|>


<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::fs::OpenOptions;
use std::io::{Read, Write};

use getopts::Options;

use base::WriteZeroes;
use disk::QcowFile;

fn show_usage(program_name: &str) {
    println!("Usage: {} [subcommand] <subcommand args>", program_name);
    println!("\nSubcommands:");
    println!(
        "{} header <file name> - Show the qcow2 header for a file.",
        program_name
    );
    println!(
        "{} l1_table <file name> - Show the L1 table entries for a file.",
        program_name
    );
    println!(
        "{} l22table <file name> <l1 index> - Show the L2 table pointed to by the nth L1 entry.",
        program_name
    );
    println!(
        "{} ref_table <file name> - Show the refblock table for the file.",
        program_name
    );
    println!(
        "{} ref_block <file_name> <table index> - Show the nth reblock in the file.",
        program_name
    );
    println!(
        "{} dd <file_name> <source_file> - Write bytes from the raw source_file to the file.",
        program_name
    );
    println!(
        "{} convert <src_file> <dst_file> - Convert from src_file to dst_file.",
        program_name
    );
}

fn main() -> std::result::Result<(), ()> {
    let args: Vec<String> = std::env::args().collect();
    let opts = Options::new();

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string()),
    };

    if matches.free.len() < 2 {
        println!("Must specify the subcommand and the QCOW file to operate on.");
        show_usage(&args[0]);
        return Err(());
    }

    match matches.free[0].as_ref() {
        "header" => show_header(&matches.free[1]),
        "help" => {
            show_usage(&args[0]);
            Ok(())
        }
        "l1_table" => show_l1_table(&matches.free[1]),
        "l2_table" => {
            if matches.free.len() < 2 {
                println!("Filename and table index are required.");
                show_usage(&args[0]);
                return Err(());
            }
            show_l2_table(&matches.free[1], matches.free[2].parse().unwrap())
        }
        "ref_table" => show_ref_table(&matches.free[1]),
        "ref_block" => {
            if matches.free.len() < 2 {
                println!("Filename and block index are required.");
                show_usage(&args[0]);
                return Err(());
            }
            show_ref_block(&matches.free[1], matches.free[2].parse().unwrap())
        }
        "dd" => {
            if matches.free.len() < 2 {
                println!("Qcow and source file are required.");
                show_usage(&args[0]);
                return Err(());
            }
            let count = if matches.free.len() > 3 {
                Some(matches.free[3].parse().unwrap())
            } else {
                None
            };
            dd(&matches.free[1], &matches.free[2], count)
        }
        "convert" => {
            if matches.free.len() < 2 {
                println!("Source and destination files are required.");
                show_usage(&args[0]);
                return Err(());
            }
            convert(&matches.free[1], &matches.free[2])
        }
        c => {
            println!("invalid subcommand: {:?}", c);
            Err(())
        }
    }
}

fn show_header(file_path: &str) -> std::result::Result<(), ()> {
    let file = match OpenOptions::new().read(true).open(file_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let qcow_file = QcowFile::from(file).map_err(|_| ())?;
    let header = qcow_file.header();

    println!("magic {:x}", header.magic);
    println!("version {:x}", header.version);
    println!("backing_file_offset {:x}", header.backing_file_offset);
    println!("backing_file_size {:x}", header.backing_file_size);
    println!("cluster_bits {:x}", header.cluster_bits);
    println!("size {:x}", header.size);
    println!("crypt_method {:x}", header.crypt_method);
    println!("l1_size {:x}", header.l1_size);
    println!("l1_table_offset {:x}", header.l1_table_offset);
    println!("refcount_table_offset {:x}", header.refcount_table_offset);
    println!(
        "refcount_table_clusters {:x}",
        header.refcount_table_clusters
    );
    println!("nb_snapshots {:x}", header.nb_snapshots);
    println!("snapshots_offset {:x}", header.snapshots_offset);
    println!("incompatible_features {:x}", header.incompatible_features);
    println!("compatible_features {:x}", header.compatible_features);
    println!("autoclear_features {:x}", header.autoclear_features);
    println!("refcount_order {:x}", header.refcount_order);
    println!("header_size {:x}", header.header_size);
    Ok(())
}

fn show_l1_table(file_path: &str) -> std::result::Result<(), ()> {
    let file = match OpenOptions::new().read(true).open(file_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let qcow_file = QcowFile::from(file).map_err(|_| ())?;
    let l1_table = qcow_file.l1_table();

    for (i, l2_offset) in l1_table.iter().enumerate() {
        println!("{}: {:x}", i, l2_offset);
    }

    Ok(())
}

fn show_l2_table(file_path: &str, index: usize) -> std::result::Result<(), ()> {
    let file = match OpenOptions::new().read(true).open(file_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let mut qcow_file = QcowFile::from(file).map_err(|_| ())?;
    let l2_table = qcow_file.l2_table(index).unwrap();

    if let Some(cluster_addrs) = l2_table {
        for (i, addr) in cluster_addrs.iter().enumerate() {
            if i % 16 == 0 {
                print!("\n{:x}:", i);
            }
            print!(" {:x}", addr);
        }
    }

    Ok(())
}

fn show_ref_table(file_path: &str) -> std::result::Result<(), ()> {
    let file = match OpenOptions::new().read(true).open(file_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let qcow_file = QcowFile::from(file).map_err(|_| ())?;
    let ref_table = qcow_file.ref_table();

    for (i, block_offset) in ref_table.iter().enumerate() {
        println!("{}: {:x}", i, block_offset);
    }

    Ok(())
}

fn show_ref_block(file_path: &str, index: usize) -> std::result::Result<(), ()> {
    let file = match OpenOptions::new().read(true).open(file_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let mut qcow_file = QcowFile::from(file).map_err(|_| ())?;
    let ref_table = qcow_file.refcount_block(index).unwrap();

    if let Some(counts) = ref_table {
        for (i, count) in counts.iter().enumerate() {
            if i % 16 == 0 {
                print!("\n{:x}:", i);
            }
            print!(" {:x}", count);
        }
    }

    Ok(())
}

// Transfers from a raw file specifiec in `source_path` to the qcow file specified in `file_path`.
fn dd(file_path: &str, source_path: &str, count: Option<usize>) -> std::result::Result<(), ()> {
    let file = match OpenOptions::new().read(true).write(true).open(file_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let mut qcow_file = QcowFile::from(file).map_err(|_| ())?;

    let mut src_file = match OpenOptions::new().read(true).open(source_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let mut read_count = 0;
    const CHUNK_SIZE: usize = 65536;
    let mut buf = [0; CHUNK_SIZE];
    loop {
        let this_count = if let Some(count) = count {
            std::cmp::min(CHUNK_SIZE, count - read_count)
        } else {
            CHUNK_SIZE
        };
        let nread = src_file.read(&mut buf[..this_count]).map_err(|_| ())?;
        // If this block is all zeros, then use write_zeros so the output file is sparse.
        if buf.iter().all(|b| *b == 0) {
            qcow_file.write_zeroes_all(CHUNK_SIZE).map_err(|_| ())?;
        } else {
            qcow_file.write(&buf).map_err(|_| ())?;
        }
        read_count = read_count + nread;
        if nread == 0 || Some(read_count) == count {
            break;
        }
    }

    println!("wrote {} bytes", read_count);

    Ok(())
}

// Reads the file at `src_path` and writes it to `dst_path`.
// The output format is detected based on the `dst_path` file extension.
fn convert(src_path: &str, dst_path: &str) -> std::result::Result<(), ()> {
    let src_file = match OpenOptions::new().read(true).open(src_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open source file {}", src_path);
            return Err(());
        }
    };

    let dst_file = match OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(dst_path)
    {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open destination file {}", dst_path);
            return Err(());
        }
    };

    let dst_type = if dst_path.ends_with("qcow2") {
        disk::ImageType::Qcow2
    } else {
        disk::ImageType::Raw
    };

    match disk::convert(src_file, dst_file, dst_type) {
        Ok(_) => {
            println!("Converted {} to {}", src_path, dst_path);
            Ok(())
        }
        Err(_) => {
            println!("Failed to copy from {} to {}", src_path, dst_path);
            Err(())
        }
    }
}
<commit_msg>qcow_img: Fix warning message.<commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::fs::OpenOptions;
use std::io::{Read, Write};

use getopts::Options;

use base::WriteZeroes;
use disk::QcowFile;

fn show_usage(program_name: &str) {
    println!("Usage: {} [subcommand] <subcommand args>", program_name);
    println!("\nSubcommands:");
    println!(
        "{} header <file name> - Show the qcow2 header for a file.",
        program_name
    );
    println!(
        "{} l1_table <file name> - Show the L1 table entries for a file.",
        program_name
    );
    println!(
        "{} l22table <file name> <l1 index> - Show the L2 table pointed to by the nth L1 entry.",
        program_name
    );
    println!(
        "{} ref_table <file name> - Show the refblock table for the file.",
        program_name
    );
    println!(
        "{} ref_block <file_name> <table index> - Show the nth reblock in the file.",
        program_name
    );
    println!(
        "{} dd <file_name> <source_file> - Write bytes from the raw source_file to the file.",
        program_name
    );
    println!(
        "{} convert <src_file> <dst_file> - Convert from src_file to dst_file.",
        program_name
    );
}

fn main() -> std::result::Result<(), ()> {
    let args: Vec<String> = std::env::args().collect();
    let opts = Options::new();

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!("{}", f.to_string()),
    };

    if matches.free.len() < 2 {
        println!("Must specify the subcommand and the QCOW file to operate on.");
        show_usage(&args[0]);
        return Err(());
    }

    match matches.free[0].as_ref() {
        "header" => show_header(&matches.free[1]),
        "help" => {
            show_usage(&args[0]);
            Ok(())
        }
        "l1_table" => show_l1_table(&matches.free[1]),
        "l2_table" => {
            if matches.free.len() < 2 {
                println!("Filename and table index are required.");
                show_usage(&args[0]);
                return Err(());
            }
            show_l2_table(&matches.free[1], matches.free[2].parse().unwrap())
        }
        "ref_table" => show_ref_table(&matches.free[1]),
        "ref_block" => {
            if matches.free.len() < 2 {
                println!("Filename and block index are required.");
                show_usage(&args[0]);
                return Err(());
            }
            show_ref_block(&matches.free[1], matches.free[2].parse().unwrap())
        }
        "dd" => {
            if matches.free.len() < 2 {
                println!("Qcow and source file are required.");
                show_usage(&args[0]);
                return Err(());
            }
            let count = if matches.free.len() > 3 {
                Some(matches.free[3].parse().unwrap())
            } else {
                None
            };
            dd(&matches.free[1], &matches.free[2], count)
        }
        "convert" => {
            if matches.free.len() < 2 {
                println!("Source and destination files are required.");
                show_usage(&args[0]);
                return Err(());
            }
            convert(&matches.free[1], &matches.free[2])
        }
        c => {
            println!("invalid subcommand: {:?}", c);
            Err(())
        }
    }
}

fn show_header(file_path: &str) -> std::result::Result<(), ()> {
    let file = match OpenOptions::new().read(true).open(file_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let qcow_file = QcowFile::from(file).map_err(|_| ())?;
    let header = qcow_file.header();

    println!("magic {:x}", header.magic);
    println!("version {:x}", header.version);
    println!("backing_file_offset {:x}", header.backing_file_offset);
    println!("backing_file_size {:x}", header.backing_file_size);
    println!("cluster_bits {:x}", header.cluster_bits);
    println!("size {:x}", header.size);
    println!("crypt_method {:x}", header.crypt_method);
    println!("l1_size {:x}", header.l1_size);
    println!("l1_table_offset {:x}", header.l1_table_offset);
    println!("refcount_table_offset {:x}", header.refcount_table_offset);
    println!(
        "refcount_table_clusters {:x}",
        header.refcount_table_clusters
    );
    println!("nb_snapshots {:x}", header.nb_snapshots);
    println!("snapshots_offset {:x}", header.snapshots_offset);
    println!("incompatible_features {:x}", header.incompatible_features);
    println!("compatible_features {:x}", header.compatible_features);
    println!("autoclear_features {:x}", header.autoclear_features);
    println!("refcount_order {:x}", header.refcount_order);
    println!("header_size {:x}", header.header_size);
    Ok(())
}

fn show_l1_table(file_path: &str) -> std::result::Result<(), ()> {
    let file = match OpenOptions::new().read(true).open(file_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let qcow_file = QcowFile::from(file).map_err(|_| ())?;
    let l1_table = qcow_file.l1_table();

    for (i, l2_offset) in l1_table.iter().enumerate() {
        println!("{}: {:x}", i, l2_offset);
    }

    Ok(())
}

fn show_l2_table(file_path: &str, index: usize) -> std::result::Result<(), ()> {
    let file = match OpenOptions::new().read(true).open(file_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let mut qcow_file = QcowFile::from(file).map_err(|_| ())?;
    let l2_table = qcow_file.l2_table(index).unwrap();

    if let Some(cluster_addrs) = l2_table {
        for (i, addr) in cluster_addrs.iter().enumerate() {
            if i % 16 == 0 {
                print!("\n{:x}:", i);
            }
            print!(" {:x}", addr);
        }
    }

    Ok(())
}

fn show_ref_table(file_path: &str) -> std::result::Result<(), ()> {
    let file = match OpenOptions::new().read(true).open(file_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let qcow_file = QcowFile::from(file).map_err(|_| ())?;
    let ref_table = qcow_file.ref_table();

    for (i, block_offset) in ref_table.iter().enumerate() {
        println!("{}: {:x}", i, block_offset);
    }

    Ok(())
}

fn show_ref_block(file_path: &str, index: usize) -> std::result::Result<(), ()> {
    let file = match OpenOptions::new().read(true).open(file_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let mut qcow_file = QcowFile::from(file).map_err(|_| ())?;
    let ref_table = qcow_file.refcount_block(index).unwrap();

    if let Some(counts) = ref_table {
        for (i, count) in counts.iter().enumerate() {
            if i % 16 == 0 {
                print!("\n{:x}:", i);
            }
            print!(" {:x}", count);
        }
    }

    Ok(())
}

// Transfers from a raw file specifiec in `source_path` to the qcow file specified in `file_path`.
fn dd(file_path: &str, source_path: &str, count: Option<usize>) -> std::result::Result<(), ()> {
    let file = match OpenOptions::new().read(true).write(true).open(file_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let mut qcow_file = QcowFile::from(file).map_err(|_| ())?;

    let mut src_file = match OpenOptions::new().read(true).open(source_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open {}", file_path);
            return Err(());
        }
    };

    let mut read_count = 0;
    const CHUNK_SIZE: usize = 65536;
    let mut buf = [0; CHUNK_SIZE];
    loop {
        let this_count = if let Some(count) = count {
            std::cmp::min(CHUNK_SIZE, count - read_count)
        } else {
            CHUNK_SIZE
        };
        let nread = src_file.read(&mut buf[..this_count]).map_err(|_| ())?;
        // If this block is all zeros, then use write_zeros so the output file is sparse.
        if buf.iter().all(|b| *b == 0) {
            qcow_file.write_zeroes_all(CHUNK_SIZE).map_err(|_| ())?;
        } else {
            qcow_file.write(&buf).map_err(|_| ())?;
        }
        read_count = read_count + nread;
        if nread == 0 || Some(read_count) == count {
            break;
        }
    }

    println!("wrote {} bytes", read_count);

    Ok(())
}

// Reads the file at `src_path` and writes it to `dst_path`.
// The output format is detected based on the `dst_path` file extension.
fn convert(src_path: &str, dst_path: &str) -> std::result::Result<(), ()> {
    let src_file = match OpenOptions::new().read(true).open(src_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open source file {}", src_path);
            return Err(());
        }
    };

    let dst_file = match OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(dst_path)
    {
        Ok(f) => f,
        Err(_) => {
            println!("Failed to open destination file {}", dst_path);
            return Err(());
        }
    };

    let dst_type = if dst_path.ends_with("qcow2") {
        disk::ImageType::Qcow2
    } else {
        disk::ImageType::Raw
    };

    match disk::convert(src_file, dst_file, dst_type) {
        Ok(_) => {
            println!("Converted {} to {}", src_path, dst_path);
            Ok(())
        }
        Err(_) => {
            println!("Failed to copy from {} to {}", src_path, dst_path);
            Err(())
        }
    }
}
<|endoftext|>


<commit_before>#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct GetMe;
<commit_msg>feat: implement Request for GetMe<commit_after>use requests::_base::*;
use types::chat::*;

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct GetMe;

impl Request for GetMe {
    type Response = User;
}
<|endoftext|>


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

use collections::string::String;

use common::event;

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

use fs::KScheme;

#[repr(packed)]
struct SerialInfo {
    pub ports: [u16; 4],
}

const SERIALINFO: *const SerialInfo = 0x400 as *const SerialInfo;

/// Serial
pub struct Serial {
    pub data: Pio<u8>,
    pub status: Pio<u8>,
    pub irq: u8,
    pub escape: bool,
    pub cursor_control: bool,
}

impl Serial {
    /// Create new
    pub fn new(port: u16, irq: u8) -> Box<Self> {
        Pio::<u8>::new(port + 1).write(0x00);
        Pio::<u8>::new(port + 3).write(0x80);
        Pio::<u8>::new(port + 0).write(0x03);
        Pio::<u8>::new(port + 1).write(0x00);
        Pio::<u8>::new(port + 3).write(0x03);
        Pio::<u8>::new(port + 2).write(0xC7);
        Pio::<u8>::new(port + 4).write(0x0B);
        Pio::<u8>::new(port + 1).write(0x01);

        box Serial {
            data: Pio::<u8>::new(port),
            status: Pio::<u8>::new(port + 5),
            irq: irq,
            escape: false,
            cursor_control: false,
        }
    }
}

impl KScheme for Serial {
    fn on_irq(&mut self, irq: u8) {
        if irq == self.irq {
            while self.status.read() & 1 == 0 {}

            let mut c = self.data.read() as char;
            let mut sc = 0;

            if self.escape {
                self.escape = false;

                if c == '[' {
                    self.cursor_control = true;
                }

                c = '\0';
            } else if self.cursor_control {
                self.cursor_control = false;

                c = '\0';

                if c == 'A' {
                    sc = event::K_UP;
                } else if c == 'B' {
                    sc = event::K_DOWN;
                } else if c == 'C' {
                    sc = event::K_RIGHT;
                } else if c == 'D' {
                    sc = event::K_LEFT;
                }
            } else if c == '\x03' {
                ::env().console.lock().write(b"^C\n");
                ::env().console.lock().commands.send(String::new());

                c = '\0';
                sc = 0;
            } else if c == '\x1B' {
                self.escape = true;
                c = '\0';
            } else if c == '\r' {
                c = '\n';
            } else if c == '\x7F' {
                c = '\0';
                sc = event::K_BKSP;
            }

            if c != '\0' || sc != 0 {
                let key_event = event::KeyEvent {
                    character: c,
                    scancode: sc,
                    pressed: true,
                };

                ::env().console.lock().event(key_event.to_event());
            }
        }
    }
}
<commit_msg>Lock console once<commit_after>use alloc::boxed::Box;

use collections::string::String;

use common::event;

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

use fs::KScheme;

#[repr(packed)]
struct SerialInfo {
    pub ports: [u16; 4],
}

const SERIALINFO: *const SerialInfo = 0x400 as *const SerialInfo;

/// Serial
pub struct Serial {
    pub data: Pio<u8>,
    pub status: Pio<u8>,
    pub irq: u8,
    pub escape: bool,
    pub cursor_control: bool,
}

impl Serial {
    /// Create new
    pub fn new(port: u16, irq: u8) -> Box<Self> {
        Pio::<u8>::new(port + 1).write(0x00);
        Pio::<u8>::new(port + 3).write(0x80);
        Pio::<u8>::new(port + 0).write(0x03);
        Pio::<u8>::new(port + 1).write(0x00);
        Pio::<u8>::new(port + 3).write(0x03);
        Pio::<u8>::new(port + 2).write(0xC7);
        Pio::<u8>::new(port + 4).write(0x0B);
        Pio::<u8>::new(port + 1).write(0x01);

        box Serial {
            data: Pio::<u8>::new(port),
            status: Pio::<u8>::new(port + 5),
            irq: irq,
            escape: false,
            cursor_control: false,
        }
    }
}

impl KScheme for Serial {
    fn on_irq(&mut self, irq: u8) {
        if irq == self.irq {
            while self.status.read() & 1 == 0 {}

            let mut c = self.data.read() as char;
            let mut sc = 0;

            let mut console = ::env().console.lock();

            if self.escape {
                self.escape = false;

                if c == '[' {
                    self.cursor_control = true;
                }

                c = '\0';
            } else if self.cursor_control {
                self.cursor_control = false;

                c = '\0';

                if c == 'A' {
                    sc = event::K_UP;
                } else if c == 'B' {
                    sc = event::K_DOWN;
                } else if c == 'C' {
                    sc = event::K_RIGHT;
                } else if c == 'D' {
                    sc = event::K_LEFT;
                }
            } else if c == '\x03' {
                console.write(b"^C\n");
                console.commands.send(String::new());

                c = '\0';
                sc = 0;
            } else if c == '\x1B' {
                self.escape = true;
                c = '\0';
            } else if c == '\r' {
                c = '\n';
            } else if c == '\x7F' {
                c = '\0';
                sc = event::K_BKSP;
            }

            if c != '\0' || sc != 0 {
                let key_event = event::KeyEvent {
                    character: c,
                    scancode: sc,
                    pressed: true,
                };

                console.event(key_event.to_event());
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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 length::Length;
use size::Size2D;
use num::Zero;

use num_lib::NumCast;
use std::fmt::{self, Formatter};
use std::ops::{Add, Neg, Mul, Sub, Div};

#[derive(Clone, Copy, RustcDecodable, RustcEncodable, Eq, Hash, PartialEq, Deserialize, Serialize)]
#[cfg_attr(feature = "heap_size", derive(HeapSizeOf))]
pub struct Point2D<T> {
    pub x: T,
    pub y: T
}

impl<T: Zero> Point2D<T> {
    pub fn zero() -> Point2D<T> {
        Point2D { x: Zero::zero(), y: Zero::zero() }
    }
}

impl<T: fmt::Debug> fmt::Debug for Point2D<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({:?},{:?})", self.x, self.y)
    }
}

impl<T: fmt::Display> fmt::Display for Point2D<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "({},{})", self.x, self.y)
    }
}

impl<T> Point2D<T> {
    pub fn new(x: T, y: T) -> Point2D<T> {
        Point2D {x: x, y: y}
    }
}

impl<T:Clone + Add<T, Output=T>> Add for Point2D<T> {
    type Output = Point2D<T>;
    fn add(self, other: Point2D<T>) -> Point2D<T> {
        Point2D::new(self.x + other.x, self.y + other.y)
    }
}

impl<T:Clone + Add<T, Output=T>> Add<Size2D<T>> for Point2D<T> {
    type Output = Point2D<T>;
    fn add(self, other: Size2D<T>) -> Point2D<T> {
        Point2D::new(self.x + other.width, self.y + other.height)
    }
}

impl<T: Copy + Add<T, Output=T>> Point2D<T> {
    pub fn add_size(&self, other: &Size2D<T>) -> Point2D<T> {
        Point2D { x: self.x + other.width, y: self.y + other.height }
    }
}

impl<T:Clone + Sub<T, Output=T>> Sub for Point2D<T> {
    type Output = Point2D<T>;
    fn sub(self, other: Point2D<T>) -> Point2D<T> {
        Point2D::new(self.x - other.x, self.y - other.y)
    }
}

impl <T:Clone + Neg<Output=T>> Neg for Point2D<T> {
    type Output = Point2D<T>;
    #[inline]
    fn neg(self) -> Point2D<T> {
        Point2D::new(-self.x, -self.y)
    }
}

impl<Scale: Copy, T0: Mul<Scale, Output=T1>, T1: Clone> Mul<Scale> for Point2D<T0> {
    type Output = Point2D<T1>;
    #[inline]
    fn mul(self, scale: Scale) -> Point2D<T1> {
        Point2D::new(self.x * scale, self.y * scale)
    }
}

impl<Scale: Copy, T0: Div<Scale, Output=T1>, T1: Clone> Div<Scale> for Point2D<T0> {
    type Output = Point2D<T1>;
    #[inline]
    fn div(self, scale: Scale) -> Point2D<T1> {
        Point2D::new(self.x / scale, self.y / scale)
    }
}

// Convenient aliases for Point2D with typed units

pub type TypedPoint2D<Unit, T> = Point2D<Length<Unit, T>>;

impl<Unit, T: Clone> Point2D<Length<Unit, T>> {
    pub fn typed(x: T, y: T) -> TypedPoint2D<Unit, T> {
        Point2D::new(Length::new(x), Length::new(y))
    }

    /// Drop the units, preserving only the numeric value.
    pub fn to_untyped(&self) -> Point2D<T> {
        Point2D::new(self.x.get(), self.y.get())
    }

    /// Tag a unitless value with units.
    pub fn from_untyped(p: &Point2D<T>) -> TypedPoint2D<Unit, T> {
        Point2D::new(Length::new(p.x.clone()), Length::new(p.y.clone()))
    }
}

impl<Unit, T0: NumCast + Clone> Point2D<Length<Unit, T0>> {
    /// Cast from one numeric representation to another, preserving the units.
    pub fn cast<T1: NumCast + Clone>(&self) -> Option<Point2D<Length<Unit, T1>>> {
        match (self.x.cast(), self.y.cast()) {
            (Some(x), Some(y)) => Some(Point2D::new(x, y)),
            _ => None
        }
    }
}

// Convenience functions for common casts
impl<Unit, T: NumCast + Clone> Point2D<Length<Unit, T>> {
    pub fn as_f32(&self) -> Point2D<Length<Unit, f32>> {
        self.cast().unwrap()
    }

    pub fn as_uint(&self) -> Point2D<Length<Unit, usize>> {
        self.cast().unwrap()
    }
}

#[derive(Clone, Copy, RustcDecodable, RustcEncodable, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "heap_size", derive(HeapSizeOf))]
pub struct Point3D<T> {
    pub x: T,
    pub y: T,
    pub z: T,
}

impl<T: Zero> Point3D<T> {
    #[inline]
    pub fn zero() -> Point3D<T> {
        Point3D { x: Zero::zero(), y: Zero::zero(), z: Zero::zero() }
    }
}

impl<T: fmt::Debug> fmt::Debug for Point3D<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({:?},{:?},{:?})", self.x, self.y, self.z)
    }
}

impl<T: fmt::Display> fmt::Display for Point3D<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "({},{},{})", self.x, self.y, self.z)
    }
}

impl<T> Point3D<T> {
    #[inline]
    pub fn new(x: T, y: T, z: T) -> Point3D<T> {
        Point3D {x: x, y: y, z: z}
    }
}

impl<T:Clone + Add<T, Output=T>> Add for Point3D<T> {
    type Output = Point3D<T>;
    fn add(self, other: Point3D<T>) -> Point3D<T> {
        Point3D::new(self.x + other.x,
                     self.y + other.y,
                     self.z + other.z)
    }
}

impl<T:Clone + Sub<T, Output=T>> Sub for Point3D<T> {
    type Output = Point3D<T>;
    fn sub(self, other: Point3D<T>) -> Point3D<T> {
        Point3D::new(self.x - other.x,
                     self.y - other.y,
                     self.z - other.z)
    }
}

impl <T:Clone + Neg<Output=T>> Neg for Point3D<T> {
    type Output = Point3D<T>;
    #[inline]
    fn neg(self) -> Point3D<T> {
        Point3D::new(-self.x, -self.y, -self.z)
    }
}

#[derive(Clone, Copy, RustcDecodable, RustcEncodable, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "heap_size", derive(HeapSizeOf))]
pub struct Point4D<T> {
    pub x: T,
    pub y: T,
    pub z: T,
    pub w: T,
}

impl<T: Zero> Point4D<T> {
    #[inline]
    pub fn zero() -> Point4D<T> {
        Point4D {
            x: Zero::zero(),
            y: Zero::zero(),
            z: Zero::zero(),
            w: Zero::zero()
        }
    }
}

impl<T: fmt::Debug> fmt::Debug for Point4D<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({:?},{:?},{:?},{:?})", self.x, self.y, self.z, self.w)
    }
}

impl<T: fmt::Display> fmt::Display for Point4D<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "({},{},{},{})", self.x, self.y, self.z, self.w)
    }
}

impl<T> Point4D<T> {
    #[inline]
    pub fn new(x: T, y: T, z: T, w: T) -> Point4D<T> {
        Point4D {x: x, y: y, z: z, w: w}
    }
}

impl<T:Clone + Add<T, Output=T>> Add for Point4D<T> {
    type Output = Point4D<T>;
    fn add(self, other: Point4D<T>) -> Point4D<T> {
        Point4D::new(self.x + other.x,
                     self.y + other.y,
                     self.z + other.z,
                     self.w + other.w)
    }
}

impl<T:Clone + Sub<T, Output=T>> Sub for Point4D<T> {
    type Output = Point4D<T>;
    fn sub(self, other: Point4D<T>) -> Point4D<T> {
        Point4D::new(self.x - other.x,
                     self.y - other.y,
                     self.z - other.z,
                     self.w - other.w)
    }
}

impl <T:Clone + Neg<Output=T>> Neg for Point4D<T> {
    type Output = Point4D<T>;
    #[inline]
    fn neg(self) -> Point4D<T> {
        Point4D::new(-self.x, -self.y, -self.z, -self.w)
    }
}
<commit_msg>Add vector inner and outer products.<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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 length::Length;
use size::Size2D;
use num::Zero;

use num_lib::NumCast;
use std::fmt::{self, Formatter};
use std::ops::{Add, Neg, Mul, Sub, Div};

#[derive(Clone, Copy, RustcDecodable, RustcEncodable, Eq, Hash, PartialEq, Deserialize, Serialize)]
#[cfg_attr(feature = "heap_size", derive(HeapSizeOf))]
pub struct Point2D<T> {
    pub x: T,
    pub y: T
}

impl<T: Zero> Point2D<T> {
    pub fn zero() -> Point2D<T> {
        Point2D { x: Zero::zero(), y: Zero::zero() }
    }
}

impl<T: fmt::Debug> fmt::Debug for Point2D<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({:?},{:?})", self.x, self.y)
    }
}

impl<T: fmt::Display> fmt::Display for Point2D<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "({},{})", self.x, self.y)
    }
}

impl<T> Point2D<T> {
    pub fn new(x: T, y: T) -> Point2D<T> {
        Point2D {x: x, y: y}
    }
}

impl<T: Mul<T, Output=T> +
        Add<T, Output=T> +
        Sub<T, Output=T> +
        Copy> Point2D<T> {
    #[inline]
    pub fn dot(self, other: Point2D<T>) -> T {
        self.x * other.x +
        self.y * other.y
    }

    #[inline]
    pub fn cross(self, other: Point2D<T>) -> T {
        self.x * other.y - self.y * other.x
    }
}

impl<T:Clone + Add<T, Output=T>> Add for Point2D<T> {
    type Output = Point2D<T>;
    fn add(self, other: Point2D<T>) -> Point2D<T> {
        Point2D::new(self.x + other.x, self.y + other.y)
    }
}

impl<T:Clone + Add<T, Output=T>> Add<Size2D<T>> for Point2D<T> {
    type Output = Point2D<T>;
    fn add(self, other: Size2D<T>) -> Point2D<T> {
        Point2D::new(self.x + other.width, self.y + other.height)
    }
}

impl<T: Copy + Add<T, Output=T>> Point2D<T> {
    pub fn add_size(&self, other: &Size2D<T>) -> Point2D<T> {
        Point2D { x: self.x + other.width, y: self.y + other.height }
    }
}

impl<T:Clone + Sub<T, Output=T>> Sub for Point2D<T> {
    type Output = Point2D<T>;
    fn sub(self, other: Point2D<T>) -> Point2D<T> {
        Point2D::new(self.x - other.x, self.y - other.y)
    }
}

impl <T:Clone + Neg<Output=T>> Neg for Point2D<T> {
    type Output = Point2D<T>;
    #[inline]
    fn neg(self) -> Point2D<T> {
        Point2D::new(-self.x, -self.y)
    }
}

impl<Scale: Copy, T0: Mul<Scale, Output=T1>, T1: Clone> Mul<Scale> for Point2D<T0> {
    type Output = Point2D<T1>;
    #[inline]
    fn mul(self, scale: Scale) -> Point2D<T1> {
        Point2D::new(self.x * scale, self.y * scale)
    }
}

impl<Scale: Copy, T0: Div<Scale, Output=T1>, T1: Clone> Div<Scale> for Point2D<T0> {
    type Output = Point2D<T1>;
    #[inline]
    fn div(self, scale: Scale) -> Point2D<T1> {
        Point2D::new(self.x / scale, self.y / scale)
    }
}

// Convenient aliases for Point2D with typed units

pub type TypedPoint2D<Unit, T> = Point2D<Length<Unit, T>>;

impl<Unit, T: Clone> Point2D<Length<Unit, T>> {
    pub fn typed(x: T, y: T) -> TypedPoint2D<Unit, T> {
        Point2D::new(Length::new(x), Length::new(y))
    }

    /// Drop the units, preserving only the numeric value.
    pub fn to_untyped(&self) -> Point2D<T> {
        Point2D::new(self.x.get(), self.y.get())
    }

    /// Tag a unitless value with units.
    pub fn from_untyped(p: &Point2D<T>) -> TypedPoint2D<Unit, T> {
        Point2D::new(Length::new(p.x.clone()), Length::new(p.y.clone()))
    }
}

impl<Unit, T0: NumCast + Clone> Point2D<Length<Unit, T0>> {
    /// Cast from one numeric representation to another, preserving the units.
    pub fn cast<T1: NumCast + Clone>(&self) -> Option<Point2D<Length<Unit, T1>>> {
        match (self.x.cast(), self.y.cast()) {
            (Some(x), Some(y)) => Some(Point2D::new(x, y)),
            _ => None
        }
    }
}

// Convenience functions for common casts
impl<Unit, T: NumCast + Clone> Point2D<Length<Unit, T>> {
    pub fn as_f32(&self) -> Point2D<Length<Unit, f32>> {
        self.cast().unwrap()
    }

    pub fn as_uint(&self) -> Point2D<Length<Unit, usize>> {
        self.cast().unwrap()
    }
}

#[derive(Clone, Copy, RustcDecodable, RustcEncodable, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "heap_size", derive(HeapSizeOf))]
pub struct Point3D<T> {
    pub x: T,
    pub y: T,
    pub z: T,
}

impl<T: Zero> Point3D<T> {
    #[inline]
    pub fn zero() -> Point3D<T> {
        Point3D { x: Zero::zero(), y: Zero::zero(), z: Zero::zero() }
    }
}

impl<T: fmt::Debug> fmt::Debug for Point3D<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({:?},{:?},{:?})", self.x, self.y, self.z)
    }
}

impl<T: fmt::Display> fmt::Display for Point3D<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "({},{},{})", self.x, self.y, self.z)
    }
}

impl<T> Point3D<T> {
    #[inline]
    pub fn new(x: T, y: T, z: T) -> Point3D<T> {
        Point3D {x: x, y: y, z: z}
    }
}

impl<T: Mul<T, Output=T> +
        Add<T, Output=T> +
        Sub<T, Output=T> +
        Copy> Point3D<T> {
    #[inline]
    pub fn dot(self, other: Point3D<T>) -> T {
        self.x * other.x +
        self.y * other.y +
        self.z * other.z
    }

    #[inline]
    pub fn cross(self, other: Point3D<T>) -> Point3D<T> {
        Point3D {
            x: self.y * other.z - self.z * other.y,
            y: self.z * other.x - self.x * other.z,
            z: self.x * other.y - self.y * other.x,
        }
    }
}

impl<T:Clone + Add<T, Output=T>> Add for Point3D<T> {
    type Output = Point3D<T>;
    fn add(self, other: Point3D<T>) -> Point3D<T> {
        Point3D::new(self.x + other.x,
                     self.y + other.y,
                     self.z + other.z)
    }
}

impl<T:Clone + Sub<T, Output=T>> Sub for Point3D<T> {
    type Output = Point3D<T>;
    fn sub(self, other: Point3D<T>) -> Point3D<T> {
        Point3D::new(self.x - other.x,
                     self.y - other.y,
                     self.z - other.z)
    }
}

impl <T:Clone + Neg<Output=T>> Neg for Point3D<T> {
    type Output = Point3D<T>;
    #[inline]
    fn neg(self) -> Point3D<T> {
        Point3D::new(-self.x, -self.y, -self.z)
    }
}

#[derive(Clone, Copy, RustcDecodable, RustcEncodable, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "heap_size", derive(HeapSizeOf))]
pub struct Point4D<T> {
    pub x: T,
    pub y: T,
    pub z: T,
    pub w: T,
}

impl<T: Zero> Point4D<T> {
    #[inline]
    pub fn zero() -> Point4D<T> {
        Point4D {
            x: Zero::zero(),
            y: Zero::zero(),
            z: Zero::zero(),
            w: Zero::zero()
        }
    }
}

impl<T: fmt::Debug> fmt::Debug for Point4D<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({:?},{:?},{:?},{:?})", self.x, self.y, self.z, self.w)
    }
}

impl<T: fmt::Display> fmt::Display for Point4D<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "({},{},{},{})", self.x, self.y, self.z, self.w)
    }
}

impl<T> Point4D<T> {
    #[inline]
    pub fn new(x: T, y: T, z: T, w: T) -> Point4D<T> {
        Point4D {x: x, y: y, z: z, w: w}
    }
}

impl<T:Clone + Add<T, Output=T>> Add for Point4D<T> {
    type Output = Point4D<T>;
    fn add(self, other: Point4D<T>) -> Point4D<T> {
        Point4D::new(self.x + other.x,
                     self.y + other.y,
                     self.z + other.z,
                     self.w + other.w)
    }
}

impl<T:Clone + Sub<T, Output=T>> Sub for Point4D<T> {
    type Output = Point4D<T>;
    fn sub(self, other: Point4D<T>) -> Point4D<T> {
        Point4D::new(self.x - other.x,
                     self.y - other.y,
                     self.z - other.z,
                     self.w - other.w)
    }
}

impl <T:Clone + Neg<Output=T>> Neg for Point4D<T> {
    type Output = Point4D<T>;
    #[inline]
    fn neg(self) -> Point4D<T> {
        Point4D::new(-self.x, -self.y, -self.z, -self.w)
    }
}

#[test]
pub fn test_dot_2d() {
    let p1 = Point2D::new(2.0, 7.0);
    let p2 = Point2D::new(13.0, 11.0);
    assert!(p1.dot(p2) == 103.0);
}

#[test]
pub fn test_dot_3d() {
    let p1 = Point3D::new(7.0, 21.0, 32.0);
    let p2 = Point3D::new(43.0, 5.0, 16.0);
    assert!(p1.dot(p2) == 918.0);
}

#[test]
pub fn test_cross_2d() {
    let p1 = Point2D::new(4.0, 7.0);
    let p2 = Point2D::new(13.0, 8.0);
    let r = p1.cross(p2);
    assert!(r == -59.0);
}

#[test]
pub fn test_cross_3d() {
    let p1 = Point3D::new(4.0, 7.0, 9.0);
    let p2 = Point3D::new(13.0, 8.0, 3.0);
    let p3 = p1.cross(p2);
    assert!(p3.x == -51.0);
    assert!(p3.y == 105.0);
    assert!(p3.z == -59.0);
}
<|endoftext|>


<commit_before>
use error::MpdResult;
use client::MpdClient;
use songs::MpdSong;
use playlists::MpdPlaylist;

pub struct MpdQueue;

pub trait MpdQueuePos {
    fn to_pos(self) -> String;
}

impl MpdQueuePos for uint {
    fn to_pos(self) -> String { self.to_string() }
}

impl MpdQueuePos for (uint, uint) {
    fn to_pos(self) -> String { format!("{}:{}", self.0, self.1) }
}

impl MpdQueue {
    pub fn clear<S: Stream>(client: &mut MpdClient<S>) -> MpdResult<()> {
        client.exec("clear").and_then(|_| client.ok())
    }

    pub fn push<S: Stream>(client: &mut MpdClient<S>, file: &str) -> MpdResult<()> {
        client.exec_arg("add", file).and_then(|_| client.ok())
    }

    pub fn insert<S: Stream>(client: &mut MpdClient<S>, index: uint, file: &str) -> MpdResult<uint> {
        let result = client.exec_arg2("addid", file, uint)
            .and_then(|_| client.iter().next().unwrap_or(Err(FromError::from_error(standard_error(IoErrorKind::InvalidInput)))))
            .and_then(|Ok(MpdPair(ref name, ref value))| if name[] == "Id" { Ok(value.parse()) } else {
                Err(FromError::from_error(standard_error(IoErrorKind::InvalidInput))) });
        try!(client.ok());
        result
    }

    pub fn swap<S: Stream>(client: &mut MpdClient<S>, index1: uint, index2: uint) -> MpdResult<uint> {
        client.exec_arg2("swap", index1, index2).and_then(|_| client.ok())
    }

    pub fn shift<S: Stream, I: MpdQueuePos>(client: &mut MpdClient<S>, index: I, target: uint) -> MpdResult<()> {
        client.exec_arg2("move", index.to_pos(), target).and_then(|_| client.ok())
    }

    pub fn get<S: Stream, I: MpdQueuePos>(client: &mut MpdClient<S>, index: I) -> MpdResult<MpdSong> {
        client.exec_arg("playlistinfo", index.to_pos()).and_then(|_| client.iter().collect())
    }

    pub fn remove<S: Stream, I: MpdQueuePos>(client: &mut MpdClient<S>, index: I) -> MpdResult<()> {
        client.exec_arg("delete", index.to_pos()).and_then(|_| client.ok())
    }

    pub fn songs<S: Stream>(client: &mut MpdClient<S>) -> MpdResult<Vec<MpdSong>> {
        client.exec("playlistinfo").and_then(|_| client.iter().collect())
    }

    pub fn shuffle_slice<S: Stream>(client: &mut MpdClient<S>, slice: (uint, uint)) -> MpdResult<()> {
        client.exec_arg("shuffle", format!("{}:{}", slice.0, slice.1)).and_then(|_| client.ok())
    }

    pub fn shuffle<S: Stream>(client: &mut MpdClient<S>) -> MpdResult<()> {
        client.exec("shuffle").and_then(|_| client.ok())
    }

    pub fn load<S: Stream>(client: &mut MpdClient<S>, name: &str) -> MpdResult<()> {
        client.exec_arg("load", name).and_then(|_| client.ok())
    }

    pub fn load_slice<S: Stream>(client: &mut MpdClient<S>, name: &str, slice: (uint, uint)) -> MpdResult<()> {
        client.exec_arg2("load", name, format!("{}:{}", slice.0, slice.1)).and_then(|_| client.ok())
    }

    pub fn save<S: Stream>(client: &mut MpdClient<S>, name: &str) -> MpdResult<()> {
        client.exec_arg("save", name).and_then(|_| client.ok())
    }
}
<commit_msg>queue operations by id<commit_after>
use error::MpdResult;
use client::MpdClient;
use songs::MpdSong;
use playlists::MpdPlaylist;

pub struct MpdQueue;

pub trait MpdQueuePos {
    fn to_pos(self) -> String;
}

impl MpdQueuePos for uint {
    fn to_pos(self) -> String { self.to_string() }
}

impl MpdQueuePos for (uint, uint) {
    fn to_pos(self) -> String { format!("{}:{}", self.0, self.1) }
}

impl MpdQueue {
    pub fn clear<S: Stream>(client: &mut MpdClient<S>) -> MpdResult<()> {
        client.exec("clear").and_then(|_| client.ok())
    }

    pub fn push<S: Stream>(client: &mut MpdClient<S>, file: &str) -> MpdResult<()> {
        client.exec_arg("add", file).and_then(|_| client.ok())
    }

    pub fn insert<S: Stream>(client: &mut MpdClient<S>, index: uint, file: &str) -> MpdResult<uint> {
        let result = client.exec_arg2("addid", file, uint)
            .and_then(|_| client.iter().next().unwrap_or(Err(FromError::from_error(standard_error(IoErrorKind::InvalidInput)))))
            .and_then(|Ok(MpdPair(ref name, ref value))| if name[] == "Id" { Ok(value.parse()) } else {
                Err(FromError::from_error(standard_error(IoErrorKind::InvalidInput))) });
        try!(client.ok());
        result
    }

    pub fn swap<S: Stream>(client: &mut MpdClient<S>, index1: uint, index2: uint) -> MpdResult<uint> {
        client.exec_arg2("swap", index1, index2).and_then(|_| client.ok())
    }

    pub fn shift<S: Stream, I: MpdQueuePos>(client: &mut MpdClient<S>, index: I, target: uint) -> MpdResult<()> {
        client.exec_arg2("move", index.to_pos(), target).and_then(|_| client.ok())
    }

    pub fn get<S: Stream>(client: &mut MpdClient<S>, index: uint) -> MpdResult<MpdSong> {
        client.exec_arg("playlistinfo", index).and_then(|_| client.iter().collect())
    }

    pub fn slice<S: Stream>(client: &mut MpdClient<S>, slice: (uint, uint)) -> MpdResult<Vec<MpdSong>> {
        client.exec_arg("playlistinfo", format!("{}:{}", slice.0, slice.1)).and_then(|_| client.iter().collect())
    }

    pub fn remove<S: Stream, I: MpdQueuePos>(client: &mut MpdClient<S>, index: I) -> MpdResult<()> {
        client.exec_arg("delete", index.to_pos()).and_then(|_| client.ok())
    }

    pub fn removeid<S: Stream>(client: &mut MpdClient<S>, id: uint) -> MpdResult<()> {
        client.exec_arg("deleteid", id).and_then(|_| client.ok())
    }

    pub fn shiftid<S: Stream>(client: &mut MpdClient<S>, id: uint, target: uint) -> MpdResult<()> {
        client.exec_arg2("moveid", id, target).and_then(|_| client.ok())
    }

    pub fn getid<S: Stream>(client: &mut MpdClient<S>, id: uint) -> MpdResult<MpdSong> {
        client.exec_arg("playlistid", id).and_then(|_| client.iter().collect())
    }

    pub fn songs<S: Stream>(client: &mut MpdClient<S>) -> MpdResult<Vec<MpdSong>> {
        client.exec("playlistinfo").and_then(|_| client.iter().collect())
    }

    pub fn shuffle_slice<S: Stream>(client: &mut MpdClient<S>, slice: (uint, uint)) -> MpdResult<()> {
        client.exec_arg("shuffle", format!("{}:{}", slice.0, slice.1)).and_then(|_| client.ok())
    }

    pub fn shuffle<S: Stream>(client: &mut MpdClient<S>) -> MpdResult<()> {
        client.exec("shuffle").and_then(|_| client.ok())
    }

    pub fn load<S: Stream>(client: &mut MpdClient<S>, name: &str) -> MpdResult<()> {
        client.exec_arg("load", name).and_then(|_| client.ok())
    }

    pub fn load_slice<S: Stream>(client: &mut MpdClient<S>, name: &str, slice: (uint, uint)) -> MpdResult<()> {
        client.exec_arg2("load", name, format!("{}:{}", slice.0, slice.1)).and_then(|_| client.ok())
    }

    pub fn save<S: Stream>(client: &mut MpdClient<S>, name: &str) -> MpdResult<()> {
        client.exec_arg("save", name).and_then(|_| client.ok())
    }
}
<|endoftext|>