<commit_before>use cssparser::{self, BasicParseError, CompactCowStr, DeclarationListParser, Parser, ParseError, ParserInput, Token};
use orbclient::Color;
use std::collections::HashSet;
use std::sync::Arc;
use std::mem;
use std::ops::Add;

static DEFAULT_THEME_CSS: &'static str = include_str!("theme.css");

lazy_static! {
    static ref DEFAULT_THEME: Arc<Theme> = {
        Arc::new(Theme {parent: None, rules: parse(DEFAULT_THEME_CSS)})
    };
}

pub struct Theme {
    parent: Option<Arc<Theme>>,
    rules: Vec<Rule>,
}

impl Theme {
    pub fn new() -> Self {
        Theme::parse("")
    }

    pub fn parse(s: &str) -> Self {
        Theme {
            parent: Some(DEFAULT_THEME.clone()),
            rules: parse(s),
        }
    }

    fn all_rules(&self) -> Vec<Rule> {
        if let Some(ref parent) = self.parent {
            parent.rules.iter().chain(self.rules.iter()).cloned().collect()
        } else {
            self.rules.clone()
        }
    }

    pub fn get(&self, property: &str, query: &Selector) -> Option<Value> {
        let mut matches: Vec<(bool, Specificity, Value)> = Vec::new();

        for rule in self.all_rules().iter().rev() {
            let matching_selectors = rule.selectors.iter().filter(|x| x.matches(query)).collect::<Vec<_>>();

            if matching_selectors.len() > 0 {
                if let Some(decl) = rule.declarations.iter().find(|decl| decl.property == property) {
                    let highest_specifity = matching_selectors.iter().map(|sel| sel.specificity()).max().unwrap();
                    matches.push((decl.important, highest_specifity, decl.value.clone()));
                }
            }
        }

        matches.sort_by_key(|x| (x.0, x.1));
        matches.last().map(|x| x.2.clone())
    }

    pub fn color(&self, property: &str, query: &Selector) -> Color {
        let default = Color { data: 0 };
        self.get(property, query).map(|v| v.color().unwrap_or(default)).unwrap_or(default)
    }

    pub fn uint(&self, property: &str, query: &Selector) -> u32 {
        self.get(property, query).map(|v| v.uint().unwrap_or(0)).unwrap_or(0)
    }
}

#[derive(Clone, Debug)]
pub struct Rule {
    pub selectors: Vec<Selector>,
    pub declarations: Vec<Declaration>,
}

#[derive(Clone, Debug)]
pub enum SelectorRelation {
    Ancestor(Selector),
    Parent(Selector),
}

impl<T: Into<String>> From<T> for Selector {
    fn from(t: T) -> Self {
        Selector::new(Some(t.into()))
    }
}

/// Describes the specificity of a selector.
///
/// The indexes are as follows:
/// 0 - number of IDs (most important)
/// 1 - number of classes and pseudo-classes
/// 2 - number of elements (least important)
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Specificity([u8; 3]);

impl Add<Self> for Specificity {
    type Output = Self;

    fn add(self, rhs: Self) -> Self::Output {
        Specificity([
            self.0[0] + rhs.0[0],
            self.0[1] + rhs.0[1],
            self.0[2] + rhs.0[2],
        ])
    }
}

#[derive(Clone, Debug, Default)]
pub struct Selector {
    pub element: Option<String>,
    pub classes: HashSet<String>,
    pub pseudo_classes: HashSet<String>,
    pub relation: Option<Box<SelectorRelation>>,
}

impl Selector {
    pub fn new<S: Into<String>>(element: Option<S>) -> Self {
        Selector {
            element: element.map(|s| s.into()),
            classes: HashSet::new(),
            pseudo_classes: HashSet::new(),
            relation: None,
        }
    }

    fn specificity(&self) -> Specificity {
        let s = Specificity([
            0,
            (self.classes.len() + self.pseudo_classes.len()) as u8,
            if self.element.is_some() { 1 } else { 0 }
        ]);

        if let Some(ref relation) = self.relation {
            match **relation {
                SelectorRelation::Ancestor(ref x) | SelectorRelation::Parent(ref x) => return x.specificity() + s,
            }
        }

        s
    }

    pub fn matches(&self, other: &Selector) -> bool {
        if self.element.is_some() && self.element != other.element {
            return false;
        }

        if !other.classes.is_superset(&self.classes) {
            return false;
        }

        if !other.pseudo_classes.is_superset(&self.pseudo_classes) {
            return false;
        }

        true
    }

    pub fn with_class<S: Into<String>>(mut self, class: S) -> Self {
        self.classes.insert(class.into());
        self
    }

    pub fn with_pseudo_class<S: Into<String>>(mut self, pseudo_class: S) -> Self {
        self.pseudo_classes.insert(pseudo_class.into());
        self
    }
}

impl Selector {
    pub fn is_empty(&self) -> bool {
        self.element.is_none() && self.classes.is_empty() && self.pseudo_classes.is_empty()
    }
}

#[derive(Clone, Debug)]
pub struct Declaration {
    pub property: String,
    pub value: Value,
    pub important: bool,
}

#[derive(Clone, Debug)]
pub enum Value {
    UInt(u32),
    Color(Color),
}

impl Value {
    pub fn uint(&self) -> Option<u32> {
        match *self {
            Value::UInt(x) => Some(x),
            _ => None,
        }
    }

    pub fn color(&self) -> Option<Color> {
        match *self {
            Value::Color(x) => Some(x),
            _ => None,
        }
    }
}

#[derive(Clone, Debug)]
pub enum CustomParseError {
    InvalidColorName(String),
    InvalidColorHex(String),
}

impl<'t> From<CustomParseError> for ParseError<'t, CustomParseError> {
    fn from(e: CustomParseError) -> Self {
        ParseError::Custom(e)
    }
}

struct RuleParser;

impl RuleParser {
    fn new() -> Self {
        RuleParser {}
    }
}

impl<'i> cssparser::QualifiedRuleParser<'i> for RuleParser {
    type Prelude = Vec<Selector>;
    type QualifiedRule = Rule;
    type Error = CustomParseError;

    fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>)
        -> Result<Self::Prelude, ParseError<'i, Self::Error>> {
        let res = parse_selectors(input)?;
        Ok(res)
    }

    fn parse_block<'t>(&mut self, selectors: Self::Prelude, input: &mut Parser<'i, 't>)
        -> Result<Self::QualifiedRule, ParseError<'i, Self::Error>> {
        let decl_parser = DeclarationParser {};

        let decls = DeclarationListParser::new(input, decl_parser).collect::<Vec<_>>();

        for decl in &decls {
            match *decl {
                Ok(_) => {},
                Err(ref e) => {
                    match e.error {
                        ParseError::Basic(ref e) => eprintln!("{:?}", e),
                        ParseError::Custom(ref e) => eprintln!("{:?}", e),
                    }
                    println!("Error occured in `{}`", input.slice(e.span.clone()));
                }
            }
        }

        let decls = decls.into_iter().filter_map(|decl| decl.ok()).collect();

        Ok(Rule {
            selectors: selectors,
            declarations: decls,
        })
    }
}

impl<'i> cssparser::AtRuleParser<'i> for RuleParser {
    type Prelude = ();
    type AtRule = Rule;
    type Error = CustomParseError;
}

fn parse_selectors<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Vec<Selector>, ParseError<'i, CustomParseError>> {
    let mut selectors = Vec::new();

    let mut selector = Selector::default();

    let mut first_token_in_selector = true;
    while let Ok(t) = input.next() {
        match t {
            // Element
            Token::Ident(ref element_name) => {
                if first_token_in_selector {
                    selector.element = Some(element_name.to_string())
                } else {
                    let mut old_selector = Selector::new(Some(element_name.to_string()));
                    mem::swap(&mut old_selector, &mut selector);
                    selector.relation = Some(Box::new(SelectorRelation::Ancestor(old_selector)));
                }
            }

            Token::Delim('>') => {
                let mut old_selector = Selector::new(Some(input.expect_ident()?.to_string()));
                mem::swap(&mut old_selector, &mut selector);
                selector.relation = Some(Box::new(SelectorRelation::Parent(old_selector)));
            }

            // Any element
            Token::Delim('*') => {}

            // Class
            Token::Delim('.') => {selector.classes.insert(input.expect_ident()?.into_owned());}

            // Pseudo-class
            Token::Colon => {selector.pseudo_classes.insert(input.expect_ident()?.into_owned());}

            // This selector is done, on to the next one
            Token::Comma => {
                selectors.push(selector);
                selector = Selector::default();
                first_token_in_selector = true;
                continue; // need to continue to avoid `first_token_in_selector` being set to false
            }

            t => {
                let basic_error = BasicParseError::UnexpectedToken(t);
                return Err(basic_error.into());
            }
        }

        first_token_in_selector = false;
    }

    selectors.push(selector);

    if selectors.iter().any(|sel| sel.relation.is_some()) {
        eprintln!("WARNING: Complex selector relations not implemented");
    }

    Ok(selectors)
}

struct DeclarationParser;

impl<'i> cssparser::DeclarationParser<'i> for DeclarationParser {
    type Declaration = Declaration;
    type Error = CustomParseError;

    fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>) -> Result<Self::Declaration, ParseError<'i, Self::Error>> {
        let value = match &*name {
            "color" | "border-color" => Value::Color(parse_basic_color(input)?),

            "background" | "foreground" => Value::Color(parse_basic_color(input)?),

            "border-radius" | "border-width" => {
                match input.next()? {
                    Token::Number { int_value: Some(x), has_sign, .. } if !has_sign && x >= 0 => Value::UInt(x as u32),
                    t => return Err(BasicParseError::UnexpectedToken(t).into())
                }
            }

            _ => return Err(BasicParseError::UnexpectedToken(input.next()?).into()),
        };

        Ok(Declaration {
            property: name.into_owned(),
            value: value,
            important: input.try(cssparser::parse_important).is_ok()
        })
    }
}

impl<'i> cssparser::AtRuleParser<'i> for DeclarationParser {
    type Prelude = ();
    type AtRule = Declaration;
    type Error = CustomParseError;
}

fn css_color(name: &str) -> Option<Color> {
    Some(hex(match name {
        "transparent" => return Some(Color { data: 0 }),

        "black" => 0x000000,
        "silver" => 0xc0c0c0,
        "gray" | "grey" => 0x808080,
        "white" => 0xffffff,
        "maroon" => 0x800000,
        "red" => 0xff0000,
        "purple" => 0x800080,
        "fuchsia" => 0xff00ff,
        "green" => 0x008000,
        "lime" => 0x00ff00,
        "olive" => 0x808000,
        "yellow" => 0xffff00,
        "navy" => 0x000080,
        "blue" => 0x0000ff,
        "teal" => 0x008080,
        "aqua" => 0x00ffff,
        _ => return None,
    }))
}

fn parse_basic_color<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Color, ParseError<'i, CustomParseError>> {
    Ok(match input.next()? {
        Token::Ident(s) => match css_color(&s) {
            Some(color) => color,
            None => return Err(CustomParseError::InvalidColorName(s.into_owned()).into()),
        },

        Token::IDHash(hash) | Token::Hash(hash) => {
            match hash.len() {
                6 | 8 => {
                    let mut x = match u32::from_str_radix(&hash, 16) {
                        Ok(x) => x,
                        Err(_) => return Err(CustomParseError::InvalidColorHex(hash.into_owned()).into()),
                    };

                    if hash.len() == 6 {
                        x |= 0xFF000000;
                    }

                    Color { data: x }
                },
                _ => return Err(CustomParseError::InvalidColorHex(hash.into_owned()).into()),
            }
        }

        t => {
            let basic_error = BasicParseError::UnexpectedToken(t);
            return Err(basic_error.into());
        }
    })
}

fn parse(s: &str) -> Vec<Rule> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);
    let rule_parser = RuleParser::new();

    let rules = {
        let rule_list_parser = cssparser::RuleListParser::new_for_stylesheet(&mut parser, rule_parser);
        rule_list_parser.collect::<Vec<_>>()
    };

    for rule in &rules {
        match *rule {
            Ok(_) => {},
            Err(ref e) => {
                match e.error {
                    ParseError::Basic(ref e) => eprintln!("{:?}", e),
                    ParseError::Custom(ref e) => eprintln!("{:?}", e),
                }
                println!("Error occured in `{}`", parser.slice(e.span.clone()));
            }
        }
    }

    rules.into_iter().filter_map(|rule| rule.ok()).collect()
}

