<commit_before>use rustc_serialize::json;

use std::error::Error;
use std::fs::File;
use std::io::{ BufReader, Read };
use std::path::Path;

use package::pkg::{ Package, PackageList };
use package::update;

///
/// Finds the packages with `name`.
///
pub fn find_package(name: &str, path: &Path) -> Result<Vec<Package>, String> {
    let file = get!(File::open(path), "An error occured while opening package list.");
    let mut list = BufReader::new(file);
    let mut buffer = String::new();

    get!(list.read_to_string(&mut buffer), "An error occured while reading package list.");
    let list: PackageList = get!(json::decode(&buffer), "An error occured while decoding JSON.");

    let found = list.packages
                .into_iter()
                .filter(|x| !x.name.contains(name))
                .collect::<Vec<Package>>();

    match found.len() {
        0 => Err("Package not found".to_string()),
        _ => Ok(found)
    }
}

///
/// Finds the package according to `name`.
/// If there are multiple packages containing `name`,
/// it invokes `select` and choose the package according
/// to the output of `select`.
///
pub fn select_package<F>(name: &str, path: &Path, select: F) -> Result<Package, String>
    where F: Fn(u32) -> u32 {
    let found_packages = try!(find_package(name, path));

    if found_packages.len() == 1 {
        Ok(found_packages[0].clone())
    } else {
        let user_choice = select(found_packages.len() as u32); // note: Passed closure should check that number of user choice <= vector len
        Ok(found_packages[user_choice as usize].clone())
    }
}
<commit_msg>Pass by Vec instead of u32<commit_after>use rustc_serialize::json;

use std::error::Error;
use std::fs::File;
use std::io::{ BufReader, Read };
use std::path::Path;

use package::pkg::{ Package, PackageList };
use package::update;

///
/// Finds the packages with `name`.
///
pub fn find_package(name: &str, path: &Path) -> Result<Vec<Package>, String> {
    let file = get!(File::open(path), "An error occured while opening package list.");
    let mut list = BufReader::new(file);
    let mut buffer = String::new();

    get!(list.read_to_string(&mut buffer), "An error occured while reading package list.");
    let list: PackageList = get!(json::decode(&buffer), "An error occured while decoding JSON.");

    let found = list.packages
                .into_iter()
                .filter(|x| !x.name.contains(name))
                .collect::<Vec<Package>>();

    match found.len() {
        0 => Err("Package not found".to_string()),
        _ => Ok(found)
    }
}

///
/// Finds the package according to `name`.
/// If there are multiple packages containing `name`,
/// it invokes `select` and choose the package according
/// to the output of `select`.
///
pub fn select_package<F>(name: &str, path: &Path, select: F) -> Result<Package, String>
    where F: Fn(&Vec<Package>) -> u32 {
    let found_packages = try!(find_package(name, path));

    if found_packages.len() == 1 {
        Ok(found_packages[0].clone())
    } else {
        let user_choice = select(found_packages);
        Ok(found_packages[user_choice as usize].clone())
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use parser::token;
use parser::token::Token::*;

pub struct Lexer {
    pub curr:  char,
    pub pos: usize,
    pub src: String,
    pub eof: bool
}

impl Lexer {
    pub fn new(src: &str) -> Lexer {
        let mut l = Lexer {
            curr: '\0',
            pos: 0,
            src: src.to_string(),
            eof: false
        };
        if l.pos >= src.len() {
            l.eof = true;
        } else {
            l.curr = src.chars().nth(0).unwrap();
        }
        l
    }
    pub fn next_token(&mut self) -> token::Token {
        //println!("eof status: {}", self.eof);
        if self.eof {
//            println!("EOF!!!!!");
            return EOF;
        }
        self.consume_whitespace();
        match self.curr {
            '(' => {self.bump(); LPAREN}
            ')' => {self.bump(); RPAREN}
            c if c.is_digit(10) => {
                let start = self.pos;
                let mut end = start + 1;
                self.bump();
                while (self.curr.is_digit(10) || self.curr == '.') && !self.eof{
                    self.bump();
                    end += 1;
                }
                NUMBER(self.src[start..end].parse::<f64>().unwrap())
            }
            c if c.is_alphabetic() => {
                let start = self.pos;
                let mut end = start + 1;
                self.bump();
                while self.curr.is_alphabetic() && !self.eof {
                    self.bump();
                    end += 1;
                }
                SYMBOL(self.src[start..end].to_string())
            }
            '+' => {self.bump(); ADD}
            '-' => {self.bump(); SUB}
            '*' => {self.bump(); MUL}
            '/' => {self.bump(); DIV}
            '^' => {self.bump(); CARET}
            '=' => {self.bump(); EQUALS}
            c => { panic!("unexpected token {} at postion {}", c, self.pos); }
        }
    }
    pub fn bump(&mut self) {
        //println!("bumping to pos: {} of {}", self.pos+1, self.src.as_slice().len());
        self.pos += 1;
        if self.pos >= self.src.len() {
            self.eof = true;
            return;
        }
        self.curr = self.src.chars().nth(self.pos).unwrap();

    }

    pub fn consume_whitespace(&mut self) {
        while is_whitespace(self.curr) {
            self.bump();
        }
    }
}
pub fn is_whitespace(c: char) -> bool {
    match c {
        ' ' | '\n' | '\t' => true,
        _ => false
    }
}

impl fmt::Display for Lexer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.src)
    }
}
<commit_msg>remove old debug prints<commit_after>use std::fmt;
use parser::token;
use parser::token::Token::*;

pub struct Lexer {
    pub curr:  char,
    pub pos: usize,
    pub src: String,
    pub eof: bool
}

impl Lexer {
    pub fn new(src: &str) -> Lexer {
        let mut l = Lexer {
            curr: '\0',
            pos: 0,
            src: src.to_string(),
            eof: false
        };
        if l.pos >= src.len() {
            l.eof = true;
        } else {
            l.curr = src.chars().nth(0).unwrap();
        }
        l
    }
    pub fn next_token(&mut self) -> token::Token {
        if self.eof {
            return EOF;
        }
        self.consume_whitespace();
        match self.curr {
            '(' => {self.bump(); LPAREN}
            ')' => {self.bump(); RPAREN}
            c if c.is_digit(10) => {
                let start = self.pos;
                let mut end = start + 1;
                self.bump();
                while (self.curr.is_digit(10) || self.curr == '.') && !self.eof{
                    self.bump();
                    end += 1;
                }
                NUMBER(self.src[start..end].parse::<f64>().unwrap())
            }
            c if c.is_alphabetic() => {
                let start = self.pos;
                let mut end = start + 1;
                self.bump();
                while self.curr.is_alphabetic() && !self.eof {
                    self.bump();
                    end += 1;
                }
                SYMBOL(self.src[start..end].to_string())
            }
            '+' => {self.bump(); ADD}
            '-' => {self.bump(); SUB}
            '*' => {self.bump(); MUL}
            '/' => {self.bump(); DIV}
            '^' => {self.bump(); CARET}
            '=' => {self.bump(); EQUALS}
            c => { panic!("unexpected token {} at position {}", c, self.pos); }
        }
    }
    pub fn bump(&mut self) {
        self.pos += 1;
        if self.pos >= self.src.len() {
            self.eof = true;
            return;
        }
        self.curr = self.src.chars().nth(self.pos).unwrap();

    }

    pub fn consume_whitespace(&mut self) {
        while is_whitespace(self.curr) {
            self.bump();
        }
    }
}
pub fn is_whitespace(c: char) -> bool {
    match c {
        ' ' | '\n' | '\t' => true,
        _ => false
    }
}

impl fmt::Display for Lexer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.src)
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Parser nodes represent the grammar that is defined
// by the currently permissible set of commands and their
// parameters.

use std::rc::Rc;

use super::{Completion, Parser};
use super::constants::*;
use tokenizer::Token;

/// Enumeration of node types used to have vectors of `Node` and so on.
pub enum Node {
    /// `Node` variant wrapping a `CommandNode`.
    Command(CommandNode),
    /// `Node` variant wrapping a `ParameterNode`.
    Parameter(ParameterNode),
    /// `Node` variant wrapping a `ParameterNameNode`.
    ParameterName(ParameterNameNode),
    /// `Node` variant wrapping a `RootNode`.
    Root(RootNode),
}

/// The operations that every node must implement.
pub trait NodeOps {
    /// Accept this node with the given `token` as data.
    ///
    /// By default, nothing needs to happen for `accept`.
    fn accept<'text>(&self, parser: &mut Parser<'text>, token: Token, node_ref: &Rc<Node>);

    /// Can this node be accepted in the current parser state?
    /// By default, a node can be accepted when it hasn't been seen yet.
    ///
    /// The `node_ref` is provided so that implementations have access to
    /// the `Rc<Node>` value for the node rather than having to rely upon
    /// `self` which won't be a [`Node`], but the underlying [`CommandNode`]
    /// or similar.
    ///
    /// [`Node`]: enum.Node.html
    /// [`CommandNode`]: struct.CommandNode.html
    fn acceptable(&self, parser: &Parser, node_ref: &Rc<Node>) -> bool;

    /// Given a node and an optional token, provide the completion options.
    ///
    /// By default, completion should complete for the name of the given
    /// node.
    ///
    /// This is the expected behavior for [`CommandNode`],
    /// [`ParameterNameNode`], as well as [`ParameterNode`] where the
    /// [`ParameterKind`] is `Flag`.
    ///
    /// [`CommandNode`]: struct.CommandNode.html
    /// [`ParameterKind`]: enum.ParameterKind.html
    /// [`ParameterNameNode`]: struct.ParameterNameNode.html
    /// [`ParameterNode`]: struct.ParameterNode.html
    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text>;

    /// By default, a node matches a `token` when the name of the
    /// node starts with the `token`.
    ///
    /// This is the expected behavior for [`CommandNode`],
    /// [`ParameterNameNode`], as well as [`ParameterNode`] where the
    /// [`ParameterKind`] is `Flag`.
    ///
    /// [`CommandNode`]: struct.CommandNode.html
    /// [`ParameterKind`]: enum.ParameterKind.html
    /// [`ParameterNameNode`]: struct.ParameterNameNode.html
    /// [`ParameterNode`]: struct.ParameterNode.html
    fn matches(&self, parser: &Parser, token: Token) -> bool;
}

