<commit_before>#![crate_name = "xpath"]
#![feature(macro_rules)]
#![feature(phase)]
#![feature(globs)]

#[phase(plugin, link)]
extern crate document;

use self::Value::*;
use self::nodeset::Nodeset;
use self::nodeset::{Node,ToNode};

use std::collections::HashMap;
use std::string;
use std::num::Float;

use tokenizer::{Tokenizer,TokenDeabbreviator};
use parser::Parser;

pub mod macros;
pub mod nodeset;
pub mod axis;
pub mod expression;
pub mod function;
mod node_test;
pub mod parser;
mod token;
pub mod tokenizer;

#[deriving(PartialEq,Show,Clone)]
pub enum Value<'d> {
    Boolean(bool),
    Number(f64),
    String(string::String),
    Nodes(Nodeset<'d>), // rename as Nodeset
}

impl<'d> Value<'d> {
    pub fn boolean(&self) -> bool {
        match *self {
            Boolean(val) => val,
            Number(n) => n != 0.0 && ! n.is_nan(),
            String(ref s) => ! s.is_empty(),
            Nodes(ref nodeset) => nodeset.size() > 0,
        }
    }

    pub fn number(&self) -> f64 {
        match *self {
            Number(val) => val,
            String(ref s) => s.trim().parse().unwrap_or(Float::nan()),
            _ => unimplemented!(),
        }
    }

    pub fn string(&self) -> string::String {
        match *self {
            String(ref val) => val.clone(),
            _ => unimplemented!(),
        }
    }

    pub fn nodeset(&self) -> Nodeset<'d> {
        match *self {
            Nodes(ref ns) => ns.clone(),
            _ => panic!("Did not evaluate to a nodeset!"),
        }
    }
}

trait StringValue {
    fn string_value(&self) -> string::String;
}

fn text_descendants_string_value(node: &Node) -> string::String {
    fn document_order_text_nodes(node: &Node, result: &mut string::String) {
        for child in node.children().iter() {
            match child {
                &Node::ElementNode(_) => document_order_text_nodes(child, result),
                &Node::TextNode(n) => result.push_str(n.text()),
                _ => {},
            }
        }
    };

    let mut result = string::String::new();
    document_order_text_nodes(node, &mut result);
    result
}

impl<'d> StringValue for Node<'d> {
    fn string_value(&self) -> string::String {
        match self {
            &Node::RootNode(_) => text_descendants_string_value(self),
            &Node::ElementNode(_) => text_descendants_string_value(self),
            &Node::AttributeNode(n) => string::String::from_str(n.value()),
            &Node::ProcessingInstructionNode(n) => string::String::from_str(n.value().unwrap_or("")),
            &Node::CommentNode(n) => string::String::from_str(n.text()),
            &Node::TextNode(n) => string::String::from_str(n.text()),
        }
    }
}

pub trait Function {
    fn evaluate<'a, 'd>(&self,
                        context: &EvaluationContext<'a, 'd>,
                        args: Vec<Value<'d>>) -> Value<'d>;
}

type BoxFunc = Box<Function + 'static>;
pub type Functions = HashMap<string::String, BoxFunc>;
pub type Variables<'d> = HashMap<string::String, Value<'d>>;
pub type Namespaces = HashMap<string::String, string::String>;

pub struct EvaluationContext<'a, 'd : 'a> {
    node: Node<'d>,
    functions: &'a Functions,
    variables: &'a Variables<'d>,
    namespaces: &'a Namespaces,
    position: uint,
}

impl<'a, 'd> EvaluationContext<'a, 'd> {
    pub fn new<N>(node: N,
                  functions: &'a Functions,
                  variables: &'a Variables<'d>,
                  namespaces: &'a Namespaces)
                  -> EvaluationContext<'a, 'd>
        where N: ToNode<'d>
    {
        EvaluationContext {
            node: node.to_node(),
            functions: functions,
            variables: variables,
            namespaces: namespaces,
            position: 0,
        }
    }

    fn new_context_for(&self, _size: uint) -> EvaluationContext<'a, 'd> {
        EvaluationContext {
            node: self.node,
            functions: self.functions,
            variables: self.variables,
            namespaces: self.namespaces,
            position: 0,
        }
    }

    pub fn next<N: ToNode<'d>>(&mut self, node: N) {
        self.node = node.to_node();
        self.position += 1;
    }

    fn position(&self) -> uint {
        self.position
    }

    fn function_for_name(&self, name: &str) -> Option<&'a BoxFunc> {
        self.functions.get(&name.to_string())
    }

    fn value_of(&self, name: &str) -> Option<&Value<'d>> {
        self.variables.get(&name.to_string())
    }

    fn namespace_for(&self, prefix: &str) -> Option<&str> {
        self.namespaces.get(prefix).map(|ns| ns.as_slice())
    }
}

pub struct Factory {
    parser: Parser,
}

impl Factory {
    pub fn new() -> Factory {
        Factory { parser: Parser::new() }
    }

    pub fn build(&self, xpath: &str) -> parser::ParseResult {
        let tokenizer = Tokenizer::new(xpath);
        let deabbreviator = TokenDeabbreviator::new(tokenizer);

        self.parser.parse(deabbreviator)
    }
}

#[doc(hidden)]
mod xpath {
    pub use nodeset;
}

#[cfg(test)]
mod test {
    use document::Package;
    use super::nodeset::ToNode;
    use super::StringValue;
    use super::Value;
    use std::num::Float;

    #[test]
    fn string_value_of_element_node_is_concatenation_of_descendant_text_nodes() {
        let package = Package::new();
        let doc = package.as_document();

        let element = doc.create_element("hello");
        let child = doc.create_element("world");
        let text1 = doc.create_text("Presenting: ");
        let text2 = doc.create_text("Earth");
        let text3 = doc.create_text("!");

        element.append_child(text1);
        element.append_child(child);
        child.append_child(text2);
        element.append_child(text3);

        assert_eq!("Presenting: Earth!", element.to_node().string_value().as_slice());
    }

    #[test]
    fn string_value_of_attribute_node_is_value() {
        let package = Package::new();
        let doc = package.as_document();
        let element = doc.create_element("hello");
        let attribute = element.set_attribute_value("world", "Earth").to_node();
        assert_eq!("Earth", attribute.string_value().as_slice());
    }

    #[test]
    fn string_value_of_pi_node_is_empty_when_no_value() {
        let package = Package::new();
        let doc = package.as_document();
        let pi = doc.create_processing_instruction("hello", None).to_node();
        assert_eq!("", pi.string_value().as_slice());
    }

    #[test]
    fn string_value_of_pi_node_is_the_value_when_value() {
        let package = Package::new();
        let doc = package.as_document();
        let pi = doc.create_processing_instruction("hello", Some("world")).to_node();
        assert_eq!("world", pi.string_value().as_slice());
    }

    #[test]
    fn string_value_of_comment_node_is_the_text() {
        let package = Package::new();
        let doc = package.as_document();
        let comment = doc.create_comment("hello world").to_node();
        assert_eq!("hello world", comment.string_value().as_slice());
    }

    #[test]
    fn string_value_of_text_node_is_the_text() {
        let package = Package::new();
        let doc = package.as_document();
        let text = doc.create_text("hello world").to_node();
        assert_eq!("hello world", text.string_value().as_slice());
    }

    #[test]
    fn number_of_string_is_ieee_754_number() {
        let v = Value::String("1.5".to_string());
        assert_eq!(1.5, v.number());
    }

    #[test]
    fn number_of_string_with_negative_is_negative_number() {
        let v = Value::String("-1.5".to_string());
        assert_eq!(-1.5, v.number());
    }

    #[test]
    fn number_of_string_with_surrounding_whitespace_is_number_without_whitespace() {
        let v = Value::String("\r\n1.5 \t".to_string());
        assert_eq!(1.5, v.number());
    }

    #[test]
    fn number_of_garbage_string_is_nan() {
        let v = Value::String("I am not an IEEE 754 number".to_string());
        assert!(v.number().is_nan());
    }
}
<commit_msg>Value::number conversion for boolean<commit_after>#![crate_name = "xpath"]
#![feature(macro_rules)]
#![feature(phase)]
#![feature(globs)]

#[phase(plugin, link)]
extern crate document;

use self::Value::*;
use self::nodeset::Nodeset;
use self::nodeset::{Node,ToNode};

use std::collections::HashMap;
use std::string;
use std::num::Float;

use tokenizer::{Tokenizer,TokenDeabbreviator};
use parser::Parser;

pub mod macros;
pub mod nodeset;
pub mod axis;
pub mod expression;
pub mod function;
mod node_test;
pub mod parser;
mod token;
pub mod tokenizer;

#[deriving(PartialEq,Show,Clone)]
pub enum Value<'d> {
    Boolean(bool),
    Number(f64),
    String(string::String),
    Nodes(Nodeset<'d>), // rename as Nodeset
}

impl<'d> Value<'d> {
    pub fn boolean(&self) -> bool {
        match *self {
            Boolean(val) => val,
            Number(n) => n != 0.0 && ! n.is_nan(),
            String(ref s) => ! s.is_empty(),
            Nodes(ref nodeset) => nodeset.size() > 0,
        }
    }

    pub fn number(&self) -> f64 {
        match *self {
            Number(val) => val,
            String(ref s) => s.trim().parse().unwrap_or(Float::nan()),
            Boolean(val) => if val { 1.0 } else { 0.0 },
            _ => unimplemented!(),
        }
    }

    pub fn string(&self) -> string::String {
        match *self {
            String(ref val) => val.clone(),
            _ => unimplemented!(),
        }
    }

    pub fn nodeset(&self) -> Nodeset<'d> {
        match *self {
            Nodes(ref ns) => ns.clone(),
            _ => panic!("Did not evaluate to a nodeset!"),
        }
    }
}

trait StringValue {
    fn string_value(&self) -> string::String;
}