const fn hex(data: u32) -> Color {
    Color { data: 0xFF000000 | data }
}
<commit_msg>Add a from_file constructor for the `Themes` struct<commit_after>use cssparser::{self, BasicParseError, CompactCowStr, DeclarationListParser, Parser, ParseError, ParserInput, Token};
use orbclient::Color;
use std::collections::HashSet;
use std::sync::Arc;
use std::mem;
use std::ops::Add;
use std::path::Path;

use std::fs::File;
use std::io::BufReader;
use std::io::Read;

static DEFAULT_THEME_CSS: &'static str = include_str!("theme.css");

lazy_static! {
    static ref DEFAULT_THEME: Arc<Theme> = {
        Arc::new(Theme {parent: None, rules: parse(DEFAULT_THEME_CSS)})
    };
}

pub struct Theme {
    parent: Option<Arc<Theme>>,
    rules: Vec<Rule>,
}

impl Theme {
    pub fn new() -> Self {
        Theme::parse("")
    }

    pub fn parse(s: &str) -> Self {
        Theme {
            parent: Some(DEFAULT_THEME.clone()),
            rules: parse(s),
        }
    }

    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Theme, String> {
        let file = try!(File::open(path).map_err(|err| format!("failed to open css: {}", err)));
        let mut reader = BufReader::new(file);
        let mut css = String::new();
        let res = reader.read_to_string(&mut css).map_err(|err| format!("failed to read css: {}", err));
        match res {
            Ok(_) => Ok(Theme::parse(&css)),
            Err(err) => Err(err),
        }
    }

    fn all_rules(&self) -> Vec<Rule> {
        if let Some(ref parent) = self.parent {
            parent.rules.iter().chain(self.rules.iter()).cloned().collect()
        } else {
            self.rules.clone()
        }
    }

    pub fn get(&self, property: &str, query: &Selector) -> Option<Value> {
        let mut matches: Vec<(bool, Specificity, Value)> = Vec::new();

        for rule in self.all_rules().iter().rev() {
            let matching_selectors = rule.selectors.iter().filter(|x| x.matches(query)).collect::<Vec<_>>();

            if matching_selectors.len() > 0 {
                if let Some(decl) = rule.declarations.iter().find(|decl| decl.property == property) {
                    let highest_specifity = matching_selectors.iter().map(|sel| sel.specificity()).max().unwrap();
                    matches.push((decl.important, highest_specifity, decl.value.clone()));
                }
            }
        }

        matches.sort_by_key(|x| (x.0, x.1));
        matches.last().map(|x| x.2.clone())
    }

    pub fn color(&self, property: &str, query: &Selector) -> Color {
        let default = Color { data: 0 };
        self.get(property, query).map(|v| v.color().unwrap_or(default)).unwrap_or(default)
    }

    pub fn uint(&self, property: &str, query: &Selector) -> u32 {
        self.get(property, query).map(|v| v.uint().unwrap_or(0)).unwrap_or(0)
    }
}

#[derive(Clone, Debug)]
pub struct Rule {
    pub selectors: Vec<Selector>,
    pub declarations: Vec<Declaration>,
}

#[derive(Clone, Debug)]
pub enum SelectorRelation {
    Ancestor(Selector),
    Parent(Selector),
}

impl<T: Into<String>> From<T> for Selector {
    fn from(t: T) -> Self {
        Selector::new(Some(t.into()))
    }
}

/// Describes the specificity of a selector.
///
/// The indexes are as follows:
/// 0 - number of IDs (most important)
/// 1 - number of classes and pseudo-classes
/// 2 - number of elements (least important)
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Specificity([u8; 3]);

impl Add<Self> for Specificity {
    type Output = Self;

    fn add(self, rhs: Self) -> Self::Output {
        Specificity([
            self.0[0] + rhs.0[0],
            self.0[1] + rhs.0[1],
            self.0[2] + rhs.0[2],
        ])
    }
}

#[derive(Clone, Debug, Default)]
pub struct Selector {
    pub element: Option<String>,
    pub classes: HashSet<String>,
    pub pseudo_classes: HashSet<String>,
    pub relation: Option<Box<SelectorRelation>>,
}

impl Selector {
    pub fn new<S: Into<String>>(element: Option<S>) -> Self {
        Selector {
            element: element.map(|s| s.into()),
            classes: HashSet::new(),
            pseudo_classes: HashSet::new(),
            relation: None,
        }
    }

    fn specificity(&self) -> Specificity {
        let s = Specificity([
            0,
            (self.classes.len() + self.pseudo_classes.len()) as u8,
            if self.element.is_some() { 1 } else { 0 }
        ]);

        if let Some(ref relation) = self.relation {
            match **relation {
                SelectorRelation::Ancestor(ref x) | SelectorRelation::Parent(ref x) => return x.specificity() + s,
            }
        }

        s
    }

    pub fn matches(&self, other: &Selector) -> bool {
        if self.element.is_some() && self.element != other.element {
            return false;
        }

        if !other.classes.is_superset(&self.classes) {
            return false;
        }

        if !other.pseudo_classes.is_superset(&self.pseudo_classes) {
            return false;
        }

        true
    }

    pub fn with_class<S: Into<String>>(mut self, class: S) -> Self {
        self.classes.insert(class.into());
        self
    }

    pub fn with_pseudo_class<S: Into<String>>(mut self, pseudo_class: S) -> Self {
        self.pseudo_classes.insert(pseudo_class.into());
        self
    }
}

impl Selector {
    pub fn is_empty(&self) -> bool {
        self.element.is_none() && self.classes.is_empty() && self.pseudo_classes.is_empty()
    }
}

#[derive(Clone, Debug)]
pub struct Declaration {
    pub property: String,
    pub value: Value,
    pub important: bool,
}

#[derive(Clone, Debug)]
pub enum Value {
    UInt(u32),
    Color(Color),
}

impl Value {
    pub fn uint(&self) -> Option<u32> {
        match *self {
            Value::UInt(x) => Some(x),
            _ => None,
        }
    }

    pub fn color(&self) -> Option<Color> {
        match *self {
            Value::Color(x) => Some(x),
            _ => None,
        }
    }
}

#[derive(Clone, Debug)]
pub enum CustomParseError {
    InvalidColorName(String),
    InvalidColorHex(String),
}

impl<'t> From<CustomParseError> for ParseError<'t, CustomParseError> {
    fn from(e: CustomParseError) -> Self {
        ParseError::Custom(e)
    }
}

struct RuleParser;

impl RuleParser {
    fn new() -> Self {
        RuleParser {}
    }
}

impl<'i> cssparser::QualifiedRuleParser<'i> for RuleParser {
    type Prelude = Vec<Selector>;
    type QualifiedRule = Rule;
    type Error = CustomParseError;

    fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>)
        -> Result<Self::Prelude, ParseError<'i, Self::Error>> {
        let res = parse_selectors(input)?;
        Ok(res)
    }

    fn parse_block<'t>(&mut self, selectors: Self::Prelude, input: &mut Parser<'i, 't>)
        -> Result<Self::QualifiedRule, ParseError<'i, Self::Error>> {
        let decl_parser = DeclarationParser {};

        let decls = DeclarationListParser::new(input, decl_parser).collect::<Vec<_>>();

        for decl in &decls {
            match *decl {
                Ok(_) => {},
                Err(ref e) => {
                    match e.error {
                        ParseError::Basic(ref e) => eprintln!("{:?}", e),
                        ParseError::Custom(ref e) => eprintln!("{:?}", e),
                    }
                    println!("Error occured in `{}`", input.slice(e.span.clone()));
                }
            }
        }

        let decls = decls.into_iter().filter_map(|decl| decl.ok()).collect();

        Ok(Rule {
            selectors: selectors,
            declarations: decls,
        })
    }
}

impl<'i> cssparser::AtRuleParser<'i> for RuleParser {
    type Prelude = ();
    type AtRule = Rule;
    type Error = CustomParseError;
}

fn parse_selectors<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Vec<Selector>, ParseError<'i, CustomParseError>> {
    let mut selectors = Vec::new();

    let mut selector = Selector::default();

    let mut first_token_in_selector = true;
    while let Ok(t) = input.next() {
        match t {
            // Element
            Token::Ident(ref element_name) => {
                if first_token_in_selector {
                    selector.element = Some(element_name.to_string())
                } else {
                    let mut old_selector = Selector::new(Some(element_name.to_string()));
                    mem::swap(&mut old_selector, &mut selector);
                    selector.relation = Some(Box::new(SelectorRelation::Ancestor(old_selector)));
                }
            }

            Token::Delim('>') => {
                let mut old_selector = Selector::new(Some(input.expect_ident()?.to_string()));
                mem::swap(&mut old_selector, &mut selector);
                selector.relation = Some(Box::new(SelectorRelation::Parent(old_selector)));
            }

            // Any element
            Token::Delim('*') => {}

            // Class
            Token::Delim('.') => {selector.classes.insert(input.expect_ident()?.into_owned());}

            // Pseudo-class
            Token::Colon => {selector.pseudo_classes.insert(input.expect_ident()?.into_owned());}

            // This selector is done, on to the next one
            Token::Comma => {
                selectors.push(selector);
                selector = Selector::default();
                first_token_in_selector = true;
                continue; // need to continue to avoid `first_token_in_selector` being set to false
            }

            t => {
                let basic_error = BasicParseError::UnexpectedToken(t);
                return Err(basic_error.into());
            }
        }

        first_token_in_selector = false;
    }

    selectors.push(selector);

    if selectors.iter().any(|sel| sel.relation.is_some()) {
        eprintln!("WARNING: Complex selector relations not implemented");
    }

    Ok(selectors)
}

struct DeclarationParser;

impl<'i> cssparser::DeclarationParser<'i> for DeclarationParser {
    type Declaration = Declaration;
    type Error = CustomParseError;

    fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>) -> Result<Self::Declaration, ParseError<'i, Self::Error>> {
        let value = match &*name {
            "color" | "border-color" => Value::Color(parse_basic_color(input)?),

            "background" | "foreground" => Value::Color(parse_basic_color(input)?),

            "border-radius" | "border-width" => {
                match input.next()? {
                    Token::Number { int_value: Some(x), has_sign, .. } if !has_sign && x >= 0 => Value::UInt(x as u32),
                    t => return Err(BasicParseError::UnexpectedToken(t).into())
                }
            }

            _ => return Err(BasicParseError::UnexpectedToken(input.next()?).into()),
        };

        Ok(Declaration {
            property: name.into_owned(),
            value: value,
            important: input.try(cssparser::parse_important).is_ok()
        })
    }
}

impl<'i> cssparser::AtRuleParser<'i> for DeclarationParser {
    type Prelude = ();
    type AtRule = Declaration;
    type Error = CustomParseError;
}

fn css_color(name: &str) -> Option<Color> {
    Some(hex(match name {
        "transparent" => return Some(Color { data: 0 }),

        "black" => 0x000000,
        "silver" => 0xc0c0c0,
        "gray" | "grey" => 0x808080,
        "white" => 0xffffff,
        "maroon" => 0x800000,
        "red" => 0xff0000,
        "purple" => 0x800080,
        "fuchsia" => 0xff00ff,
        "green" => 0x008000,
        "lime" => 0x00ff00,
        "olive" => 0x808000,
        "yellow" => 0xffff00,
        "navy" => 0x000080,
        "blue" => 0x0000ff,
        "teal" => 0x008080,
        "aqua" => 0x00ffff,
        _ => return None,
    }))
}

fn parse_basic_color<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Color, ParseError<'i, CustomParseError>> {
    Ok(match input.next()? {
        Token::Ident(s) => match css_color(&s) {
            Some(color) => color,
            None => return Err(CustomParseError::InvalidColorName(s.into_owned()).into()),
        },

        Token::IDHash(hash) | Token::Hash(hash) => {
            match hash.len() {
                6 | 8 => {
                    let mut x = match u32::from_str_radix(&hash, 16) {
                        Ok(x) => x,
                        Err(_) => return Err(CustomParseError::InvalidColorHex(hash.into_owned()).into()),
                    };

                    if hash.len() == 6 {
                        x |= 0xFF000000;
                    }

                    Color { data: x }
                },
                _ => return Err(CustomParseError::InvalidColorHex(hash.into_owned()).into()),
            }
        }

        t => {
            let basic_error = BasicParseError::UnexpectedToken(t);
            return Err(basic_error.into());
        }
    })
}

