<commit_before>use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use std::collections::HashMap;
use std::fmt::Debug;
use std::ops::Deref;
use std::str::FromStr;

use error::*;
use ser::ConfigSerializer;
use source::Source;

use path;
use value::{Table, Value, ValueKind};

#[derive(Clone, Debug)]
enum ConfigKind {
    // A mutable configuration. This is the default.
    Mutable {
        defaults: HashMap<path::Expression, Value>,
        overrides: HashMap<path::Expression, Value>,
        sources: Vec<Box<dyn Source + Send + Sync>>,
    },

    // A frozen configuration.
    // Configuration can no longer be mutated.
    Frozen,
}

impl Default for ConfigKind {
    fn default() -> Self {
        ConfigKind::Mutable {
            defaults: HashMap::new(),
            overrides: HashMap::new(),
            sources: Vec::new(),
        }
    }
}

/// A prioritized configuration repository. It maintains a set of
/// configuration sources, fetches values to populate those, and provides
/// them according to the source's priority.
#[derive(Default, Clone, Debug)]
pub struct Config {
    kind: ConfigKind,

    /// Root of the cached configuration.
    pub cache: Value,
}

impl Config {
    pub fn new() -> Self {
        Self {
            kind: ConfigKind::default(),
            // Config root should be instantiated as an empty table
            // to avoid deserialization errors.
            cache: Value::new(None, Table::new()),
        }
    }

    /// Merge in a configuration property source.
    pub fn merge<T>(&mut self, source: T) -> Result<&mut Config>
    where
        T: 'static,
        T: Source + Send + Sync,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut sources, ..
            } => {
                sources.push(Box::new(source));
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        }

        self.refresh()
    }

    /// Merge in a configuration property source.
    pub fn with_merged<T>(mut self, source: T) -> Result<Self>
    where
        T: 'static,
        T: Source + Send + Sync,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut sources, ..
            } => {
                sources.push(Box::new(source));
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        }

        self.refresh()?;
        Ok(self)
    }

    /// Refresh the configuration cache with fresh
    /// data from added sources.
    ///
    /// Configuration is automatically refreshed after a mutation
    /// operation (`set`, `merge`, `set_default`, etc.).
    pub fn refresh(&mut self) -> Result<&mut Config> {
        self.cache = match self.kind {
            // TODO: We need to actually merge in all the stuff
            ConfigKind::Mutable {
                ref overrides,
                ref sources,
                ref defaults,
            } => {
                let mut cache: Value = HashMap::<String, Value>::new().into();

                // Add defaults
                for (key, val) in defaults {
                    key.set(&mut cache, val.clone());
                }

                // Add sources
                sources.collect_to(&mut cache)?;

                // Add overrides
                for (key, val) in overrides {
                    key.set(&mut cache, val.clone());
                }

                cache
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        };

        Ok(self)
    }

    pub fn set_default<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
    where
        T: Into<Value>,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut defaults, ..
            } => {
                defaults.insert(key.parse()?, value.into());
            }

            ConfigKind::Frozen => return Err(ConfigError::Frozen),
        };

        self.refresh()
    }

    pub fn set<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
    where
        T: Into<Value>,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut overrides, ..
            } => {
                overrides.insert(key.parse()?, value.into());
            }

            ConfigKind::Frozen => return Err(ConfigError::Frozen),
        };

        self.refresh()
    }

    pub fn set_once(&mut self, key: &str, value: Value) -> Result<()> {
        let expr: path::Expression = key.parse()?;

        // Traverse the cache using the path to (possibly) retrieve a value
        if let Some(ref mut val) = expr.get_mut(&mut self.cache) {
            **val = value;
        } else {
            expr.set(&mut self.cache, value);
        }
        Ok(())
    }

    pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
        // Parse the key into a path expression
        let expr: path::Expression = key.parse()?;

        // Traverse the cache using the path to (possibly) retrieve a value
        let value = expr.get(&self.cache).cloned();

        match value {
            Some(value) => {
                // Deserialize the received value into the requested type
                T::deserialize(value).map_err(|e| e.extend_with_key(key))
            }

            None => Err(ConfigError::NotFound(key.into())),
        }
    }

    pub fn get_str(&self, key: &str) -> Result<String> {
        self.get(key).and_then(Value::into_str)
    }

    pub fn get_int(&self, key: &str) -> Result<i64> {
        self.get(key).and_then(Value::into_int)
    }

    pub fn get_float(&self, key: &str) -> Result<f64> {
        self.get(key).and_then(Value::into_float)
    }

    pub fn get_bool(&self, key: &str) -> Result<bool> {
        self.get(key).and_then(Value::into_bool)
    }

    pub fn get_table(&self, key: &str) -> Result<HashMap<String, Value>> {
        self.get(key).and_then(Value::into_table)
    }

    pub fn get_array(&self, key: &str) -> Result<Vec<Value>> {
        self.get(key).and_then(Value::into_array)
    }

    /// Attempt to deserialize the entire configuration into the requested type.
    pub fn try_into<'de, T: Deserialize<'de>>(self) -> Result<T> {
        T::deserialize(self)
    }

    /// Attempt to serialize the entire configuration from the given type.
    pub fn try_from<T: Serialize>(from: &T) -> Result<Self> {
        let mut serializer = ConfigSerializer::default();
        from.serialize(&mut serializer)?;
        Ok(serializer.output)
    }

    #[deprecated(since = "0.7.0", note = "please use 'try_into' instead")]
    pub fn deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
        self.try_into()
    }
}

impl Source for Config {
    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
        Box::new((*self).clone())
    }

    fn collect(&self) -> Result<HashMap<String, Value>> {
        self.cache.clone().into_table()
    }
}
<commit_msg>Add doc: Config:set()<commit_after>use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use std::collections::HashMap;
use std::fmt::Debug;
use std::ops::Deref;
use std::str::FromStr;

use error::*;
use ser::ConfigSerializer;
use source::Source;

use path;
use value::{Table, Value, ValueKind};

#[derive(Clone, Debug)]
enum ConfigKind {
    // A mutable configuration. This is the default.
    Mutable {
        defaults: HashMap<path::Expression, Value>,
        overrides: HashMap<path::Expression, Value>,
        sources: Vec<Box<dyn Source + Send + Sync>>,
    },

    // A frozen configuration.
    // Configuration can no longer be mutated.
    Frozen,
}

impl Default for ConfigKind {
    fn default() -> Self {
        ConfigKind::Mutable {
            defaults: HashMap::new(),
            overrides: HashMap::new(),
            sources: Vec::new(),
        }
    }
}

/// A prioritized configuration repository. It maintains a set of
/// configuration sources, fetches values to populate those, and provides
/// them according to the source's priority.
#[derive(Default, Clone, Debug)]
pub struct Config {
    kind: ConfigKind,

    /// Root of the cached configuration.
    pub cache: Value,
}

impl Config {
    pub fn new() -> Self {
        Self {
            kind: ConfigKind::default(),
            // Config root should be instantiated as an empty table
            // to avoid deserialization errors.
            cache: Value::new(None, Table::new()),
        }
    }

    /// Merge in a configuration property source.
    pub fn merge<T>(&mut self, source: T) -> Result<&mut Config>
    where
        T: 'static,
        T: Source + Send + Sync,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut sources, ..
            } => {
                sources.push(Box::new(source));
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        }

        self.refresh()
    }

    /// Merge in a configuration property source.
    pub fn with_merged<T>(mut self, source: T) -> Result<Self>
    where
        T: 'static,
        T: Source + Send + Sync,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut sources, ..
            } => {
                sources.push(Box::new(source));
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        }

        self.refresh()?;
        Ok(self)
    }

    /// Refresh the configuration cache with fresh
    /// data from added sources.
    ///
    /// Configuration is automatically refreshed after a mutation
    /// operation (`set`, `merge`, `set_default`, etc.).
    pub fn refresh(&mut self) -> Result<&mut Config> {
        self.cache = match self.kind {
            // TODO: We need to actually merge in all the stuff
            ConfigKind::Mutable {
                ref overrides,
                ref sources,
                ref defaults,
            } => {
                let mut cache: Value = HashMap::<String, Value>::new().into();

                // Add defaults
                for (key, val) in defaults {
                    key.set(&mut cache, val.clone());
                }

                // Add sources
                sources.collect_to(&mut cache)?;

                // Add overrides
                for (key, val) in overrides {
                    key.set(&mut cache, val.clone());
                }

                cache
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        };

        Ok(self)
    }

    pub fn set_default<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
    where
        T: Into<Value>,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut defaults, ..
            } => {
                defaults.insert(key.parse()?, value.into());
            }

            ConfigKind::Frozen => return Err(ConfigError::Frozen),
        };

        self.refresh()
    }

    /// Set an overwrite
    ///
    /// This function sets an overwrite value.
    /// The overwrite `value` is written to the `key` location on every `refresh()`
    ///
    /// # Warning
    ///
    /// Errors if config is frozen
    pub fn set<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
    where
        T: Into<Value>,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut overrides, ..
            } => {
                overrides.insert(key.parse()?, value.into());
            }

            ConfigKind::Frozen => return Err(ConfigError::Frozen),
        };

        self.refresh()
    }

    pub fn set_once(&mut self, key: &str, value: Value) -> Result<()> {
        let expr: path::Expression = key.parse()?;

        // Traverse the cache using the path to (possibly) retrieve a value
        if let Some(ref mut val) = expr.get_mut(&mut self.cache) {
            **val = value;
        } else {
            expr.set(&mut self.cache, value);
        }
        Ok(())
    }

    pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
        // Parse the key into a path expression
        let expr: path::Expression = key.parse()?;

        // Traverse the cache using the path to (possibly) retrieve a value
        let value = expr.get(&self.cache).cloned();

        match value {
            Some(value) => {
                // Deserialize the received value into the requested type
                T::deserialize(value).map_err(|e| e.extend_with_key(key))
            }

            None => Err(ConfigError::NotFound(key.into())),
        }
    }

    pub fn get_str(&self, key: &str) -> Result<String> {
        self.get(key).and_then(Value::into_str)
    }

    pub fn get_int(&self, key: &str) -> Result<i64> {
        self.get(key).and_then(Value::into_int)
    }

    pub fn get_float(&self, key: &str) -> Result<f64> {
        self.get(key).and_then(Value::into_float)
    }

    pub fn get_bool(&self, key: &str) -> Result<bool> {
        self.get(key).and_then(Value::into_bool)
    }

    pub fn get_table(&self, key: &str) -> Result<HashMap<String, Value>> {
        self.get(key).and_then(Value::into_table)
    }

    pub fn get_array(&self, key: &str) -> Result<Vec<Value>> {
        self.get(key).and_then(Value::into_array)
    }

    /// Attempt to deserialize the entire configuration into the requested type.
    pub fn try_into<'de, T: Deserialize<'de>>(self) -> Result<T> {
        T::deserialize(self)
    }

    /// Attempt to serialize the entire configuration from the given type.
    pub fn try_from<T: Serialize>(from: &T) -> Result<Self> {
        let mut serializer = ConfigSerializer::default();
        from.serialize(&mut serializer)?;
        Ok(serializer.output)
    }

    #[deprecated(since = "0.7.0", note = "please use 'try_into' instead")]
    pub fn deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
        self.try_into()
    }
}