fn text_descendants_string_value(node: &Node) -> string::String {
    fn document_order_text_nodes(node: &Node, result: &mut string::String) {
        for child in node.children().iter() {
            match child {
                &Node::ElementNode(_) => document_order_text_nodes(child, result),
                &Node::TextNode(n) => result.push_str(n.text()),
                _ => {},
            }
        }
    };

    let mut result = string::String::new();
    document_order_text_nodes(node, &mut result);
    result
}

impl<'d> StringValue for Node<'d> {
    fn string_value(&self) -> string::String {
        match self {
            &Node::RootNode(_) => text_descendants_string_value(self),
            &Node::ElementNode(_) => text_descendants_string_value(self),
            &Node::AttributeNode(n) => string::String::from_str(n.value()),
            &Node::ProcessingInstructionNode(n) => string::String::from_str(n.value().unwrap_or("")),
            &Node::CommentNode(n) => string::String::from_str(n.text()),
            &Node::TextNode(n) => string::String::from_str(n.text()),
        }
    }
}

pub trait Function {
    fn evaluate<'a, 'd>(&self,
                        context: &EvaluationContext<'a, 'd>,
                        args: Vec<Value<'d>>) -> Value<'d>;
}

type BoxFunc = Box<Function + 'static>;
pub type Functions = HashMap<string::String, BoxFunc>;
pub type Variables<'d> = HashMap<string::String, Value<'d>>;
pub type Namespaces = HashMap<string::String, string::String>;

pub struct EvaluationContext<'a, 'd : 'a> {
    node: Node<'d>,
    functions: &'a Functions,
    variables: &'a Variables<'d>,
    namespaces: &'a Namespaces,
    position: uint,
}

impl<'a, 'd> EvaluationContext<'a, 'd> {
    pub fn new<N>(node: N,
                  functions: &'a Functions,
                  variables: &'a Variables<'d>,
                  namespaces: &'a Namespaces)
                  -> EvaluationContext<'a, 'd>
        where N: ToNode<'d>
    {
        EvaluationContext {
            node: node.to_node(),
            functions: functions,
            variables: variables,
            namespaces: namespaces,
            position: 0,
        }
    }

    fn new_context_for(&self, _size: uint) -> EvaluationContext<'a, 'd> {
        EvaluationContext {
            node: self.node,
            functions: self.functions,
            variables: self.variables,
            namespaces: self.namespaces,
            position: 0,
        }
    }

    pub fn next<N: ToNode<'d>>(&mut self, node: N) {
        self.node = node.to_node();
        self.position += 1;
    }

    fn position(&self) -> uint {
        self.position
    }

    fn function_for_name(&self, name: &str) -> Option<&'a BoxFunc> {
        self.functions.get(&name.to_string())
    }

    fn value_of(&self, name: &str) -> Option<&Value<'d>> {
        self.variables.get(&name.to_string())
    }

    fn namespace_for(&self, prefix: &str) -> Option<&str> {
        self.namespaces.get(prefix).map(|ns| ns.as_slice())
    }
}

pub struct Factory {
    parser: Parser,
}

impl Factory {
    pub fn new() -> Factory {
        Factory { parser: Parser::new() }
    }

    pub fn build(&self, xpath: &str) -> parser::ParseResult {
        let tokenizer = Tokenizer::new(xpath);
        let deabbreviator = TokenDeabbreviator::new(tokenizer);

        self.parser.parse(deabbreviator)
    }
}

#[doc(hidden)]
mod xpath {
    pub use nodeset;
}

#[cfg(test)]
mod test {
    use document::Package;
    use super::nodeset::ToNode;
    use super::StringValue;
    use super::Value;
    use std::num::Float;

    #[test]
    fn string_value_of_element_node_is_concatenation_of_descendant_text_nodes() {
        let package = Package::new();
        let doc = package.as_document();

        let element = doc.create_element("hello");
        let child = doc.create_element("world");
        let text1 = doc.create_text("Presenting: ");
        let text2 = doc.create_text("Earth");
        let text3 = doc.create_text("!");

        element.append_child(text1);
        element.append_child(child);
        child.append_child(text2);
        element.append_child(text3);

        assert_eq!("Presenting: Earth!", element.to_node().string_value().as_slice());
    }

    #[test]
    fn string_value_of_attribute_node_is_value() {
        let package = Package::new();
        let doc = package.as_document();
        let element = doc.create_element("hello");
        let attribute = element.set_attribute_value("world", "Earth").to_node();
        assert_eq!("Earth", attribute.string_value().as_slice());
    }

    #[test]
    fn string_value_of_pi_node_is_empty_when_no_value() {
        let package = Package::new();
        let doc = package.as_document();
        let pi = doc.create_processing_instruction("hello", None).to_node();
        assert_eq!("", pi.string_value().as_slice());
    }

    #[test]
    fn string_value_of_pi_node_is_the_value_when_value() {
        let package = Package::new();
        let doc = package.as_document();
        let pi = doc.create_processing_instruction("hello", Some("world")).to_node();
        assert_eq!("world", pi.string_value().as_slice());
    }

    #[test]
    fn string_value_of_comment_node_is_the_text() {
        let package = Package::new();
        let doc = package.as_document();
        let comment = doc.create_comment("hello world").to_node();
        assert_eq!("hello world", comment.string_value().as_slice());
    }

    #[test]
    fn string_value_of_text_node_is_the_text() {
        let package = Package::new();
        let doc = package.as_document();
        let text = doc.create_text("hello world").to_node();
        assert_eq!("hello world", text.string_value().as_slice());
    }

    #[test]
    fn number_of_string_is_ieee_754_number() {
        let v = Value::String("1.5".to_string());
        assert_eq!(1.5, v.number());
    }

    #[test]
    fn number_of_string_with_negative_is_negative_number() {
        let v = Value::String("-1.5".to_string());
        assert_eq!(-1.5, v.number());
    }

    #[test]
    fn number_of_string_with_surrounding_whitespace_is_number_without_whitespace() {
        let v = Value::String("\r\n1.5 \t".to_string());
        assert_eq!(1.5, v.number());
    }

    #[test]
    fn number_of_garbage_string_is_nan() {
        let v = Value::String("I am not an IEEE 754 number".to_string());
        assert!(v.number().is_nan());
    }

    #[test]
    fn number_of_boolean_true_is_1() {
        let v = Value::Boolean(true);
        assert_eq!(1.0, v.number());
    }

    #[test]
    fn number_of_boolean_false_is_0() {
        let v = Value::Boolean(false);
        assert_eq!(0.0, v.number());
    }
}
<|endoftext|>


<commit_before>#![feature(old_io)]

extern crate "rustc-serialize" as rustc_serialize;
extern crate hyper;
extern crate mime;
extern crate url;

use hyper::Url;
use hyper::header::{ Accept, Authorization, ContentType, UserAgent, qitem };
use hyper::method::Method;
use mime::{ Attr, Mime, Value };
use mime::TopLevel::Application;
use mime::SubLevel::Json;
use rustc_serialize::{ Decoder, Decodable, json };
use std::old_io::IoError;
use std::result;

pub type Result<T> = result::Result<T, IoError>;

pub struct Client {
  host: String,
  token: Option<String>
}

#[derive(RustcDecodable)]
struct Status {
  ok: bool
}

#[derive(RustcDecodable)]
struct Following {
  following: bool
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct User {
  pub id: u32,
  pub login: String,
  pub avatar: String,
  pub email: Option<String>,
  pub name: Option<String>,
}

#[derive(RustcDecodable)]
struct Users {
  users: Vec<User>
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Crate {
  pub name: String,
  pub description: Option<String>,
  pub max_version: String
}

// RustcDecodable be derived because the key used in json is `crate`,
// a reserved word
struct CrateReq {
  krate: Crate
}

impl Decodable for CrateReq {
  fn decode<D: Decoder>(d: &mut D) -> result::Result<CrateReq, D::Error> {
    d.read_struct("CrateReq", 1usize, |_d| {
      Ok(CrateReq {
        krate: try!(_d.read_struct_field("crate", 0usize, |_d| Decodable::decode(_d)))
      })
    })
  }
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Download {
  pub date: String,
  pub downloads: u32
}

#[derive(RustcDecodable)]
struct VersionDownloads {
  version_downloads: Vec<Download>
}

#[derive(RustcDecodable)]
struct ExtraDownloads {
  extra_downloads: Vec<Download>
}

#[derive(RustcDecodable)]
struct MetaDownloads {
  meta: ExtraDownloads
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Dependency {
  pub crate_id: String,
  pub default_features: bool,
  pub features: String,
  pub kind: String,
  pub optional: bool,
  pub req: String
}

#[derive(RustcDecodable)]
struct Dependencies {
  dependencies: Vec<Dependency>
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Version {
  // crate: String,
  pub created_at: String,
  pub dl_path: String,
  pub downloads: u32,
  pub num: String,
  pub updated_at: String,
  pub yanked: bool
}

#[derive(RustcDecodable)]
struct VersionReq {
  version: Version
}

#[derive(RustcDecodable)]
struct Versions {
  versions: Vec<Version>
}

#[derive(RustcDecodable)]
struct Meta {
  names: Vec<String>
}

#[derive(RustcDecodable)]
struct Authors {
  meta: Meta
}

#[derive(RustcEncodable)]
pub struct OwnersReq<'a> {
  users: &'a [&'a str]
}

#[derive(RustcDecodable)]
struct Crates {
  crates: Vec<Crate>
}

impl Client {
  pub fn new() -> Client {
    Client::host("https://crates.io")
  }

  pub fn host(addr: &str) -> Client {
    Client { host: addr.to_string(), token: None }
  }

  pub fn token(self, auth: &str) -> Client {
    Client {
      host: self.host,
      token: Some(auth.to_string())
    }
  }