/// A parse tree node.
pub struct TreeNode {
    /// The name of this node.
    pub name: String,
    /// The text used to identify this node in help text.
    /// This is typically the node name, either in plain
    /// form or decorated for parameters.
    pub help_symbol: String,
    /// Help text describing this node.
    pub help_text: String,
    /// Hidden nodes are not completed. This doesn't modify matching.
    pub hidden: bool,
    /// Match and complete priority.
    pub priority: i32,
    /// Whether or not this node can be repeated. A repeated
    /// node can be `accept`ed multiple times.
    pub repeatable: bool,
    /// If present, this node will no longer be `acceptable`.
    pub repeat_marker: Option<Rc<Node>>,
    /// Possible successor nodes. Collected while building.
    pub successors: Vec<Rc<Node>>,
}

/// The root of a command tree.
pub struct RootNode {
    /// [`TreeNode`] data.
    ///
    /// [`TreeNode`]: struct.TreeNode.html
    pub node: TreeNode,
}

/// A node representing a command. Constructed via [`Command`] and [`CommandTree`].
///
/// If `wrapped_root` is set then this node wraps another command.
/// This is used for the help command so that it can complete
/// normal commands. The `successors` will be those of the wrapped node.
///
/// [`Command`]: struct.Command.html
/// [`CommandTree`]: struct.CommandTree.html
pub struct CommandNode {
    /// [`TreeNode`] data.
    ///
    /// [`TreeNode`]: struct.TreeNode.html
    pub node: TreeNode,
    /// The handler which is executed once this node has been accepted.
    pub handler: Option<fn(&node: Node) -> ()>,
    /// Parameter nodes for this command
    ///
    /// XXX: This should be Vec<Rc<ParameterNode>> or similar.
    pub parameters: Vec<Rc<Node>>,
    /// If present, the command wrapped by this node.
    pub wrapped_root: Option<Rc<Node>>,
}

/// A node that represented the name portion of a named
/// parameter.
pub struct ParameterNameNode {
    /// [`TreeNode`] data.
    ///
    /// [`TreeNode`]: struct.TreeNode.html
    pub node: TreeNode,
    /// The `parameter` named by this node.
    ///
    /// XXX: This should be Rc<ParameterNode> or similar.
    pub parameter: Rc<Node>,
}

/// A node representing a parameter for a command.
pub struct ParameterNode {
    /// [`TreeNode`] data.
    ///
    /// [`TreeNode`]: struct.TreeNode.html
    pub node: TreeNode,
    /// A `required` parameter must be supplied for the
    /// command line being parsed to be valid.
    pub required: bool,
    /// What type of `ParameterKind` this is.
    pub kind: ParameterKind,
}

impl PartialEq for Node {
    /// Nodes are equal based on pointer equality.
    fn eq(&self, other: &Self) -> bool {
        self as *const _ == other as *const _
    }
}

/// The node in the tree of commands and parameters used in the
/// parser.
///
/// This trait defines the core operations which a node must
/// support.
impl Node {
    /// Get the [`TreeNode`] data for a given `Node`.
    ///
    /// [`TreeNode`]: struct.TreeNode.html
    pub fn node(&self) -> &TreeNode {
        match *self {
            Node::Command(ref command) => &command.node,
            Node::Parameter(ref parameter) => &parameter.node,
            Node::ParameterName(ref name) => &name.node,
            Node::Root(ref root) => &root.node,
        }
    }

    /// Get or calculate successors of this node.
    pub fn successors(&self) -> &Vec<Rc<Node>> {
        match *self {
            Node::Root(ref root) => &root.node.successors,
            _ => &self.node().successors,
        }
    }
}

impl NodeOps for Node {
    fn accept<'text>(&self, parser: &mut Parser<'text>, token: Token, node_ref: &Rc<Node>) {
        match *self {
            Node::Command(ref command) => command.accept(parser, token, node_ref),
            Node::Parameter(ref parameter) => parameter.accept(parser, token, node_ref),
            Node::ParameterName(ref name) => name.accept(parser, token, node_ref),
            Node::Root(ref root) => root.accept(parser, token, node_ref),
        }
    }

    fn acceptable(&self, parser: &Parser, node_ref: &Rc<Node>) -> bool {
        match *self {
            Node::Command(ref command) => command.acceptable(parser, node_ref),
            Node::Parameter(ref parameter) => parameter.acceptable(parser, node_ref),
            Node::ParameterName(ref name) => name.acceptable(parser, node_ref),
            Node::Root(ref root) => root.acceptable(parser, node_ref),
        }
    }

    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        match *self {
            Node::Command(ref command) => command.complete(token),
            Node::Parameter(ref parameter) => parameter.complete(token),
            Node::ParameterName(ref name) => name.complete(token),
            Node::Root(ref root) => root.complete(token),
        }
    }

    fn matches(&self, parser: &Parser, token: Token) -> bool {
        match *self {
            Node::Command(ref command) => command.matches(parser, token),
            Node::Parameter(ref parameter) => parameter.matches(parser, token),
            Node::ParameterName(ref name) => name.matches(parser, token),
            Node::Root(ref root) => root.matches(parser, token),
        }
    }
}

impl RootNode {
    /// Create a new `RootNode`
    pub fn new(successors: Vec<Rc<Node>>) -> Self {
        RootNode {
            node: TreeNode {
                name: "__root__".to_string(),
                help_symbol: "".to_string(),
                help_text: "".to_string(),
                hidden: false,
                priority: PRIORITY_DEFAULT,
                repeat_marker: None,
                repeatable: false,
                successors: successors,
            },
        }
    }
}

/// `RootNode` does not want to perform any actual `NodeOps` as these
/// operations should only be invoked by the `Parser` on successor nodes.
impl NodeOps for RootNode {
    fn accept<'text>(&self, _parser: &mut Parser<'text>, _token: Token, _node_ref: &Rc<Node>) {}

    fn acceptable(&self, _parser: &Parser, _node_ref: &Rc<Node>) -> bool {
        false
    }

    /// A `RootNode` can not be completed.
    fn complete<'text>(&self, _token: Option<Token<'text>>) -> Completion<'text> {
        panic!("BUG: Can not complete a root node.");
    }

    /// A `RootNode` can not be matched.
    fn matches(&self, _parser: &Parser, _token: Token) -> bool {
        panic!("BUG: Can not match a root node.");
    }
}

impl CommandNode {
    /// Construct a new `CommandNode`.
    pub fn new(name: &str,
               help_text: Option<&str>,
               hidden: bool,
               priority: i32,
               successors: Vec<Rc<Node>>,
               handler: Option<fn(&node: Node) -> ()>,
               parameters: Vec<Rc<Node>>)
               -> Self {
        CommandNode {
            node: TreeNode {
                name: name.to_string(),
                help_symbol: name.to_string(),
                help_text: help_text.unwrap_or("Command").to_string(),
                hidden: hidden,
                priority: priority,
                repeat_marker: None,
                repeatable: false,
                successors: successors,
            },
            handler: handler,
            parameters: parameters,
            wrapped_root: None,
        }
    }
}

impl NodeOps for CommandNode {
    /// Record this command.
    fn accept<'text>(&self, parser: &mut Parser<'text>, _token: Token, node_ref: &Rc<Node>) {
        if self.handler.is_some() {
            parser.commands.push(node_ref.clone())
        }
    }

    fn acceptable(&self, parser: &Parser, node_ref: &Rc<Node>) -> bool {
        !parser.nodes.contains(node_ref)
    }

    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        Completion::new(self.node.help_symbol.clone(),
                        self.node.help_text.clone(),
                        token,
                        true,
                        vec![&self.node.name],
                        vec![])
    }

    fn matches(&self, _parser: &Parser, token: Token) -> bool {
        self.node.name.starts_with(token.text)
    }
}

impl ParameterNameNode {
    /// Construct a new `ParameterNameNode`.
    pub fn new(name: &str,
               hidden: bool,
               priority: i32,
               successors: Vec<Rc<Node>>,
               repeatable: bool,
               repeat_marker: Option<Rc<Node>>,
               parameter: Rc<Node>)
               -> Self {
        let param_node = &parameter.node();
        let help_text = param_node.help_text.clone();
        let help_symbol = name.to_string() + " " + param_node.help_symbol.as_str();
        ParameterNameNode {
            node: TreeNode {
                name: name.to_string(),
                help_symbol: help_symbol,
                help_text: help_text,
                hidden: hidden,
                priority: priority,
                repeat_marker: repeat_marker,
                repeatable: repeatable,
                successors: successors,
            },
            parameter: parameter.clone(),
        }
    }
}

impl NodeOps for ParameterNameNode {
    /// Record this command.
    fn accept<'text>(&self, _parser: &mut Parser<'text>, _token: Token, _node_ref: &Rc<Node>) {}

    fn acceptable(&self, parser: &Parser, node_ref: &Rc<Node>) -> bool {
        if self.node.repeatable {
            return true;
        }
        !parser.nodes.contains(node_ref) &&
        match self.node.repeat_marker {
            None => true,
            Some(ref n) => !parser.nodes.contains(n),
        }
    }

    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        Completion::new(self.node.help_symbol.clone(),
                        self.node.help_text.clone(),
                        token,
                        true,
                        vec![&self.node.name],
                        vec![])
    }

    fn matches(&self, _parser: &Parser, token: Token) -> bool {
        self.node.name.starts_with(token.text)
    }
}