impl Source for Config {
    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
        Box::new((*self).clone())
    }

    fn collect(&self) -> Result<HashMap<String, Value>> {
        self.cache.clone().into_table()
    }
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc_front::hir::*;
use utils::{get_parent_expr, in_macro, is_block_equal, is_exp_equal, span_lint, span_note_and_lint};

/// **What it does:** This lint checks for consecutive `ifs` with the same condition. This lint is
/// `Warn` by default.
///
/// **Why is this bad?** This is probably a copy & paste error.
///
/// **Known problems:** Hopefully none.
///
/// **Example:** `if a == b { .. } else if a == b { .. }`
declare_lint! {
    pub IFS_SAME_COND,
    Warn,
    "consecutive `ifs` with the same condition"
}

/// **What it does:** This lint checks for `if/else` with the same body as the *then* part and the
/// *else* part. This lint is `Warn` by default.
///
/// **Why is this bad?** This is probably a copy & paste error.
///
/// **Known problems:** Hopefully none.
///
/// **Example:** `if .. { 42 } else { 42 }`
declare_lint! {
    pub IF_SAME_THEN_ELSE,
    Warn,
    "if with the same *then* and *else* blocks"
}

#[derive(Copy, Clone, Debug)]
pub struct CopyAndPaste;

impl LintPass for CopyAndPaste {
    fn get_lints(&self) -> LintArray {
        lint_array![
            IFS_SAME_COND,
            IF_SAME_THEN_ELSE
        ]
    }
}

impl LateLintPass for CopyAndPaste {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        if !in_macro(cx, expr.span) {
            lint_same_then_else(cx, expr);
            lint_same_cond(cx, expr);
        }
    }
}

/// Implementation of `IF_SAME_THEN_ELSE`.
fn lint_same_then_else(cx: &LateContext, expr: &Expr) {
    if let ExprIf(_, ref then_block, Some(ref else_expr)) = expr.node {
        let must_lint = if let ExprBlock(ref else_block) = else_expr.node {
            is_block_equal(cx, &then_block, &else_block, false)
        }
        else {
            false
        };

        if must_lint {
            span_lint(cx, IF_SAME_THEN_ELSE, expr.span, "this if has the same then and else blocks");
        }
    }
}

/// Implementation of `IFS_SAME_COND`.
fn lint_same_cond(cx: &LateContext, expr: &Expr) {
    // skip ifs directly in else, it will be checked in the parent if
    if let Some(&Expr{node: ExprIf(_, _, Some(ref else_expr)), ..}) = get_parent_expr(cx, expr) {
        if else_expr.id == expr.id {
            return;
        }
    }

    let conds = condition_sequence(expr);

    for (n, i) in conds.iter().enumerate() {
        for j in conds.iter().skip(n+1) {
            if is_exp_equal(cx, i, j, true) {
                span_note_and_lint(cx, IFS_SAME_COND, j.span, "this if has the same condition as a previous if", i.span, "same as this");
            }
        }
    }
}

/// Return the list of condition expressions in a sequence of `if/else`.
/// Eg. would return `[a, b]` for the expression `if a {..} else if b {..}`.
fn condition_sequence(mut expr: &Expr) -> Vec<&Expr> {
    let mut result = vec![];

    while let ExprIf(ref cond, _, ref else_expr) = expr.node {
        result.push(&**cond);

        if let Some(ref else_expr) = *else_expr {
            expr = else_expr;
        }
        else {
            break;
        }
    }

    result
}
<commit_msg>Small cleanup<commit_after>use rustc::lint::*;
use rustc_front::hir::*;
use utils::{get_parent_expr, in_macro, is_block_equal, is_exp_equal, span_lint, span_note_and_lint};

/// **What it does:** This lint checks for consecutive `ifs` with the same condition. This lint is
/// `Warn` by default.
///
/// **Why is this bad?** This is probably a copy & paste error.
///
/// **Known problems:** Hopefully none.
///
/// **Example:** `if a == b { .. } else if a == b { .. }`
declare_lint! {
    pub IFS_SAME_COND,
    Warn,
    "consecutive `ifs` with the same condition"
}

/// **What it does:** This lint checks for `if/else` with the same body as the *then* part and the
/// *else* part. This lint is `Warn` by default.
///
/// **Why is this bad?** This is probably a copy & paste error.
///
/// **Known problems:** Hopefully none.
///
/// **Example:** `if .. { 42 } else { 42 }`
declare_lint! {
    pub IF_SAME_THEN_ELSE,
    Warn,
    "if with the same *then* and *else* blocks"
}

#[derive(Copy, Clone, Debug)]
pub struct CopyAndPaste;

impl LintPass for CopyAndPaste {
    fn get_lints(&self) -> LintArray {
        lint_array![
            IFS_SAME_COND,
            IF_SAME_THEN_ELSE
        ]
    }
}

impl LateLintPass for CopyAndPaste {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        if !in_macro(cx, expr.span) {
            lint_same_then_else(cx, expr);
            lint_same_cond(cx, expr);
        }
    }
}

/// Implementation of `IF_SAME_THEN_ELSE`.
fn lint_same_then_else(cx: &LateContext, expr: &Expr) {
    if let ExprIf(_, ref then_block, Some(ref else_expr)) = expr.node {
        if let ExprBlock(ref else_block) = else_expr.node {
            if is_block_equal(cx, &then_block, &else_block, false) {
                span_lint(cx, IF_SAME_THEN_ELSE, expr.span, "this if has the same then and else blocks");
            }
        }
    }
}

/// Implementation of `IFS_SAME_COND`.
fn lint_same_cond(cx: &LateContext, expr: &Expr) {
    // skip ifs directly in else, it will be checked in the parent if
    if let Some(&Expr{node: ExprIf(_, _, Some(ref else_expr)), ..}) = get_parent_expr(cx, expr) {
        if else_expr.id == expr.id {
            return;
        }
    }

    let conds = condition_sequence(expr);

    for (n, i) in conds.iter().enumerate() {
        for j in conds.iter().skip(n+1) {
            if is_exp_equal(cx, i, j, true) {
                span_note_and_lint(cx, IFS_SAME_COND, j.span, "this if has the same condition as a previous if", i.span, "same as this");
            }
        }
    }
}

/// Return the list of condition expressions in a sequence of `if/else`.
/// Eg. would return `[a, b]` for the expression `if a {..} else if b {..}`.
fn condition_sequence(mut expr: &Expr) -> Vec<&Expr> {
    let mut result = vec![];

    while let ExprIf(ref cond, _, ref else_expr) = expr.node {
        result.push(&**cond);

        if let Some(ref else_expr) = *else_expr {
            expr = else_expr;
        }
        else {
            break;
        }
    }

    result
}
<|endoftext|>


<commit_before>extern crate rustbox;

use std::char;
use std::comm::{Receiver, Sender};
use std::num;
use std::io::{File, FileMode, FileAccess};

use rdit::Response;
use buffer::Buffer;
use cursor::Direction;
use keyboard::Key;

enum EventStatus {
    Handled(Response),
    NotHandled,
}

pub struct Editor<'e> {
    pub sender: Sender<rustbox::Event>,
    events: Receiver<rustbox::Event>,
    active_buffer: Buffer<'e>,
}

impl<'e> Editor<'e> {
    pub fn new(filename: String) -> Editor<'e> {
        let path = Path::new(filename);
        let buffer = Buffer::new_from_file(&path);