  // todo: soft (downloads|name), by letter/keyword/user_id/following
  pub fn find(&mut self, query: &str) -> Result<Vec<Crate>> {
    let body = try!(self.get(format!("/crates?q={}&sort={}", query, "name")));
    Ok(json::decode::<Crates>(&body).unwrap().crates)
  }

  pub fn named(&mut self, name: &str) -> Result<Crate> { // can't decode this automagically because it contains the key "crate"!
    let body = try!(self.get(format!("/crates/{}", name)));
    Ok(json::decode::<CrateReq>(&body).unwrap().krate)
  }

  // todo: publish -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L76

  pub fn version(&mut self, name: &str, version: &str) -> Result<Version> {
    let body = try!(self.get(format!("/crates/{}/{}", name, version)));
    Ok(json::decode::<VersionReq>(&body).unwrap().version)
  }

  // todo: version download -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L78

  pub fn dependencies(&mut self, name: &str, version: &str) -> Result<Vec<Dependency>> {
    let body = try!(self.get(format!("/crates/{}/{}/dependencies", name, version)));
    Ok(json::decode::<Dependencies>(&body).unwrap().dependencies)
  }

  pub fn downloads(&mut self, name: &str, version: &str) -> Result<Vec<Download>> {
    let body = try!(self.get(format!("/crates/{}/{}/downloads", name, version)));
    Ok(json::decode::<VersionDownloads>(&body).unwrap().version_downloads)
  }

  pub fn authors(&mut self, name: &str, version: &str) -> Result<Vec<String>> {
    let body = try!(self.get(format!("/crates/{}/{}/authors", name, version)));
    Ok(json::decode::<Authors>(&body).unwrap().meta.names)
  }

  pub fn all_downloads(&mut self, name: &str) -> Result<Vec<Download>> {
    let body = try!(self.get(format!("/crates/{}/downloads", name)));
    Ok(json::decode::<MetaDownloads>(&body).unwrap().meta.extra_downloads)
  }

  pub fn versions(&mut self, name: &str) -> Result<Vec<Version>> {
    let body = try!(self.get(format!("/crates/{}/versions", name)));
    let versions: Vec<Version> = json::decode::<Versions>(&body).unwrap().versions;
    Ok(versions)
  }