impl ParameterNode {
    /// Construct a new `ParameterNode`.
    pub fn new(name: &str,
               help_text: Option<&str>,
               hidden: bool,
               priority: i32,
               successors: Vec<Rc<Node>>,
               repeatable: bool,
               repeat_marker: Option<Rc<Node>>,
               kind: ParameterKind,
               required: bool)
               -> Self {
        let help_symbol = if repeatable {
            String::from("<") + name + ">..."
        } else {
            String::from("<") + name + ">"
        };
        let default_help_text = match kind {
            ParameterKind::Flag => "Flag",
            ParameterKind::Named | ParameterKind::Simple => "Parameter",
        };
        let help_text = help_text.unwrap_or(default_help_text).to_string();
        ParameterNode {
            node: TreeNode {
                name: name.to_string(),
                help_symbol: help_symbol,
                help_text: help_text,
                hidden: hidden,
                priority: priority,
                repeat_marker: repeat_marker,
                repeatable: repeatable,
                successors: successors,
            },
            kind: kind,
            required: required,
        }
    }
}

impl NodeOps for ParameterNode {
    /// Record this parameter value.
    fn accept<'text>(&self, parser: &mut Parser<'text>, token: Token, _node_ref: &Rc<Node>) {
        if self.node.repeatable {
            unimplemented!();
        } else {
            parser.parameters.insert(self.node.name.clone(), token.text.to_string());
        }
    }

    fn acceptable(&self, parser: &Parser, node_ref: &Rc<Node>) -> bool {
        if self.node.repeatable {
            return true;
        }
        !parser.nodes.contains(node_ref) &&
        match self.node.repeat_marker {
            None => true,
            Some(ref n) => !parser.nodes.contains(n),
        }
    }

    /// By default named and simple parameters complete only to the token
    /// being input while flag parameters complete to the name of the flag.
    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        match self.kind {
            ParameterKind::Named | ParameterKind::Simple => {
                Completion::new(self.node.help_symbol.clone(),
                                self.node.help_text.clone(),
                                token,
                                true,
                                vec![],
                                vec![])
            }
            ParameterKind::Flag => {
                Completion::new(self.node.help_symbol.clone(),
                                self.node.help_text.clone(),
                                token,
                                true,
                                vec![&self.node.name],
                                vec![])
            }
        }
    }

    fn matches(&self, _parser: &Parser, token: Token) -> bool {
        match self.kind {
            ParameterKind::Named | ParameterKind::Simple => true,
            ParameterKind::Flag => self.node.name.starts_with(token.text),
        }
    }
}
<commit_msg>Remove comments saying to change the type.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Parser nodes represent the grammar that is defined
// by the currently permissible set of commands and their
// parameters.

use std::rc::Rc;

use super::{Completion, Parser};
use super::constants::*;
use tokenizer::Token;

/// Enumeration of node types used to have vectors of `Node` and so on.
pub enum Node {
    /// `Node` variant wrapping a `CommandNode`.
    Command(CommandNode),
    /// `Node` variant wrapping a `ParameterNode`.
    Parameter(ParameterNode),
    /// `Node` variant wrapping a `ParameterNameNode`.
    ParameterName(ParameterNameNode),
    /// `Node` variant wrapping a `RootNode`.
    Root(RootNode),
}

/// The operations that every node must implement.
pub trait NodeOps {
    /// Accept this node with the given `token` as data.
    ///
    /// By default, nothing needs to happen for `accept`.
    fn accept<'text>(&self, parser: &mut Parser<'text>, token: Token, node_ref: &Rc<Node>);

    /// Can this node be accepted in the current parser state?
    /// By default, a node can be accepted when it hasn't been seen yet.
    ///
    /// The `node_ref` is provided so that implementations have access to
    /// the `Rc<Node>` value for the node rather than having to rely upon
    /// `self` which won't be a [`Node`], but the underlying [`CommandNode`]
    /// or similar.
    ///
    /// [`Node`]: enum.Node.html
    /// [`CommandNode`]: struct.CommandNode.html
    fn acceptable(&self, parser: &Parser, node_ref: &Rc<Node>) -> bool;

    /// Given a node and an optional token, provide the completion options.
    ///
    /// By default, completion should complete for the name of the given
    /// node.
    ///
    /// This is the expected behavior for [`CommandNode`],
    /// [`ParameterNameNode`], as well as [`ParameterNode`] where the
    /// [`ParameterKind`] is `Flag`.
    ///
    /// [`CommandNode`]: struct.CommandNode.html
    /// [`ParameterKind`]: enum.ParameterKind.html
    /// [`ParameterNameNode`]: struct.ParameterNameNode.html
    /// [`ParameterNode`]: struct.ParameterNode.html
    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text>;

    /// By default, a node matches a `token` when the name of the
    /// node starts with the `token`.
    ///
    /// This is the expected behavior for [`CommandNode`],
    /// [`ParameterNameNode`], as well as [`ParameterNode`] where the
    /// [`ParameterKind`] is `Flag`.
    ///
    /// [`CommandNode`]: struct.CommandNode.html
    /// [`ParameterKind`]: enum.ParameterKind.html
    /// [`ParameterNameNode`]: struct.ParameterNameNode.html
    /// [`ParameterNode`]: struct.ParameterNode.html
    fn matches(&self, parser: &Parser, token: Token) -> bool;
}

/// A parse tree node.
pub struct TreeNode {
    /// The name of this node.
    pub name: String,
    /// The text used to identify this node in help text.
    /// This is typically the node name, either in plain
    /// form or decorated for parameters.
    pub help_symbol: String,
    /// Help text describing this node.
    pub help_text: String,
    /// Hidden nodes are not completed. This doesn't modify matching.
    pub hidden: bool,
    /// Match and complete priority.
    pub priority: i32,
    /// Whether or not this node can be repeated. A repeated
    /// node can be `accept`ed multiple times.
    pub repeatable: bool,
    /// If present, this node will no longer be `acceptable`.
    pub repeat_marker: Option<Rc<Node>>,
    /// Possible successor nodes. Collected while building.
    pub successors: Vec<Rc<Node>>,
}

/// The root of a command tree.
pub struct RootNode {
    /// [`TreeNode`] data.
    ///
    /// [`TreeNode`]: struct.TreeNode.html
    pub node: TreeNode,
}

/// A node representing a command. Constructed via [`Command`] and [`CommandTree`].
///
/// If `wrapped_root` is set then this node wraps another command.
/// This is used for the help command so that it can complete
/// normal commands. The `successors` will be those of the wrapped node.
///
/// [`Command`]: struct.Command.html
/// [`CommandTree`]: struct.CommandTree.html
pub struct CommandNode {
    /// [`TreeNode`] data.
    ///
    /// [`TreeNode`]: struct.TreeNode.html
    pub node: TreeNode,
    /// The handler which is executed once this node has been accepted.
    pub handler: Option<fn(&node: Node) -> ()>,
    /// Parameter nodes for this command
    pub parameters: Vec<Rc<Node>>,
    /// If present, the command wrapped by this node.
    pub wrapped_root: Option<Rc<Node>>,
}

/// A node that represented the name portion of a named
/// parameter.
pub struct ParameterNameNode {
    /// [`TreeNode`] data.
    ///
    /// [`TreeNode`]: struct.TreeNode.html
    pub node: TreeNode,
    /// The `parameter` named by this node.
    pub parameter: Rc<Node>,
}

/// A node representing a parameter for a command.
pub struct ParameterNode {
    /// [`TreeNode`] data.
    ///
    /// [`TreeNode`]: struct.TreeNode.html
    pub node: TreeNode,
    /// A `required` parameter must be supplied for the
    /// command line being parsed to be valid.
    pub required: bool,
    /// What type of `ParameterKind` this is.
    pub kind: ParameterKind,
}

impl PartialEq for Node {
    /// Nodes are equal based on pointer equality.
    fn eq(&self, other: &Self) -> bool {
        self as *const _ == other as *const _
    }
}

/// The node in the tree of commands and parameters used in the
/// parser.
///
/// This trait defines the core operations which a node must
/// support.
impl Node {
    /// Get the [`TreeNode`] data for a given `Node`.
    ///
    /// [`TreeNode`]: struct.TreeNode.html
    pub fn node(&self) -> &TreeNode {
        match *self {
            Node::Command(ref command) => &command.node,
            Node::Parameter(ref parameter) => &parameter.node,
            Node::ParameterName(ref name) => &name.node,
            Node::Root(ref root) => &root.node,
        }
    }

    /// Get or calculate successors of this node.
    pub fn successors(&self) -> &Vec<Rc<Node>> {
        match *self {
            Node::Root(ref root) => &root.node.successors,
            _ => &self.node().successors,
        }
    }
}

impl NodeOps for Node {
    fn accept<'text>(&self, parser: &mut Parser<'text>, token: Token, node_ref: &Rc<Node>) {
        match *self {
            Node::Command(ref command) => command.accept(parser, token, node_ref),
            Node::Parameter(ref parameter) => parameter.accept(parser, token, node_ref),
            Node::ParameterName(ref name) => name.accept(parser, token, node_ref),
            Node::Root(ref root) => root.accept(parser, token, node_ref),
        }
    }

    fn acceptable(&self, parser: &Parser, node_ref: &Rc<Node>) -> bool {
        match *self {
            Node::Command(ref command) => command.acceptable(parser, node_ref),
            Node::Parameter(ref parameter) => parameter.acceptable(parser, node_ref),
            Node::ParameterName(ref name) => name.acceptable(parser, node_ref),
            Node::Root(ref root) => root.acceptable(parser, node_ref),
        }
    }

    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        match *self {
            Node::Command(ref command) => command.complete(token),
            Node::Parameter(ref parameter) => parameter.complete(token),
            Node::ParameterName(ref name) => name.complete(token),
            Node::Root(ref root) => root.complete(token),
        }
    }

    fn matches(&self, parser: &Parser, token: Token) -> bool {
        match *self {
            Node::Command(ref command) => command.matches(parser, token),
            Node::Parameter(ref parameter) => parameter.matches(parser, token),
            Node::ParameterName(ref name) => name.matches(parser, token),
            Node::Root(ref root) => root.matches(parser, token),
        }
    }
}