fn parse(s: &str) -> Vec<Rule> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);
    let rule_parser = RuleParser::new();

    let rules = {
        let rule_list_parser = cssparser::RuleListParser::new_for_stylesheet(&mut parser, rule_parser);
        rule_list_parser.collect::<Vec<_>>()
    };

    for rule in &rules {
        match *rule {
            Ok(_) => {},
            Err(ref e) => {
                match e.error {
                    ParseError::Basic(ref e) => eprintln!("{:?}", e),
                    ParseError::Custom(ref e) => eprintln!("{:?}", e),
                }
                println!("Error occured in `{}`", parser.slice(e.span.clone()));
            }
        }
    }

    rules.into_iter().filter_map(|rule| rule.ok()).collect()
}

const fn hex(data: u32) -> Color {
    Color { data: 0xFF000000 | data }
}
<|endoftext|>


<commit_before>use std::process::Command;
use std::path::Path;
use std::fs::{self, File};
use std::io::{self, Read, Write};
use std::env;
use std::ffi::OsString;

use libflate::gzip;
use tar;

pub struct ExecutionStatus {
    status: Option< i32 >
}

impl ExecutionStatus {
    pub fn is_ok( &self ) -> bool {
        self.status == Some( 0 )
    }
}

pub trait CommandExt {
    fn run( &mut self ) -> ExecutionStatus;
    fn append_to_path< P: AsRef< Path > >( &mut self, path: P ) -> &mut Self;
}

impl CommandExt for Command {
    fn run( &mut self ) -> ExecutionStatus {
        let mut child = match self.spawn() {
            Ok( child ) => child,
            Err( _ ) => {
                return ExecutionStatus {
                    status: None
                };
            }
        };
        let result = child.wait();
        let status = result.unwrap().code().unwrap();
        ExecutionStatus {
            status: Some( status )
        }
    }

    fn append_to_path< P: AsRef< Path > >( &mut self, path: P ) -> &mut Self {
        let mut paths = env::var_os( "PATH" ).map( |paths| env::split_paths( &paths ).collect() ).unwrap_or( Vec::new() );
        paths.push( path.as_ref().into() );
        let new_path = env::join_paths( paths ).unwrap();

        self.env( "PATH", new_path );
        self
    }
}

pub fn read< P: AsRef< Path > >( path: P ) -> Result< String, io::Error > {
    let mut fp = File::open( path.as_ref() )?;
    let mut output = String::new();
    fp.read_to_string( &mut output )?;
    Ok( output )
}

pub fn read_bytes< P: AsRef< Path > >( path: P ) -> Result< Vec< u8 >, io::Error > {
    let mut fp = File::open( path.as_ref() )?;
    let mut output = Vec::new();
    fp.read_to_end( &mut output )?;
    Ok( output )
}

pub fn write< P: AsRef< Path > >( path: P, string: &str ) -> Result< (), io::Error > {
    let mut fp = File::create( path )?;
    fp.write_all( string.as_bytes() )?;
    Ok( () )
}

pub fn has_cmd( cmd: &str ) -> bool {
    let path = env::var_os( "PATH" ).unwrap_or( OsString::new() );
    env::split_paths( &path ).map( |p| {
        p.join( &cmd )
    }).any( |p| {
        p.exists()
    })
}

pub fn find_cmd< 'a >( cmds: &[ &'a str ] ) -> Option< &'a str > {
    cmds.into_iter().map( |&s| s ).filter( |&s| has_cmd( s ) ).next()
}

pub fn unpack< I: AsRef< Path >, O: AsRef< Path > >( input_path: I, output_path: O ) -> Result< (), Box< io::Error > > {
    let output_path = output_path.as_ref();
    let file = fs::File::open( input_path )?;
    let decoder = gzip::Decoder::new( file )?;
    let mut archive = tar::Archive::new( decoder );
    archive.unpack( output_path )?;

    Ok(())
}
<commit_msg>Improve unpacking performance with buffered IO<commit_after>use std::process::Command;
use std::path::Path;
use std::fs::{self, File};
use std::io::{self, BufReader, Read, Write};
use std::env;
use std::ffi::OsString;

use libflate::gzip;
use tar;

pub struct ExecutionStatus {
    status: Option< i32 >
}

impl ExecutionStatus {
    pub fn is_ok( &self ) -> bool {
        self.status == Some( 0 )
    }
}

pub trait CommandExt {
    fn run( &mut self ) -> ExecutionStatus;
    fn append_to_path< P: AsRef< Path > >( &mut self, path: P ) -> &mut Self;
}

impl CommandExt for Command {
    fn run( &mut self ) -> ExecutionStatus {
        let mut child = match self.spawn() {
            Ok( child ) => child,
            Err( _ ) => {
                return ExecutionStatus {
                    status: None
                };
            }
        };
        let result = child.wait();
        let status = result.unwrap().code().unwrap();
        ExecutionStatus {
            status: Some( status )
        }
    }

    fn append_to_path< P: AsRef< Path > >( &mut self, path: P ) -> &mut Self {
        let mut paths = env::var_os( "PATH" ).map( |paths| env::split_paths( &paths ).collect() ).unwrap_or( Vec::new() );
        paths.push( path.as_ref().into() );
        let new_path = env::join_paths( paths ).unwrap();

        self.env( "PATH", new_path );
        self
    }
}

pub fn read< P: AsRef< Path > >( path: P ) -> Result< String, io::Error > {
    let mut fp = File::open( path.as_ref() )?;
    let mut output = String::new();
    fp.read_to_string( &mut output )?;
    Ok( output )
}

pub fn read_bytes< P: AsRef< Path > >( path: P ) -> Result< Vec< u8 >, io::Error > {
    let mut fp = File::open( path.as_ref() )?;
    let mut output = Vec::new();
    fp.read_to_end( &mut output )?;
    Ok( output )
}

pub fn write< P: AsRef< Path > >( path: P, string: &str ) -> Result< (), io::Error > {
    let mut fp = File::create( path )?;
    fp.write_all( string.as_bytes() )?;
    Ok( () )
}

pub fn has_cmd( cmd: &str ) -> bool {
    let path = env::var_os( "PATH" ).unwrap_or( OsString::new() );
    env::split_paths( &path ).map( |p| {
        p.join( &cmd )
    }).any( |p| {
        p.exists()
    })
}

pub fn find_cmd< 'a >( cmds: &[ &'a str ] ) -> Option< &'a str > {
    cmds.into_iter().map( |&s| s ).filter( |&s| has_cmd( s ) ).next()
}

pub fn unpack< I: AsRef< Path >, O: AsRef< Path > >( input_path: I, output_path: O ) -> Result< (), Box< io::Error > > {
    let output_path = output_path.as_ref();
    let file = fs::File::open( input_path )?;
    let reader = BufReader::new( file );
    let decoder = gzip::Decoder::new( reader )?;
    let mut archive = tar::Archive::new( decoder );
    archive.unpack( output_path )?;

    Ok(())
}
<|endoftext|>


<commit_before>//! Internal module providing handy function

use encoding_rs::{self, Encoding};

/// Converts a &[u8] into a &[u32]
pub fn to_u32(s: &[u8]) -> &[u32] {
    assert!(s.len() % 4 == 0);
    unsafe { ::std::slice::from_raw_parts(s as *const [u8] as *const u32, s.len() / 4) }
}
pub fn read_slice<T>(s: &[u8]) -> T {
    unsafe { ::std::ptr::read(&s[..::std::mem::size_of::<T>()] as *const [u8] as *const T) }
}

pub fn read_u32(s: &[u8]) -> u32 {
    read_slice(s)
}

pub fn read_u16(s: &[u8]) -> u16 {
    read_slice(s)
}

pub fn read_usize(s: &[u8]) -> usize {
    read_u32(s) as usize
}

/// Returns an encoding from Windows code page number.
/// http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx
/// Sometimes it can return a *superset* of the requested encoding, e.g. for several CJK encodings.
///
/// The code is copied from [rust-encoding](https://github.com/lifthrasiir/rust-encoding)
pub fn encoding_from_windows_code_page(cp: usize) -> Option<&'static Encoding> {
    match cp {
        65001 => Some(encoding_rs::UTF_8),
        866 => Some(encoding_rs::IBM866),
        28592 => Some(encoding_rs::ISO_8859_2),
        28593 => Some(encoding_rs::ISO_8859_3),
        28594 => Some(encoding_rs::ISO_8859_4),
        28595 => Some(encoding_rs::ISO_8859_5),
        28596 => Some(encoding_rs::ISO_8859_6),
        28597 => Some(encoding_rs::ISO_8859_7),
        28598 => Some(encoding_rs::ISO_8859_8),
        28603 => Some(encoding_rs::ISO_8859_13),
        28605 => Some(encoding_rs::ISO_8859_15),
        20866 => Some(encoding_rs::KOI8_R),
        21866 => Some(encoding_rs::KOI8_U),
        10000 => Some(encoding_rs::MACINTOSH),
        874 => Some(encoding_rs::WINDOWS_874),
        1250 => Some(encoding_rs::WINDOWS_1250),
        1251 => Some(encoding_rs::WINDOWS_1251),
        1252 => Some(encoding_rs::WINDOWS_1252),
        1253 => Some(encoding_rs::WINDOWS_1253),
        1254 => Some(encoding_rs::WINDOWS_1254),
        1255 => Some(encoding_rs::WINDOWS_1255),
        1256 => Some(encoding_rs::WINDOWS_1256),
        1257 => Some(encoding_rs::WINDOWS_1257),
        1258 => Some(encoding_rs::WINDOWS_1258),
        1259 | 10007 => Some(encoding_rs::X_MAC_CYRILLIC),
        936 | 54936 => Some(encoding_rs::GB18030), // XXX technicencoding_rsy wrong
        950 => Some(encoding_rs::BIG5),
        20932 => Some(encoding_rs::EUC_JP),
        50220 => Some(encoding_rs::ISO_2022_JP),
        932 => Some(encoding_rs::SHIFT_JIS),
        1201 => Some(encoding_rs::UTF_16BE),
        1200 => Some(encoding_rs::UTF_16LE),
        // Not available because not in the Encoding Standard
        //28591 => Some(encoding_rs::ISO_8859_1),
        //38598 => Some(encoding_rs::whatwg::ISO_8859_8_I),
        //52936 => Some(encoding_rs::HZ),
        // not supported?
        //949 => Some(encoding_rs::WINDOWS_949),
        _ => None,
    }
}