  pub fn follow(&mut self, krate: &str) -> Result<()> {
    let body = try!(self.put(format!("/crates/{}/follow", krate), &vec![]));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn unfollow(&mut self, krate: &str) -> Result<()> {
    let body = try!(self.delete(format!("/crates/{}/follow", krate), None));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn following(&mut self, krate: &str) -> Result<bool> {
    let body = try!(self.get(format!("/crates/{}/following", krate)));
    Ok(json::decode::<Following>(&body).unwrap().following)
  }

  pub fn owners(&mut self, krate: &str) -> Result<Vec<User>> {
    let body = try!(self.get(format!("/crates/{}/owners", krate)));
    Ok(json::decode::<Users>(&body).unwrap().users)
  }

  pub fn add_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
    let body = json::encode(&OwnersReq { users: owners }).unwrap();
    let body = try!(self.put(format!("/crates/{}/owners", krate),
                   body.as_bytes()));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn remove_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
    let body = json::encode(&OwnersReq { users: owners }).unwrap();
    let body = try!(self.delete(format!("/crates/{}/owners", krate),
                     Some(body.as_bytes())));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn yank(&mut self, krate: &str, version: &str) -> Result<()> {
    let body = try!(self.delete(format!("/crates/{}/{}/yank", krate, version), None));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn unyank(&mut self, krate: &str, version: &str) -> Result<()> {
    let body = try!(self.put(format!("/crates/{}/{}/unyank", krate, version), &vec![]));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  // todo: reverse deps -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L92

  // todo: all versions -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L93

  // todo: version? -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L94

  // todo: keyboards? -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L95

  // todo: keyboard -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L96

  fn get(&mut self, path: String) -> Result<String> {
    self.req(path, None, Method::Get)
  }

  fn delete(&mut self, path: String, body: Option<&[u8]>) -> Result<String> {
    self.req(path, body, Method::Delete)
  }

  fn put(&mut self, path: String, b: &[u8]) -> Result<String> {
    self.req(path, Some(b), Method::Put)
  }

  fn req(&mut self, path: String, body: Option<&[u8]>, method: Method) -> Result<String> {
     let uri = Url::parse(&format!("{}/api/v1{}", self.host, path)).ok().expect("invalid url");
     let mut cli = hyper::Client::new();
     let bound = cli.request(method, uri)
        .header(UserAgent("cargopants/0.1.0".to_string()))
        .header(Accept(vec![qitem(Mime(Application, Json, vec![(Attr::Charset, Value::Utf8)]))]))
        .header(ContentType(Mime(Application, Json, vec![(Attr::Charset, Value::Utf8)])));
      let authenticated = match self.token.clone() {
        Some(auth) => bound.header(Authorization(auth)),
                 _ => bound
      };
      let embodied = match body {
        Some(data) => authenticated.body(data),
                 _ => authenticated
      };
      let mut res = match embodied.send() {
        Ok(r) => r,
        Err(err) => panic!("failed request: {:?}", err)
      };
      res.read_to_string()
  }
}

#[test]
fn it_works() {
}
<commit_msg>remove outdated comment<commit_after>#![feature(old_io)]

extern crate "rustc-serialize" as rustc_serialize;
extern crate hyper;
extern crate mime;
extern crate url;

use hyper::Url;
use hyper::header::{ Accept, Authorization, ContentType, UserAgent, qitem };
use hyper::method::Method;
use mime::{ Attr, Mime, Value };
use mime::TopLevel::Application;
use mime::SubLevel::Json;
use rustc_serialize::{ Decoder, Decodable, json };
use std::old_io::IoError;
use std::result;

pub type Result<T> = result::Result<T, IoError>;

pub struct Client {
  host: String,
  token: Option<String>
}

#[derive(RustcDecodable)]
struct Status {
  ok: bool
}

#[derive(RustcDecodable)]
struct Following {
  following: bool
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct User {
  pub id: u32,
  pub login: String,
  pub avatar: String,
  pub email: Option<String>,
  pub name: Option<String>,
}

#[derive(RustcDecodable)]
struct Users {
  users: Vec<User>
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Crate {
  pub name: String,
  pub description: Option<String>,
  pub max_version: String
}

// RustcDecodable be derived because the key used in json is `crate`,
// a reserved word
struct CrateReq {
  krate: Crate
}

impl Decodable for CrateReq {
  fn decode<D: Decoder>(d: &mut D) -> result::Result<CrateReq, D::Error> {
    d.read_struct("CrateReq", 1usize, |_d| {
      Ok(CrateReq {
        krate: try!(_d.read_struct_field("crate", 0usize, |_d| Decodable::decode(_d)))
      })
    })
  }
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Download {
  pub date: String,
  pub downloads: u32
}

#[derive(RustcDecodable)]
struct VersionDownloads {
  version_downloads: Vec<Download>
}

#[derive(RustcDecodable)]
struct ExtraDownloads {
  extra_downloads: Vec<Download>
}

#[derive(RustcDecodable)]
struct MetaDownloads {
  meta: ExtraDownloads
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Dependency {
  pub crate_id: String,
  pub default_features: bool,
  pub features: String,
  pub kind: String,
  pub optional: bool,
  pub req: String
}

#[derive(RustcDecodable)]
struct Dependencies {
  dependencies: Vec<Dependency>
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Version {
  // crate: String,
  pub created_at: String,
  pub dl_path: String,
  pub downloads: u32,
  pub num: String,
  pub updated_at: String,
  pub yanked: bool
}

#[derive(RustcDecodable)]
struct VersionReq {
  version: Version
}

#[derive(RustcDecodable)]
struct Versions {
  versions: Vec<Version>
}

#[derive(RustcDecodable)]
struct Meta {
  names: Vec<String>
}

#[derive(RustcDecodable)]
struct Authors {
  meta: Meta
}

#[derive(RustcEncodable)]
pub struct OwnersReq<'a> {
  users: &'a [&'a str]
}

#[derive(RustcDecodable)]
struct Crates {
  crates: Vec<Crate>
}

impl Client {
  pub fn new() -> Client {
    Client::host("https://crates.io")
  }

  pub fn host(addr: &str) -> Client {
    Client { host: addr.to_string(), token: None }
  }

  pub fn token(self, auth: &str) -> Client {
    Client {
      host: self.host,
      token: Some(auth.to_string())
    }
  }

  // todo: soft (downloads|name), by letter/keyword/user_id/following
  pub fn find(&mut self, query: &str) -> Result<Vec<Crate>> {
    let body = try!(self.get(format!("/crates?q={}&sort={}", query, "name")));
    Ok(json::decode::<Crates>(&body).unwrap().crates)
  }

  pub fn named(&mut self, name: &str) -> Result<Crate> {
    let body = try!(self.get(format!("/crates/{}", name)));
    Ok(json::decode::<CrateReq>(&body).unwrap().krate)
  }

  // todo: publish -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L76

  pub fn version(&mut self, name: &str, version: &str) -> Result<Version> {
    let body = try!(self.get(format!("/crates/{}/{}", name, version)));
    Ok(json::decode::<VersionReq>(&body).unwrap().version)
  }

  // todo: version download -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L78

  pub fn dependencies(&mut self, name: &str, version: &str) -> Result<Vec<Dependency>> {
    let body = try!(self.get(format!("/crates/{}/{}/dependencies", name, version)));
    Ok(json::decode::<Dependencies>(&body).unwrap().dependencies)
  }

  pub fn downloads(&mut self, name: &str, version: &str) -> Result<Vec<Download>> {
    let body = try!(self.get(format!("/crates/{}/{}/downloads", name, version)));
    Ok(json::decode::<VersionDownloads>(&body).unwrap().version_downloads)
  }

  pub fn authors(&mut self, name: &str, version: &str) -> Result<Vec<String>> {
    let body = try!(self.get(format!("/crates/{}/{}/authors", name, version)));
    Ok(json::decode::<Authors>(&body).unwrap().meta.names)
  }

  pub fn all_downloads(&mut self, name: &str) -> Result<Vec<Download>> {
    let body = try!(self.get(format!("/crates/{}/downloads", name)));
    Ok(json::decode::<MetaDownloads>(&body).unwrap().meta.extra_downloads)
  }

  pub fn versions(&mut self, name: &str) -> Result<Vec<Version>> {
    let body = try!(self.get(format!("/crates/{}/versions", name)));
    let versions: Vec<Version> = json::decode::<Versions>(&body).unwrap().versions;
    Ok(versions)
  }

  pub fn follow(&mut self, krate: &str) -> Result<()> {
    let body = try!(self.put(format!("/crates/{}/follow", krate), &vec![]));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn unfollow(&mut self, krate: &str) -> Result<()> {
    let body = try!(self.delete(format!("/crates/{}/follow", krate), None));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn following(&mut self, krate: &str) -> Result<bool> {
    let body = try!(self.get(format!("/crates/{}/following", krate)));
    Ok(json::decode::<Following>(&body).unwrap().following)
  }

  pub fn owners(&mut self, krate: &str) -> Result<Vec<User>> {
    let body = try!(self.get(format!("/crates/{}/owners", krate)));
    Ok(json::decode::<Users>(&body).unwrap().users)
  }

  pub fn add_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
    let body = json::encode(&OwnersReq { users: owners }).unwrap();
    let body = try!(self.put(format!("/crates/{}/owners", krate),
                   body.as_bytes()));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn remove_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
    let body = json::encode(&OwnersReq { users: owners }).unwrap();
    let body = try!(self.delete(format!("/crates/{}/owners", krate),
                     Some(body.as_bytes())));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn yank(&mut self, krate: &str, version: &str) -> Result<()> {
    let body = try!(self.delete(format!("/crates/{}/{}/yank", krate, version), None));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn unyank(&mut self, krate: &str, version: &str) -> Result<()> {
    let body = try!(self.put(format!("/crates/{}/{}/unyank", krate, version), &vec![]));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  // todo: reverse deps -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L92

  // todo: all versions -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L93

  // todo: version? -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L94

  // todo: keyboards? -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L95

  // todo: keyboard -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L96

  fn get(&mut self, path: String) -> Result<String> {
    self.req(path, None, Method::Get)
  }

  fn delete(&mut self, path: String, body: Option<&[u8]>) -> Result<String> {
    self.req(path, body, Method::Delete)
  }

  fn put(&mut self, path: String, b: &[u8]) -> Result<String> {
    self.req(path, Some(b), Method::Put)
  }

  fn req(&mut self, path: String, body: Option<&[u8]>, method: Method) -> Result<String> {
     let uri = Url::parse(&format!("{}/api/v1{}", self.host, path)).ok().expect("invalid url");
     let mut cli = hyper::Client::new();
     let bound = cli.request(method, uri)
        .header(UserAgent("cargopants/0.1.0".to_string()))
        .header(Accept(vec![qitem(Mime(Application, Json, vec![(Attr::Charset, Value::Utf8)]))]))
        .header(ContentType(Mime(Application, Json, vec![(Attr::Charset, Value::Utf8)])));
      let authenticated = match self.token.clone() {
        Some(auth) => bound.header(Authorization(auth)),
                 _ => bound
      };
      let embodied = match body {
        Some(data) => authenticated.body(data),
                 _ => authenticated
      };
      let mut res = match embodied.send() {
        Ok(r) => r,
        Err(err) => panic!("failed request: {:?}", err)
      };
      res.read_to_string()
  }
}

#[test]
fn it_works() {
}
<|endoftext|>


<commit_before>
//! **petgraph** is a graph data structure library.
//!
//! - [`Graph`](./graph/struct.Graph.html) which is an adjacency list graph with
//! arbitrary associated data.
//!
//! - [`StableGraph`](./stable_graph/struct.StableGraph.html) is similar
//! to `Graph`, but it keeps indices stable across removals.
//!
//! - [`GraphMap`](./graphmap/struct.GraphMap.html) is an adjacency list graph
//! which is backed by a hash table and the node identifiers are the keys
//! into the table.
//!
//! - [`MatrixGraph`](./matrix_graph/struct.MatrixGraph.html) is an adjacency matrix graph.
//!
//! - [`CSR`](./csr/struct.Csr.html) is a sparse adjacency matrix graph with
//! arbitrary associated data.
//!
//! Optional crate feature: `"serde-1"`, see the Readme for more information.
//!
#![doc(html_root_url = "https://docs.rs/petgraph/0.4/")]

extern crate fixedbitset;
#[cfg(feature = "graphmap")]
extern crate indexmap;

#[cfg(feature = "serde-1")]
extern crate serde;
#[cfg(feature = "serde-1")]
#[macro_use]
extern crate serde_derive;

#[cfg(all(feature = "serde-1", test))]
extern crate itertools;

#[doc(no_inline)]
pub use crate::graph::Graph;

pub use crate::Direction::{Outgoing, Incoming};

#[macro_use]
mod macros;
mod scored;

// these modules define trait-implementing macros
#[macro_use]
pub mod visit;
#[macro_use]
pub mod data;

pub mod algo;
#[cfg(feature = "generate")]
pub mod generate;
#[cfg(feature = "graphmap")]
pub mod graphmap;
#[cfg(feature = "matrix_graph")]
pub mod matrix_graph;
mod graph_impl;
pub mod dot;
pub mod unionfind;
mod dijkstra;
mod astar;
mod simple_paths;
pub mod csr;
mod iter_format;
mod iter_utils;
mod isomorphism;
mod traits_graph;
mod util;
#[cfg(feature = "quickcheck")]
mod quickcheck;
#[cfg(feature = "serde-1")]
mod serde_utils;

pub mod prelude;

/// `Graph<N, E, Ty, Ix>` is a graph datastructure using an adjacency list representation.
pub mod graph {
    pub use crate::graph_impl::{
        Edge,
        EdgeIndex,
        EdgeIndices,
        EdgeReference,
        EdgeReferences,
        EdgeWeightsMut,
        Edges,
        Externals,
        Frozen,
        Graph,
        Neighbors,
        Node,
        NodeIndex,
        NodeIndices,
        NodeWeightsMut,
        NodeReferences,
        WalkNeighbors,
        GraphIndex,
        IndexType,
        edge_index,
        node_index,
        DefaultIx,
        DiGraph,
        UnGraph,
    };
}

#[cfg(feature = "stable_graph")]
pub use crate::graph_impl::stable_graph;

macro_rules! copyclone {
    ($name:ident) => {
        impl Clone for $name {
            #[inline]
            fn clone(&self) -> Self { *self }
        }
    }
}

// Index into the NodeIndex and EdgeIndex arrays
/// Edge direction.
#[derive(Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
#[repr(usize)]
pub enum Direction {
    /// An `Outgoing` edge is an outward edge *from* the current node.
    Outgoing = 0,
    /// An `Incoming` edge is an inbound edge *to* the current node.
    Incoming = 1
}

copyclone!(Direction);

impl Direction {
    /// Return the opposite `Direction`.
    #[inline]
    pub fn opposite(&self) -> Direction {
        match *self {
            Outgoing => Incoming,
            Incoming => Outgoing,
        }
    }

    /// Return `0` for `Outgoing` and `1` for `Incoming`.
    #[inline]
    pub fn index(&self) -> usize {
        (*self as usize) & 0x1
    }
}

#[doc(hidden)]
pub use crate::Direction as EdgeDirection;

/// Marker type for a directed graph.
#[derive(Copy, Debug)]
pub enum Directed { }
copyclone!(Directed);

/// Marker type for an undirected graph.
#[derive(Copy, Debug)]
pub enum Undirected { }
copyclone!(Undirected);

/// A graph's edge type determines whether it has directed edges or not.
pub trait EdgeType {
    fn is_directed() -> bool;
}

impl EdgeType for Directed {
    #[inline]
    fn is_directed() -> bool { true }
}

impl EdgeType for Undirected {
    #[inline]
    fn is_directed() -> bool { false }
}

/// Convert an element like `(i, j)` or `(i, j, w)` into
/// a triple of source, target, edge weight.
///
/// For `Graph::from_edges` and `GraphMap::from_edges`.
pub trait IntoWeightedEdge<E> {
    type NodeId;
    fn into_weighted_edge(self) -> (Self::NodeId, Self::NodeId, E);
}

impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix)
    where E: Default
{
    type NodeId = Ix;

    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (s, t) = self;
        (s, t, E::default())
    }
}

impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix, E)
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        self
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for (Ix, Ix, &'a E)
    where E: Clone
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (a, b, c) = self;
        (a, b, c.clone())
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix)
    where Ix: Copy, E: Default
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (s, t) = *self;
        (s, t, E::default())
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix, E)
    where Ix: Copy, E: Clone
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        self.clone()
    }
}
<commit_msg>Polish lib docs.<commit_after>
//! `petgraph` is a graph data structure library.
//!
//! Graphs are collections of nodes, and edges between nodes. `petgraph`
//! provides several [graph types](index.html#graph-types) (each differing in the
//! tradeoffs taken in their internal representation),
//! [algorithms](./algo/index.html#functions) on those graphs, and functionality to
//! [output graphs](./doc/petgraph/dot/struct.Dot.html) in
//! [`graphviz`](https://www.graphviz.org/) format. Both nodes and edges
//! can have arbitrary associated data, and edges may be either directed or undirected.
//!
//! # Example
//!
//! ```rust
//! use petgraph::prelude::*;
//! use petgraph::algo::{dijkstra, min_spanning_tree};
//! use petgraph::data::FromElements;
//! use petgraph::dot::{Dot, Config};
//!
//! // Create an undirected graph where nodes are &str, and edges have no weight.
//! let g = UnGraphMap::<&str, ()>::from_edges(&[
//!     ("a", "b"), ("b", "c"), ("c", "d"),
//!     ("a", "d")]);
//!
//! // Find the shortest path from "a" to "d" using 1 as the cost for every edge.
//! let node_map = dijkstra(&g, "a", Some("d"), |_| 1);
//! assert_eq!(&1, node_map.get("d").unwrap());
//!
//! // Get the minimum spanning tree of the graph as a new graph, and check that
//! // one edge was trimmed.
//! let mst = UnGraphMap::from_elements(min_spanning_tree(&g));
//! assert_eq!(g.all_edges().count() - 1, mst.all_edges().count());
//!
//! // Output the tree to graphviz DOT format
//! println!("{:?}", Dot::with_config(&mst, &[Config::EdgeNoLabel]));
//! // graph {
//! //     0 [label="\"a\""]
//! //     1 [label="\"b\""]
//! //     2 [label="\"c\""]
//! //     3 [label="\"d\""]
//! //     0 -- 1
//! //     2 -- 3
//! //     1 -- 2
//! // }
//! ```
//!
//! # Graph types
//!
//! * [`Graph`](./graph/struct.Graph.html) -
//!   An adjacency list graph with arbitrary associated data.
//! * [`StableGraph`](./stable_graph/struct.StableGraph.html) -
//!   Similar to `Graph`, but it keeps indices stable across removals.
//! * [`GraphMap`](./graphmap/struct.GraphMap.html) -
//!   An adjacency list graph backed by a hash table. The node identifiers are the keys
//!   into the table.
//! * [`MatrixGraph`](./matrix_graph/struct.MatrixGraph.html) -
//!   An adjacency matrix graph.
//! * [`CSR`](./csr/struct.Csr.html) -
//!   A sparse adjacency matrix graph with arbitrary associated data.
//!
//! ### Generic parameters
//!
//! Each graph type is generic over a handful of parameters. All graphs share 3 common
//! parameters, `N`, `E`, and `Ty`. This is a broad overview of what those are. Each
//! type's documentation will have finer detail on these parameters.
//!
//! `N` & `E` are called *weights* in this implementation, and are associated with
//! nodes and edges respectively. They can generally be of arbitrary type, and don't have to
//! be what you might conventionally consider weight-like. For example, using `&str` for `N`
//! will work. Many algorithms that require costs let you provide a cost function that
//! translates your `N` and `E` weights into costs appropriate to the algorithm. Some graph
//! types and choices do impose bounds on `N` or `E`.
//! [`min_spanning_tree`](./algo/fn.min_spanning_tree.html) for example requires edge weights that
//! implement [`PartialOrd`](https://doc.rust-lang.org/stable/core/cmp/trait.PartialOrd.html).
//! [`GraphMap`](./graphmap/struct.GraphMap.html) requires node weights that can serve as hash
//! map keys, since that graph type does not create standalone node indices.
//!
//! `Ty` controls whether edges are [`Directed`](./petgraph/enum.Directed.html) or
//! [`Undirected`](./petgraph/enum.Unirected.html).
//!
//! `Ix` appears on graph types that use indices. It is exposed so you can control
//! the size of node and edge indices, and therefore the memory footprint of your graphs.
//! Allowed values are `u8`, `u16`, `u32`, and `usize`, with `u32` being the default.
//!
//! ### Shorthand types
//!
//! Each graph type vends a few shorthand type definitions that name some specific
//! generic choices. For example, [`DiGraph<_, _>`](./graph/type.DiGraph.html) is shorthand
//! for [`Graph<_, _, Undirected>`](graph/struct.Graph.html).
//! [`UnMatrix<_, _>`](./matrix_graph/type.UnMatrix.html) is shorthand for
//! [`MatrixGraph<_, _, Undirected>`](./matrix_graph/struct.MatrixGraph.html). Each graph type's
//! module documentation lists the available shorthand types.
//!
//! # Crate features
//!
//! * **serde-1** -
//!   Defaults off. Enables serialization for ``Graph, StableGraph`` using
//!   [`serde 1.0`](https://crates.io/crates/serde). May require a more recent version
//!   of Rust than petgraph alone.
//! * **graphmap** -
//!   Defaults on. Enables [`GraphMap`](./graphmap/struct.GraphMap.html).
//! * **stable_graph** -
//!   Defaults on. Enables [`StableGraph`](./stable_graph/struct.StableGraph.html).
//! * **matrix_graph** -
//!   Defaults on. Enables [`MatrixGraph`](./matrix_graph/struct.MatrixGraph.html).
//!
#![doc(html_root_url = "https://docs.rs/petgraph/0.4/")]

extern crate fixedbitset;
#[cfg(feature = "graphmap")]
extern crate indexmap;

#[cfg(feature = "serde-1")]
extern crate serde;
#[cfg(feature = "serde-1")]
#[macro_use]
extern crate serde_derive;

#[cfg(all(feature = "serde-1", test))]
extern crate itertools;

#[doc(no_inline)]
pub use crate::graph::Graph;

pub use crate::Direction::{Outgoing, Incoming};

#[macro_use]
mod macros;
mod scored;

// these modules define trait-implementing macros
#[macro_use]
pub mod visit;
#[macro_use]
pub mod data;

pub mod algo;
#[cfg(feature = "generate")]
pub mod generate;
#[cfg(feature = "graphmap")]
pub mod graphmap;
#[cfg(feature = "matrix_graph")]
pub mod matrix_graph;
mod graph_impl;
pub mod dot;
pub mod unionfind;
mod dijkstra;
mod astar;
mod simple_paths;
pub mod csr;
mod iter_format;
mod iter_utils;
mod isomorphism;
mod traits_graph;
mod util;
#[cfg(feature = "quickcheck")]
mod quickcheck;
#[cfg(feature = "serde-1")]
mod serde_utils;

pub mod prelude;

/// `Graph<N, E, Ty, Ix>` is a graph datastructure using an adjacency list representation.
pub mod graph {
    pub use crate::graph_impl::{
        Edge,
        EdgeIndex,
        EdgeIndices,
        EdgeReference,
        EdgeReferences,
        EdgeWeightsMut,
        Edges,
        Externals,
        Frozen,
        Graph,
        Neighbors,
        Node,
        NodeIndex,
        NodeIndices,
        NodeWeightsMut,
        NodeReferences,
        WalkNeighbors,
        GraphIndex,
        IndexType,
        edge_index,
        node_index,
        DefaultIx,
        DiGraph,
        UnGraph,
    };
}

#[cfg(feature = "stable_graph")]
pub use crate::graph_impl::stable_graph;

macro_rules! copyclone {
    ($name:ident) => {
        impl Clone for $name {
            #[inline]
            fn clone(&self) -> Self { *self }
        }
    }
}

// Index into the NodeIndex and EdgeIndex arrays
/// Edge direction.
#[derive(Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
#[repr(usize)]
pub enum Direction {
    /// An `Outgoing` edge is an outward edge *from* the current node.
    Outgoing = 0,
    /// An `Incoming` edge is an inbound edge *to* the current node.
    Incoming = 1
}

copyclone!(Direction);

impl Direction {
    /// Return the opposite `Direction`.
    #[inline]
    pub fn opposite(&self) -> Direction {
        match *self {
            Outgoing => Incoming,
            Incoming => Outgoing,
        }
    }

    /// Return `0` for `Outgoing` and `1` for `Incoming`.
    #[inline]
    pub fn index(&self) -> usize {
        (*self as usize) & 0x1
    }
}

#[doc(hidden)]
pub use crate::Direction as EdgeDirection;

/// Marker type for a directed graph.
#[derive(Copy, Debug)]
pub enum Directed { }
copyclone!(Directed);

/// Marker type for an undirected graph.
#[derive(Copy, Debug)]
pub enum Undirected { }
copyclone!(Undirected);

/// A graph's edge type determines whether it has directed edges or not.
pub trait EdgeType {
    fn is_directed() -> bool;
}

impl EdgeType for Directed {
    #[inline]
    fn is_directed() -> bool { true }
}

impl EdgeType for Undirected {
    #[inline]
    fn is_directed() -> bool { false }
}

/// Convert an element like `(i, j)` or `(i, j, w)` into
/// a triple of source, target, edge weight.
///
/// For `Graph::from_edges` and `GraphMap::from_edges`.
pub trait IntoWeightedEdge<E> {
    type NodeId;
    fn into_weighted_edge(self) -> (Self::NodeId, Self::NodeId, E);
}

impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix)
    where E: Default
{
    type NodeId = Ix;

    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (s, t) = self;
        (s, t, E::default())
    }
}

impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix, E)
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        self
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for (Ix, Ix, &'a E)
    where E: Clone
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (a, b, c) = self;
        (a, b, c.clone())
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix)
    where Ix: Copy, E: Default
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (s, t) = *self;
        (s, t, E::default())
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix, E)
    where Ix: Copy, E: Clone
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        self.clone()
    }
}
<|endoftext|>


<commit_before>extern crate libc;

mod context;
mod ffi;
mod measure;
mod measures;
mod node;

pub use ffi::Align;
pub use ffi::Dimensions;
pub use ffi::Direction;
pub use ffi::Edge;
pub use ffi::ExperimentalFeature;
pub use ffi::FlexDirection;
pub use ffi::FlexWrap;
pub use ffi::JustifyContent;
pub use ffi::LogLevel;
pub use ffi::MeasureMode;
pub use ffi::Overflow;
pub use ffi::PositionType;
pub use ffi::PrintOptions;
pub use ffi::Size;

pub use context::{Context, ContextFactory};
pub use measures::Measures;
pub use node::Node;
<commit_msg>fix(lib): export measure<commit_after>extern crate libc;

mod context;
mod ffi;
mod measure;
mod measures;
mod node;

pub use ffi::Align;
pub use ffi::Dimensions;
pub use ffi::Direction;
pub use ffi::Edge;
pub use ffi::ExperimentalFeature;
pub use ffi::FlexDirection;
pub use ffi::FlexWrap;
pub use ffi::JustifyContent;
pub use ffi::LogLevel;
pub use ffi::MeasureMode;
pub use ffi::Overflow;
pub use ffi::PositionType;
pub use ffi::PrintOptions;
pub use ffi::Size;

pub use context::{Context, ContextFactory};
pub use measure::measure;
pub use measures::Measures;
pub use node::Node;
<|endoftext|>


<commit_before>//! Compile-time assertions to ensure that invariants are met.
//!
//! # Usage
//!
//! This crate is available [on crates.io][crate] and can be used by adding the
//! following to your project's `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! static_assertions = "0.1"
//! ```
//!
//! and this to your crate root:
//!
//! ```
//! #[macro_use]
//! extern crate static_assertions;
//! # fn main() {}
//! ```
//!
//! # Assert Equal Size
//!
//! When performing operations such as pointer casts or dealing with [`usize`]
//! versus [`u64`] versus [`u32`], the size of your types matter. This is where
//! [`assert_eq_size`] comes into play. Types provided as arguments to
//! [`assert_eq_size`] are ensured to be the same size at compile-time. If the
//! types differ in size, the code will fail to compile.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! // Can be declared outside of a function if labeled
//! assert_eq_size!(bytes; (u8, u8), u16);
//!
//! // Fails to compile (same label):
//! // assert_eq_size!(bytes; u8, u8);
//!
//! fn main() {
//!     assert_eq_size!([u8; 4], (u16, u16), u32);
//!
//!     // Produces a compilation failure:
//!     // assert_eq_size!(u32, u8);
//! }
//! ```
//!
//! Similar to [`assert_eq_size`], there is [`assert_eq_size_val`]. Instead of
//! specifying types to compare, values' sizes can be directly compared against
//! each other.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! let x = 42u8;
//! let y = true;
//!
//! assert_eq_size_val!(x, y);
//! # }
//! ```
//! [`assert_eq_size_val`] doesn't consume its arguments and thus works for
//! non-[`Clone`]able values.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! struct Buffer([u8; 256]);
//!
//! let buf = Buffer([0; 256]);
//! let val = [0u64; 32];
//!
//! assert_eq_size_val!(buf, val);
//!
//! // `buf` and `val` can be used here
//! # }
//! ```
//!
//! Rather than dereference a pointer to achieve the same effect as
//! [`assert_eq_size_val`], there is also the option of [`assert_eq_size_ptr`].
//!
//! # Assert Constant Expression
//!
//! Constant expressions can be ensured to have certain properties via
//! [`const_assert`]. If the expression evaluates to `false`, the file will fail
//! to compile. This is synonymous to [`static_assert` in C++][static_assert].
//!
//! As a [limitation](#limitations), a unique label is required if the macro is
//! used outside of a function.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! const NUM: usize = 32;
//!
//! const_assert!(NUM * NUM == 1024);
//! # }
//! ```
//!
//! As a shorthand for `const_assert!(a == b)`, there's [`const_assert_eq`]:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! const TWO: usize = 2;
//! const_assert_eq!(two; TWO * TWO, TWO + TWO, 4);
//!
//! // Produces a compilation failure:
//! // const_assert_eq!(two; TWO, TWO);
//!
//! fn main() {
//!     const NUM: usize = 32;
//!     const_assert_eq!(NUM + NUM, 64);
//! }
//! ```
//!
//! # Limitations
//!
//! Due to implementation details, [`assert_eq_size`], [`const_assert`], and
//! [`const_assert_eq`] can only be used normally from within the context of a
//! function.
//!
//! To use these macros in other contexts, a unique label must be provided.
//!
//! [crate]: https://crates.io/crates/static_assertions
//! [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert
//! [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
//! [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html
//! [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html
//! [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html
//! [`assert_eq_size_val`]: macro.assert_eq_size_val.html
//! [`assert_eq_size_ptr`]: macro.assert_eq_size_ptr.html
//! [`assert_eq_size`]: macro.assert_eq_size.html
//! [`const_assert`]: macro.const_assert.html
//! [`const_assert_eq`]: macro.const_assert_eq.html

#![no_std]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts at compile-time that the types have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// struct Byte(u8);
///
/// assert_eq_size!(pair; (u16, u16), [u16; 2], [u8; 4]);
///
/// // Fails to compile (same label):
/// // assert_eq_size!(pair; u8, u8);
///
/// fn main() {
///     assert_eq_size!(Byte, u8);
///
///     // Supports unlimited arguments:
///     assert_eq_size!([Byte; 4], [u16; 2], u32);
///
///     // Produces a compilation failure:
///     // assert_eq_size!(Byte, u16);
/// }
/// ```
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $($xs:ty),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::mem::{forget, transmute, uninitialized};
            $(forget::<$xs>(transmute(uninitialized::<$x>()));)+
        }
    };
    ($label:ident; $x:ty, $($xs:ty),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_eq_size!($x, $($xs),+) }
    };
}