        let (send, recv) = channel();
        Editor {
            sender: send,
            events: recv,
            active_buffer: buffer,
        }
    }

    pub fn handle_key_event(&mut self, key: u16, ch: u32) -> Response {
        let input_key: Option<Key> = num::from_u16(key);

        let event_status = self.handle_system_event(input_key.unwrap());
        match event_status {
            EventStatus::Handled(r) => { return r }
            EventStatus::NotHandled => { /* keep going */ }
        }

        print!("k: {} ", key);
        print!("c: {} **", ch);

        match char::from_u32(ch) {
            Some(c) => {
                self.active_buffer.insert_char(c);
                return Response::Continue
            }
            _ => {}
        }

        Response::Continue
    }

    pub fn save_active_buffer(&mut self) {
        let lines = &self.active_buffer.lines;
        let path = Path::new(&self.active_buffer.file_path);

        let mut file = match File::open_mode(&path, FileMode::Open, FileAccess::Write) {
            Ok(f) => f,
            Err(e) => panic!("file error: {}", e),
        };

        for line in lines.iter() {
            let data = format!("{}\n", line.borrow().data);
            let result = file.write(data.as_bytes());

            if result.is_err() {
                // TODO: figure out what to do here.
            }
        }
    }

    pub fn draw(&mut self) {
        self.active_buffer.draw_contents();
        self.active_buffer.draw_status();
        self.active_buffer.cursor.draw();
    }

    pub fn start(&mut self) -> bool {
        loop {
            rustbox::clear();
            self.draw();
            rustbox::present();
            match self.events.try_recv() {
                Ok(rustbox::KeyEvent(_, key, ch)) => {
                    match self.handle_key_event(key, ch) {
                        Response::Quit => break,
                        Response::Continue => {
                            rustbox::clear();
                            rustbox::present();
                        }
                    }
                },
                _ => {}
            }
        }
        return false
    }

    fn handle_system_event(&mut self, key: Key) -> EventStatus {
        match key {
            Key::Up        => { self.active_buffer.adjust_cursor(Direction::Up); }
            Key::Down      => { self.active_buffer.adjust_cursor(Direction::Down); }
            Key::Left      => { self.active_buffer.adjust_cursor(Direction::Left); }
            Key::Right     => { self.active_buffer.adjust_cursor(Direction::Right); }
            Key::Enter     => { self.active_buffer.insert_line(); }
            Key::Space     => { self.active_buffer.insert_char(' '); }
            Key::Backspace => { self.active_buffer.delete_char(); }
            Key::CtrlS     => { self.save_active_buffer(); }
            Key::CtrlQ     => { return EventStatus::Handled(Response::Quit) }
            _              => { return EventStatus::NotHandled }
        }
        // event is handled and we want to keep the editor running
        EventStatus::Handled(Response::Continue)
    }

}

<commit_msg>Remove unneeded clear & redraw of buffer - fixes #2<commit_after>extern crate rustbox;

use std::char;
use std::comm::{Receiver, Sender};
use std::num;
use std::io::{File, FileMode, FileAccess};

use rdit::Response;
use buffer::Buffer;
use cursor::Direction;
use keyboard::Key;

enum EventStatus {
    Handled(Response),
    NotHandled,
}

pub struct Editor<'e> {
    pub sender: Sender<rustbox::Event>,
    events: Receiver<rustbox::Event>,
    active_buffer: Buffer<'e>,
}

impl<'e> Editor<'e> {
    pub fn new(filename: String) -> Editor<'e> {
        let path = Path::new(filename);
        let buffer = Buffer::new_from_file(&path);

        let (send, recv) = channel();
        Editor {
            sender: send,
            events: recv,
            active_buffer: buffer,
        }
    }

    pub fn handle_key_event(&mut self, key: u16, ch: u32) -> Response {
        let input_key: Option<Key> = num::from_u16(key);

        let event_status = self.handle_system_event(input_key.unwrap());
        match event_status {
            EventStatus::Handled(r) => { return r }
            EventStatus::NotHandled => { /* keep going */ }
        }

        print!("k: {} ", key);
        print!("c: {} **", ch);

        match char::from_u32(ch) {
            Some(c) => {
                self.active_buffer.insert_char(c);
                return Response::Continue
            }
            _ => {}
        }

        Response::Continue
    }

    pub fn save_active_buffer(&mut self) {
        let lines = &self.active_buffer.lines;
        let path = Path::new(&self.active_buffer.file_path);

        let mut file = match File::open_mode(&path, FileMode::Open, FileAccess::Write) {
            Ok(f) => f,
            Err(e) => panic!("file error: {}", e),
        };

        for line in lines.iter() {
            let data = format!("{}\n", line.borrow().data);
            let result = file.write(data.as_bytes());

            if result.is_err() {
                // TODO: figure out what to do here.
            }
        }
    }

    pub fn draw(&mut self) {
        self.active_buffer.draw_contents();
        self.active_buffer.draw_status();
        self.active_buffer.cursor.draw();
    }

    pub fn start(&mut self) -> bool {
        loop {
            rustbox::clear();
            self.draw();
            rustbox::present();
            match self.events.try_recv() {
                Ok(rustbox::KeyEvent(_, key, ch)) => {
                    match self.handle_key_event(key, ch) {
                        Response::Continue => { /* keep going*/ }
                        Response::Quit     => break,
                    }
                },
                _ => {}
            }
        }
        return false
    }

    fn handle_system_event(&mut self, key: Key) -> EventStatus {
        match key {
            Key::Up        => { self.active_buffer.adjust_cursor(Direction::Up); }
            Key::Down      => { self.active_buffer.adjust_cursor(Direction::Down); }
            Key::Left      => { self.active_buffer.adjust_cursor(Direction::Left); }
            Key::Right     => { self.active_buffer.adjust_cursor(Direction::Right); }
            Key::Enter     => { self.active_buffer.insert_line(); }
            Key::Space     => { self.active_buffer.insert_char(' '); }
            Key::Backspace => { self.active_buffer.delete_char(); }
            Key::CtrlS     => { self.save_active_buffer(); }
            Key::CtrlQ     => { return EventStatus::Handled(Response::Quit) }
            _              => { return EventStatus::NotHandled }
        }
        // event is handled and we want to keep the editor running
        EventStatus::Handled(Response::Continue)
    }

}

<|endoftext|>


<commit_before>use std::fmt;
use std::error;

use rustc_serialize::base64::FromBase64Error;

#[derive(Debug, Clone)]
pub enum WeChatError {
    InvalidSignature,
    InvalidAppId,
    InvalidBase64(FromBase64Error),
    ClientError { errcode: i32, errmsg: String },
}

impl fmt::Display for WeChatError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            WeChatError::InvalidSignature => write!(f, "Invalid signature"),
            WeChatError::InvalidAppId => write!(f, "Invalid app_id"),
            WeChatError::InvalidBase64(ref err) => err.fmt(f),
            WeChatError::ClientError { errcode, ref errmsg } => write!(f, "Client error code: {}, message: {}", errcode, errmsg),
        }
    }
}

impl error::Error for WeChatError {

    #[allow(unused_variables)]
    fn description(&self) -> &str {
        match *self {
            WeChatError::InvalidSignature => "Invalid signature",
            WeChatError::InvalidAppId => "Invalid app_id",
            WeChatError::InvalidBase64(ref err) => err.description(),
            WeChatError::ClientError { errcode, ref errmsg } => errmsg,
        }
    }
}
<commit_msg>Add From<FromBase64Error> for WeChatError<commit_after>use std::fmt;
use std::error;

use rustc_serialize::base64::FromBase64Error;

#[derive(Debug, Clone)]
pub enum WeChatError {
    InvalidSignature,
    InvalidAppId,
    InvalidBase64(FromBase64Error),
    ClientError { errcode: i32, errmsg: String },
}

impl fmt::Display for WeChatError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            WeChatError::InvalidSignature => write!(f, "Invalid signature"),
            WeChatError::InvalidAppId => write!(f, "Invalid app_id"),
            WeChatError::InvalidBase64(ref err) => err.fmt(f),
            WeChatError::ClientError { errcode, ref errmsg } => write!(f, "Client error code: {}, message: {}", errcode, errmsg),
        }
    }
}

impl error::Error for WeChatError {

    #[allow(unused_variables)]
    fn description(&self) -> &str {
        match *self {
            WeChatError::InvalidSignature => "Invalid signature",
            WeChatError::InvalidAppId => "Invalid app_id",
            WeChatError::InvalidBase64(ref err) => err.description(),
            WeChatError::ClientError { errcode, ref errmsg } => errmsg,
        }
    }
}