/// Push literal column into a String buffer
pub fn push_column(mut col: u32, buf: &mut String) {
    if col < 26 {
        buf.push((b'A' + col as u8) as char);
    } else {
        let mut rev = String::new();
        while col >= 26 {
            let c = col % 26;
            rev.push((b'A' + c as u8) as char);
            col -= c;
            col /= 26;
        }
        buf.extend(rev.chars().rev());
    }
}
<commit_msg>add EUC_KR encoding (#84)<commit_after>//! Internal module providing handy function

use encoding_rs::{self, Encoding};

/// Converts a &[u8] into a &[u32]
pub fn to_u32(s: &[u8]) -> &[u32] {
    assert!(s.len() % 4 == 0);
    unsafe { ::std::slice::from_raw_parts(s as *const [u8] as *const u32, s.len() / 4) }
}
pub fn read_slice<T>(s: &[u8]) -> T {
    unsafe { ::std::ptr::read(&s[..::std::mem::size_of::<T>()] as *const [u8] as *const T) }
}

pub fn read_u32(s: &[u8]) -> u32 {
    read_slice(s)
}

pub fn read_u16(s: &[u8]) -> u16 {
    read_slice(s)
}

pub fn read_usize(s: &[u8]) -> usize {
    read_u32(s) as usize
}

/// Returns an encoding from Windows code page number.
/// http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx
/// Sometimes it can return a *superset* of the requested encoding, e.g. for several CJK encodings.
///
/// The code is copied from [rust-encoding](https://github.com/lifthrasiir/rust-encoding)
pub fn encoding_from_windows_code_page(cp: usize) -> Option<&'static Encoding> {
    match cp {
        65001 => Some(encoding_rs::UTF_8),
        866 => Some(encoding_rs::IBM866),
        28592 => Some(encoding_rs::ISO_8859_2),
        28593 => Some(encoding_rs::ISO_8859_3),
        28594 => Some(encoding_rs::ISO_8859_4),
        28595 => Some(encoding_rs::ISO_8859_5),
        28596 => Some(encoding_rs::ISO_8859_6),
        28597 => Some(encoding_rs::ISO_8859_7),
        28598 => Some(encoding_rs::ISO_8859_8),
        28603 => Some(encoding_rs::ISO_8859_13),
        28605 => Some(encoding_rs::ISO_8859_15),
        20866 => Some(encoding_rs::KOI8_R),
        21866 => Some(encoding_rs::KOI8_U),
        10000 => Some(encoding_rs::MACINTOSH),
        874 => Some(encoding_rs::WINDOWS_874),
        1250 => Some(encoding_rs::WINDOWS_1250),
        1251 => Some(encoding_rs::WINDOWS_1251),
        1252 => Some(encoding_rs::WINDOWS_1252),
        1253 => Some(encoding_rs::WINDOWS_1253),
        1254 => Some(encoding_rs::WINDOWS_1254),
        1255 => Some(encoding_rs::WINDOWS_1255),
        1256 => Some(encoding_rs::WINDOWS_1256),
        1257 => Some(encoding_rs::WINDOWS_1257),
        1258 => Some(encoding_rs::WINDOWS_1258),
        1259 | 10007 => Some(encoding_rs::X_MAC_CYRILLIC),
        936 | 54936 => Some(encoding_rs::GB18030), // XXX technicencoding_rsy wrong
        950 => Some(encoding_rs::BIG5),
        20932 => Some(encoding_rs::EUC_JP),
        50220 => Some(encoding_rs::ISO_2022_JP),
        932 => Some(encoding_rs::SHIFT_JIS),
        1201 => Some(encoding_rs::UTF_16BE),
        1200 => Some(encoding_rs::UTF_16LE),
        949 => Some(encoding_rs::EUC_KR),
        // Not available because not in the Encoding Standard
        //28591 => Some(encoding_rs::ISO_8859_1),
        //38598 => Some(encoding_rs::whatwg::ISO_8859_8_I),
        //52936 => Some(encoding_rs::HZ),
        _ => None,
    }
}

/// Push literal column into a String buffer
pub fn push_column(mut col: u32, buf: &mut String) {
    if col < 26 {
        buf.push((b'A' + col as u8) as char);
    } else {
        let mut rev = String::new();
        while col >= 26 {
            let c = col % 26;
            rev.push((b'A' + c as u8) as char);
            col -= c;
            col /= 26;
        }
        buf.extend(rev.chars().rev());
    }
}
<|endoftext|>


<commit_before>//! Utility functions that patch holes in wayland-rs.

use std::ptr;

use wlroots_sys::{wl_list, wl_signal};
use wayland_sys::server::{WAYLAND_SERVER_HANDLE, wl_notify_func_t};

macro_rules! offset_of {
    ($ty:ty, $field:ident) => {
        &(*(0 as *const $ty)).$field as *const _ as usize
    }
}

macro_rules! wl_container_of {
    ($ptr:ident, $ty:ty, $field:ident) => {
        ($ptr as usize - offset_of!($ty, $field)) as *const $ty
    }
}

/// Real definition of wl_listener, as defined in the Wayland server headers
#[repr(C)]
pub struct wl_listener {
    link: wl_list,
    notify: wl_notify_func_t
}

impl wl_listener {
    pub fn new(notify: wl_notify_func_t) -> Self {
        wl_listener {
            link: wl_list {
                prev: ptr::null_mut(),
                next: ptr::null_mut()
            },
            notify
        }
    }
}

/// This is what wl_signal_add is suppose to be but it's not defined in
/// wayland-rs for some reason, so we define it here.
pub unsafe fn wl_signal_add(signal: &mut wl_signal,
                        listener: &mut self::wl_listener) {
    ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                  wl_list_insert,
                  signal.listener_list.prev as *mut _,
                  &mut listener.link as *mut _ as *mut _)
}
<commit_msg>Export those macros (wl_container_of mainly)<commit_after>//! Utility functions that patch holes in wayland-rs.

use std::ptr;

use wlroots_sys::{wl_list, wl_signal};
use wayland_sys::server::{WAYLAND_SERVER_HANDLE, wl_notify_func_t};

#[macro_export]
macro_rules! offset_of {
    ($ty:ty, $field:ident) => {
        &(*(0 as *const $ty)).$field as *const _ as usize
    }
}

#[macro_export]
macro_rules! wl_container_of {
    ($ptr:ident, $ty:ty, $field:ident) => {
        ($ptr as usize - offset_of!($ty, $field)) as *const $ty
    }
}

/// Real definition of wl_listener, as defined in the Wayland server headers
#[repr(C)]
pub struct wl_listener {
    link: wl_list,
    notify: wl_notify_func_t
}

impl wl_listener {
    pub fn new(notify: wl_notify_func_t) -> Self {
        wl_listener {
            link: wl_list {
                prev: ptr::null_mut(),
                next: ptr::null_mut()
            },
            notify
        }
    }
}

/// This is what wl_signal_add is suppose to be but it's not defined in
/// wayland-rs for some reason, so we define it here.
pub unsafe fn wl_signal_add(signal: &mut wl_signal,
                        listener: &mut self::wl_listener) {
    ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                  wl_list_insert,
                  signal.listener_list.prev as *mut _,
                  &mut listener.link as *mut _ as *mut _)
}
<|endoftext|>


<commit_before>use super::{Result, Error};

use std::io::{Read, Write};
use std::sync::mpsc;
use std::net::UdpSocket;

use websocket::ws::sender::Sender as SenderTrait;
use websocket::client::{Client, Sender, Receiver};
use websocket::stream::WebSocketStream;
use websocket::message::{Message as WsMessage, Type as MessageType};

use serde_json;
use serde_json::builder::ObjectBuilder;

use byteorder::{LittleEndian, BigEndian, WriteBytesExt, ReadBytesExt};

use super::model::*;

/// A websocket connection to the voice servers.
///
/// A VoiceConnection may be active or inactive. Use `voice_connect` and
/// `voice_disconnect` on the `Connection` you are feeding it events from to
/// change what channel it is connected to.
pub struct VoiceConnection {
	user_id: UserId,
	session_id: Option<String>,
	channel: Option<mpsc::Sender<Status>>,
	queue: Vec<AudioSource>,
}

impl VoiceConnection {
	/// Prepare a VoiceConnection for later use.
	pub fn new(user_id: UserId) -> VoiceConnection {
		VoiceConnection {
			user_id: user_id,
			session_id: None,
			channel: None,
			queue: Vec::new(),
		}
	}

	/// Update the voice state based on an event.
	pub fn update(&mut self, event: &Event) {
		match *event {
			Event::VoiceStateUpdate(_, ref voice_state) => {
				if voice_state.user_id == self.user_id {
					println!("[Voice] Session id: {}", voice_state.session_id);
					self.session_id = Some(voice_state.session_id.clone());
					if !voice_state.channel_id.is_some() {
						self.channel.take(); // drop the connection
					}
				}
			}
			Event::VoiceServerUpdate { ref server_id, ref endpoint, ref token } => {
				println!("[Voice] Connecting to: {}", endpoint);
				self.connect(server_id, endpoint.clone(), token).expect("Voice::connect failure")
			}
			_ => {}
		}
	}

	/// Check whether the voice thread is currently running.
	pub fn is_running(&self) -> bool {
		match self.channel {
			None => false,
			Some(ref channel) => channel.send(Status::NoOp).is_ok(),
		}
	}

	/// Push the raw PCM file at the given path to the queue.
	pub fn push_pcm_file<R: Read + Send + 'static>(&mut self, read: R) {
		self.push_internal(AudioSource::Pcm(Box::new(read)));
	}

	/// Stop any currently playing audio and clear the queue.
	pub fn stop_audio(&mut self) {
		self.channel.as_ref().map(|ch| ch.send(Status::Clear));
		self.queue.clear();
	}

	fn push_internal(&mut self, source: AudioSource) {
		match self.channel {
			None => self.queue.push(source),
			Some(ref channel) => match channel.send(Status::Push(source)) {
				Ok(()) => {},
				Err(mpsc::SendError(Status::Push(source))) => self.queue.push(source),
				Err(_) => unreachable!()
			}
		}
	}

	fn connect(&mut self, server_id: &ServerId, mut endpoint: String, token: &str) -> Result<()> {
		self.channel.take(); // drop any previous connection

		// prepare the URL: drop the :80 and prepend wss://
		if endpoint.ends_with(":80") {
			let len = endpoint.len();
			endpoint.truncate(len - 3);
		}
		// establish the websocket connection
		let url = match ::websocket::client::request::Url::parse(&format!("wss://{}", endpoint)) {
			Ok(url) => url,
			Err(_) => return Err(Error::Other("Invalid URL in Voice::connect()"))
		};
		let response = try!(try!(Client::connect(url)).send());
		try!(response.validate());
		let (mut sender, receiver) = response.begin().split();

		// send the handshake
		let map = ObjectBuilder::new()
			.insert("op", 0)
			.insert_object("d", |object| object
				.insert("server_id", &server_id.0)
				.insert("user_id", &self.user_id.0)
				.insert("session_id", self.session_id.as_ref().expect("no session id"))
				.insert("token", token)
			)
			.unwrap();
		try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

		// spin up the voice thread, where most of the action will take place
		let (tx, rx) = mpsc::channel();
		try!(::std::thread::Builder::new()
			.name("Discord Voice Thread".into())
			.spawn(move || voice_thread(endpoint, sender, receiver, rx).unwrap()));
		for source in ::std::mem::replace(&mut self.queue, Vec::new()) {
			let _ = tx.send(Status::Push(source));
		}
		self.channel = Some(tx);
		Ok(())
	}
}

enum Status {
	Push(AudioSource),
	Clear,
	NoOp,
}

fn recv_message(receiver: &mut Receiver<WebSocketStream>) -> Result<VoiceEvent> {
	use websocket::ws::receiver::Receiver;
	let message: WsMessage = try!(receiver.recv_message());
	if message.opcode != MessageType::Text {
		return Err(Error::Other("Got an non-Text frame as voice handshake response"))
	}
	let json: serde_json::Value = try!(serde_json::from_reader(&message.payload[..]));
	let original = format!("{:?}", json);
	VoiceEvent::decode(json).map_err(|err| {
		// If there was a decode failure, print the original json for debugging
		println!("[Warning] Error vdecoding: {}", original);
		err
	})
}