/// Asserts at compile-time that the values pointed to have equal sizes.
///
/// This especially is useful for when coercing pointers between different types
/// and ensuring the underlying values are the same size.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// fn operation(x: &(u32, u32), y: &[u16; 4]) {
///     assert_eq_size_ptr!(x, y);
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! assert_eq_size_ptr {
    ($x:expr, $($xs:expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::{mem, ptr};
            let mut copy = ptr::read($x);
            $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+
            mem::forget(copy);
        }
    }
}

/// Asserts at compile-time that the values have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// struct Byte(u8);
///
/// let x = 10u8;
/// let y = Byte(42); // Works for non-cloneable types
///
/// assert_eq_size_val!(x, y);
/// assert_eq_size_val!(x, y, 0u8);
///
/// // Fails to compile:
/// // assert_eq_size_val!(x, 0u32);
/// # }
/// ```
#[macro_export]
macro_rules! assert_eq_size_val {
    ($x:expr, $($xs:expr),+) => {
        assert_eq_size_ptr!(&$x, $(&$xs),+);
    }
}

/// Asserts at compile-time that the constant expression evaluates to `true`.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// const_assert!(2 + 2 == 4);
///
/// const FIVE: usize = 5;
/// const_assert!(FIVE - FIVE == 0);
///
/// // Fails to compile:
/// // const_assert!(1 >= 2);
/// # }
/// ```
#[macro_export]
macro_rules! const_assert {
    ($($xs:expr),+) => {
        let _ = [(); 0 - (!($($xs)&&+) as usize)];
    };
    ($label:ident; $($xs:expr),+) => {
        #[allow(dead_code, non_camel_case_types)]
        type $label = [(); 0 - (!($($xs)&&+) as usize)];
    };
}