impl From<FromBase64Error> for WeChatError {
    fn from(err: FromBase64Error) -> WeChatError {
        WeChatError::InvalidBase64(err)
    }
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Events
//
// Rust uses condition variables (Condvars) for asynchronous event processing.  Each Mutex has a
// list of zero or more Condvars, which are essentially events that the task may wait on or signal
// when it holds the mutex.  When a task begins to wait on a condvar, it enters a waiting state
// until the condvar is signaled by another task, at which point it resumes processing.  However,
// there is one subtlety--if another task signals the condvar before the task that wishes to be
// notified can begin waiting, the message will be missed.  For this reason, condvars alone are not
// enough to represent events--one must also include the event state within the mutex, setting it
// to RESET initially and SIGNAL when the event is signaled.  Thus, while a Mutex may represent
// many events,

extern crate sync;
extern crate time;

use std::io::timer::Timer;
use std::sync::Arc;
use std::time::duration::Duration;
use sync::raw::Mutex;

// Helper states to demonstrate the control flow of the program.
#[deriving(PartialEq, Show)]

// Given a duration to wait before sending an event from one process to another, returns the
// elapsed time before the event was actually sent.
fn handle_event(duration: Duration) -> Duration {
    // Create a Mutex.  By default a Mutex is created with a single condition variable (condvar_id
    // 0) but it can be created with an arbitrary number using Mutex::new_with_condvars();
    let mutex = Arc::new(Mutex::new());
    let mutex_ = mutex.clone();
    let mut timer = Timer::new().unwrap();
    let start = time::precise_time_ns();
    // Lock the mutex
    let guard = mutex.lock();
    // Start our secondary task (which will signal our waiting main task)
    spawn(proc() {
        // Lock the mutex
        let guard = mutex_.lock();
        // Sleep for `duration`.
        timer.sleep(duration);
        // Signal the waiting mutex (equivalent to guard.cond.signal_on(0)).
        // One can also signal to all tasks on the waiting mutex with broadcast (broadcast_on(0)).
        //
        // Note that if no tasks are actually waiting yet (which is possible, if we got the lock
        // before the other task), then this might report that it failed to wake up any tasks.
        // That is why the mutex was locked before the task was spawned--we know we cannot possibly
        // get past the mutex at the top of the task until the wait() statement below is reached.
        guard.cond.signal();
        // Although we signaled the waiting mutex, it will not awaken until this guard is dropped.
    });
    // Wait for the event state to be set to signaled (equivalent to guard.cond.wait_on(0)).
    guard.cond.wait();
    // Should be done signaling (i.e. we've waited for `duration`).
    let end = time::precise_time_ns();
    // When the guard exits scope, the condvar is reset.
    drop(guard);
    // Return the elapsed time
    Duration::nanoseconds((end - start) as i64)
}

#[cfg(not(test))]
pub fn main() {
    let duration = Duration::seconds(1); // Process event after one second.
    println!("{} elapsed before event triggered", handle_event(duration));
}

#[test]
pub fn test_events() {
    let duration = Duration::seconds(1) / 10; // Process event after one tenth of a second.
    // Make sure it really did take at least that long for the event to be processed.
    assert!(duration <= handle_event(duration));
}
<commit_msg>Fixing description of condvars.<commit_after>// Implements http://rosettacode.org/wiki/Events
//
// Rust uses condition variables (Condvars) for asynchronous event processing.  Each Mutex has a
// list of zero or more Condvars, which are essentially events that the task may wait on or signal
// when it holds the mutex.  When a task begins to wait on a condvar, it enters a waiting state
// until the condvar is signaled by another task, at which point it resumes processing.  Thus, each
// condvar represents an event on which a task may wait.  The one subtlety is that condvar signals
// are only received if there is actually a task waiting on the signal--see the below program for
// an example of how this may be achieved in practice.

extern crate sync;
extern crate time;

use std::io::timer::Timer;
use std::sync::Arc;
use std::time::duration::Duration;
use sync::raw::Mutex;

// Helper states to demonstrate the control flow of the program.
#[deriving(PartialEq, Show)]

// Given a duration to wait before sending an event from one process to another, returns the
// elapsed time before the event was actually sent.
fn handle_event(duration: Duration) -> Duration {
    // Create a Mutex.  By default a Mutex is created with a single condition variable (condvar_id
    // 0) but it can be created with an arbitrary number using Mutex::new_with_condvars();
    let mutex = Arc::new(Mutex::new());
    let mutex_ = mutex.clone();
    let mut timer = Timer::new().unwrap();
    let start = time::precise_time_ns();
    // Lock the mutex
    let guard = mutex.lock();
    // Start our secondary task (which will signal our waiting main task)
    spawn(proc() {
        // Lock the mutex
        let guard = mutex_.lock();
        // Sleep for `duration`.
        timer.sleep(duration);
        // Signal the waiting mutex (equivalent to guard.cond.signal_on(0)).
        // One can also signal to all tasks on the waiting mutex with broadcast (broadcast_on(0)).
        //
        // Note that if no tasks are actually waiting yet (which is possible, if we got the lock
        // before the other task), then this might report that it failed to wake up any tasks.
        // That is why the mutex was locked before the task was spawned--we know we cannot possibly
        // get past the mutex at the top of the task until the wait() statement below is reached.
        guard.cond.signal();
        // Although we signaled the waiting mutex, it will not awaken until this guard is dropped.
    });
    // Wait for the event state to be set to signaled (equivalent to guard.cond.wait_on(0)).
    guard.cond.wait();
    // Should be done signaling (i.e. we've waited for `duration`).
    let end = time::precise_time_ns();
    // When the guard exits scope, the condvar is reset.
    drop(guard);
    // Return the elapsed time
    Duration::nanoseconds((end - start) as i64)
}

#[cfg(not(test))]
pub fn main() {
    let duration = Duration::seconds(1); // Process event after one second.
    println!("{} elapsed before event triggered", handle_event(duration));
}

#[test]
pub fn test_events() {
    let duration = Duration::seconds(1) / 10; // Process event after one tenth of a second.
    // Make sure it really did take at least that long for the event to be processed.
    assert!(duration <= handle_event(duration));
}
<|endoftext|>


<commit_before>//! Traits, helpers, and type definitions for Tokio I/O & non-blocking IO
//! functionality.
//!
//! # Readiness
//!
//! A source is **ready** when performing an operation has a high likelihood
//! (but not a guarantee) of successfully making progress.
//!
//! For example, a TCP socket is ready to perform a read operation when the
//! internal buffer has pending bytes. The same socket is ready to perform a
//! write when its write buffer is not full.
//!
//! The `Readiness` trait represents this concept. The `Readiness` trait also
//! acts as a marker trait to denotate types which are *Tokio aware*. A Tokio
//! aware type is able to observe usage and signal interest to the `Reactor`.
//!
//! In the case of `TcpStream`, the Tokio aware TCP socket, when
//! `TcpStream::try_read` is called and `Ok(None)` is returned, read interest
//! is automatically registered with the reactor an associated with the
//! currently running task. The logic being that, by trying to read from the
//! socket, the current task has indicated that read readiness is required for
//! the task to make progress. Once the TCP socket becomes read ready, the
//! task's `tick` function is called again, and this time a call to
//! `TcpStream::try_read` will (most likely) read some bytes OR result in an
//! error.
//!
//! # Transport
//!
//! A typed stream that may be read from and written to without blocking.
//!
//! A `Transport` does protocol specific serialization / deserialization. It
//! usually is composed of some lower level source, for example a TCP Stream
//! and reads / writes protocol frames.
//!
//! For example, imagine a protocol that is UTF-8 string based and framed with
//! new lines, aka each message is terminated by "\n". The transport would look
//! something like:
//!
//! ```rust,no_run
//! use tokio::io::{TryRead, TryWrite, Readiness, Transport};
//! use std::io;
//!
//! struct LineTransport<T> {
//!     source: T,
//!     rd: Vec<u8>,
//!     wr: Vec<u8>,
//! }
//!
//! impl<T: TryRead + TryWrite + Readiness> Transport for LineTransport<T> {
//!     type In = String;
//!     type Out = String;
//!
//!     fn read(&mut self) -> io::Result<Option<String>> {
//!         loop {
//!             // First, try to parse a new line from what was buffered
//!             if let Some(line) = parse_new_line(&mut self.rd) {
//!                 return Ok(Some(line));
//!             }
//!         }
//!     }
//!
//!     fn write(&mut self, req: String) -> io::Result<Option<()>> {
//!         // Append the message to the buffer
//!         self.wr.append(&mut req.into_bytes());
//!         self.flush()
//!     }
//!
//!     fn flush(&mut self) -> io::Result<Option<()>> {
//!         while !self.wr.is_empty() {
//!             match try!(self.source.try_write(&mut self.wr)) {
//!                 Some(n) => shift(&mut self.wr, n),
//!                 None => return Ok(None),
//!             }
//!         }
//!
//!         Ok(Some(()))
//!     }
//! }
//!
//! impl<T: Readiness> Readiness for LineTransport<T> {
//!     fn is_readable(&self) -> bool {
//!         self.rd.contains(&b'\n') || self.source.is_readable()
//!     }
//!
//!     fn is_writable(&self) -> bool {
//!         // The source is always writable since we don't cap the write
//!         // buffer size. Not an ideal production behavior...
//!         true
//!     }
//! }
//!
//! fn parse_new_line(buf: &mut Vec<u8>) -> Option<String> {
//!     // Search for "\n", if found, read everything from the start of the
//!     // buffer to the newline as a string then shift all bytes after the
//!     // newline to the beginning of the buffer.
//!     unimplemented!();
//! }
//!
//! fn shift(buf: &mut Vec<u8>, n: usize) {
//!     // Drop the first `n` bytes in the buffer and move all bytes after that
//!     // point to the front of the buffer.
//! }
//! ```

mod ready;
mod transport;

pub use self::ready::{Readiness, Ready};
pub use self::transport::Transport;
use std::io;

/// A refinement of `std::io::Read` for reading from non-blocking sources.
///
/// When reading from a non-blocking source, receiving a
/// `ErrorKind::WouldBlock` is expected and not an error. A such, it is useful
/// to split out the would-block case from the other error cases.
pub trait TryRead: io::Read {

    /// Pull some bytes from this source into the specified buffer, returning
    /// how many bytes were read.
    ///
    /// If the source is not able to perform the operation due to not having
    /// any bytes to read, `Ok(None)` is returned.
    ///
    /// Aside from the signature, behavior is identical to `std::io::Read`. For
    /// more details, read the `std::io::Read` documentation.
    fn try_read(&mut self, buf: &mut [u8]) -> io::Result<Option<usize>>;
}

impl<T: io::Read> TryRead for T {
    fn try_read(&mut self, buf: &mut [u8]) -> io::Result<Option<usize>> {
        match self.read(buf) {
            Ok(n) => Ok(Some(n)),
            Err(e) => {
                if e.kind() == io::ErrorKind::WouldBlock {
                    return Ok(None);
                }
                Err(e)
            }
        }
    }
}

/// A refinement of `std::io::Write` for reading from non-blocking sources.
///
/// When reading from a non-blocking source, receiving a
/// `ErrorKind::WouldBlock` is expected and not an error. A such, it is useful
/// to split out the would-block case from the other error cases.
pub trait TryWrite: io::Write {