fn voice_thread(
	endpoint: String,
	mut sender: Sender<WebSocketStream>,
	mut receiver: Receiver<WebSocketStream>,
	channel: mpsc::Receiver<Status>,
) -> Result<()> {
	use std::io::Cursor;

	// read the first websocket message
	let (interval, port, ssrc, modes) = match try!(recv_message(&mut receiver)) {
		VoiceEvent::Handshake { heartbeat_interval, port, ssrc, modes } => (heartbeat_interval, port, ssrc, modes),
		_ => return Err(Error::Other("First voice message was not 4/handshake"))
	};
	if !modes.iter().find(|&s| s == "plain").is_some() {
		return Err(Error::Other("Plain voice mode is unavailable"))
	}

	// bind a UDP socket and send the ssrc value in a packet as identification
	let udp = try!(UdpSocket::bind("0.0.0.0:0"));
	let mut bytes = [0; 4];
	try!(Cursor::new(&mut bytes[..]).write_u32::<BigEndian>(ssrc));
	try!(udp.send_to(&bytes, (&endpoint[..], port)));

	// receive the response to the identification to get port and address info
	let mut bytes = [0; 256];
	let (len, _remote_addr) = try!(udp.recv_from(&mut bytes));
	let mut cursor = Cursor::new(&bytes[..len]);
	let _ = try!(cursor.read_u32::<LittleEndian>()); // discard padding
	let port_number = try!(cursor.read_u16::<LittleEndian>());

	// send the acknowledgement websocket message
	let map = ObjectBuilder::new()
		.insert("op", 1)
		.insert_object("d", |object| object
			.insert("protocol", "udp")
			.insert_object("data", |object| object
				.insert("address", "")
				.insert("port", port_number)
				.insert("mode", "plain")
			)
		)
		.unwrap();
	try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

	// discard websocket messages until we get the Ready
	loop {
		match try!(recv_message(&mut receiver)) {
			VoiceEvent::Ready { mode, secret_key } => {
				if secret_key.len() != 0 {
					println!("[Voice] Got secret key: {:?}", secret_key);
				}
				if mode != "plain" {
					return Err(Error::Other("Voice mode in Ready was not 'plain'"))
				}
				break
			}
			VoiceEvent::Unknown(op, value) => println!("[Voice] Unknown {}/{:?}", op, value),
			_ => {},
		}
	}

	// prepare buffers for later use
	let mut opus = ::utils::OpusEncoder::new().expect("failed new");
	let mut audio_queue = ::std::collections::VecDeque::new();
	let mut audio_buffer = vec![0; 960];
	let mut packet = Vec::with_capacity(256);
	let mut sequence = 0;
	let mut timestamp = 0;

	// tell 'em that we're speaking
	let map = ObjectBuilder::new()
		.insert("op", 5)
		.insert_object("d", |object| object
			.insert("speaking", true)
			.insert("delay", 0)
		)
		.unwrap();
	try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

	let audio_duration = ::time::Duration::milliseconds(20);
	let keepalive_duration = ::time::Duration::milliseconds(interval as i64);
	let mut audio_timer = ::utils::Timer::new(::time::Duration::zero());
	let mut keepalive_timer = ::utils::Timer::new(keepalive_duration);

	// start the main loop
	println!("[Voice] Ready");
	'outer: loop {
		::std::thread::sleep_ms(3);

		loop {
			match channel.try_recv() {
				Ok(Status::Push(source)) => {
					audio_queue.push_back(source)
				},
				Ok(Status::Clear) => audio_queue.clear(),
				Ok(Status::NoOp) => {},
				Err(mpsc::TryRecvError::Empty) => break,
				Err(mpsc::TryRecvError::Disconnected) => break 'outer,
			}
		}

		if keepalive_timer.check_and_add(keepalive_duration) {
			let map = ObjectBuilder::new()
				.insert("op", 3)
				.insert("d", serde_json::Value::Null)
				.unwrap();
			let json = try!(serde_json::to_string(&map));
			try!(sender.send_message(&WsMessage::text(json)));
		}

		if audio_timer.check_and_add(audio_duration) && audio_queue.len() > 0 {
			const HEADER_LEN: usize = 12;
			// prepare the packet header
			packet.clear();
			try!(packet.write_all(&[0x80, 0x78]));
			try!(packet.write_u16::<BigEndian>(sequence));
			try!(packet.write_u32::<BigEndian>(timestamp));
			try!(packet.write_u32::<BigEndian>(ssrc));
			let zeroes = packet.capacity() - HEADER_LEN;
			packet.extend(::std::iter::repeat(0).take(zeroes));

			// read the audio from the source and zero-fill any leftovers
			let len = try!(audio_queue[0].next(&mut audio_buffer[..]));
			if len < audio_buffer.len() {
				// zero-fill the buffer and advance to the next audio source
				for value in &mut audio_buffer[len..] {
					*value = 0;
				}
				audio_queue.pop_front();
			}

			// encode the audio data and transmit it
			let len = opus.encode(&audio_buffer, &mut packet[HEADER_LEN..]).expect("failed encode");
			try!(udp.send_to(&packet[..len + HEADER_LEN], (&endpoint[..], port)));

			sequence = sequence.wrapping_add(1);
			timestamp = timestamp.wrapping_add(960);
		}
	}

	// stop speaking
	::std::thread::sleep_ms(500);
	let map = ObjectBuilder::new()
		.insert("op", 5)
		.insert_object("d", |object| object
			.insert("speaking", false)
			.insert("delay", 0)
		)
		.unwrap();
	try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

	try!(receiver.get_mut().get_mut().shutdown(::std::net::Shutdown::Both));
	try!(sender.get_mut().shutdown(::std::net::Shutdown::Both));
	Ok(())
}

enum AudioSource {
	Pcm(Box<::std::io::Read + Send>),
}

impl AudioSource {
	fn next(&mut self, buffer: &mut [i16]) -> Result<usize> {
		match *self {
			AudioSource::Pcm(ref mut read) => {
				for (i, val) in buffer.iter_mut().enumerate() {
					*val = match read.read_i16::<LittleEndian>() {
						Ok(val) => val / 6,
						Err(::byteorder::Error::UnexpectedEOF) => return Ok(i),
						Err(::byteorder::Error::Io(e)) => return Err(From::from(e))
					};
				}
				Ok(buffer.len())
			}
		}
	}
}
<commit_msg>Add support for piping ffmpeg output<commit_after>use super::{Result, Error};

use std::io::{Read, Write};
use std::sync::mpsc;
use std::net::UdpSocket;

use websocket::ws::sender::Sender as SenderTrait;
use websocket::client::{Client, Sender, Receiver};
use websocket::stream::WebSocketStream;
use websocket::message::{Message as WsMessage, Type as MessageType};

use serde_json;
use serde_json::builder::ObjectBuilder;

use byteorder::{LittleEndian, BigEndian, WriteBytesExt, ReadBytesExt};

use super::model::*;

/// A websocket connection to the voice servers.
///
/// A VoiceConnection may be active or inactive. Use `voice_connect` and
/// `voice_disconnect` on the `Connection` you are feeding it events from to
/// change what channel it is connected to.
pub struct VoiceConnection {
	user_id: UserId,
	session_id: Option<String>,
	channel: Option<mpsc::Sender<Status>>,
	queue: Vec<AudioSource>,
}

impl VoiceConnection {
	/// Prepare a VoiceConnection for later use.
	pub fn new(user_id: UserId) -> VoiceConnection {
		VoiceConnection {
			user_id: user_id,
			session_id: None,
			channel: None,
			queue: Vec::new(),
		}
	}

	/// Update the voice state based on an event.
	pub fn update(&mut self, event: &Event) {
		match *event {
			Event::VoiceStateUpdate(_, ref voice_state) => {
				if voice_state.user_id == self.user_id {
					self.session_id = Some(voice_state.session_id.clone());
					if !voice_state.channel_id.is_some() {
						self.channel.take(); // drop the connection
					}
				}
			}
			Event::VoiceServerUpdate { ref server_id, ref endpoint, ref token } => {
				self.connect(server_id, endpoint.clone(), token).expect("Voice::connect failure")
			}
			_ => {}
		}
	}

	/// Check whether the voice thread is currently running.
	pub fn is_running(&self) -> bool {
		match self.channel {
			None => false,
			Some(ref channel) => channel.send(Status::NoOp).is_ok(),
		}
	}

	/// Push a source of raw PCM data to the queue.
	#[inline]
	pub fn push_pcm<R: Read + Send + 'static>(&mut self, read: R) {
		self.push_internal(Box::new(read));
	}

	/// Push the path to an audio file which ffmpeg can decode.
	pub fn push_file<P: AsRef<::std::path::Path>>(&mut self, path: P) -> Result<()> {
		use std::process::{Command, Stdio};
		let child = try!(Command::new("ffmpeg")
			.args(&[
				"-i", try!(path.as_ref().to_str().ok_or(Error::Other("File path is not utf8 - fixme?"))),
				"-f", "s16le",
				"-ac", "1",
				"-ar", "48000",
				"-acodec", "pcm_s16le",
				"-"])
			.stdin(Stdio::null())
			.stdout(Stdio::piped())
			.stderr(Stdio::null())
			.spawn());
		let stdout = try!(child.stdout.ok_or(Error::Other("Child process missing stdout")));
		self.push_internal(Box::new(stdout));
		Ok(())
	}

	/// Stop any currently playing audio and clear the queue.
	pub fn stop_audio(&mut self) {
		self.channel.as_ref().map(|ch| ch.send(Status::Clear));
		self.queue.clear();
	}

	fn push_internal(&mut self, source: AudioSource) {
		match self.channel {
			None => self.queue.push(source),
			Some(ref channel) => match channel.send(Status::Push(source)) {
				Ok(()) => {},
				Err(mpsc::SendError(Status::Push(source))) => self.queue.push(source),
				Err(_) => unreachable!()
			}
		}
	}

	fn connect(&mut self, server_id: &ServerId, mut endpoint: String, token: &str) -> Result<()> {
		self.channel.take(); // drop any previous connection

		// prepare the URL: drop the :80 and prepend wss://
		if endpoint.ends_with(":80") {
			let len = endpoint.len();
			endpoint.truncate(len - 3);
		}
		// establish the websocket connection
		let url = match ::websocket::client::request::Url::parse(&format!("wss://{}", endpoint)) {
			Ok(url) => url,
			Err(_) => return Err(Error::Other("Invalid URL in Voice::connect()"))
		};
		let response = try!(try!(Client::connect(url)).send());
		try!(response.validate());
		let (mut sender, receiver) = response.begin().split();

		// send the handshake
		let map = ObjectBuilder::new()
			.insert("op", 0)
			.insert_object("d", |object| object
				.insert("server_id", &server_id.0)
				.insert("user_id", &self.user_id.0)
				.insert("session_id", self.session_id.as_ref().expect("no session id"))
				.insert("token", token)
			)
			.unwrap();
		try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

		// spin up the voice thread, where most of the action will take place
		let (tx, rx) = mpsc::channel();
		try!(::std::thread::Builder::new()
			.name("Discord Voice Thread".into())
			.spawn(move || voice_thread(endpoint, sender, receiver, rx).unwrap()));
		for source in ::std::mem::replace(&mut self.queue, Vec::new()) {
			let _ = tx.send(Status::Push(source));
		}
		self.channel = Some(tx);
		Ok(())
	}
}

type AudioSource = Box<::std::io::Read + Send>;

enum Status {
	Push(AudioSource),
	Clear,
	NoOp,
}

fn recv_message(receiver: &mut Receiver<WebSocketStream>) -> Result<VoiceEvent> {
	use websocket::ws::receiver::Receiver;
	let message: WsMessage = try!(receiver.recv_message());
	if message.opcode != MessageType::Text {
		return Err(Error::Other("Got an non-Text frame as voice handshake response"))
	}
	let json: serde_json::Value = try!(serde_json::from_reader(&message.payload[..]));
	let original = format!("{:?}", json);
	VoiceEvent::decode(json).map_err(|err| {
		// If there was a decode failure, print the original json for debugging
		println!("[Warning] Error vdecoding: {}", original);
		err
	})
}