/// Asserts at compile-time that the constants are equal in value.
#[macro_export]
macro_rules! const_assert_eq {
    ($x:expr, $($xs:expr),+) => {
        const_assert!($($x == $xs),+);
    };
    ($label:ident; $x:expr, $($xs:expr),+) => {
        const_assert!($label; $($x == $xs),+);
    };
}
<commit_msg>Make labeled const_assert impl like assert_eq_size<commit_after>//! Compile-time assertions to ensure that invariants are met.
//!
//! # Usage
//!
//! This crate is available [on crates.io][crate] and can be used by adding the
//! following to your project's `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! static_assertions = "0.1"
//! ```
//!
//! and this to your crate root:
//!
//! ```
//! #[macro_use]
//! extern crate static_assertions;
//! # fn main() {}
//! ```
//!
//! # Assert Equal Size
//!
//! When performing operations such as pointer casts or dealing with [`usize`]
//! versus [`u64`] versus [`u32`], the size of your types matter. This is where
//! [`assert_eq_size`] comes into play. Types provided as arguments to
//! [`assert_eq_size`] are ensured to be the same size at compile-time. If the
//! types differ in size, the code will fail to compile.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! // Can be declared outside of a function if labeled
//! assert_eq_size!(bytes; (u8, u8), u16);
//!
//! // Fails to compile (same label):
//! // assert_eq_size!(bytes; u8, u8);
//!
//! fn main() {
//!     assert_eq_size!([u8; 4], (u16, u16), u32);
//!
//!     // Produces a compilation failure:
//!     // assert_eq_size!(u32, u8);
//! }
//! ```
//!
//! Similar to [`assert_eq_size`], there is [`assert_eq_size_val`]. Instead of
//! specifying types to compare, values' sizes can be directly compared against
//! each other.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! let x = 42u8;
//! let y = true;
//!
//! assert_eq_size_val!(x, y);
//! # }
//! ```
//! [`assert_eq_size_val`] doesn't consume its arguments and thus works for
//! non-[`Clone`]able values.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! struct Buffer([u8; 256]);
//!
//! let buf = Buffer([0; 256]);
//! let val = [0u64; 32];
//!
//! assert_eq_size_val!(buf, val);
//!
//! // `buf` and `val` can be used here
//! # }
//! ```
//!
//! Rather than dereference a pointer to achieve the same effect as
//! [`assert_eq_size_val`], there is also the option of [`assert_eq_size_ptr`].
//!
//! # Assert Constant Expression
//!
//! Constant expressions can be ensured to have certain properties via
//! [`const_assert`]. If the expression evaluates to `false`, the file will fail
//! to compile. This is synonymous to [`static_assert` in C++][static_assert].
//!
//! As a [limitation](#limitations), a unique label is required if the macro is
//! used outside of a function.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! const NUM: usize = 32;
//!
//! const_assert!(NUM * NUM == 1024);
//! # }
//! ```
//!
//! As a shorthand for `const_assert!(a == b)`, there's [`const_assert_eq`]:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! const TWO: usize = 2;
//! const_assert_eq!(two; TWO * TWO, TWO + TWO, 4);
//!
//! // Produces a compilation failure:
//! // const_assert_eq!(two; TWO, TWO);
//!
//! fn main() {
//!     const NUM: usize = 32;
//!     const_assert_eq!(NUM + NUM, 64);
//! }
//! ```
//!
//! # Limitations
//!
//! Due to implementation details, [`assert_eq_size`], [`const_assert`], and
//! [`const_assert_eq`] can only be used normally from within the context of a
//! function.
//!
//! To use these macros in other contexts, a unique label must be provided.
//!
//! [crate]: https://crates.io/crates/static_assertions
//! [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert
//! [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
//! [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html
//! [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html
//! [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html
//! [`assert_eq_size_val`]: macro.assert_eq_size_val.html
//! [`assert_eq_size_ptr`]: macro.assert_eq_size_ptr.html
//! [`assert_eq_size`]: macro.assert_eq_size.html
//! [`const_assert`]: macro.const_assert.html
//! [`const_assert_eq`]: macro.const_assert_eq.html