    /// Write a buffer into this object, returning how many bytes were written.
    ///
    /// If the source is not able to perform the operation due to not being
    /// ready, `Ok(None)` is returned.
    ///
    /// Aside from the signature, behavior is identical to `std::io::Write`.
    /// For more details, read the `std::io::Write` documentation.
    fn try_write(&mut self, buf: &[u8]) -> io::Result<Option<usize>>;
}

impl<T: io::Write> TryWrite for T {
    fn try_write(&mut self, buf: &[u8]) -> io::Result<Option<usize>> {
        match self.write(buf) {
            Ok(n) => Ok(Some(n)),
            Err(e) => {
                if e.kind() == io::ErrorKind::WouldBlock {
                    return Ok(None);
                }
                Err(e)
            }
        }
    }
}
<commit_msg>io: Use pattern guards in blanket TryRead / TryWrite impls<commit_after>//! Traits, helpers, and type definitions for Tokio I/O & non-blocking IO
//! functionality.
//!
//! # Readiness
//!
//! A source is **ready** when performing an operation has a high likelihood
//! (but not a guarantee) of successfully making progress.
//!
//! For example, a TCP socket is ready to perform a read operation when the
//! internal buffer has pending bytes. The same socket is ready to perform a
//! write when its write buffer is not full.
//!
//! The `Readiness` trait represents this concept. The `Readiness` trait also
//! acts as a marker trait to denotate types which are *Tokio aware*. A Tokio
//! aware type is able to observe usage and signal interest to the `Reactor`.
//!
//! In the case of `TcpStream`, the Tokio aware TCP socket, when
//! `TcpStream::try_read` is called and `Ok(None)` is returned, read interest
//! is automatically registered with the reactor an associated with the
//! currently running task. The logic being that, by trying to read from the
//! socket, the current task has indicated that read readiness is required for
//! the task to make progress. Once the TCP socket becomes read ready, the
//! task's `tick` function is called again, and this time a call to
//! `TcpStream::try_read` will (most likely) read some bytes OR result in an
//! error.
//!
//! # Transport
//!
//! A typed stream that may be read from and written to without blocking.
//!
//! A `Transport` does protocol specific serialization / deserialization. It
//! usually is composed of some lower level source, for example a TCP Stream
//! and reads / writes protocol frames.
//!
//! For example, imagine a protocol that is UTF-8 string based and framed with
//! new lines, aka each message is terminated by "\n". The transport would look
//! something like:
//!
//! ```rust,no_run
//! use tokio::io::{TryRead, TryWrite, Readiness, Transport};
//! use std::io;
//!
//! struct LineTransport<T> {
//!     source: T,
//!     rd: Vec<u8>,
//!     wr: Vec<u8>,
//! }
//!
//! impl<T: TryRead + TryWrite + Readiness> Transport for LineTransport<T> {
//!     type In = String;
//!     type Out = String;
//!
//!     fn read(&mut self) -> io::Result<Option<String>> {
//!         loop {
//!             // First, try to parse a new line from what was buffered
//!             if let Some(line) = parse_new_line(&mut self.rd) {
//!                 return Ok(Some(line));
//!             }
//!         }
//!     }
//!
//!     fn write(&mut self, req: String) -> io::Result<Option<()>> {
//!         // Append the message to the buffer
//!         self.wr.append(&mut req.into_bytes());
//!         self.flush()
//!     }
//!
//!     fn flush(&mut self) -> io::Result<Option<()>> {
//!         while !self.wr.is_empty() {
//!             match try!(self.source.try_write(&mut self.wr)) {
//!                 Some(n) => shift(&mut self.wr, n),
//!                 None => return Ok(None),
//!             }
//!         }
//!
//!         Ok(Some(()))
//!     }
//! }
//!
//! impl<T: Readiness> Readiness for LineTransport<T> {
//!     fn is_readable(&self) -> bool {
//!         self.rd.contains(&b'\n') || self.source.is_readable()
//!     }
//!
//!     fn is_writable(&self) -> bool {
//!         // The source is always writable since we don't cap the write
//!         // buffer size. Not an ideal production behavior...
//!         true
//!     }
//! }
//!
//! fn parse_new_line(buf: &mut Vec<u8>) -> Option<String> {
//!     // Search for "\n", if found, read everything from the start of the
//!     // buffer to the newline as a string then shift all bytes after the
//!     // newline to the beginning of the buffer.
//!     unimplemented!();
//! }
//!
//! fn shift(buf: &mut Vec<u8>, n: usize) {
//!     // Drop the first `n` bytes in the buffer and move all bytes after that
//!     // point to the front of the buffer.
//! }
//! ```

mod ready;
mod transport;

pub use self::ready::{Readiness, Ready};
pub use self::transport::Transport;
use std::io;

/// A refinement of `std::io::Read` for reading from non-blocking sources.
///
/// When reading from a non-blocking source, receiving a
/// `ErrorKind::WouldBlock` is expected and not an error. A such, it is useful
/// to split out the would-block case from the other error cases.
pub trait TryRead: io::Read {

    /// Pull some bytes from this source into the specified buffer, returning
    /// how many bytes were read.
    ///
    /// If the source is not able to perform the operation due to not having
    /// any bytes to read, `Ok(None)` is returned.
    ///
    /// Aside from the signature, behavior is identical to `std::io::Read`. For
    /// more details, read the `std::io::Read` documentation.
    fn try_read(&mut self, buf: &mut [u8]) -> io::Result<Option<usize>>;
}

impl<T: io::Read> TryRead for T {
    fn try_read(&mut self, buf: &mut [u8]) -> io::Result<Option<usize>> {
        match self.read(buf) {
            Ok(n) => Ok(Some(n)),
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Ok(None),
            Err(e) => Err(e),
        }
    }
}

/// A refinement of `std::io::Write` for reading from non-blocking sources.
///
/// When reading from a non-blocking source, receiving a
/// `ErrorKind::WouldBlock` is expected and not an error. A such, it is useful
/// to split out the would-block case from the other error cases.
pub trait TryWrite: io::Write {

    /// Write a buffer into this object, returning how many bytes were written.
    ///
    /// If the source is not able to perform the operation due to not being
    /// ready, `Ok(None)` is returned.
    ///
    /// Aside from the signature, behavior is identical to `std::io::Write`.
    /// For more details, read the `std::io::Write` documentation.
    fn try_write(&mut self, buf: &[u8]) -> io::Result<Option<usize>>;
}

impl<T: io::Write> TryWrite for T {
    fn try_write(&mut self, buf: &[u8]) -> io::Result<Option<usize>> {
        match self.write(buf) {
            Ok(n) => Ok(Some(n)),
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Ok(None),
            Err(e) => Err(e),
        }
    }
}
<|endoftext|>


<commit_before>use super::log::{self, Log, LogLevel, LogMetadata, LogRecord, SetLoggerError};

struct Logger {
    log_level: LogLevel
}

impl Log for Logger {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.log_level
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            println!("{:<5} [{}] {}",
                record.level().to_string(),
                record.location().module_path(),
                record.args());
        }
    }
}

pub fn init(level: &str) -> Result<(), SetLoggerError> {
    if level != "off" {
        let log_level = match level {
            "trace" => LogLevel::Trace,
            "info" => LogLevel::Info,
            "debug" => LogLevel::Debug,
            "warn" => LogLevel::Warn,
            "error" | _ => LogLevel::Error,
        };
        log::set_logger(|max_log_level| {
            max_log_level.set(log_level.to_log_level_filter());
            return Box::new(Logger { log_level: log_level });
        })
    } else {
        Ok(())
    }
}<commit_msg>[upd] log message<commit_after>use super::log::{self, Log, LogLevel, LogMetadata, LogRecord, SetLoggerError};

struct Logger {
    log_level: LogLevel
}

impl Log for Logger {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.log_level
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            println!("[{:>5}@{}] {}",
                record.level().to_string(),
                record.location().module_path(),
                record.args());
        }
    }
}

pub fn init(level: &str) -> Result<(), SetLoggerError> {
    if level != "off" {
        let log_level = match level {
            "trace" => LogLevel::Trace,
            "info" => LogLevel::Info,
            "debug" => LogLevel::Debug,
            "warn" => LogLevel::Warn,
            "error" | _ => LogLevel::Error,
        };
        log::set_logger(|max_log_level| {
            max_log_level.set(log_level.to_log_level_filter());
            return Box::new(Logger { log_level: log_level });
        })
    } else {
        Ok(())
    }
}<|endoftext|>