fn voice_thread(
	endpoint: String,
	mut sender: Sender<WebSocketStream>,
	mut receiver: Receiver<WebSocketStream>,
	channel: mpsc::Receiver<Status>,
) -> Result<()> {
	use std::io::Cursor;

	// read the first websocket message
	let (interval, port, ssrc, modes) = match try!(recv_message(&mut receiver)) {
		VoiceEvent::Handshake { heartbeat_interval, port, ssrc, modes } => (heartbeat_interval, port, ssrc, modes),
		_ => return Err(Error::Other("First voice message was not 4/handshake"))
	};
	if !modes.iter().find(|&s| s == "plain").is_some() {
		return Err(Error::Other("Plain voice mode is unavailable"))
	}

	// bind a UDP socket and send the ssrc value in a packet as identification
	let udp = try!(UdpSocket::bind("0.0.0.0:0"));
	let mut bytes = [0; 4];
	try!(Cursor::new(&mut bytes[..]).write_u32::<BigEndian>(ssrc));
	try!(udp.send_to(&bytes, (&endpoint[..], port)));

	// receive the response to the identification to get port and address info
	let mut bytes = [0; 256];
	let (len, _remote_addr) = try!(udp.recv_from(&mut bytes));
	let mut cursor = Cursor::new(&bytes[..len]);
	let _ = try!(cursor.read_u32::<LittleEndian>()); // discard padding
	let port_number = try!(cursor.read_u16::<LittleEndian>());

	// send the acknowledgement websocket message
	let map = ObjectBuilder::new()
		.insert("op", 1)
		.insert_object("d", |object| object
			.insert("protocol", "udp")
			.insert_object("data", |object| object
				.insert("address", "")
				.insert("port", port_number)
				.insert("mode", "plain")
			)
		)
		.unwrap();
	try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

	// discard websocket messages until we get the Ready
	loop {
		match try!(recv_message(&mut receiver)) {
			VoiceEvent::Ready { mode, secret_key } => {
				if secret_key.len() != 0 {
					println!("[Voice] Got secret key: {:?}", secret_key);
				}
				if mode != "plain" {
					return Err(Error::Other("Voice mode in Ready was not 'plain'"))
				}
				break
			}
			VoiceEvent::Unknown(op, value) => println!("[Voice] Unknown {}/{:?}", op, value),
			_ => {},
		}
	}

	// prepare buffers for later use
	let mut opus = ::utils::OpusEncoder::new().expect("failed new");
	let mut audio_queue = ::std::collections::VecDeque::new();
	let mut audio_buffer = vec![0; 960];
	let mut packet = Vec::with_capacity(256);
	let mut sequence = 0;
	let mut timestamp = 0;

	// tell 'em that we're speaking
	let map = ObjectBuilder::new()
		.insert("op", 5)
		.insert_object("d", |object| object
			.insert("speaking", true)
			.insert("delay", 0)
		)
		.unwrap();
	try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

	let audio_duration = ::time::Duration::milliseconds(20);
	let keepalive_duration = ::time::Duration::milliseconds(interval as i64);
	let mut audio_timer = ::utils::Timer::new(audio_duration);
	let mut keepalive_timer = ::utils::Timer::new(keepalive_duration);

	// start the main loop
	println!("[Voice] Connected to {}", endpoint);
	'outer: loop {
		::std::thread::sleep_ms(3);

		loop {
			match channel.try_recv() {
				Ok(Status::Push(source)) => {
					audio_queue.push_back(source)
				},
				Ok(Status::Clear) => audio_queue.clear(),
				Ok(Status::NoOp) => {},
				Err(mpsc::TryRecvError::Empty) => break,
				Err(mpsc::TryRecvError::Disconnected) => break 'outer,
			}
		}

		if keepalive_timer.check_and_add(keepalive_duration) {
			let map = ObjectBuilder::new()
				.insert("op", 3)
				.insert("d", serde_json::Value::Null)
				.unwrap();
			let json = try!(serde_json::to_string(&map));
			try!(sender.send_message(&WsMessage::text(json)));
		}

		if audio_timer.check_and_add(audio_duration) && audio_queue.len() > 0 {
			const HEADER_LEN: usize = 12;
			// prepare the packet header
			packet.clear();
			try!(packet.write_all(&[0x80, 0x78]));
			try!(packet.write_u16::<BigEndian>(sequence));
			try!(packet.write_u32::<BigEndian>(timestamp));
			try!(packet.write_u32::<BigEndian>(ssrc));
			let zeroes = packet.capacity() - HEADER_LEN;
			packet.extend(::std::iter::repeat(0).take(zeroes));

			// read the audio from the source
			let len = try!(next_frame(&mut audio_queue[0], &mut audio_buffer[..]));
			if len < audio_buffer.len() {
				// zero-fill the buffer and advance to the next audio source
				for value in &mut audio_buffer[len..] {
					*value = 0;
				}
				audio_queue.pop_front();
			}

			// encode the audio data and transmit it
			let len = opus.encode(&audio_buffer, &mut packet[HEADER_LEN..]).expect("failed encode");
			try!(udp.send_to(&packet[..len + HEADER_LEN], (&endpoint[..], port)));

			sequence = sequence.wrapping_add(1);
			timestamp = timestamp.wrapping_add(960);
		}
	}

	// stop speaking
	::std::thread::sleep_ms(500);
	let map = ObjectBuilder::new()
		.insert("op", 5)
		.insert_object("d", |object| object
			.insert("speaking", false)
			.insert("delay", 0)
		)
		.unwrap();
	try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

	try!(receiver.get_mut().get_mut().shutdown(::std::net::Shutdown::Both));
	try!(sender.get_mut().shutdown(::std::net::Shutdown::Both));
	Ok(())
}

fn next_frame(source: &mut AudioSource, buffer: &mut [i16]) -> Result<usize> {
	for (i, val) in buffer.iter_mut().enumerate() {
		*val = match source.read_i16::<LittleEndian>() {
			Ok(val) => val / 6, // TODO: add volume controls
			Err(::byteorder::Error::UnexpectedEOF) => return Ok(i),
			Err(::byteorder::Error::Io(e)) => return Err(From::from(e))
		};
	}
	Ok(buffer.len())
}
<|endoftext|>


<commit_before>use ffi;
use libc;
use super::Connection;

use std::mem;
use std::cell::RefCell;
use std::os::unix::io::{RawFd, AsRawFd};
use std::os::raw::{c_void, c_uint};

/// A file descriptor to watch for incoming events (for async I/O).
///
/// # Example
/// ```
/// extern crate libc;
/// extern crate dbus;
/// fn main() {
///     use dbus::{Connection, BusType, WatchEvent};
///     let c = Connection::get_private(BusType::Session).unwrap();
///
///     // Get a list of fds to poll for
///     let mut fds: Vec<_> = c.watch_fds().iter().map(|w| w.to_pollfd()).collect();
///
///     // Poll them with a 1 s timeout
///     let r = unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, 1000) };
///     assert!(r >= 0);
///
///     // And handle incoming events
///     for pfd in fds.iter().filter(|pfd| pfd.revents != 0) {
///         for item in c.watch_handle(pfd.fd, WatchEvent::from_revents(pfd.revents)) {
///             // Handle item
///             println!("Received ConnectionItem: {:?}", item);
///         }
///     }
/// }
/// ```

#[repr(C)]
#[derive(Debug, PartialEq, Copy, Clone)]
/// The enum is here for backwards compatibility mostly.
///
/// It should really be bitflags instead.
pub enum WatchEvent {
    /// The fd is readable
    Readable = 1,
    /// The fd is writable
    Writable = 2,
    /// An error occured on the fd
    Error = 4,
    /// The fd received a hangup.
    Hangup = 8,
}

impl WatchEvent {
    /// After running poll, this transforms the revents into a parameter you can send into `Connection::watch_handle`
    pub fn from_revents(revents: libc::c_short) -> c_uint {
        0 +
        if (revents & libc::POLLIN) != 0 { WatchEvent::Readable as c_uint } else { 0 } +
        if (revents & libc::POLLOUT) != 0 { WatchEvent::Writable as c_uint } else { 0 } +
        if (revents & libc::POLLERR) != 0 { WatchEvent::Error as c_uint } else { 0 } +
        if (revents & libc::POLLHUP) != 0 { WatchEvent::Hangup as c_uint } else { 0 }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
/// A file descriptor, and an indication whether it should be read from, written to, or both.
pub struct Watch {
    fd: RawFd,
    read: bool,
    write: bool,
}

impl Watch {
    /// Get the RawFd this Watch is for
    pub fn fd(&self) -> RawFd { self.fd }
    /// Add POLLIN to events to listen for
    pub fn readable(&self) -> bool { self.read }
    /// Add POLLOUT to events to listen for
    pub fn writable(&self) -> bool { self.write }
    /// Returns the current watch as a libc::pollfd, to use with libc::poll
    pub fn to_pollfd(&self) -> libc::pollfd {
        libc::pollfd { fd: self.fd, revents: 0, events: libc::POLLERR + libc::POLLHUP +
            if self.readable() { libc::POLLIN } else { 0 } +
            if self.writable() { libc::POLLOUT } else { 0 },
        }
    }
}

impl AsRawFd for Watch {
    fn as_raw_fd(&self) -> RawFd { self.fd }
}

/// Note - internal struct, not to be used outside API. Moving it outside its box will break things.
pub struct WatchList {
    watches: RefCell<Vec<*mut ffi::DBusWatch>>,
    enabled_fds: RefCell<Vec<Watch>>,
    on_update: Box<Fn(Watch)>
}

impl WatchList {
    pub fn new(c: &Connection, on_update: Box<Fn(Watch)>) -> Box<WatchList> {
        let w = Box::new(WatchList { on_update: on_update, watches: RefCell::new(vec!()), enabled_fds: RefCell::new(vec!()) });
        if unsafe { ffi::dbus_connection_set_watch_functions(super::connection::conn_handle(c),
            Some(add_watch_cb), Some(remove_watch_cb), Some(toggled_watch_cb), &*w as *const _ as *mut _, None) } == 0 {
            panic!("dbus_connection_set_watch_functions failed");
        }
        w
    }

    pub fn watch_handle(&self, fd: RawFd, flags: c_uint) {
        // println!("watch_handle {} flags {}", fd, flags);
        for &q in self.watches.borrow().iter() {
            let w = self.get_watch(q);
            if w.fd != fd { continue };
            if unsafe { ffi::dbus_watch_handle(q, flags) } == 0 {
                panic!("dbus_watch_handle failed");
            }
            self.update(q);
        };
    }

    pub fn get_enabled_fds(&self) -> Vec<Watch> {
        self.enabled_fds.borrow().clone()
    }

    fn get_watch(&self, watch: *mut ffi::DBusWatch) -> Watch {
        let mut w = Watch { fd: unsafe { ffi::dbus_watch_get_unix_fd(watch) }, read: false, write: false};
        let enabled = self.watches.borrow().contains(&watch) && unsafe { ffi::dbus_watch_get_enabled(watch) != 0 };
        let flags = unsafe { ffi::dbus_watch_get_flags(watch) };
        if enabled {
            w.read = (flags & WatchEvent::Readable as c_uint) != 0;
            w.write = (flags & WatchEvent::Writable as c_uint) != 0;
        }
        // println!("Get watch fd {:?} ptr {:?} enabled {:?} flags {:?}", w, watch, enabled, flags);
        w
    }

    fn update(&self, watch: *mut ffi::DBusWatch) {
        let mut w = self.get_watch(watch);

        for &q in self.watches.borrow().iter() {
            if q == watch { continue };
            let ww = self.get_watch(q);
            if ww.fd != w.fd { continue };
            w.read |= ww.read;
            w.write |= ww.write;
        }
        // println!("Updated sum: {:?}", w);

        {
            let mut fdarr = self.enabled_fds.borrow_mut();

            if w.write || w.read {
                if fdarr.contains(&w) { return; } // Nothing changed
            }
            else if !fdarr.iter().any(|q| w.fd == q.fd) { return; } // Nothing changed

            fdarr.retain(|f| f.fd != w.fd);
            if w.write || w.read { fdarr.push(w) };
        }
        (*self.on_update)(w);
    }
}

extern "C" fn add_watch_cb(watch: *mut ffi::DBusWatch, data: *mut c_void) -> u32 {
    let wlist: &WatchList = unsafe { mem::transmute(data) };
    // println!("Add watch {:?}", watch);
    wlist.watches.borrow_mut().push(watch);
    wlist.update(watch);
    1
}

extern "C" fn remove_watch_cb(watch: *mut ffi::DBusWatch, data: *mut c_void) {
    let wlist: &WatchList = unsafe { mem::transmute(data) };
    // println!("Removed watch {:?}", watch);
    wlist.watches.borrow_mut().retain(|w| *w != watch);
    wlist.update(watch);
}

extern "C" fn toggled_watch_cb(watch: *mut ffi::DBusWatch, data: *mut c_void) {
    let wlist: &WatchList = unsafe { mem::transmute(data) };
    // println!("Toggled watch {:?}", watch);
    wlist.update(watch);
}

#[cfg(test)]
mod test {
    use libc;
    use super::super::{Connection, Message, BusType, WatchEvent, ConnectionItem, MessageType};

    #[test]
    fn async() {
        let c = Connection::get_private(BusType::Session).unwrap();
        c.register_object_path("/test").unwrap();
        let m = Message::new_method_call(&c.unique_name(), "/test", "com.example.asynctest", "AsyncTest").unwrap();
        let serial = c.send(m).unwrap();
        println!("Async: sent serial {}", serial);

        let mut fds: Vec<_> = c.watch_fds().iter().map(|w| w.to_pollfd()).collect();
        let mut new_fds = None;
        let mut i = 0;
        let mut success = false;
        while !success {
            i += 1;
            if let Some(q) = new_fds { fds = q; new_fds = None };

            for f in fds.iter_mut() { f.revents = 0 };
            assert!(unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, 1000) } > 0);

            for f in fds.iter().filter(|pfd| pfd.revents != 0) {
                let m = WatchEvent::from_revents(f.revents);
                println!("Async: fd {}, revents {} -> {}", f.fd, f.revents, m);
                assert!(f.revents & libc::POLLIN != 0 || f.revents & libc::POLLOUT != 0);

                for e in c.watch_handle(f.fd, m) {
                    println!("Async: got {:?}", e);
                    match e {
                        ConnectionItem::WatchFd(_) => new_fds = Some(c.watch_fds().iter().map(|w| w.to_pollfd()).collect()),
                        ConnectionItem::MethodCall(m) => {
                            assert_eq!(m.headers(), (MessageType::MethodCall, Some("/test".to_string()),
                                Some("com.example.asynctest".into()), Some("AsyncTest".to_string())));
                            let mut mr = Message::new_method_return(&m).unwrap();
                            mr.append_items(&["Goodies".into()]);
                            c.send(mr).unwrap();
                        }
                        ConnectionItem::MethodReturn(m) => {
                            assert_eq!(m.headers().0, MessageType::MethodReturn);
                            assert_eq!(m.get_reply_serial().unwrap(), serial);
                            let i = m.get_items();
                            let s: &str = i[0].inner().unwrap();
                            assert_eq!(s, "Goodies");
                            success = true;
                        }
                        _ => (),
                    }
                }
                if i > 100 { panic!() };
            }
        }
    }
}
<commit_msg>Make WatchEvent use ffi constants<commit_after>use ffi;
use libc;
use super::Connection;