#![no_std]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts at compile-time that the types have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// struct Byte(u8);
///
/// assert_eq_size!(pair; (u16, u16), [u16; 2], [u8; 4]);
///
/// // Fails to compile (same label):
/// // assert_eq_size!(pair; u8, u8);
///
/// fn main() {
///     assert_eq_size!(Byte, u8);
///
///     // Supports unlimited arguments:
///     assert_eq_size!([Byte; 4], [u16; 2], u32);
///
///     // Produces a compilation failure:
///     // assert_eq_size!(Byte, u16);
/// }
/// ```
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $($xs:ty),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::mem::{forget, transmute, uninitialized};
            $(forget::<$xs>(transmute(uninitialized::<$x>()));)+
        }
    };
    ($label:ident; $x:ty, $($xs:ty),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_eq_size!($x, $($xs),+) }
    };
}

/// Asserts at compile-time that the values pointed to have equal sizes.
///
/// This especially is useful for when coercing pointers between different types
/// and ensuring the underlying values are the same size.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// fn operation(x: &(u32, u32), y: &[u16; 4]) {
///     assert_eq_size_ptr!(x, y);
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! assert_eq_size_ptr {
    ($x:expr, $($xs:expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::{mem, ptr};
            let mut copy = ptr::read($x);
            $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+
            mem::forget(copy);
        }
    }
}

/// Asserts at compile-time that the values have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// struct Byte(u8);
///
/// let x = 10u8;
/// let y = Byte(42); // Works for non-cloneable types
///
/// assert_eq_size_val!(x, y);
/// assert_eq_size_val!(x, y, 0u8);
///
/// // Fails to compile:
/// // assert_eq_size_val!(x, 0u32);
/// # }
/// ```
#[macro_export]
macro_rules! assert_eq_size_val {
    ($x:expr, $($xs:expr),+) => {
        assert_eq_size_ptr!(&$x, $(&$xs),+);
    }
}

/// Asserts at compile-time that the constant expression evaluates to `true`.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// const_assert!(2 + 2 == 4);
///
/// const FIVE: usize = 5;
/// const_assert!(FIVE - FIVE == 0);
///
/// // Fails to compile:
/// // const_assert!(1 >= 2);
/// # }
/// ```
#[macro_export]
macro_rules! const_assert {
    ($($xs:expr),+) => {
        let _ = [(); 0 - (!($($xs)&&+) as usize)];
    };
    ($label:ident; $($xs:expr),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { const_assert!($($xs),+); }
    };
}

/// Asserts at compile-time that the constants are equal in value.
#[macro_export]
macro_rules! const_assert_eq {
    ($x:expr, $($xs:expr),+) => {
        const_assert!($($x == $xs),+);
    };
    ($label:ident; $x:expr, $($xs:expr),+) => {
        const_assert!($label; $($x == $xs),+);
    };
}
<|endoftext|>


<commit_before>//! A Hamelin process-hosting backend.
#![feature(collections, io, old_io, old_path)]

extern crate mio;
extern crate nix;

use std::borrow::ToOwned;
use std::io::{Error, ErrorKind, Result};
use std::io::ErrorKind::{Other, TimedOut};
use std::old_io::{IoError, IoErrorKind, Writer};
use std::old_io::process::{Command, Process};
use std::old_path::BytesContainer;
use std::os::unix::prelude::*;
use std::str::from_utf8;
use mio::{FromFd, TryRead, TryWrite, PipeReader};
use nix::fcntl::{O_NONBLOCK, O_CLOEXEC, fcntl};
use nix::fcntl::FcntlArg::F_SETFL;
use nix::unistd::close;

/// A Hamelin daemon.
pub struct Hamelin {
    process: String,
    args: Option<Vec<String>>,
}

impl Hamelin {
    /// Constructs a Hamelin daemon from the process and optionally arguments.
    pub fn new(process: &str, args: Option<&[String]>) -> Hamelin {
        Hamelin {
            process: process.to_owned(),
            args: args.map(|s| s.to_owned()),
        }
    }

    /// Spawns a Hamelin server from the daemon.
    pub fn spawn(&self) -> Result<HamelinGuard> {
        let client_str = format!("{} ({:?})", self.process, self.args);
        let mut cmd = Command::new(&self.process);
        cmd.env_set_all(&[("H-VERSION", "hamelin.rs"),
                          ("H-TYPE", "HAMELIN.RS-GENERIC-0.1"),
                          ("H-CLIENT", &client_str)]);
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn().map_err(convert_io_error))))
    }

    /// Spawns a Hamelin server from the daemon using the specified environment variables.
    pub fn spawn_with_env<T, U>(&self, env: &[(T, U)]) -> Result<HamelinGuard>
        where T: BytesContainer, U: BytesContainer {
        let mut cmd = Command::new(&self.process);
        cmd.env_set_all(env);
        cmd.env("H-VERSION", "hamelin.rs");
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn().map_err(convert_io_error))))
    }
}

/// A Hamelin server.
pub struct HamelinGuard {
    process: Process,
    alr: AsyncLineReader,
}

impl HamelinGuard {
    /// Creates a new Hamelin server from the specified process.
    pub fn new(process: Process) -> HamelinGuard {
        let pipe = process.stdout.as_ref().map(|s| s.clone()).unwrap();
        let fd = pipe.as_raw_fd();
        fcntl(fd, F_SETFL(O_NONBLOCK | O_CLOEXEC)).unwrap();
        HamelinGuard {
            process: process,
            alr: AsyncLineReader::new(FromFd::from_fd(fd)),
        }
    }

    /// Writes a line to the server's stdin.
    pub fn write_line(&mut self, line: &str) -> Result<()> {
        self.process.stdin.as_mut().map(|mut s| s.write_line(line)).unwrap()
            .map_err(convert_io_error)
    }

    /// Reads a line asynchronously from the server's stdout.
    pub fn read_line(&mut self) -> Result<String> {
        self.alr.read_line()
    }

    /// Closes the server's stdin.
    pub fn eof(&mut self) -> Result<()> {
        self.process.stdin.as_ref().map(|s| close(s.as_raw_fd())).unwrap().map_err(|_|
            Error::new(Other, "Failed to close stdin.")
        )
    }

    /// Awaits the completion of the server.
    pub fn wait(&mut self) -> Result<()> {
        self.process.wait().map(|_| ()).map_err(convert_io_error)
    }

    /// Sends a kill signal to the server.
    pub fn kill(&mut self) -> Result<()> {
        try!(self.process.signal_exit().map_err(convert_io_error));
        self.process.set_timeout(Some(1000));
        if let Ok(_) = self.process.wait() {
            return Ok(())
        }
        self.process.signal_kill().map_err(convert_io_error)
    }
}

struct AsyncLineReader { read: PipeReader, buf: Vec<u8> }