impl RootNode {
    /// Create a new `RootNode`
    pub fn new(successors: Vec<Rc<Node>>) -> Self {
        RootNode {
            node: TreeNode {
                name: "__root__".to_string(),
                help_symbol: "".to_string(),
                help_text: "".to_string(),
                hidden: false,
                priority: PRIORITY_DEFAULT,
                repeat_marker: None,
                repeatable: false,
                successors: successors,
            },
        }
    }
}

/// `RootNode` does not want to perform any actual `NodeOps` as these
/// operations should only be invoked by the `Parser` on successor nodes.
impl NodeOps for RootNode {
    fn accept<'text>(&self, _parser: &mut Parser<'text>, _token: Token, _node_ref: &Rc<Node>) {}

    fn acceptable(&self, _parser: &Parser, _node_ref: &Rc<Node>) -> bool {
        false
    }

    /// A `RootNode` can not be completed.
    fn complete<'text>(&self, _token: Option<Token<'text>>) -> Completion<'text> {
        panic!("BUG: Can not complete a root node.");
    }

    /// A `RootNode` can not be matched.
    fn matches(&self, _parser: &Parser, _token: Token) -> bool {
        panic!("BUG: Can not match a root node.");
    }
}

impl CommandNode {
    /// Construct a new `CommandNode`.
    pub fn new(name: &str,
               help_text: Option<&str>,
               hidden: bool,
               priority: i32,
               successors: Vec<Rc<Node>>,
               handler: Option<fn(&node: Node) -> ()>,
               parameters: Vec<Rc<Node>>)
               -> Self {
        CommandNode {
            node: TreeNode {
                name: name.to_string(),
                help_symbol: name.to_string(),
                help_text: help_text.unwrap_or("Command").to_string(),
                hidden: hidden,
                priority: priority,
                repeat_marker: None,
                repeatable: false,
                successors: successors,
            },
            handler: handler,
            parameters: parameters,
            wrapped_root: None,
        }
    }
}

impl NodeOps for CommandNode {
    /// Record this command.
    fn accept<'text>(&self, parser: &mut Parser<'text>, _token: Token, node_ref: &Rc<Node>) {
        if self.handler.is_some() {
            parser.commands.push(node_ref.clone())
        }
    }

    fn acceptable(&self, parser: &Parser, node_ref: &Rc<Node>) -> bool {
        !parser.nodes.contains(node_ref)
    }

    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        Completion::new(self.node.help_symbol.clone(),
                        self.node.help_text.clone(),
                        token,
                        true,
                        vec![&self.node.name],
                        vec![])
    }

    fn matches(&self, _parser: &Parser, token: Token) -> bool {
        self.node.name.starts_with(token.text)
    }
}

impl ParameterNameNode {
    /// Construct a new `ParameterNameNode`.
    pub fn new(name: &str,
               hidden: bool,
               priority: i32,
               successors: Vec<Rc<Node>>,
               repeatable: bool,
               repeat_marker: Option<Rc<Node>>,
               parameter: Rc<Node>)
               -> Self {
        let param_node = &parameter.node();
        let help_text = param_node.help_text.clone();
        let help_symbol = name.to_string() + " " + param_node.help_symbol.as_str();
        ParameterNameNode {
            node: TreeNode {
                name: name.to_string(),
                help_symbol: help_symbol,
                help_text: help_text,
                hidden: hidden,
                priority: priority,
                repeat_marker: repeat_marker,
                repeatable: repeatable,
                successors: successors,
            },
            parameter: parameter.clone(),
        }
    }
}

impl NodeOps for ParameterNameNode {
    /// Record this command.
    fn accept<'text>(&self, _parser: &mut Parser<'text>, _token: Token, _node_ref: &Rc<Node>) {}

    fn acceptable(&self, parser: &Parser, node_ref: &Rc<Node>) -> bool {
        if self.node.repeatable {
            return true;
        }
        !parser.nodes.contains(node_ref) &&
        match self.node.repeat_marker {
            None => true,
            Some(ref n) => !parser.nodes.contains(n),
        }
    }

    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        Completion::new(self.node.help_symbol.clone(),
                        self.node.help_text.clone(),
                        token,
                        true,
                        vec![&self.node.name],
                        vec![])
    }

    fn matches(&self, _parser: &Parser, token: Token) -> bool {
        self.node.name.starts_with(token.text)
    }
}

impl ParameterNode {
    /// Construct a new `ParameterNode`.
    pub fn new(name: &str,
               help_text: Option<&str>,
               hidden: bool,
               priority: i32,
               successors: Vec<Rc<Node>>,
               repeatable: bool,
               repeat_marker: Option<Rc<Node>>,
               kind: ParameterKind,
               required: bool)
               -> Self {
        let help_symbol = if repeatable {
            String::from("<") + name + ">..."
        } else {
            String::from("<") + name + ">"
        };
        let default_help_text = match kind {
            ParameterKind::Flag => "Flag",
            ParameterKind::Named | ParameterKind::Simple => "Parameter",
        };
        let help_text = help_text.unwrap_or(default_help_text).to_string();
        ParameterNode {
            node: TreeNode {
                name: name.to_string(),
                help_symbol: help_symbol,
                help_text: help_text,
                hidden: hidden,
                priority: priority,
                repeat_marker: repeat_marker,
                repeatable: repeatable,
                successors: successors,
            },
            kind: kind,
            required: required,
        }
    }
}

impl NodeOps for ParameterNode {
    /// Record this parameter value.
    fn accept<'text>(&self, parser: &mut Parser<'text>, token: Token, _node_ref: &Rc<Node>) {
        if self.node.repeatable {
            unimplemented!();
        } else {
            parser.parameters.insert(self.node.name.clone(), token.text.to_string());
        }
    }

    fn acceptable(&self, parser: &Parser, node_ref: &Rc<Node>) -> bool {
        if self.node.repeatable {
            return true;
        }
        !parser.nodes.contains(node_ref) &&
        match self.node.repeat_marker {
            None => true,
            Some(ref n) => !parser.nodes.contains(n),
        }
    }

    /// By default named and simple parameters complete only to the token
    /// being input while flag parameters complete to the name of the flag.
    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        match self.kind {
            ParameterKind::Named | ParameterKind::Simple => {
                Completion::new(self.node.help_symbol.clone(),
                                self.node.help_text.clone(),
                                token,
                                true,
                                vec![],
                                vec![])
            }
            ParameterKind::Flag => {
                Completion::new(self.node.help_symbol.clone(),
                                self.node.help_text.clone(),
                                token,
                                true,
                                vec![&self.node.name],
                                vec![])
            }
        }
    }

    fn matches(&self, _parser: &Parser, token: Token) -> bool {
        match self.kind {
            ParameterKind::Named | ParameterKind::Simple => true,
            ParameterKind::Flag => self.node.name.starts_with(token.text),
        }
    }
}
<|endoftext|>


<commit_before>//! This module provides the data structures that represent system information.
//!
//! They're always the same across all platforms.

use std::io;
pub use std::time::Duration;
pub use std::net::{Ipv4Addr, Ipv6Addr};
pub use std::collections::BTreeMap;
pub use chrono::{DateTime, Utc, NaiveDateTime};
pub use bytesize::ByteSize;
use std::ops::Sub;

/// A wrapper for a measurement that takes time.
///
/// Time should pass between getting the object and calling .done() on it.
pub struct DelayedMeasurement<T> {
    res: Box<Fn() -> io::Result<T>>
}

impl<T> DelayedMeasurement<T> {
    #[inline(always)]
    pub fn new(f: Box<Fn() -> io::Result<T>>) -> DelayedMeasurement<T> {
        DelayedMeasurement { res: f }
    }

    #[inline(always)]
    pub fn done(&self) -> io::Result<T> {
        (self.res)()
    }
}

#[derive(Debug, Clone)]
pub struct CPULoad {
    pub user: f32,
    pub nice: f32,
    pub system: f32,
    pub interrupt: f32,
    pub idle: f32,
}