<commit_before>#[macro_export]
macro_rules! rusty_peg {
    { parser $name:ident<'input>: $base:ty { $($grammar_defn:tt)* } } => {
        rusty_peg_parser! {
            parser $name: $base { $($grammar_defn)* }
        }
    };

    { parser $name:ident<'input> { $($grammar_defn:tt)* } } => {
        rusty_peg_parser! {
            parser $name: () { $($grammar_defn)* }
        }
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_parser {
    { parser $name:ident: $base:ty { $($grammar_defn:tt)* } } => {
        rusty_peg_with_nonterminals! {
            rusty_peg_declare_parser(($name) ($base)); $($grammar_defn)*
        }

        rusty_peg_with_nonterminals! {
            rusty_peg_init_parser(($name) ($base)); $($grammar_defn)*
        }

        rusty_peg_declare_nonterminals! { $name, $($grammar_defn)* }
    }
}

/// This is a higher-order macro. It should be called like:
///
/// ```ignore
/// rusty_peg_with_nonterminals! { $macro_name($args); $grammar... }
/// ```
///
/// it will parse the grammar definition `$grammar` into a list of
/// triples, one for each nonterminal: `($name:ident, $type:ty,
/// $defn:tt)`.  Here $defn matches one of the following token-tree
/// definitions, which match the syntax the user uses, but that they
/// are wrapped in parentheses:
///
/// - `($defn:tt => $body:expr)`
/// - `($defn:tt)`
///
/// So, as an example, if you invoke
///
/// ```ignore
/// rusty_peg_with_nonterminals! { foo(1 2); X: u32 = "X" => 1; Y: u32 = X; }
/// ```
///
/// it would translate into a call like
///
/// ```ignore
/// foo! { 1 2 (X, u32, ("X" => 1)) (Y, u32, (X)) }
/// ```
#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_with_nonterminals {
    ( $m:ident($($args:tt)*) ;
      $nonterminal:ident: $ty:ty = $defn:tt => $body:expr ;
      $($remainder:tt)* ) => {
        rusty_peg_with_nonterminals! { $m($($args)* ($nonterminal, $ty, ($defn => $body)));
                                       $($remainder)* }
    };
    ( $m:ident($($args:tt)*) ;
      $nonterminal:ident: $ty:ty = $defn:tt ;
      $($remainder:tt)* ) => {
        rusty_peg_with_nonterminals! { $m($($args)* ($nonterminal, $ty, ($defn)));
                                       $($remainder)* }
    };
    ( $m:ident($($args:tt)*) ; ) => {
        $m! { $($args)* }
    };
}

/// Creates declaration of the parser struct. Expects to be invoked
/// from `rusty_peg_with_nonterminals`, with the initial arguments
/// `($name:ident) ($base:ty)`, where `$name` is the name of the
/// parser struct type and `$base` is the type of the base field.
#[macro_export]
macro_rules! rusty_peg_declare_parser {
    ( ($name:ident) ($base:ty) $(($nonterminal:ident, $ty:ty, $defn:tt))* ) => {
        #[allow(non_snake_case)]
        pub struct $name<'input> {
            marker: $crate::util::PhantomData<&'input()>,
            base: $base,
            $($nonterminal: $crate::Cache<'input,$ty>),*
        }
    }
}

/// Creates an impl block declaring the `new` method that initializes
/// the parser type. Expects to be invoked from
/// `rusty_peg_with_nonterminals` with initial arguments
/// `($name:ident) ($base:ty)`, as `rusty_peg_declare_parser`.
#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_init_parser {
    ( ($name:ident) ($base:ty) $(($nonterminal:ident, $ty:ty, $defn:tt))* ) => {
        impl<'input> $name<'input> {
            fn new(base: $base) -> $name<'input> {
                $name {
                    marker: $crate::util::PhantomData,
                    base: base,
                    $($nonterminal: $crate::util::HashMap::new()),*
                }
            }
        }
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_declare_nonterminals {
    ( $grammar:ident, $nonterminal:ident: $ty:ty = $defn:tt => $body:expr ;
      $($remainder:tt)* ) => {
        rusty_peg_declare_map_nonterminal! { $grammar, $nonterminal, $ty, $defn, $body }
        rusty_peg_declare_nonterminals! { $grammar, $($remainder)* }
    };
    ( $grammar:ident, $nonterminal:ident: $ty:ty = $defn:tt ;
      $($remainder:tt)* ) => {
        rusty_peg_declare_identity_nonterminal! { $grammar, $nonterminal, $ty, $defn }
        rusty_peg_declare_nonterminals! { $grammar, $($remainder)* }
    };
    ( $grammar:ident, ) => {
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_declare_map_nonterminal {
    ($grammar:ident, $nonterminal:ident, $ty:ty, $defn:tt, $body:expr) => {
        #[allow(non_camel_case_types)]
        #[derive(Debug)]
        pub struct $nonterminal;

        impl<'input> $crate::Symbol<'input,$grammar<'input>> for $nonterminal {
            type Output = $ty;

            fn pretty_print(&self) -> String {
                format!("{:?}", self)
            }

            fn parse(&self,
                     grammar: &mut $grammar<'input>,
                     start: $crate::Input<'input>)
                     -> $crate::ParseResult<'input,$ty>
            {
                $crate::util::memoize(
                    grammar,
                    |g| &mut g.$nonterminal,
                    start.offset,
                    |g| {
                        let parser = rusty_peg_named_item!($defn);
                        let (end, rusty_peg_named_item_pat!($defn)) =
                            try!($crate::Symbol::parse(&parser, g, start));
                        Ok((end,$body))
                    })
            }
        }
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_declare_identity_nonterminal {
    ($grammar:ident, $nonterminal:ident, $ty:ty, $defn:tt) => {
        #[allow(non_camel_case_types)]
        #[derive(Debug)]
        pub struct $nonterminal;

        impl<'input> $crate::Symbol<'input,$grammar<'input>> for $nonterminal {
            type Output = $ty;

            fn pretty_print(&self) -> String {
                format!("{:?}", self)
            }

            fn parse(&self,
                     grammar: &mut $grammar<'input>,
                     start: $crate::Input<'input>)
                     -> $crate::ParseResult<'input,$ty>
            {
                $crate::util::memoize(
                    grammar,
                    |g| &mut g.$nonterminal,
                    start.offset,
                    |g| {
                        let parser = rusty_peg_item!($defn);
                        $crate::Symbol::parse(&parser, g, start)
                    })
            }
        }
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_named_item {
    ( ( $($a:tt)* ) ) => {
        rusty_peg_named_items!($($a)*)
    };
    ( $a:tt ) => {
        rusty_peg_item!($a)
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_named_items {
    ( < $name:ident : $a:tt > , $($bs:tt)* ) => {
        {
            let bs = rusty_peg_named_items!($($bs)*);
            rusty_peg_items!($a, bs)
        }
    };
    ( < $name:ident : $a:tt > ) => {
        rusty_peg_item!($a)
    };
    ( $a:tt, $($bs:tt)* ) => {
        {
            let bs = rusty_peg_named_items!($($bs)*);
            rusty_peg_items!($a, bs)
        }
    };
    ( $a:tt ) => {
        rusty_peg_item!($a)
    };
    ( ) => {
        Empty
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_named_item_pat {
    ( ( $($a:tt)* ) ) => {
        rusty_peg_named_items_pat!($($a)*)
    };
    ( $a:tt ) => {
        _
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_named_items_pat {
    ( < $name:ident : $a:tt > , $($bs:tt)* ) => {
        ($name, rusty_peg_named_items_pat!($($bs)*))
    };
    ( < $name:ident : $a:tt > ) => {
        $name
    };
    ( $a:tt, $($bs:tt)* ) => {
        (_, rusty_peg_named_items_pat!($($bs)*))
    };
    ( $a:tt ) => {
        _
    };
    ( ) => {
        ()
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_items {
    ( $a:tt, $($bs:tt)* ) => {
        $crate::util::Join { first: rusty_peg_item!($a), second: rusty_peg_items!($($bs)*), }
    };
    ( $a:tt / $($bs:tt)* ) => {
        $crate::util::Or { a: rusty_peg_item!($a), b: rusty_peg_items!($($bs)*) }
    };
    ( $a:tt ) => {
        rusty_peg_item!($a)
    };
    ( ) => {
        Empty
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_item {
    { ( ) } => {
        Empty
    };

    { ( $tt:tt ) } => {
        rusty_peg_item!($tt)
    };

    { ( $($tt:tt)* ) } => {
        rusty_peg_items!($($tt)*)
    };

    { [ $($tt:tt)* ] } => {
        $crate::util::Optional { parser: rusty_peg_items!($($tt)*) }
    };

    { { + $($tt:tt)* } } => {
        $crate::util::Repeat { parser: rusty_peg_items!($($tt)*), min: 1,
                               separator: $crate::util::Whitespace }
    };

    { { * $($tt:tt)* } } => {
        $crate::util::Repeat { parser: rusty_peg_items!($($tt)*), min: 0,
                               separator: $crate::util::Whitespace }
    };

    { { $($tt:tt)* } } => {
        $crate::util::Repeat { parser: rusty_peg_items!($($tt)*), min: 0,
                               separator: $crate::util::Whitespace }
    };

    { $name:expr } => {
        $name
    };
}

<commit_msg>Rework the macro parsing to be better structured and documented, and more extensible.<commit_after>// NOTE: The only macro intentionally exported is `rusty_peg`. All
// other macros should be marked `#[doc(hidden)]` and considered
// internal implementation details.

#[macro_export]
macro_rules! rusty_peg {
    { parser $name:ident<'input>: $base:ty { $($grammar_defn:tt)* } } => {
        rusty_peg_parser! {
            parser $name: $base { $($grammar_defn)* }
        }
    };

    { parser $name:ident<'input> { $($grammar_defn:tt)* } } => {
        rusty_peg_parser! {
            parser $name: () { $($grammar_defn)* }
        }
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_parser {
    { parser $name:ident: $base:ty { $($grammar_defn:tt)* } } => {
        rusty_peg_parse_grammar_definition! {
            rusty_peg_parser_parsed {
                (arg ($name) ($base))
                    (any)
                    (def)
                    (map)
                    (reg)
            }
            $($grammar_defn)*
        }
    }
}

// This macro is used to parse the user's grammar definition and segregate
// the nonterminals into various distinct categories. Ultimately, it invokes
// `rusty_peg_parser_parsed` with a particular form:
//
// ```
// rusty_peg_parser_parsed! {
//   (arg ...)
//   (any (<ident>, <ty>)...)
//   (def (<ident>, <ty>, (<tt>))...)
//   (map (<ident>, <ty>, (<tt> => <expr>))...)
//   (reg (<ident>, <ty>, (<expr>))...)
// }
// ```
//
// Here:
// -  `...` is used to mean "repeated an arbitrary number of times.
// - `<ident>` is the identifier of some non-terminal.
// - `<ty>` is the type the user declared for that non-terminal.
// - `<tt>` refers to a token tree representing the definition of a nonterminal.
// - `<expr>` refers to a Rust expression.
//
// As you can see, `rusty_peg_parser_parsed` is invoked with five
// lists, each tagged with an identifier. The first list, tagged
// `any`, contains the names and types of ALL nonterminals. Each other
// list contains only those entries of a particular kind:
//
// - `map`: nonterminals defined like `FOO: u32 = ("a" "b") => { 22
//   };`.  Here, `<ident>` would be `FOO`, `<ty>` would be `u32`,
//   `<tt>` would be `("a" "b")`, and `<expr>` would be `{ 22 }`.
// - `def`: nonterminals defined like `FOO: &'static str =
//   "bar";`. Here, `<ident>` would be Foo`, `<ty>` would be `&'static
//   str`, and `<tt>` would be `"bar".
// - `reg`: nonterminals defined like `FOO: &'input str = regexp r"something";`
//   Here, `<ident>` would be Foo`, `<ty>` would be `&'input
//   str`, and `<expr>` would be `r"something"`.
//
// These strings are deliberately constructed to be easy to match and
// work with in subsequent macro definitions.
#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_parse_grammar_definition {
    // Base case.
    {
        $m:ident {
            (arg $($args:tt)*)
                (any $(($any_nt:ident, $any_ty:ty))*)
                (def $(($def_nt:ident, $def_ty:ty, $def_tt:tt))*)
                (map $(($map_nt:ident, $map_ty:ty, $map_tt:tt))*)
                (reg $(($reg_nt:ident, $reg_ty:ty, $reg_tt:tt))*)
        }
    } => {
        rusty_peg_parser_parsed! {
            (arg $($args)*)
            (any $(($any_nt, $any_ty))*)
            (def $(($def_nt, $def_ty, $def_tt))*)
            (map $(($map_nt, $map_ty, $map_tt))*)
            (reg $(($reg_nt, $reg_ty, $reg_tt))*)
        }
    };

    // Match a "map" definition:
    {
        $m:ident {
            (arg $($args:tt)*)
                (any $(($any_nt:ident, $any_ty:ty))*)
                (def $(($def_nt:ident, $def_ty:ty, $def_tt:tt))*)
                (map $(($map_nt:ident, $map_ty:ty, $map_tt:tt))*)
                (reg $(($reg_nt:ident, $reg_ty:ty, $reg_tt:tt))*)
        }
        $nonterminal:ident: $ty:ty = $defn:tt => $body:expr ;
        $($remainder:tt)*
    } => {
        rusty_peg_parse_grammar_definition! {
            $m {
                (arg $($args)*)
                    (any $(($any_nt, $any_ty))* ($nonterminal, $ty))
                    (def $(($def_nt, $def_ty, $def_tt))*)
                    (map $(($map_nt, $map_ty, $map_tt))* ($nonterminal, $ty, ($defn => $body)))
                    (reg $(($reg_nt, $reg_ty, $reg_tt))*)
            }
            $($remainder)*
        }
    };

    // Match a "equate" definition:
    {
        $m:ident {
            (arg $($args:tt)*)
                (any $(($any_nt:ident, $any_ty:ty))*)
                (def $(($def_nt:ident, $def_ty:ty, $def_tt:tt))*)
                (map $(($map_nt:ident, $map_ty:ty, $map_tt:tt))*)
                (reg $(($reg_nt:ident, $reg_ty:ty, $reg_tt:tt))*)
        }
        $nonterminal:ident: $ty:ty = $defn:tt ;
        $($remainder:tt)*
    } => {
        rusty_peg_parse_grammar_definition! {
            $m {
                (arg $($args)*)
                    (any $(($any_nt, $any_ty))* ($nonterminal, $ty))
                    (def $(($def_nt, $def_ty, $def_tt))* ($nonterminal, $ty, ($defn)))
                    (map $(($map_nt, $map_ty, $map_tt))*)
                    (reg $(($reg_nt, $reg_ty, $reg_tt))*)
            }
            $($remainder)*
        }
    };
}

// Invoked by rusty_peg_parse_grammar_definition, actually generates
// the parser structs and so forth.
#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_parser_parsed {
    {
        (arg ($name:ident) ($base:ty))
            (any $(($any_nt:ident, $any_ty:ty))*)
            (def $(($def_nt:ident, $def_ty:ty, ($def_tt:tt)))*)
            (map $(($map_nt:ident, $map_ty:ty, ($map_tt:tt => $map_expr:expr)))*)
            (reg $(($reg_nt:ident, $reg_ty:ty, $reg_tt:tt))*)
    } => {
        #[allow(non_snake_case)]
        pub struct $name<'input> {
            marker: $crate::util::PhantomData<&'input()>,
            base: $base,
            $($any_nt: $crate::Cache<'input,$any_ty>),*
        }

        impl<'input> $name<'input> {
            fn new(base: $base) -> $name<'input> {
                $name {
                    marker: $crate::util::PhantomData,
                    base: base,
                    $($any_nt: $crate::util::HashMap::new()),*
                }
            }
        }

        $(rusty_peg_declare_map_nonterminal!{$name, $map_nt, $map_ty, $map_tt, $map_expr})*
        $(rusty_peg_declare_identity_nonterminal!{$name, $def_nt, $def_ty, $def_tt})*
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_declare_map_nonterminal {
    ($grammar:ident, $nonterminal:ident, $ty:ty, $defn:tt, $body:expr) => {
        #[allow(non_camel_case_types)]
        #[derive(Debug)]
        pub struct $nonterminal;

        impl<'input> $crate::Symbol<'input,$grammar<'input>> for $nonterminal {
            type Output = $ty;

            fn pretty_print(&self) -> String {
                format!("{:?}", self)
            }

            fn parse(&self,
                     grammar: &mut $grammar<'input>,
                     start: $crate::Input<'input>)
                     -> $crate::ParseResult<'input,$ty>
            {
                $crate::util::memoize(
                    grammar,
                    |g| &mut g.$nonterminal,
                    start.offset,
                    |g| {
                        let parser = rusty_peg_named_item!($defn);
                        let (end, rusty_peg_named_item_pat!($defn)) =
                            try!($crate::Symbol::parse(&parser, g, start));
                        Ok((end,$body))
                    })
            }
        }
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_declare_identity_nonterminal {
    ($grammar:ident, $nonterminal:ident, $ty:ty, $defn:tt) => {
        #[allow(non_camel_case_types)]
        #[derive(Debug)]
        pub struct $nonterminal;

        impl<'input> $crate::Symbol<'input,$grammar<'input>> for $nonterminal {
            type Output = $ty;

            fn pretty_print(&self) -> String {
                format!("{:?}", self)
            }

            fn parse(&self,
                     grammar: &mut $grammar<'input>,
                     start: $crate::Input<'input>)
                     -> $crate::ParseResult<'input,$ty>
            {
                $crate::util::memoize(
                    grammar,
                    |g| &mut g.$nonterminal,
                    start.offset,
                    |g| {
                        let parser = rusty_peg_item!($defn);
                        $crate::Symbol::parse(&parser, g, start)
                    })
            }
        }
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_named_item {
    ( ( $($a:tt)* ) ) => {
        rusty_peg_named_items!($($a)*)
    };
    ( $a:tt ) => {
        rusty_peg_item!($a)
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_named_items {
    ( < $name:ident : $a:tt > , $($bs:tt)* ) => {
        {
            let bs = rusty_peg_named_items!($($bs)*);
            rusty_peg_items!($a, bs)
        }
    };
    ( < $name:ident : $a:tt > ) => {
        rusty_peg_item!($a)
    };
    ( $a:tt, $($bs:tt)* ) => {
        {
            let bs = rusty_peg_named_items!($($bs)*);
            rusty_peg_items!($a, bs)
        }
    };
    ( $a:tt ) => {
        rusty_peg_item!($a)
    };
    ( ) => {
        Empty
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_named_item_pat {
    ( ( $($a:tt)* ) ) => {
        rusty_peg_named_items_pat!($($a)*)
    };
    ( $a:tt ) => {
        _
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_named_items_pat {
    ( < $name:ident : $a:tt > , $($bs:tt)* ) => {
        ($name, rusty_peg_named_items_pat!($($bs)*))
    };
    ( < $name:ident : $a:tt > ) => {
        $name
    };
    ( $a:tt, $($bs:tt)* ) => {
        (_, rusty_peg_named_items_pat!($($bs)*))
    };
    ( $a:tt ) => {
        _
    };
    ( ) => {
        ()
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_items {
    ( $a:tt, $($bs:tt)* ) => {
        $crate::util::Join { first: rusty_peg_item!($a), second: rusty_peg_items!($($bs)*), }
    };
    ( $a:tt / $($bs:tt)* ) => {
        $crate::util::Or { a: rusty_peg_item!($a), b: rusty_peg_items!($($bs)*) }
    };
    ( $a:tt ) => {
        rusty_peg_item!($a)
    };
    ( ) => {
        Empty
    }
}

#[macro_export]
#[doc(hidden)]
macro_rules! rusty_peg_item {
    { ( ) } => {
        Empty
    };

    { ( $tt:tt ) } => {
        rusty_peg_item!($tt)
    };

    { ( $($tt:tt)* ) } => {
        rusty_peg_items!($($tt)*)
    };

    { [ $($tt:tt)* ] } => {
        $crate::util::Optional { parser: rusty_peg_items!($($tt)*) }
    };

    { { + $($tt:tt)* } } => {
        $crate::util::Repeat { parser: rusty_peg_items!($($tt)*), min: 1,
                               separator: $crate::util::Whitespace }
    };

    { { * $($tt:tt)* } } => {
        $crate::util::Repeat { parser: rusty_peg_items!($($tt)*), min: 0,
                               separator: $crate::util::Whitespace }
    };

    { { $($tt:tt)* } } => {
        $crate::util::Repeat { parser: rusty_peg_items!($($tt)*), min: 0,
                               separator: $crate::util::Whitespace }
    };

    { $name:expr } => {
        $name
    };
}

<|endoftext|>


<commit_before>pub mod responses {

    use std::fmt;

    use serde;
    use serde_json as json;

    #[derive(Deserialize, Debug)]
    pub struct AuthResponse {
        pub session: SessionResponse,
    }

    #[derive(Deserialize, Debug, Clone)]
    pub struct SessionResponse {
        pub key: String,
        pub subscriber: i64,
        pub name: String,
    }

    #[derive(Deserialize)]
    pub struct NowPlayingResponseWrapper {
        pub nowplaying: NowPlayingResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct NowPlayingResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
    }

    #[derive(Deserialize)]
    pub struct ScrobbleResponseWrapper {
        pub scrobbles: Scrobbles,
    }

    #[derive(Deserialize)]
    pub struct Scrobbles {
        pub scrobble: ScrobbleResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct ScrobbleResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
        pub timestamp: String,
    }

    #[derive(Deserialize, Debug)]
    pub struct CorrectableString {
        #[serde(deserialize_with="CorrectableString::deserialize_corrected_field")]
        pub corrected: bool,
        #[serde(rename="#text", default)]
        pub text: String,
    }

    impl CorrectableString {
        fn deserialize_corrected_field<'de, D>(de: D) -> Result<bool, D::Error>
            where D: serde::Deserializer<'de>
        {
            let deser_result: json::Value = try!(serde::Deserialize::deserialize(de));
            match deser_result {
                json::Value::String(ref s) if &*s == "1" => Ok(true),
                json::Value::String(ref s) if &*s == "0" => Ok(false),
                _ => Err(serde::de::Error::custom("Unexpected value")),
            }
        }
    }

    impl fmt::Display for CorrectableString {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{}", self.text)
        }
    }

}

pub mod metadata {

    use std::collections::HashMap;

    /// Repesents a single track play (aka a "scrobble")
    pub struct Scrobble {
        artist: String,
        track: String,
        album: String
    }

    impl Scrobble {

        /// Constructs a new Scrobble instance, representing a music track
        /// played in the past.
        pub fn new(artist: String, track: String, album: String) -> Scrobble {
            Scrobble{ artist: artist, track: track, album: album }
        }

        /// Converts the Scrobble metadata (track name, artist & album name)
        /// into a HashMap. Map keys are `"track"`, `"artist"` and `"album"`,
        /// respectively.
        pub fn as_map(&self) -> HashMap<&str, String> {
            let mut params = HashMap::new();
            params.insert("track", self.track.clone());
            params.insert("artist", self.artist.clone());
            params.insert("album", self.album.clone());

            params
        }

    }

}<commit_msg>Scrobble impls most commonly advised deriable impls (from API guidelines) (Issue #11)<commit_after>pub mod responses {

    use std::fmt;

    use serde;
    use serde_json as json;

    #[derive(Deserialize, Debug)]
    pub struct AuthResponse {
        pub session: SessionResponse,
    }

    #[derive(Deserialize, Debug, Clone)]
    pub struct SessionResponse {
        pub key: String,
        pub subscriber: i64,
        pub name: String,
    }

    #[derive(Deserialize)]
    pub struct NowPlayingResponseWrapper {
        pub nowplaying: NowPlayingResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct NowPlayingResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
    }

    #[derive(Deserialize)]
    pub struct ScrobbleResponseWrapper {
        pub scrobbles: Scrobbles,
    }

    #[derive(Deserialize)]
    pub struct Scrobbles {
        pub scrobble: ScrobbleResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct ScrobbleResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
        pub timestamp: String,
    }

    #[derive(Deserialize, Debug)]
    pub struct CorrectableString {
        #[serde(deserialize_with="CorrectableString::deserialize_corrected_field")]
        pub corrected: bool,
        #[serde(rename="#text", default)]
        pub text: String,
    }

    impl CorrectableString {
        fn deserialize_corrected_field<'de, D>(de: D) -> Result<bool, D::Error>
            where D: serde::Deserializer<'de>
        {
            let deser_result: json::Value = try!(serde::Deserialize::deserialize(de));
            match deser_result {
                json::Value::String(ref s) if &*s == "1" => Ok(true),
                json::Value::String(ref s) if &*s == "0" => Ok(false),
                _ => Err(serde::de::Error::custom("Unexpected value")),
            }
        }
    }

    impl fmt::Display for CorrectableString {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{}", self.text)
        }
    }

}

pub mod metadata {

    use std::collections::HashMap;

    /// Repesents a single track play (aka a "scrobble")
    #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
    pub struct Scrobble {
        artist: String,
        track: String,
        album: String
    }

    impl Scrobble {

        /// Constructs a new Scrobble instance, representing a music track
        /// played in the past.
        pub fn new(artist: String, track: String, album: String) -> Scrobble {
            Scrobble{ artist: artist, track: track, album: album }
        }

        /// Converts the Scrobble metadata (track name, artist & album name)
        /// into a HashMap. Map keys are `"track"`, `"artist"` and `"album"`,
        /// respectively.
        pub fn as_map(&self) -> HashMap<&str, String> {
            let mut params = HashMap::new();
            params.insert("track", self.track.clone());
            params.insert("artist", self.artist.clone());
            params.insert("album", self.album.clone());

            params
        }

    }

}<|endoftext|>


<commit_before>use failure::Error;
use feed::Feed;
use feed::statistics::ListenerStats;

pub enum Icon {
    Update,
    Error,
}

#[cfg(any(unix, macos))]
mod unix {
    extern crate notify_rust;

    use self::notify_rust::Notification;
    use super::*;

    #[derive(Fail, Debug)]
    #[fail(display = "failed to create notification")]
    pub struct CreationFailedError;

    impl Icon {
        fn get_name(&self) -> &str {
            match *self {
                Icon::Update => "emblem-sound",
                Icon::Error => "dialog-error",
            }
        }
    }

    pub fn create(icon: &Icon, title: &str, body: &str) -> Result<(), CreationFailedError> {
        Notification::new()
            .summary(title)
            .body(body)
            .icon(icon.get_name())
            .show()
            .map_err(|_| CreationFailedError)?;

        Ok(())
    }
}

#[cfg(windows)]
mod windows {
    use failure::Error;
    use winrt::FastHString;
    use winrt::windows::data::xml::dom::*;
    use winrt::windows::ui::notifications::*;
    use super::Icon;

    // The purpose of having an inner create function is so that we only have to specify the error
    // type once if creation fails
    fn inner_create(title: &str, body: &str) -> Result<(), ::winrt::Error> {
        unsafe {
            let toast_xml =
                ToastNotificationManager::get_template_content(ToastTemplateType::ToastText02)?;

            let toast_text_elements =
                toast_xml.get_elements_by_tag_name(&FastHString::new("text"))?;

            let add_text = |i, string| {
                let node = &*toast_xml
                    .create_text_node(&FastHString::new(string))?
                    .query_interface::<IXmlNode>()
                    .unwrap();

                toast_text_elements.item(i)?.append_child(node)
            };

            add_text(0, title)?;
            add_text(1, body)?;

            let toast = ToastNotification::create_toast_notification(&*toast_xml)?;
            let id = env!("CARGO_PKG_NAME");

            ToastNotificationManager::create_toast_notifier_with_id(&FastHString::new(id))?
                .show(&*toast)?;
        }

        Ok(())
    }

    pub fn create(_: &Icon, title: &str, body: &str) -> Result<(), Error> {
        inner_create(title, body).map_err(|err| format_err!("{:?}", err))?;

        Ok(())
    }
}

#[cfg(any(unix, macos))]
use self::unix::create;

#[cfg(windows)]
use self::windows::create;

pub fn create_update(
    index: i32,
    max_index: i32,
    feed: &Feed,
    feed_stats: &ListenerStats,
) -> Result<(), Error> {
    let title = format!(
        "{} - Broadcastify Update ({} of {})",
        feed.state.abbrev, index, max_index
    );

    let alert = match feed.alert {
        Some(ref alert) => format!("\nAlert: {}", alert),
        None => String::new(),
    };

    let body = format!(
        "Name: {}\nListeners: {} (^{}){}\nLink: http://broadcastify.com/listen/feed/{}",
        feed.name,
        feed.listeners,
        feed_stats.get_jump(feed.listeners) as i32,
        &alert,
        feed.id
    );

    create(&Icon::Update, &title, &body)?;
    Ok(())
}

pub fn create_error(body: &str) -> Result<(), Error> {
    create(&Icon::Error, "Broadcastify Update Error", body)?;
    Ok(())
}
<commit_msg>Avoid allocation when no alert is present<commit_after>use failure::Error;
use feed::Feed;
use feed::statistics::ListenerStats;
use std::borrow::Cow;

pub enum Icon {
    Update,
    Error,
}

#[cfg(any(unix, macos))]
mod unix {
    extern crate notify_rust;

    use self::notify_rust::Notification;
    use super::*;

    #[derive(Fail, Debug)]
    #[fail(display = "failed to create notification")]
    pub struct CreationFailedError;

    impl Icon {
        fn get_name(&self) -> &str {
            match *self {
                Icon::Update => "emblem-sound",
                Icon::Error => "dialog-error",
            }
        }
    }

    pub fn create(icon: &Icon, title: &str, body: &str) -> Result<(), CreationFailedError> {
        Notification::new()
            .summary(title)
            .body(body)
            .icon(icon.get_name())
            .show()
            .map_err(|_| CreationFailedError)?;

        Ok(())
    }
}

#[cfg(windows)]
mod windows {
    use failure::Error;
    use winrt::FastHString;
    use winrt::windows::data::xml::dom::*;
    use winrt::windows::ui::notifications::*;
    use super::Icon;

    // The purpose of having an inner create function is so that we only have to specify the error
    // type once if creation fails
    fn inner_create(title: &str, body: &str) -> Result<(), ::winrt::Error> {
        unsafe {
            let toast_xml =
                ToastNotificationManager::get_template_content(ToastTemplateType::ToastText02)?;

            let toast_text_elements =
                toast_xml.get_elements_by_tag_name(&FastHString::new("text"))?;

            let add_text = |i, string| {
                let node = &*toast_xml
                    .create_text_node(&FastHString::new(string))?
                    .query_interface::<IXmlNode>()
                    .unwrap();

                toast_text_elements.item(i)?.append_child(node)
            };

            add_text(0, title)?;
            add_text(1, body)?;

            let toast = ToastNotification::create_toast_notification(&*toast_xml)?;
            let id = env!("CARGO_PKG_NAME");

            ToastNotificationManager::create_toast_notifier_with_id(&FastHString::new(id))?
                .show(&*toast)?;
        }

        Ok(())
    }

    pub fn create(_: &Icon, title: &str, body: &str) -> Result<(), Error> {
        inner_create(title, body).map_err(|err| format_err!("{:?}", err))?;

        Ok(())
    }
}

#[cfg(any(unix, macos))]
use self::unix::create;

#[cfg(windows)]
use self::windows::create;

pub fn create_update(
    index: i32,
    max_index: i32,
    feed: &Feed,
    feed_stats: &ListenerStats,
) -> Result<(), Error> {
    let title = format!(
        "{} - Broadcastify Update ({} of {})",
        feed.state.abbrev, index, max_index
    );

    let alert = match feed.alert {
        Some(ref alert) => Cow::Owned(format!("\nAlert: {}", alert)),
        None => Cow::Borrowed(""),
    };

    let body = format!(
        "Name: {}\nListeners: {} (^{}){}\nLink: http://broadcastify.com/listen/feed/{}",
        feed.name,
        feed.listeners,
        feed_stats.get_jump(feed.listeners) as i32,
        &alert,
        feed.id
    );

    create(&Icon::Update, &title, &body)?;
    Ok(())
}

pub fn create_error(body: &str) -> Result<(), Error> {
    create(&Icon::Error, "Broadcastify Update Error", body)?;
    Ok(())
}
<|endoftext|>