impl AsyncLineReader {
    pub fn new(pr: PipeReader) -> AsyncLineReader {
        AsyncLineReader { read: pr, buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> Result<String> {
        if let Some(pos) = self.buf.position_elem(&b'\n') {
            let mut rest = self.buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.buf).unwrap().to_owned();
            self.buf = rest;
            return Ok(result);
        }
        let mut buf = [0; 100];
        match self.read.read_slice(&mut buf) {
            Ok(None) => {
                return Err(Error::new(TimedOut, "Reading would've blocked."))
            },
            Ok(Some(size)) => {
                self.buf.push_all(&buf[..size]);
                match self.buf.position_elem(&b'\n') {
                    Some(pos) => {
                        let mut rest = self.buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.buf).unwrap().to_owned();
                        self.buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(Error::new(TimedOut, "Reading would've blocked."))
                    }
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Reading would've blocked."))
        }
    }
}

pub struct AsyncBufStream<T: TryRead + TryWrite> {
    pub stream: T,
    read_buf: Vec<u8>
}

impl<T: TryRead + TryWrite> AsyncBufStream<T> {
    pub fn new(stream: T) -> AsyncBufStream<T> {
        AsyncBufStream { stream: stream, read_buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> Result<String> {
        if let Some(pos) = self.read_buf.position_elem(&b'\n') {
            let mut rest = self.read_buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.read_buf).unwrap().to_owned();
            self.read_buf = rest;
            return Ok(result);
        } else if let Some(_) = self.read_buf.position_elem(&4) {
            return Err(Error::new(Other, "End of File reached."));
        }
        let mut buf = [0; 100];
        match self.stream.read_slice(&mut buf) {
            Ok(None) => Err(Error::new(TimedOut, "Reading would've blocked.")),
            Ok(Some(0)) => Err(Error::new(TimedOut, "Reading would've blocked.")),
            Ok(Some(size)) => {
                self.read_buf.push_all(&buf[..size]);
                match self.read_buf.position_elem(&b'\n') {
                    Some(pos) => {
                        let mut rest = self.read_buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.read_buf).unwrap().to_owned();
                        self.read_buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(Error::new(TimedOut, "Reading would've blocked."))
                    }
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Reading would've blocked."))
        }
    }

    pub fn write_line(&mut self, s: &str) -> Result<()> {
        match self.stream.write_slice(&s.as_bytes()) {
            Ok(None) => Err(Error::new(TimedOut, "Writing would've blocked.")),
            Ok(Some(0)) => Err(Error::new(Other, "End of File reached.")),
            Ok(Some(_)) => {
                match self.stream.write_slice(b"\n") {
                    Ok(None) => Err(Error::new(TimedOut, "Writing would've blocked.")),
                    Ok(_) => Ok(()),
                    Err(_) => Err(Error::new(TimedOut, "Writing would've blocked."))
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Writing would've blocked."))
        }
    }
}

fn convert_io_error(e: IoError) -> Error {
    Error::new(match e.kind {
        IoErrorKind::FileNotFound => ErrorKind::NotFound,
        IoErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
        IoErrorKind::ConnectionRefused => ErrorKind::ConnectionRefused,
        IoErrorKind::ConnectionReset => ErrorKind::ConnectionReset,
        IoErrorKind::ConnectionAborted => ErrorKind::ConnectionAborted,
        IoErrorKind::NotConnected => ErrorKind::NotConnected,
        IoErrorKind::BrokenPipe => ErrorKind::BrokenPipe,
        IoErrorKind::PathAlreadyExists => ErrorKind::AlreadyExists,
        IoErrorKind::PathDoesntExist => ErrorKind::NotFound,
        IoErrorKind::InvalidInput => ErrorKind::InvalidInput,
        IoErrorKind::TimedOut => ErrorKind::TimedOut,
        IoErrorKind::ShortWrite(0) => ErrorKind::WriteZero,
        _ => ErrorKind::Other
    }, e.desc)
}
<commit_msg>Cut back on deprecated usage of collections API.<commit_after>//! A Hamelin process-hosting backend.
#![feature(collections, io, old_io, old_path)]

extern crate mio;
extern crate nix;

use std::borrow::ToOwned;
use std::io::{Error, ErrorKind, Result};
use std::io::ErrorKind::{Other, TimedOut};
use std::old_io::{IoError, IoErrorKind, Writer};
use std::old_io::process::{Command, Process};
use std::old_path::BytesContainer;
use std::os::unix::prelude::*;
use std::str::from_utf8;
use mio::{FromFd, TryRead, TryWrite, PipeReader};
use nix::fcntl::{O_NONBLOCK, O_CLOEXEC, fcntl};
use nix::fcntl::FcntlArg::F_SETFL;
use nix::unistd::close;

/// A Hamelin daemon.
pub struct Hamelin {
    process: String,
    args: Option<Vec<String>>,
}

impl Hamelin {
    /// Constructs a Hamelin daemon from the process and optionally arguments.
    pub fn new(process: &str, args: Option<&[String]>) -> Hamelin {
        Hamelin {
            process: process.to_owned(),
            args: args.map(|s| s.to_owned()),
        }
    }

    /// Spawns a Hamelin server from the daemon.
    pub fn spawn(&self) -> Result<HamelinGuard> {
        let client_str = format!("{} ({:?})", self.process, self.args);
        let mut cmd = Command::new(&self.process);
        cmd.env_set_all(&[("H-VERSION", "hamelin.rs"),
                          ("H-TYPE", "HAMELIN.RS-GENERIC-0.1"),
                          ("H-CLIENT", &client_str)]);
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn().map_err(convert_io_error))))
    }

    /// Spawns a Hamelin server from the daemon using the specified environment variables.
    pub fn spawn_with_env<T, U>(&self, env: &[(T, U)]) -> Result<HamelinGuard>
        where T: BytesContainer, U: BytesContainer {
        let mut cmd = Command::new(&self.process);
        cmd.env_set_all(env);
        cmd.env("H-VERSION", "hamelin.rs");
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn().map_err(convert_io_error))))
    }
}

/// A Hamelin server.
pub struct HamelinGuard {
    process: Process,
    alr: AsyncLineReader,
}

impl HamelinGuard {
    /// Creates a new Hamelin server from the specified process.
    pub fn new(process: Process) -> HamelinGuard {
        let pipe = process.stdout.as_ref().map(|s| s.clone()).unwrap();
        let fd = pipe.as_raw_fd();
        fcntl(fd, F_SETFL(O_NONBLOCK | O_CLOEXEC)).unwrap();
        HamelinGuard {
            process: process,
            alr: AsyncLineReader::new(FromFd::from_fd(fd)),
        }
    }

    /// Writes a line to the server's stdin.
    pub fn write_line(&mut self, line: &str) -> Result<()> {
        self.process.stdin.as_mut().map(|mut s| s.write_line(line)).unwrap()
            .map_err(convert_io_error)
    }

    /// Reads a line asynchronously from the server's stdout.
    pub fn read_line(&mut self) -> Result<String> {
        self.alr.read_line()
    }

    /// Closes the server's stdin.
    pub fn eof(&mut self) -> Result<()> {
        self.process.stdin.as_ref().map(|s| close(s.as_raw_fd())).unwrap().map_err(|_|
            Error::new(Other, "Failed to close stdin.")
        )
    }

    /// Awaits the completion of the server.
    pub fn wait(&mut self) -> Result<()> {
        self.process.wait().map(|_| ()).map_err(convert_io_error)
    }

    /// Sends a kill signal to the server.
    pub fn kill(&mut self) -> Result<()> {
        try!(self.process.signal_exit().map_err(convert_io_error));
        self.process.set_timeout(Some(1000));
        if let Ok(_) = self.process.wait() {
            return Ok(())
        }
        self.process.signal_kill().map_err(convert_io_error)
    }
}

struct AsyncLineReader { read: PipeReader, buf: Vec<u8> }

impl AsyncLineReader {
    pub fn new(pr: PipeReader) -> AsyncLineReader {
        AsyncLineReader { read: pr, buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> Result<String> {
        if let Some(pos) = self.buf.iter().position(|x| x == &b'\n') {
            let mut rest = self.buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.buf).unwrap().to_owned();
            self.buf = rest;
            return Ok(result);
        }
        let mut buf = [0; 100];
        match self.read.read_slice(&mut buf) {
            Ok(None) => {
                return Err(Error::new(TimedOut, "Reading would've blocked."))
            },
            Ok(Some(size)) => {
                self.buf.extend(buf[..size].iter().map(|x| *x));
                match self.buf.iter().position(|x| x == &b'\n') {
                    Some(pos) => {
                        let mut rest = self.buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.buf).unwrap().to_owned();
                        self.buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(Error::new(TimedOut, "Reading would've blocked."))
                    }
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Reading would've blocked."))
        }
    }
}

pub struct AsyncBufStream<T: TryRead + TryWrite> {
    pub stream: T,
    read_buf: Vec<u8>
}

impl<T: TryRead + TryWrite> AsyncBufStream<T> {
    pub fn new(stream: T) -> AsyncBufStream<T> {
        AsyncBufStream { stream: stream, read_buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> Result<String> {
        if let Some(pos) = self.read_buf.iter().position(|x| x == &b'\n') {
            let mut rest = self.read_buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.read_buf).unwrap().to_owned();
            self.read_buf = rest;
            return Ok(result);
        } else if let Some(_) = self.read_buf.iter().position(|x| x == &4) {
            return Err(Error::new(Other, "End of File reached."));
        }
        let mut buf = [0; 100];
        match self.stream.read_slice(&mut buf) {
            Ok(None) => Err(Error::new(TimedOut, "Reading would've blocked.")),
            Ok(Some(0)) => Err(Error::new(TimedOut, "Reading would've blocked.")),
            Ok(Some(size)) => {
                self.read_buf.extend(buf[..size].iter().map(|x| *x));
                match self.read_buf.iter().position(|x| x == &b'\n') {
                    Some(pos) => {
                        let mut rest = self.read_buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.read_buf).unwrap().to_owned();
                        self.read_buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(Error::new(TimedOut, "Reading would've blocked."))
                    }
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Reading would've blocked."))
        }
    }

    pub fn write_line(&mut self, s: &str) -> Result<()> {
        match self.stream.write_slice(&s.as_bytes()) {
            Ok(None) => Err(Error::new(TimedOut, "Writing would've blocked.")),
            Ok(Some(0)) => Err(Error::new(Other, "End of File reached.")),
            Ok(Some(_)) => {
                match self.stream.write_slice(b"\n") {
                    Ok(None) => Err(Error::new(TimedOut, "Writing would've blocked.")),
                    Ok(_) => Ok(()),
                    Err(_) => Err(Error::new(TimedOut, "Writing would've blocked."))
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Writing would've blocked."))
        }
    }
}

fn convert_io_error(e: IoError) -> Error {
    Error::new(match e.kind {
        IoErrorKind::FileNotFound => ErrorKind::NotFound,
        IoErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
        IoErrorKind::ConnectionRefused => ErrorKind::ConnectionRefused,
        IoErrorKind::ConnectionReset => ErrorKind::ConnectionReset,
        IoErrorKind::ConnectionAborted => ErrorKind::ConnectionAborted,
        IoErrorKind::NotConnected => ErrorKind::NotConnected,
        IoErrorKind::BrokenPipe => ErrorKind::BrokenPipe,
        IoErrorKind::PathAlreadyExists => ErrorKind::AlreadyExists,
        IoErrorKind::PathDoesntExist => ErrorKind::NotFound,
        IoErrorKind::InvalidInput => ErrorKind::InvalidInput,
        IoErrorKind::TimedOut => ErrorKind::TimedOut,
        IoErrorKind::ShortWrite(0) => ErrorKind::WriteZero,
        _ => ErrorKind::Other
    }, e.desc)
}
<|endoftext|>