use std::mem;
use std::cell::RefCell;
use std::os::unix::io::{RawFd, AsRawFd};
use std::os::raw::{c_void, c_uint};

/// A file descriptor to watch for incoming events (for async I/O).
///
/// # Example
/// ```
/// extern crate libc;
/// extern crate dbus;
/// fn main() {
///     use dbus::{Connection, BusType, WatchEvent};
///     let c = Connection::get_private(BusType::Session).unwrap();
///
///     // Get a list of fds to poll for
///     let mut fds: Vec<_> = c.watch_fds().iter().map(|w| w.to_pollfd()).collect();
///
///     // Poll them with a 1 s timeout
///     let r = unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, 1000) };
///     assert!(r >= 0);
///
///     // And handle incoming events
///     for pfd in fds.iter().filter(|pfd| pfd.revents != 0) {
///         for item in c.watch_handle(pfd.fd, WatchEvent::from_revents(pfd.revents)) {
///             // Handle item
///             println!("Received ConnectionItem: {:?}", item);
///         }
///     }
/// }
/// ```

#[repr(C)]
#[derive(Debug, PartialEq, Copy, Clone)]
/// The enum is here for backwards compatibility mostly.
///
/// It should really be bitflags instead.
pub enum WatchEvent {
    /// The fd is readable
    Readable = ffi::DBUS_WATCH_READABLE as isize,
    /// The fd is writable
    Writable = ffi::DBUS_WATCH_WRITABLE as isize,
    /// An error occured on the fd
    Error = ffi::DBUS_WATCH_ERROR as isize,
    /// The fd received a hangup.
    Hangup = ffi::DBUS_WATCH_HANGUP as isize,
}

impl WatchEvent {
    /// After running poll, this transforms the revents into a parameter you can send into `Connection::watch_handle`
    pub fn from_revents(revents: libc::c_short) -> c_uint {
        0 +
        if (revents & libc::POLLIN) != 0 { WatchEvent::Readable as c_uint } else { 0 } +
        if (revents & libc::POLLOUT) != 0 { WatchEvent::Writable as c_uint } else { 0 } +
        if (revents & libc::POLLERR) != 0 { WatchEvent::Error as c_uint } else { 0 } +
        if (revents & libc::POLLHUP) != 0 { WatchEvent::Hangup as c_uint } else { 0 }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
/// A file descriptor, and an indication whether it should be read from, written to, or both.
pub struct Watch {
    fd: RawFd,
    read: bool,
    write: bool,
}

impl Watch {
    /// Get the RawFd this Watch is for
    pub fn fd(&self) -> RawFd { self.fd }
    /// Add POLLIN to events to listen for
    pub fn readable(&self) -> bool { self.read }
    /// Add POLLOUT to events to listen for
    pub fn writable(&self) -> bool { self.write }
    /// Returns the current watch as a libc::pollfd, to use with libc::poll
    pub fn to_pollfd(&self) -> libc::pollfd {
        libc::pollfd { fd: self.fd, revents: 0, events: libc::POLLERR + libc::POLLHUP +
            if self.readable() { libc::POLLIN } else { 0 } +
            if self.writable() { libc::POLLOUT } else { 0 },
        }
    }
}

impl AsRawFd for Watch {
    fn as_raw_fd(&self) -> RawFd { self.fd }
}

/// Note - internal struct, not to be used outside API. Moving it outside its box will break things.
pub struct WatchList {
    watches: RefCell<Vec<*mut ffi::DBusWatch>>,
    enabled_fds: RefCell<Vec<Watch>>,
    on_update: Box<Fn(Watch)>
}

impl WatchList {
    pub fn new(c: &Connection, on_update: Box<Fn(Watch)>) -> Box<WatchList> {
        let w = Box::new(WatchList { on_update: on_update, watches: RefCell::new(vec!()), enabled_fds: RefCell::new(vec!()) });
        if unsafe { ffi::dbus_connection_set_watch_functions(super::connection::conn_handle(c),
            Some(add_watch_cb), Some(remove_watch_cb), Some(toggled_watch_cb), &*w as *const _ as *mut _, None) } == 0 {
            panic!("dbus_connection_set_watch_functions failed");
        }
        w
    }

    pub fn watch_handle(&self, fd: RawFd, flags: c_uint) {
        // println!("watch_handle {} flags {}", fd, flags);
        for &q in self.watches.borrow().iter() {
            let w = self.get_watch(q);
            if w.fd != fd { continue };
            if unsafe { ffi::dbus_watch_handle(q, flags) } == 0 {
                panic!("dbus_watch_handle failed");
            }
            self.update(q);
        };
    }

    pub fn get_enabled_fds(&self) -> Vec<Watch> {
        self.enabled_fds.borrow().clone()
    }

    fn get_watch(&self, watch: *mut ffi::DBusWatch) -> Watch {
        let mut w = Watch { fd: unsafe { ffi::dbus_watch_get_unix_fd(watch) }, read: false, write: false};
        let enabled = self.watches.borrow().contains(&watch) && unsafe { ffi::dbus_watch_get_enabled(watch) != 0 };
        let flags = unsafe { ffi::dbus_watch_get_flags(watch) };
        if enabled {
            w.read = (flags & WatchEvent::Readable as c_uint) != 0;
            w.write = (flags & WatchEvent::Writable as c_uint) != 0;
        }
        // println!("Get watch fd {:?} ptr {:?} enabled {:?} flags {:?}", w, watch, enabled, flags);
        w
    }

    fn update(&self, watch: *mut ffi::DBusWatch) {
        let mut w = self.get_watch(watch);

        for &q in self.watches.borrow().iter() {
            if q == watch { continue };
            let ww = self.get_watch(q);
            if ww.fd != w.fd { continue };
            w.read |= ww.read;
            w.write |= ww.write;
        }
        // println!("Updated sum: {:?}", w);

        {
            let mut fdarr = self.enabled_fds.borrow_mut();

            if w.write || w.read {
                if fdarr.contains(&w) { return; } // Nothing changed
            }
            else if !fdarr.iter().any(|q| w.fd == q.fd) { return; } // Nothing changed

            fdarr.retain(|f| f.fd != w.fd);
            if w.write || w.read { fdarr.push(w) };
        }
        (*self.on_update)(w);
    }
}

extern "C" fn add_watch_cb(watch: *mut ffi::DBusWatch, data: *mut c_void) -> u32 {
    let wlist: &WatchList = unsafe { mem::transmute(data) };
    // println!("Add watch {:?}", watch);
    wlist.watches.borrow_mut().push(watch);
    wlist.update(watch);
    1
}

extern "C" fn remove_watch_cb(watch: *mut ffi::DBusWatch, data: *mut c_void) {
    let wlist: &WatchList = unsafe { mem::transmute(data) };
    // println!("Removed watch {:?}", watch);
    wlist.watches.borrow_mut().retain(|w| *w != watch);
    wlist.update(watch);
}

extern "C" fn toggled_watch_cb(watch: *mut ffi::DBusWatch, data: *mut c_void) {
    let wlist: &WatchList = unsafe { mem::transmute(data) };
    // println!("Toggled watch {:?}", watch);
    wlist.update(watch);
}

#[cfg(test)]
mod test {
    use libc;
    use super::super::{Connection, Message, BusType, WatchEvent, ConnectionItem, MessageType};

    #[test]
    fn async() {
        let c = Connection::get_private(BusType::Session).unwrap();
        c.register_object_path("/test").unwrap();
        let m = Message::new_method_call(&c.unique_name(), "/test", "com.example.asynctest", "AsyncTest").unwrap();
        let serial = c.send(m).unwrap();
        println!("Async: sent serial {}", serial);

        let mut fds: Vec<_> = c.watch_fds().iter().map(|w| w.to_pollfd()).collect();
        let mut new_fds = None;
        let mut i = 0;
        let mut success = false;
        while !success {
            i += 1;
            if let Some(q) = new_fds { fds = q; new_fds = None };

            for f in fds.iter_mut() { f.revents = 0 };
            assert!(unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, 1000) } > 0);

            for f in fds.iter().filter(|pfd| pfd.revents != 0) {
                let m = WatchEvent::from_revents(f.revents);
                println!("Async: fd {}, revents {} -> {}", f.fd, f.revents, m);
                assert!(f.revents & libc::POLLIN != 0 || f.revents & libc::POLLOUT != 0);

                for e in c.watch_handle(f.fd, m) {
                    println!("Async: got {:?}", e);
                    match e {
                        ConnectionItem::WatchFd(_) => new_fds = Some(c.watch_fds().iter().map(|w| w.to_pollfd()).collect()),
                        ConnectionItem::MethodCall(m) => {
                            assert_eq!(m.headers(), (MessageType::MethodCall, Some("/test".to_string()),
                                Some("com.example.asynctest".into()), Some("AsyncTest".to_string())));
                            let mut mr = Message::new_method_return(&m).unwrap();
                            mr.append_items(&["Goodies".into()]);
                            c.send(mr).unwrap();
                        }
                        ConnectionItem::MethodReturn(m) => {
                            assert_eq!(m.headers().0, MessageType::MethodReturn);
                            assert_eq!(m.get_reply_serial().unwrap(), serial);
                            let i = m.get_items();
                            let s: &str = i[0].inner().unwrap();
                            assert_eq!(s, "Goodies");
                            success = true;
                        }
                        _ => (),
                    }
                }
                if i > 100 { panic!() };
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::path::{Display, PathBuf};
use std::process::ExitStatus;
use std::{env, mem};
use std::io::{self, Write};

use toml::Value;
use rustc_version::VersionMeta;

use CompilationMode;
use cargo::{Config, Root, Rustflags, Subcommand};
use cli::Args;
use errors::*;
use extensions::CommandExt;
use flock::{FileLock, Filesystem};
use {cargo, util};

pub fn run(
    args: &Args,
    cmode: &CompilationMode,
    rustflags: Rustflags,
    home: &Home,
    meta: &VersionMeta,
    config: Option<&Config>,
    verbose: bool,
) -> Result<ExitStatus> {
    let mut cmd = cargo::command();
    cmd.args(args.all());

    if args.subcommand() == Some(Subcommand::Doc) {
        cmd.env(
            "RUSTDOCFLAGS",
            cargo::rustdocflags(config, cmode.triple())?.for_xargo(home),
        );
    }

    let flags = rustflags.for_xargo(home);
    if verbose {
        writeln!(io::stderr(), "+ RUSTFLAGS={:?}", flags).ok();
    }
    cmd.env("RUSTFLAGS", flags);

    let locks = (home.lock_ro(&meta.host), home.lock_ro(cmode.triple()));

    let status = cmd.run_and_get_status(verbose)?;

    mem::drop(locks);

    Ok(status)
}

pub struct Home {
    path: Filesystem,
}

impl Home {
    pub fn display(&self) -> Display {
        self.path.display()
    }

    fn path(&self, triple: &str) -> Filesystem {
        self.path.join("lib/rustlib").join(triple)
    }

    pub fn lock_ro(&self, triple: &str) -> Result<FileLock> {
        let fs = self.path(triple);

        fs.open_ro(".sentinel", &format!("{}'s sysroot", triple))
            .chain_err(|| {
                format!("couldn't lock {}'s sysroot as read-only", triple)
            })
    }

    pub fn lock_rw(&self, triple: &str) -> Result<FileLock> {
        let fs = self.path(triple);

        fs.open_rw(".sentinel", &format!("{}'s sysroot", triple))
            .chain_err(|| {
                format!("couldn't lock {}'s sysroot as read-only", triple)
            })
    }
}

pub fn home(cmode: &CompilationMode) -> Result<Home> {
    let mut p = if let Some(h) = env::var_os("XARGO_HOME") {
        PathBuf::from(h)
    } else {
        dirs::home_dir()
            .ok_or_else(|| "couldn't find your home directory. Is $HOME set?")?
            .join(".xargo")
    };

    if cmode.is_native() {
        p.push("HOST");
    }

    Ok(Home {
        path: Filesystem::new(p),
    })
}

pub struct Toml {
    table: Value,
}

impl Toml {
    /// Returns the `dependencies` part of `Xargo.toml`
    pub fn dependencies(&self) -> Option<&Value> {
        self.table.lookup("dependencies")
    }

    /// Returns the `target.{}.dependencies` part of `Xargo.toml`
    pub fn target_dependencies(&self, target: &str) -> Option<&Value> {
        self.table
            .lookup(&format!("target.{}.dependencies", target))
    }

    /// Returns the `patch` part of `Xargo.toml`
    pub fn patch(&self) -> Option<&Value> {
        self.table.lookup("patch")
    }
}

pub fn toml(root: &Root) -> Result<Option<Toml>> {
    let p = root.path().join("Xargo.toml");

    if p.exists() {
        util::parse(&p).map(|t| Some(Toml { table: t }))
    } else {
        Ok(None)
    }
}
<commit_msg>Search for Xargo.toml in parent directories.<commit_after>use std::path::{Display, PathBuf};
use std::process::ExitStatus;
use std::{env, mem};
use std::io::{self, Write};

use toml::Value;
use rustc_version::VersionMeta;

use CompilationMode;
use cargo::{Config, Root, Rustflags, Subcommand};
use cli::Args;
use errors::*;
use extensions::CommandExt;
use flock::{FileLock, Filesystem};
use {cargo, util};

pub fn run(
    args: &Args,
    cmode: &CompilationMode,
    rustflags: Rustflags,
    home: &Home,
    meta: &VersionMeta,
    config: Option<&Config>,
    verbose: bool,
) -> Result<ExitStatus> {
    let mut cmd = cargo::command();
    cmd.args(args.all());

    if args.subcommand() == Some(Subcommand::Doc) {
        cmd.env(
            "RUSTDOCFLAGS",
            cargo::rustdocflags(config, cmode.triple())?.for_xargo(home),
        );
    }

    let flags = rustflags.for_xargo(home);
    if verbose {
        writeln!(io::stderr(), "+ RUSTFLAGS={:?}", flags).ok();
    }
    cmd.env("RUSTFLAGS", flags);

    let locks = (home.lock_ro(&meta.host), home.lock_ro(cmode.triple()));

    let status = cmd.run_and_get_status(verbose)?;

    mem::drop(locks);

    Ok(status)
}

pub struct Home {
    path: Filesystem,
}

impl Home {
    pub fn display(&self) -> Display {
        self.path.display()
    }

    fn path(&self, triple: &str) -> Filesystem {
        self.path.join("lib/rustlib").join(triple)
    }

    pub fn lock_ro(&self, triple: &str) -> Result<FileLock> {
        let fs = self.path(triple);

        fs.open_ro(".sentinel", &format!("{}'s sysroot", triple))
            .chain_err(|| {
                format!("couldn't lock {}'s sysroot as read-only", triple)
            })
    }

    pub fn lock_rw(&self, triple: &str) -> Result<FileLock> {
        let fs = self.path(triple);

        fs.open_rw(".sentinel", &format!("{}'s sysroot", triple))
            .chain_err(|| {
                format!("couldn't lock {}'s sysroot as read-only", triple)
            })
    }
}

pub fn home(cmode: &CompilationMode) -> Result<Home> {
    let mut p = if let Some(h) = env::var_os("XARGO_HOME") {
        PathBuf::from(h)
    } else {
        dirs::home_dir()
            .ok_or_else(|| "couldn't find your home directory. Is $HOME set?")?
            .join(".xargo")
    };

    if cmode.is_native() {
        p.push("HOST");
    }

    Ok(Home {
        path: Filesystem::new(p),
    })
}

pub struct Toml {
    table: Value,
}

impl Toml {
    /// Returns the `dependencies` part of `Xargo.toml`
    pub fn dependencies(&self) -> Option<&Value> {
        self.table.lookup("dependencies")
    }

    /// Returns the `target.{}.dependencies` part of `Xargo.toml`
    pub fn target_dependencies(&self, target: &str) -> Option<&Value> {
        self.table
            .lookup(&format!("target.{}.dependencies", target))
    }

    /// Returns the `patch` part of `Xargo.toml`
    pub fn patch(&self) -> Option<&Value> {
        self.table.lookup("patch")
    }
}

pub fn toml(root: &Root) -> Result<Option<Toml>> {
    if let Some(p) = util::search(root.path(), "Xargo.toml") {
        util::parse(&p.join("Xargo.toml")).map(|t| Some(Toml { table: t }))
    }
    else {
        Ok(None)
    }
}
<|endoftext|>


<commit_before>use crate::syntax::atom::Atom::*;
use crate::syntax::{Derive, ExternFn, Receiver, Ref, Signature, Slice, Ty1, Type, Var};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{quote_spanned, ToTokens};
use syn::Token;

impl ToTokens for Type {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match self {
            Type::Ident(ident) => {
                if ident == CxxString {
                    let span = ident.span();
                    tokens.extend(quote_spanned!(span=> ::cxx::));
                }
                ident.to_tokens(tokens);
            }
            Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) | Type::RustVec(ty) => {
                ty.to_tokens(tokens)
            }
            Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
            Type::Slice(s) => s.to_tokens(tokens),
            Type::Fn(f) => f.to_tokens(tokens),
            Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
        }
    }
}

impl ToTokens for Var {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.ident.to_tokens(tokens);
        Token![:](self.ident.span()).to_tokens(tokens);
        self.ty.to_tokens(tokens);
    }
}

impl ToTokens for Ty1 {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        // Do not add cxx namespace to Vector since we're defining it in the user crate
        if self.name == "UniquePtr" || self.name == "RustVec" {
            let span = self.name.span();
            tokens.extend(quote_spanned!(span=> ::cxx::));
        }
        self.name.to_tokens(tokens);
        self.langle.to_tokens(tokens);
        self.inner.to_tokens(tokens);
        self.rangle.to_tokens(tokens);
    }
}