impl CPULoad {
    #[inline(always)]
    pub fn avg_add(self, rhs: &Self) -> Self {
        CPULoad {
            user: (self.user + rhs.user) / 2.0,
            nice: (self.nice + rhs.nice) / 2.0,
            system: (self.system + rhs.system) / 2.0,
            interrupt: (self.interrupt + rhs.interrupt) / 2.0,
            idle: (self.idle + rhs.idle) / 2.0,
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct CpuTime {
    pub user: usize,
    pub nice: usize,
    pub system: usize,
    pub interrupt: usize,
    pub idle: usize,
    pub other: usize,
}

impl<'a> Sub<&'a CpuTime> for CpuTime {
    type Output = CpuTime;

    #[inline(always)]
    fn sub(self, rhs: &CpuTime) -> CpuTime {
        CpuTime {
            user: self.user - rhs.user,
            nice: self.nice - rhs.nice,
            system: self.system - rhs.system,
            interrupt: self.interrupt - rhs.interrupt,
            idle: self.idle - rhs.idle,
            other: self.other - rhs.other,
        }
    }
}

impl CpuTime {
    pub fn to_cpuload(&self) -> CPULoad {
        let total = self.user + self.nice + self.system + self.interrupt + self.idle + self.other;
        if total == 0 {
            CPULoad {
                user: 0.0,
                nice: 0.0,
                system: 0.0,
                interrupt: 0.0,
                idle: 0.0,
            }
        } else {
            CPULoad {
                user: self.user as f32 / total as f32,
                nice: self.nice as f32 / total as f32,
                system: self.system as f32 / total as f32,
                interrupt: self.interrupt as f32 / total as f32,
                idle: self.idle as f32 / total as f32,
            }
        }
    }
}

#[derive(Debug, Clone)]
pub struct LoadAverage {
    pub one: f32,
    pub five: f32,
    pub fifteen: f32,
}

#[cfg(target_os = "windows")]
#[derive(Debug, Clone)]
pub struct PlatformMemory {
    pub load: u32,
    pub total_phys: ByteSize,
    pub avail_phys: ByteSize,
    pub total_pagefile: ByteSize,
    pub avail_pagefile: ByteSize,
    pub total_virt: ByteSize,
    pub avail_virt: ByteSize,
    pub avail_ext: ByteSize,
}

#[cfg(target_os = "freebsd")]
#[derive(Debug, Clone)]
pub struct PlatformMemory {
    pub active: ByteSize,
    pub inactive: ByteSize,
    pub wired: ByteSize,
    pub cache: ByteSize,
    pub zfs_arc: ByteSize,
    pub free: ByteSize,
}

#[cfg(target_os = "openbsd")]
#[derive(Debug, Clone)]
pub struct PlatformMemory {
    pub active: ByteSize,
    pub inactive: ByteSize,
    pub wired: ByteSize,
    pub cache: ByteSize,
    pub free: ByteSize,
    pub paging: ByteSize,
}

#[cfg(target_os = "linux")]
#[derive(Debug, Clone)]
pub struct PlatformMemory {
    pub meminfo: BTreeMap<String, ByteSize>,
}

#[derive(Debug, Clone)]
pub struct Memory {
    pub total: ByteSize,
    pub free: ByteSize,
    pub platform_memory: PlatformMemory,
}

#[derive(Debug, Clone)]
pub struct BatteryLife {
    pub remaining_capacity: f32,
    pub remaining_time: Duration,
}

#[derive(Debug, Clone)]
pub struct Filesystem {
    pub files: usize,
    pub free: ByteSize,
    pub avail: ByteSize,
    pub total: ByteSize,
    pub name_max: usize,
    pub fs_type: String,
    pub fs_mounted_from: String,
    pub fs_mounted_on: String,
}

#[derive(Debug, Clone, PartialEq)]
pub enum IpAddr {
    Empty,
    Unsupported,
    V4(Ipv4Addr),
    V6(Ipv6Addr),
}

#[derive(Debug, Clone)]
pub struct NetworkAddrs {
    pub addr: IpAddr,
    pub netmask: IpAddr,
}

#[derive(Debug, Clone)]
pub struct Network {
    pub name: String,
    pub addrs: Vec<NetworkAddrs>,
}
<commit_msg>Prevent panic if CPU measurement is lower in the future<commit_after>//! This module provides the data structures that represent system information.
//!
//! They're always the same across all platforms.

use std::io;
pub use std::time::Duration;
pub use std::net::{Ipv4Addr, Ipv6Addr};
pub use std::collections::BTreeMap;
pub use chrono::{DateTime, Utc, NaiveDateTime};
pub use bytesize::ByteSize;
use std::ops::Sub;

/// A wrapper for a measurement that takes time.
///
/// Time should pass between getting the object and calling .done() on it.
pub struct DelayedMeasurement<T> {
    res: Box<Fn() -> io::Result<T>>,
}

impl<T> DelayedMeasurement<T> {
    #[inline(always)]
    pub fn new(f: Box<Fn() -> io::Result<T>>) -> DelayedMeasurement<T> {
        DelayedMeasurement { res: f }
    }

    #[inline(always)]
    pub fn done(&self) -> io::Result<T> {
        (self.res)()
    }
}

#[derive(Debug, Clone)]
pub struct CPULoad {
    pub user: f32,
    pub nice: f32,
    pub system: f32,
    pub interrupt: f32,
    pub idle: f32,
}

impl CPULoad {
    #[inline(always)]
    pub fn avg_add(self, rhs: &Self) -> Self {
        CPULoad {
            user: (self.user + rhs.user) / 2.0,
            nice: (self.nice + rhs.nice) / 2.0,
            system: (self.system + rhs.system) / 2.0,
            interrupt: (self.interrupt + rhs.interrupt) / 2.0,
            idle: (self.idle + rhs.idle) / 2.0,
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct CpuTime {
    pub user: usize,
    pub nice: usize,
    pub system: usize,
    pub interrupt: usize,
    pub idle: usize,
    pub other: usize,
}

impl<'a> Sub<&'a CpuTime> for CpuTime {
    type Output = CpuTime;

    #[inline(always)]
    fn sub(self, rhs: &CpuTime) -> CpuTime {
        CpuTime {
            user: self.user.saturating_sub(rhs.user),
            nice: self.nice.saturating_sub(rhs.nice),
            system: self.system.saturating_sub(rhs.system),
            interrupt: self.interrupt.saturating_sub(rhs.interrupt),
            idle: self.idle.saturating_sub(rhs.idle),
            other: self.other.saturating_sub(rhs.other),
        }
    }
}

impl CpuTime {
    pub fn to_cpuload(&self) -> CPULoad {
        let total = self.user + self.nice + self.system + self.interrupt + self.idle + self.other;
        if total == 0 {
            CPULoad {
                user: 0.0,
                nice: 0.0,
                system: 0.0,
                interrupt: 0.0,
                idle: 0.0,
            }
        } else {
            CPULoad {
                user: self.user as f32 / total as f32,
                nice: self.nice as f32 / total as f32,
                system: self.system as f32 / total as f32,
                interrupt: self.interrupt as f32 / total as f32,
                idle: self.idle as f32 / total as f32,
            }
        }
    }
}

#[derive(Debug, Clone)]
pub struct LoadAverage {
    pub one: f32,
    pub five: f32,
    pub fifteen: f32,
}

#[cfg(target_os = "windows")]
#[derive(Debug, Clone)]
pub struct PlatformMemory {
    pub load: u32,
    pub total_phys: ByteSize,
    pub avail_phys: ByteSize,
    pub total_pagefile: ByteSize,
    pub avail_pagefile: ByteSize,
    pub total_virt: ByteSize,
    pub avail_virt: ByteSize,
    pub avail_ext: ByteSize,
}

#[cfg(target_os = "freebsd")]
#[derive(Debug, Clone)]
pub struct PlatformMemory {
    pub active: ByteSize,
    pub inactive: ByteSize,
    pub wired: ByteSize,
    pub cache: ByteSize,
    pub zfs_arc: ByteSize,
    pub free: ByteSize,
}

#[cfg(target_os = "openbsd")]
#[derive(Debug, Clone)]
pub struct PlatformMemory {
    pub active: ByteSize,
    pub inactive: ByteSize,
    pub wired: ByteSize,
    pub cache: ByteSize,
    pub free: ByteSize,
    pub paging: ByteSize,
}

#[cfg(target_os = "linux")]
#[derive(Debug, Clone)]
pub struct PlatformMemory {
    pub meminfo: BTreeMap<String, ByteSize>,
}

#[derive(Debug, Clone)]
pub struct Memory {
    pub total: ByteSize,
    pub free: ByteSize,
    pub platform_memory: PlatformMemory,
}

#[derive(Debug, Clone)]
pub struct BatteryLife {
    pub remaining_capacity: f32,
    pub remaining_time: Duration,
}

#[derive(Debug, Clone)]
pub struct Filesystem {
    pub files: usize,
    pub free: ByteSize,
    pub avail: ByteSize,
    pub total: ByteSize,
    pub name_max: usize,
    pub fs_type: String,
    pub fs_mounted_from: String,
    pub fs_mounted_on: String,
}

#[derive(Debug, Clone, PartialEq)]
pub enum IpAddr {
    Empty,
    Unsupported,
    V4(Ipv4Addr),
    V6(Ipv6Addr),
}

#[derive(Debug, Clone)]
pub struct NetworkAddrs {
    pub addr: IpAddr,
    pub netmask: IpAddr,
}

#[derive(Debug, Clone)]
pub struct Network {
    pub name: String,
    pub addrs: Vec<NetworkAddrs>,
}
<|endoftext|>


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

use serde::Serialize;
use serde::Serializer;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Visitor;
use serde::de::Error as SerdeError;
use chrono::naive::datetime::NaiveDateTime;

#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub struct Date(NaiveDateTime);

impl From<NaiveDateTime> for Date {

    fn from(ndt: NaiveDateTime) -> Date {
        Date(ndt)
    }

}

pub static TASKWARRIOR_DATETIME_TEMPLATE : &'static str = "%Y%m%dT%H%M%SZ";

impl Serialize for Date {

    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        serializer.serialize_str(&format!("{}", self.0))
    }

}

impl Deserialize for Date {

    fn deserialize<D>(deserializer: &mut D) -> Result<Date, D::Error>
        where D: Deserializer
    {
        struct DateVisitor;

        impl Visitor for DateVisitor {
            type Value = Date;

            fn visit_str<E>(&mut self, value: &str) -> Result<Date, E>
                where E: SerdeError
            {
                NaiveDateTime::parse_from_str(value, TASKWARRIOR_DATETIME_TEMPLATE)
                    .map(|d| Date(d))
                    .map_err(|e| SerdeError::custom(e.description()))
            }
        }

        deserializer.deserialize(DateVisitor)
    }

}
<commit_msg>Fix serialiation format<commit_after>use std::error::Error;

use serde::Serialize;
use serde::Serializer;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Visitor;
use serde::de::Error as SerdeError;
use chrono::naive::datetime::NaiveDateTime;

#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub struct Date(NaiveDateTime);

impl From<NaiveDateTime> for Date {

    fn from(ndt: NaiveDateTime) -> Date {
        Date(ndt)
    }

}

pub static TASKWARRIOR_DATETIME_TEMPLATE : &'static str = "%Y%m%dT%H%M%SZ";

impl Serialize for Date {

    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        let formatted = self.0.format(TASKWARRIOR_DATETIME_TEMPLATE);
        serializer.serialize_str(&format!("{}", formatted))
    }

}

impl Deserialize for Date {

    fn deserialize<D>(deserializer: &mut D) -> Result<Date, D::Error>
        where D: Deserializer
    {
        struct DateVisitor;

        impl Visitor for DateVisitor {
            type Value = Date;

            fn visit_str<E>(&mut self, value: &str) -> Result<Date, E>
                where E: SerdeError
            {
                NaiveDateTime::parse_from_str(value, TASKWARRIOR_DATETIME_TEMPLATE)
                    .map(|d| Date(d))
                    .map_err(|e| SerdeError::custom(e.description()))
            }
        }

        deserializer.deserialize(DateVisitor)
    }

}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[cfg(not(test))]
#[lang="stack_exhausted"]
#[no_split_stack]
extern fn stack_exhausted() {}

#[cfg(not(test))]
#[lang="eh_personality"]
#[no_split_stack]
extern fn eh_personality() {}

#[cfg(not(test))]
#[lang="begin_unwind"]
#[no_split_stack]
extern fn begin_unwind() {}
<commit_msg>Add fail_fmt language item<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use core::fmt::Arguments;

#[cfg(not(test))]
#[lang="stack_exhausted"]
#[no_split_stack]
extern fn stack_exhausted() {}

#[cfg(not(test))]
#[lang="eh_personality"]
#[no_split_stack]
extern fn eh_personality() {}

#[cfg(not(test))]
#[lang="begin_unwind"]
#[no_split_stack]
extern fn begin_unwind() {}

#[cfg(not(test))]
#[lang="fail_fmt"]
#[no_split_stack]
pub fn fail_fmt(fmt: &Arguments, file_line: &(&'static str, uint)) -> ! {
  loop { }
}
<|endoftext|>


<commit_before>// Copyright 2013 The noise-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std;
use std::num::{cast, Float};
use std::rand::Rng;

use {math, Quality};
use super::Source;

static DEFAULT_SEED : int = 0;
static DEFAULT_OCTAVE_COUNT : uint = 6;
static DEFAULT_FREQUENCY : f64 = 1.0;
static DEFAULT_LACUNARITY : f64 = 2.0;
static DEFAULT_EXPONENT : f64 = 1.0;
static DEFAULT_OFFSET : f64 = 1.0;
static DEFAULT_GAIN : f64 = 2.0;

#[deriving(Clone)]
pub struct RidgedMulti {
    pub seed: int,
    pub frequency: f64,
    pub quality: Quality,
    pub offset: f64,
    pub gain: f64,
    octaves: uint,
    lacunarity: f64,
    exponent: f64,
    spectral_weights: Vec<f64>,
}

impl RidgedMulti {
    pub fn new() -> RidgedMulti {
        RidgedMulti {
            seed: DEFAULT_SEED,
            octaves: DEFAULT_OCTAVE_COUNT,
            frequency: DEFAULT_FREQUENCY,
            quality: ::Quality::Fast,
            offset: DEFAULT_OFFSET,
            gain: DEFAULT_GAIN,
            lacunarity: DEFAULT_LACUNARITY,
            exponent: DEFAULT_EXPONENT,
            spectral_weights: Vec::new(),
        }.calc_spectral_weights()
    }

    pub fn seed(self, seed: int) -> RidgedMulti {
        RidgedMulti { seed: seed, ..self }
    }

    pub fn frequency(self, frequency: f64) -> RidgedMulti {
        RidgedMulti { frequency: frequency, ..self }
    }

    // Set a random seed
    pub fn random_seed(self) -> RidgedMulti {
        self.seed(std::rand::weak_rng().gen())
    }

    pub fn lacunarity(self, l: f64) -> RidgedMulti {
        RidgedMulti { lacunarity: l, ..self }.calc_spectral_weights()
    }

    pub fn exponent(self, e: f64) -> RidgedMulti {
        RidgedMulti{ exponent: e, ..self }.calc_spectral_weights()
    }

    pub fn octaves(self, o: uint) -> RidgedMulti {
        RidgedMulti{ octaves: o, ..self }.calc_spectral_weights()
    }

    fn calc_spectral_weights(self) -> RidgedMulti {
        let mut freq = 1.0f64;
        let spectral_weights = Vec::from_fn(self.octaves, |_| {
            let w = freq.powf(-self.exponent);
            freq *= self.lacunarity;
            w
        });
        RidgedMulti { spectral_weights: spectral_weights, ..self }
    }
}

impl Source for RidgedMulti {
    fn get<F:Float>(&self, x: F, y: F, z: F) -> F {
        let mut value : F = Float::zero();
        let mut weight : F = Float::one();

        let offset : F = cast(self.offset).unwrap();
        let gain = cast(self.gain).unwrap();
        let frequency = cast(self.frequency).unwrap();
        let lacunarity = cast(self.lacunarity).unwrap();

        let mut x = x * frequency;
        let mut y = y * frequency;
        let mut z = z * frequency;

        for i in range(0, self.octaves) {
            let seed = self.seed + i as int;

            let signal = ::gen::gradient_coherent_noise_3d(
                x.clone(),
                y.clone(),
                z.clone(), seed, self.quality);

            let signal = signal.abs();
            let signal = offset - signal;
            let signal = signal * signal;
            let signal = signal * weight;

            weight = math::clamp(signal * gain, Float::zero(), Float::one());

            value = value + (signal * cast(self.spectral_weights[i]).unwrap());

            x = x * lacunarity;
            y = y * lacunarity;
            z = z * lacunarity;

        }

        value - offset
    }
}
<commit_msg>Update for lastest Rust nightly.<commit_after>// Copyright 2013 The noise-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std;
use std::num::{cast, Float};
use std::rand::Rng;

use {math, Quality};
use super::Source;

static DEFAULT_SEED : int = 0;
static DEFAULT_OCTAVE_COUNT : uint = 6;
static DEFAULT_FREQUENCY : f64 = 1.0;
static DEFAULT_LACUNARITY : f64 = 2.0;
static DEFAULT_EXPONENT : f64 = 1.0;
static DEFAULT_OFFSET : f64 = 1.0;
static DEFAULT_GAIN : f64 = 2.0;

#[deriving(Clone)]
pub struct RidgedMulti {
    pub seed: int,
    pub frequency: f64,
    pub quality: Quality,
    pub offset: f64,
    pub gain: f64,
    octaves: uint,
    lacunarity: f64,
    exponent: f64,
    spectral_weights: Vec<f64>,
}

impl RidgedMulti {
    pub fn new() -> RidgedMulti {
        RidgedMulti {
            seed: DEFAULT_SEED,
            octaves: DEFAULT_OCTAVE_COUNT,
            frequency: DEFAULT_FREQUENCY,
            quality: ::Quality::Fast,
            offset: DEFAULT_OFFSET,
            gain: DEFAULT_GAIN,
            lacunarity: DEFAULT_LACUNARITY,
            exponent: DEFAULT_EXPONENT,
            spectral_weights: Vec::new(),
        }.calc_spectral_weights()
    }

    pub fn seed(self, seed: int) -> RidgedMulti {
        RidgedMulti { seed: seed, ..self }
    }

    pub fn frequency(self, frequency: f64) -> RidgedMulti {
        RidgedMulti { frequency: frequency, ..self }
    }

    // Set a random seed
    pub fn random_seed(self) -> RidgedMulti {
        self.seed(std::rand::weak_rng().gen())
    }

    pub fn lacunarity(self, l: f64) -> RidgedMulti {
        RidgedMulti { lacunarity: l, ..self }.calc_spectral_weights()
    }

    pub fn exponent(self, e: f64) -> RidgedMulti {
        RidgedMulti{ exponent: e, ..self }.calc_spectral_weights()
    }

    pub fn octaves(self, o: uint) -> RidgedMulti {
        RidgedMulti{ octaves: o, ..self }.calc_spectral_weights()
    }

    fn calc_spectral_weights(self) -> RidgedMulti {
        let mut freq = 1.0f64;
        let spectral_weights = range(0, self.octaves).map(|_| {
            let w = freq.powf(-self.exponent);
            freq *= self.lacunarity;
            w
        }).collect();
        RidgedMulti { spectral_weights: spectral_weights, ..self }
    }
}

impl Source for RidgedMulti {
    fn get<F:Float>(&self, x: F, y: F, z: F) -> F {
        let mut value : F = Float::zero();
        let mut weight : F = Float::one();

        let offset : F = cast(self.offset).unwrap();
        let gain = cast(self.gain).unwrap();
        let frequency = cast(self.frequency).unwrap();
        let lacunarity = cast(self.lacunarity).unwrap();

        let mut x = x * frequency;
        let mut y = y * frequency;
        let mut z = z * frequency;

        for i in range(0, self.octaves) {
            let seed = self.seed + i as int;

            let signal = ::gen::gradient_coherent_noise_3d(
                x.clone(),
                y.clone(),
                z.clone(), seed, self.quality);

            let signal = signal.abs();
            let signal = offset - signal;
            let signal = signal * signal;
            let signal = signal * weight;

            weight = math::clamp(signal * gain, Float::zero(), Float::one());

            value = value + (signal * cast(self.spectral_weights[i]).unwrap());

            x = x * lacunarity;
            y = y * lacunarity;
            z = z * lacunarity;

        }

        value - offset
    }
}
<|endoftext|>


<commit_before>use std::io::Error;
use std::net::SocketAddr;
use futures::{self, Future, BoxFuture};
use regex::Regex;
use fibers::net::TcpStream;
use handy_async::pattern::{Pattern, Endian};
use handy_async::pattern::combinators::BE;
use handy_async::pattern::read::{U8, U16, U32, All, Utf8, LengthPrefixedBytes};
use handy_async::io::{ReadFrom, WriteInto, ExternalSize, AsyncIoError};

pub const DEFAULT_EPMD_PORT: u16 = 4369;

const TAG_KILL_REQ: u8 = 107;
const TAG_PORT_PLEASE2_REQ: u8 = 122;
const TAG_PORT2_RESP: u8 = 119;
const TAG_NAMES_REQ: u8 = 110;
const TAG_DUMP_REQ: u8 = 100;
const TAG_ALIVE2_REQ: u8 = 120;
const TAG_ALIVE2_RESP: u8 = 121;

pub type Kill = BoxFuture<String, Error>;
pub type GetNodeInfo = BoxFuture<Option<NodeInfo>, Error>;
pub type Names = BoxFuture<Vec<Registered>, Error>;
pub type Dump = BoxFuture<String, Error>;
pub type Register = BoxFuture<Connection, Error>;

#[derive(Debug)]
pub struct Connection {
    socket: TcpStream,
    creation: u16,
}
impl Connection {
    pub fn creation(&self) -> u16 {
        self.creation
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Registered {
    pub name: String,
    pub port: u16,
}

#[derive(Debug)]
pub struct EpmdClient {
    server_addr: SocketAddr,
}
impl EpmdClient {
    pub fn new(server_addr: SocketAddr) -> Self {
        EpmdClient { server_addr: server_addr }
    }

    pub fn register(&self, node: NodeInfo) -> Register {
        self.with_connect(|socket| {
            futures::finished((socket, ()))
                .and_then(move |(socket, _)| {
                    let pattern = (TAG_ALIVE2_REQ,
                                   node.port.be(),
                                   node.node_type.as_u8(),
                                   node.protocol.as_u8(),
                                   node.highest_version.be(),
                                   node.lowest_version.be(),
                                   (node.name.len() as u16).be(),
                                   node.name,
                                   (node.extra.len() as u16).be(),
                                   node.extra);
                    request(pattern).write_into(socket)
                })
                .and_then(|(socket, _)| {
                    (U8.expect_eq(TAG_ALIVE2_RESP), U8, U16.be()).read_from(socket)
                })
                .and_then(|(socket, (_, result, creation))| {
                    if result != 0 {
                        let e = invalid_data!("ALVIE2 request failed: result={}", result);
                        Err(AsyncIoError::new(socket, e))
                    } else {
                        Ok((socket.clone(),
                            Connection {
                            socket: socket,
                            creation: creation,
                        }))
                    }
                })
        })
    }

    pub fn kill(&self) -> Kill {
        self.with_connect(|socket| {
            futures::finished((socket, ()))
                .and_then(|(socket, _)| request(TAG_KILL_REQ).write_into(socket))
                .and_then(|(socket, _)| Utf8(All).read_from(socket))
        })
    }
    pub fn get_node_addr(&self, node_name: &str) -> BoxFuture<Option<SocketAddr>, Error> {
        let ip = self.server_addr.ip();
        self.get_node_info(node_name)
            .map(move |info| info.map(|info| SocketAddr::new(ip, info.port)))
            .boxed()
    }
    pub fn get_node_info(&self, node_name: &str) -> GetNodeInfo {
        let name = node_name.to_string();
        self.with_connect(|socket| {
            futures::finished((socket, ()))
                .and_then(|(socket, _)| request((TAG_PORT_PLEASE2_REQ, name)).write_into(socket))
                .and_then(|(socket, _)| {
                    let info = (U16.be(),
                                U8,
                                U8,
                                U16.be(),
                                U16.be(),
                                Utf8(LengthPrefixedBytes(U16.be())),
                                LengthPrefixedBytes(U16.be()))
                        .map(|t| {
                            NodeInfo {
                                port: t.0,
                                node_type: From::from(t.1),
                                protocol: From::from(t.2),
                                highest_version: t.3,
                                lowest_version: t.4,
                                name: t.5,
                                extra: t.6,
                            }
                        });
                    let resp = (U8.expect_eq(TAG_PORT2_RESP), U8)
                        .and_then(|(_, result)| { if result == 0 { Some(info) } else { None } });
                    resp.read_from(socket)
                })
        })
    }
    pub fn get_names(&self) -> Names {
        self.with_connect(|socket| {
            futures::finished((socket, ()))
                .and_then(|(socket, _)| request(TAG_NAMES_REQ).write_into(socket))
                .and_then(|(socket, _)| (U32.be(), Utf8(All)).read_from(socket))
                .and_then(|(socket, (_epmd_port, info))| {
                    let re = Regex::new("name (.+) at port ([0-9]+)").unwrap();
                    let names = re.captures_iter(&info)
                        .map(|cap| {
                            Ok(Registered {
                                name: cap.at(1).unwrap().to_string(),
                                port: cap.at(2)
                                    .unwrap()
                                    .parse()
                                    .map_err(|e| invalid_data!("Invalid port number: {}", e))?,
                            })
                        })
                        .collect::<Result<_, _>>();
                    match names {
                        Ok(names) => Ok((socket, names)),
                        Err(e) => Err(AsyncIoError::new(socket, e)),
                    }
                })
        })
    }
    pub fn dump(&self) -> Dump {
        self.with_connect(|socket| {
            futures::finished((socket, ()))
                .and_then(|(socket, _)| request(TAG_DUMP_REQ).write_into(socket))
                .and_then(|(socket, _)| {
                    (U32.be(), Utf8(All)).map(|(_, dump)| dump).read_from(socket)
                })
        })
    }

    fn with_connect<F, T, R>(&self, f: F) -> BoxFuture<T, Error>
        where F: FnOnce(TcpStream) -> R + Send + 'static,
              R: Future<Item = (TcpStream, T), Error = AsyncIoError<TcpStream>> + Send + 'static
    {
        TcpStream::connect(self.server_addr.clone())
            .and_then(|socket| f(socket).map(|(_, v)| v).map_err(|e| e.into_error()))
            .boxed()
    }
}

#[derive(Debug, Clone)]
pub struct NodeInfo {
    pub name: String,
    pub port: u16,
    pub node_type: NodeType,
    pub protocol: Protocol,
    pub highest_version: u16,
    pub lowest_version: u16,
    pub extra: Vec<u8>,
}
impl NodeInfo {
    pub fn new(name: &str, port: u16) -> Self {
        NodeInfo {
            name: name.to_string(),
            port: port,
            node_type: NodeType::Normal,
            protocol: Protocol::TcpIpV4,
            highest_version: 5,
            lowest_version: 5,
            extra: Vec::new(),
        }
    }
    pub fn set_hidden(&mut self) -> &mut Self {
        self.node_type = NodeType::Hidden;
        self
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Protocol {
    TcpIpV4,
    Unknown(u8),
}
impl Protocol {
    fn as_u8(&self) -> u8 {
        match *self {
            Protocol::TcpIpV4 => 0,
            Protocol::Unknown(b) => b,
        }
    }
}
impl From<u8> for Protocol {
    fn from(f: u8) -> Self {
        match f {
            0 => Protocol::TcpIpV4,
            _ => Protocol::Unknown(f),
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NodeType {
    Hidden,
    Normal,
    Unknown(u8),
}
impl NodeType {
    fn as_u8(&self) -> u8 {
        match *self {
            NodeType::Hidden => 72,
            NodeType::Normal => 77,
            NodeType::Unknown(b) => b,
        }
    }
}
impl From<u8> for NodeType {
    fn from(f: u8) -> Self {
        match f {
            72 => NodeType::Hidden,
            77 => NodeType::Normal,
            _ => NodeType::Unknown(f),
        }
    }
}

fn request<P: ExternalSize>(pattern: P) -> (BE<u16>, P) {
    ((pattern.external_size() as u16).be(), pattern)
}
<commit_msg>Rewrite epmd module<commit_after>//! EPMD protocol implementations.
//!
//! "EPMD" stands for "Erlang Port Mapper Daemon" and
//! it provides name resolution functionalities for distributed erlang nodes.
//!
//! See [12.1 EPMD Protocol](http://erlang.org/doc/apps/erts/erl_dist_protocol.html#id103099)
//! for more details about EPMD protocol.
use std::io::{Read, Write, Error};
use futures::{self, Future, BoxFuture};
use handy_async::pattern::{Pattern, Endian};
use handy_async::pattern::combinators::BE;
use handy_async::pattern::read::{U8, U16, U32, All, Utf8, LengthPrefixedBytes};
use handy_async::io::{ReadFrom, WriteInto, ExternalSize};

use Creation;

/// The default listening port of the EPMD.
pub const DEFAULT_EPMD_PORT: u16 = 4369;

const TAG_KILL_REQ: u8 = 107;
const TAG_PORT_PLEASE2_REQ: u8 = 122;
const TAG_PORT2_RESP: u8 = 119;
const TAG_NAMES_REQ: u8 = 110;
const TAG_DUMP_REQ: u8 = 100;
const TAG_ALIVE2_REQ: u8 = 120;
const TAG_ALIVE2_RESP: u8 = 121;

/// EPMD client.
///
/// This implements the client side of the EPMD protocol.
///
/// # Examples
///
/// Queries the information of the "foo" node:
///
/// ```no_run
/// # extern crate erl_dist;
/// # extern crate fibers;
/// # extern crate futures;
/// use fibers::{Executor, InPlaceExecutor};
/// use fibers::net::TcpStream;
/// use futures::Future;
/// use erl_dist::epmd::{DEFAULT_EPMD_PORT, EpmdClient};
///
/// # fn main() {
/// let epmd_addr = format!("127.0.0.1:{}", DEFAULT_EPMD_PORT).parse().unwrap();
/// let target_node = "foo";
/// let mut executor = InPlaceExecutor::new().unwrap();
///
/// // Queries the node information asynchronously.
/// let monitor = executor.spawn_monitor(TcpStream::connect(epmd_addr)
///     .and_then(move |socket| EpmdClient::new().get_node_info(socket, target_node)));
/// let result = executor.run_fiber(monitor).unwrap();
///
/// match result {
///     Err(e) => println!("Failed: {}", e),
///     Ok(None) => println!("Not found:"),
///     Ok(Some(info)) => println!("Found: {:?}", info),
/// }
/// # }
/// ```
///
/// See [epmd_cli.rs](https://github.com/sile/erl_dist/blob/master/examples/epmd_cli.rs) file
/// for more comprehensive examples.
#[derive(Debug)]
pub struct EpmdClient {
    _dummy: (),
}
impl EpmdClient {
    /// Makes a new `EpmdClient` instance.
    pub fn new() -> Self {
        EpmdClient { _dummy: () }
    }

    /// Registers a node in the EPMD connected by `stream`.
    ///
    /// The connection created to the EPMD must be kept as long as the node is a distributed node.
    /// When the connection is closed, the node is automatically unregistered from the EPMD.
    ///
    /// # Note
    ///
    /// For executing asynchronously, we assume that `stream` returns
    /// the `std::io::ErrorKind::WouldBlock` error if an I/O operation would be about to block.
    pub fn register<S>(&self, stream: S, node: NodeInfo) -> BoxFuture<(S, Creation), Error>
        where S: Read + Write + Send + 'static
    {
        futures::finished(stream)
            .and_then(move |stream| {
                let req = (TAG_ALIVE2_REQ,
                           node.port.be(),
                           node.node_type.as_u8(),
                           node.protocol.as_u8(),
                           node.highest_version.be(),
                           node.lowest_version.be(),
                           ((node.name.len() as u16).be(), node.name),
                           ((node.extra.len() as u16).be(), node.extra));
                with_len(req).write_into(stream)
            })
            .and_then(|(stream, _)| {
                let to_creation = |c| {
                    Creation::from_u16(c).ok_or_else(|| invalid_data!("Too large creation: {}", c))
                };
                (U8.expect_eq(TAG_ALIVE2_RESP), U8.expect_eq(0), U16.be().and_then(to_creation))
                    .read_from(stream)
            })
            .map(|(stream, (_, _, creation))| (stream, creation))
            .map_err(|e| e.into_error())
            .boxed()
    }

    /// Queries the distribution port (and other information) of
    /// the `node_name` node to the EPMD connected by `stream`.
    ///
    /// If the node has not been registered in the EPMD, this will return `None`.
    ///
    /// # Note
    ///
    /// For executing asynchronously, we assume that `stream` returns
    /// the `std::io::ErrorKind::WouldBlock` error if an I/O operation would be about to block.
    pub fn get_node_info<S>(&self, stream: S, node_name: &str) -> BoxFuture<Option<NodeInfo>, Error>
        where S: Read + Write + Send + 'static
    {
        let name = node_name.to_string();
        futures::finished((stream, ()))
            .and_then(|(stream, _)| with_len((TAG_PORT_PLEASE2_REQ, name)).write_into(stream))
            .and_then(|(stream, _)| {
                let info = (U16.be(),
                            U8,
                            U8,
                            U16.be(),
                            U16.be(),
                            Utf8(LengthPrefixedBytes(U16.be())),
                            LengthPrefixedBytes(U16.be()))
                    .map(|t| {
                        NodeInfo {
                            port: t.0,
                            node_type: NodeType::from(t.1),
                            protocol: Protocol::from(t.2),
                            highest_version: t.3,
                            lowest_version: t.4,
                            name: t.5,
                            extra: t.6,
                        }
                    });
                let resp = (U8.expect_eq(TAG_PORT2_RESP), U8)
                    .and_then(|(_, result)| { if result == 0 { Some(info) } else { None } });
                resp.read_from(stream)
            })
            .map(|(_, info)| info)
            .map_err(|e| e.into_error())
            .boxed()
    }

    /// Kills the EPMD connected by `stream`.
    ///
    /// This request kills the running EPMD.
    /// It is almost never used.
    ///
    /// If the EPMD is killed, it will returns `"OK"`.
    ///
    /// # Note
    ///
    /// For executing asynchronously, we assume that `stream` returns
    /// the `std::io::ErrorKind::WouldBlock` error if an I/O operation would be about to block.
    pub fn kill<S>(&self, stream: S) -> BoxFuture<String, Error>
        where S: Read + Write + Send + 'static
    {
        futures::finished((stream, ()))
            .and_then(|(stream, _)| with_len(TAG_KILL_REQ).write_into(stream))
            .and_then(|(stream, _)| Utf8(All).read_from(stream))
            .map(|(_, v)| v)
            .map_err(|e| e.into_error())
            .boxed()
    }

    /// Gets all registered names from the EPMD connected by `stream`.
    ///
    /// The result value is a string written for each active node.
    /// The format of each entry is `"name ${NODE_NAME} at port ${PORT}\n"`.
    ///
    /// # Note
    ///
    /// For executing asynchronously, we assume that `stream` returns
    /// the `std::io::ErrorKind::WouldBlock` error if an I/O operation would be about to block.
    pub fn get_names<S>(&self, stream: S) -> BoxFuture<String, Error>
        where S: Read + Write + Send + 'static
    {
        futures::finished((stream, ()))
            .and_then(|(stream, _)| with_len(TAG_NAMES_REQ).write_into(stream))
            .and_then(|(stream, _)| (U32.be(), Utf8(All)).read_from(stream))
            .map(|(_, (_, names))| names)
            .map_err(|e| e.into_error())
            .boxed()
    }

    /// Dumps all data from the EPMD connected by `stream`.
    ///
    /// This request is not really used, it is to be regarded as a debug feature.
    ///
    /// The result value is a string written for each node kept in the EPMD.
    ///
    /// The format of each entry is
    ///
    /// ```shell
    /// "active name ${NODE_NAME} at port ${PORT}, fd = ${FD}\n"
    /// ```
    ///
    /// or
    ///
    /// ```shell
    /// "old/unused name ${NODE_NAME} at port ${PORT}, fd = ${FD}\n"
    /// ```
    ///
    /// # Note
    ///
    /// For executing asynchronously, we assume that `stream` returns
    /// the `std::io::ErrorKind::WouldBlock` error if an I/O operation would be about to block.
    pub fn dump<S>(&self, stream: S) -> BoxFuture<String, Error>
        where S: Read + Write + Send + 'static
    {
        futures::finished((stream, ()))
            .and_then(|(stream, _)| with_len(TAG_DUMP_REQ).write_into(stream))
            .and_then(|(stream, _)| (U32.be(), Utf8(All)).read_from(stream))
            .map(|(_, (_, dump))| dump)
            .map_err(|e| e.into_error())
            .boxed()
    }
}

/// Information on a distributed node that registered in the EPMD.
#[derive(Debug, Clone)]
pub struct NodeInfo {
    /// The node name.
    pub name: String,

    /// The port number on which the node accept connection requests.
    pub port: u16,

    /// The node type.
    pub node_type: NodeType,

    /// The protocol for communicating with the node.
    pub protocol: Protocol,

    /// The highest distribution version that this node can handle.
    ///
    /// The value in Erlang/OTP R6B and later is 5.
    pub highest_version: u16,

    /// The lowest distribution version that this node can handle.
    ///
    /// The value in Erlang/OTP R6B and later is 5.
    pub lowest_version: u16,

    /// Extra field.
    pub extra: Vec<u8>,
}
impl NodeInfo {
    /// Makes a new `NodeInfo` with the default parameters.
    ///
    /// This is equivalent to the following code:
    ///
    /// ```
    /// # use erl_dist::epmd::{NodeInfo, NodeType, Protocol};
    /// # let name = "foo";
    /// # let port = 0;
    /// NodeInfo {
    ///     name: name.to_string(),
    ///     port: port,
    ///     node_type: NodeType::Normal,
    ///     protocol: Protocol::TcpIpV4,
    ///     highest_version: 5,
    ///     lowest_version: 5,
    ///     extra: Vec::new(),
    /// }
    /// # ;
    /// ```
    pub fn new(name: &str, port: u16) -> Self {
        NodeInfo {
            name: name.to_string(),
            port: port,
            node_type: NodeType::Normal,
            protocol: Protocol::TcpIpV4,
            highest_version: 5,
            lowest_version: 5,
            extra: Vec::new(),
        }
    }

    /// Sets the node type of this `NodeInfo` to `Hidden`.
    pub fn set_hidden(&mut self) -> &mut Self {
        self.node_type = NodeType::Hidden;
        self
    }
}

/// Protocol for communicating with a distributed node.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Protocol {
    /// TCP/IPv4.
    TcpIpV4,

    /// Unknown protocol.
    Unknown(u8),
}
impl Protocol {
    fn as_u8(&self) -> u8 {
        match *self {
            Protocol::TcpIpV4 => 0,
            Protocol::Unknown(b) => b,
        }
    }
}
impl From<u8> for Protocol {
    fn from(f: u8) -> Self {
        match f {
            0 => Protocol::TcpIpV4,
            _ => Protocol::Unknown(f),
        }
    }
}

/// Type of a distributed node.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NodeType {
    /// Hidden node (C-node).
    Hidden,

    /// Normal Erlang node.
    Normal,

    /// Unknown node type.
    Unknown(u8),
}
impl NodeType {
    fn as_u8(&self) -> u8 {
        match *self {
            NodeType::Hidden => 72,
            NodeType::Normal => 77,
            NodeType::Unknown(b) => b,
        }
    }
}
impl From<u8> for NodeType {
    fn from(f: u8) -> Self {
        match f {
            72 => NodeType::Hidden,
            77 => NodeType::Normal,
            _ => NodeType::Unknown(f),
        }
    }
}

fn with_len<P: ExternalSize>(pattern: P) -> (BE<u16>, P) {
    ((pattern.external_size() as u16).be(), pattern)
}
<|endoftext|>