impl ToTokens for Ref {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.ampersand.to_tokens(tokens);
        self.lifetime.to_tokens(tokens);
        self.mutability.to_tokens(tokens);
        self.inner.to_tokens(tokens);
    }
}

impl ToTokens for Slice {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.bracket.surround(tokens, |tokens| {
            self.inner.to_tokens(tokens);
        });
    }
}

impl ToTokens for Derive {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let name = match self {
            Derive::Clone => "Clone",
            Derive::Copy => "Copy",
        };
        Ident::new(name, Span::call_site()).to_tokens(tokens);
    }
}

impl ToTokens for ExternFn {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        // Notional token range for error reporting purposes.
        self.sig.fn_token.to_tokens(tokens);
        self.semi_token.to_tokens(tokens);
    }
}

impl ToTokens for Signature {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.fn_token.to_tokens(tokens);
        self.paren_token.surround(tokens, |tokens| {
            self.args.to_tokens(tokens);
        });
        if let Some(ret) = &self.ret {
            Token![->](self.paren_token.span).to_tokens(tokens);
            if let Some((result, langle, rangle)) = self.throws_tokens {
                result.to_tokens(tokens);
                langle.to_tokens(tokens);
                ret.to_tokens(tokens);
                rangle.to_tokens(tokens);
            } else {
                ret.to_tokens(tokens);
            }
        }
    }
}

pub struct ReceiverType<'a>(&'a Receiver);

impl Receiver {
    // &TheType
    pub fn ty(&self) -> ReceiverType {
        ReceiverType(self)
    }
}

impl ToTokens for ReceiverType<'_> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.0.ampersand.to_tokens(tokens);
        self.0.lifetime.to_tokens(tokens);
        self.0.mutability.to_tokens(tokens);
        self.0.ty.to_tokens(tokens);
    }
}
<commit_msg>Emit prefixed path when using CxxVector type<commit_after>use crate::syntax::atom::Atom::*;
use crate::syntax::{Derive, ExternFn, Receiver, Ref, Signature, Slice, Ty1, Type, Var};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{quote_spanned, ToTokens};
use syn::Token;

impl ToTokens for Type {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match self {
            Type::Ident(ident) => {
                if ident == CxxString {
                    let span = ident.span();
                    tokens.extend(quote_spanned!(span=> ::cxx::));
                }
                ident.to_tokens(tokens);
            }
            Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) | Type::RustVec(ty) => {
                ty.to_tokens(tokens)
            }
            Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
            Type::Slice(s) => s.to_tokens(tokens),
            Type::Fn(f) => f.to_tokens(tokens),
            Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
        }
    }
}

impl ToTokens for Var {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.ident.to_tokens(tokens);
        Token![:](self.ident.span()).to_tokens(tokens);
        self.ty.to_tokens(tokens);
    }
}

impl ToTokens for Ty1 {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        if let "UniquePtr" | "RustVec" | "CxxVector" = self.name.to_string().as_str() {
            let span = self.name.span();
            tokens.extend(quote_spanned!(span=> ::cxx::));
        }
        self.name.to_tokens(tokens);
        self.langle.to_tokens(tokens);
        self.inner.to_tokens(tokens);
        self.rangle.to_tokens(tokens);
    }
}

impl ToTokens for Ref {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.ampersand.to_tokens(tokens);
        self.lifetime.to_tokens(tokens);
        self.mutability.to_tokens(tokens);
        self.inner.to_tokens(tokens);
    }
}

impl ToTokens for Slice {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.bracket.surround(tokens, |tokens| {
            self.inner.to_tokens(tokens);
        });
    }
}

impl ToTokens for Derive {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let name = match self {
            Derive::Clone => "Clone",
            Derive::Copy => "Copy",
        };
        Ident::new(name, Span::call_site()).to_tokens(tokens);
    }
}

impl ToTokens for ExternFn {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        // Notional token range for error reporting purposes.
        self.sig.fn_token.to_tokens(tokens);
        self.semi_token.to_tokens(tokens);
    }
}

impl ToTokens for Signature {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.fn_token.to_tokens(tokens);
        self.paren_token.surround(tokens, |tokens| {
            self.args.to_tokens(tokens);
        });
        if let Some(ret) = &self.ret {
            Token![->](self.paren_token.span).to_tokens(tokens);
            if let Some((result, langle, rangle)) = self.throws_tokens {
                result.to_tokens(tokens);
                langle.to_tokens(tokens);
                ret.to_tokens(tokens);
                rangle.to_tokens(tokens);
            } else {
                ret.to_tokens(tokens);
            }
        }
    }
}

pub struct ReceiverType<'a>(&'a Receiver);

impl Receiver {
    // &TheType
    pub fn ty(&self) -> ReceiverType {
        ReceiverType(self)
    }
}

impl ToTokens for ReceiverType<'_> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.0.ampersand.to_tokens(tokens);
        self.0.lifetime.to_tokens(tokens);
        self.0.mutability.to_tokens(tokens);
        self.0.ty.to_tokens(tokens);
    }
}
<|endoftext|>