<commit_before>use std::io;
use std::io::prelude::*;
use std::fs::File;

pub struct Compiler;

impl Compiler {
    pub fn compile(file_path: &'static str) -> Result<String, String> {
        let doc = match Document::new(file_path) {
            Ok(doc) => doc,
            Err(e) => return Err(format!("{}: {}", e, file_path))
        };

        if let Some(e) = doc.validate() {
            return Err(format!("{}: {}", e, file_path));
        }

        let output = doc.compile();

        Ok(output)
    }
}

// TODO: move document into its own file
struct DocumentNode {
    depth: i32,
    tokens: Vec<String>,
    content: String
}

impl DocumentNode {
    fn new(line: &str) -> DocumentNode {
        let mut indent = 0;

        for c in line.chars() {
            if c.is_whitespace() {
                indent += 1;
            } else {
                break;
            }
        }

        let (tokens, content) = split_tokens(String::from(line.trim()));

        DocumentNode {
            depth: indent,
            tokens: tokens,
            content: content
        }
    }

    fn render(&self) -> String {
        let mut output = String::new();

        output.push_str(&self.render_open().to_string());

        if !self.content.is_empty() {
            output.push_str(&self.content.to_string())
        }

        output.push_str(&self.render_end().to_string());
        output
    }

    fn render_open(&self) -> String {
        let tag_tokens = &self.tokens;
        let mut output = String::new();

        output.push_str(&format!("<{}", tag_tokens[0]).to_string());

        if tag_tokens.len() > 1 {
            let mut classes = String::new();
            let mut attributes = String::new();

            for t in &tag_tokens[1..] {
                if t.starts_with('#') {
                    output.push_str(&format!(" id=\"{}\"", t[1..].to_string()))
                } else if t.starts_with('.') {
                    classes.push_str(&format!(" {}", t[1..].to_string()));
                } else if t.starts_with('(') {
                    let attrs: Vec<_> = t[1..].split(',').collect();

                    attributes.push_str(&attrs.concat().to_string());
                }
            }

            if !classes.is_empty() {
                output.push_str(&format!(" class=\"{}\"", classes.trim()));
            }

            if !attributes.is_empty() {
                output.push_str(&format!(" {}", attributes).to_string());
            }
        }

        output.push('>');
        output
    }

    fn render_end(&self) -> String {
        format!("</{}>", &self.tokens[0])
    }
}

struct Document {
    path: &'static str,
    contents: String
}

impl Document {
    fn new(path: &'static str) -> Result<Document, io::Error> {
        let mut f = try!(File::open(path));

        let mut contents = String::new();
        try!(f.read_to_string(&mut contents));

        Ok(Document {
            path: path,
            contents: contents
        })
    }

    fn validate(&self) -> Option<&'static str> {
        if self.contents.len() == 0 {
            return Some("The file was empty");
        }

        if !self.contents.starts_with("doctype") && !self.contents.starts_with("extends") {
            return Some("The document must start with a 'doctype' or 'extends'");
        }

        None
    }

    fn compile(self) -> String {
        let nodes = parse(self.contents);

        let mut parent_stack: Vec<&DocumentNode> = Vec::new();
        let mut output = String::new();
        let len = nodes.len();
        let mut i = 0;

        for n in &nodes {
            if i == 0 {
                if n.tokens[0] == "doctype" {
                    if let Some(doctype) = generate_doctype(&n.content) {
                        output.push_str(&doctype.to_string());
                    } else {
                        panic!("Unknown 'doctype' suppied");
                    }
                } /*else if n.tokens[0] == "extends" {
                    // TODO: when extends is added
                }*/

                i += 1;
                continue;
            }

            // TODO: sort this code nesting out, it's too deep
            let has_next = i + 1 < len;
            let has_sub = has_next && nodes[i + 1].depth > n.depth;

            if has_sub {
                output.push_str(&n.render_open().to_string());

                if has_sub {
                    parent_stack.push(n);
                }
            } else {
                output.push_str(&n.render().to_string());

                if has_next && nodes[i + 1].depth < n.depth {
                    loop {
                        match parent_stack.pop() {
                            None =>  { break; },
                            Some(p) => {
                                output.push_str(&p.render_end().to_string());

                                if p.depth == nodes[i + 1].depth {
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if !has_next && parent_stack.len() > 0 {
                loop {
                    match parent_stack.pop() {
                        None =>  { break; },
                        Some(p) => {
                            output.push_str(&p.render_end().to_string());
                        }
                    }
                }
            }

            i += 1;
        }

        output
    }
}

fn parse(content: String) -> Vec<DocumentNode> {
    let mut nodes: Vec<DocumentNode> = Vec::new();

    for line in content.lines() {
        if line.is_empty() {
            continue;
        }

        nodes.push(DocumentNode::new(line));
    }

    nodes
}

fn split_tokens(s: String) -> (Vec<String>, String) {
    let mut tokens: Vec<String> = Vec::new();

    let mut start = 0;
    let len = s.len();
    let mut mode = 0;
    let mut content = String::new();

    for (i, c) in s.chars().enumerate() {
        if c.is_whitespace() && mode == 0 {
            if start < i {
                tokens.push(s[start..i].to_string());
            }

            content.push_str(&s[i..len].trim().to_string());
            break;
        }

        if c == ')' {
            if mode != 1 {
                // TODO: proper error handling
                panic!("Invalid attribute closing brace");
            }

            tokens.push(s[start..i].to_string());

            mode = 0;
            start = i;
        } else {
            if (c == '#' || c == '.' || c == '(') || i == len - 1 {
                if i == len - 1 {
                    tokens.push(s[start..].to_string());
                } else if i > start {
                    tokens.push(s[start..i].to_string());
                }

                if c == '(' {
                    mode = 1;
                }

                start = i;
            }
        }
    }

    // TODO: pretty sure this can be done using a pattern in the starts_with
    if tokens.len() > 0 && (tokens[0].starts_with(".") || tokens[0].starts_with("#")) {
        tokens.insert(0, "div".to_string());
    }

    (tokens, content)
}

// TODO: need to abstract this stuff to support multiple doctypes
fn generate_doctype(content: &String) -> Option<String> {
    return match content.as_ref() {
        "html" => Some(format!("<!DOCTYPE {}>", content)),
        "xml" => Some("<?xml version=\"1.0\" encoding=\"utf-8\" ?>".to_string()),
        _ => None
    };
}
<commit_msg>added missing todo<commit_after>use std::io;
use std::io::prelude::*;
use std::fs::File;

pub struct Compiler;

impl Compiler {
    pub fn compile(file_path: &'static str) -> Result<String, String> {
        let doc = match Document::new(file_path) {
            Ok(doc) => doc,
            Err(e) => return Err(format!("{}: {}", e, file_path))
        };

        if let Some(e) = doc.validate() {
            return Err(format!("{}: {}", e, file_path));
        }

        let output = doc.compile();

        Ok(output)
    }
}

// TODO: move document into its own file
struct DocumentNode {
    depth: i32,
    tokens: Vec<String>,
    content: String
}

impl DocumentNode {
    fn new(line: &str) -> DocumentNode {
        let mut indent = 0;

        for c in line.chars() {
            if c.is_whitespace() {
                indent += 1;
            } else {
                break;
            }
        }

        let (tokens, content) = split_tokens(String::from(line.trim()));

        DocumentNode {
            depth: indent,
            tokens: tokens,
            content: content
        }
    }

    fn render(&self) -> String {
        let mut output = String::new();

        output.push_str(&self.render_open().to_string());

        if !self.content.is_empty() {
            output.push_str(&self.content.to_string())
        }

        output.push_str(&self.render_end().to_string());
        output
    }

    fn render_open(&self) -> String {
        let tag_tokens = &self.tokens;
        let mut output = String::new();

        output.push_str(&format!("<{}", tag_tokens[0]).to_string());

        if tag_tokens.len() > 1 {
            let mut classes = String::new();
            let mut attributes = String::new();

            for t in &tag_tokens[1..] {
                if t.starts_with('#') {
                    output.push_str(&format!(" id=\"{}\"", t[1..].to_string()))
                } else if t.starts_with('.') {
                    classes.push_str(&format!(" {}", t[1..].to_string()));
                } else if t.starts_with('(') {
                    let attrs: Vec<_> = t[1..].split(',').collect();

                    attributes.push_str(&attrs.concat().to_string());
                }
            }

            if !classes.is_empty() {
                output.push_str(&format!(" class=\"{}\"", classes.trim()));
            }

            if !attributes.is_empty() {
                output.push_str(&format!(" {}", attributes).to_string());
            }
        }

        output.push('>');
        output
    }

    fn render_end(&self) -> String {
        format!("</{}>", &self.tokens[0])
    }
}

struct Document {
    path: &'static str,
    contents: String
}

impl Document {
    fn new(path: &'static str) -> Result<Document, io::Error> {
        let mut f = try!(File::open(path));

        let mut contents = String::new();
        try!(f.read_to_string(&mut contents));

        Ok(Document {
            path: path,
            contents: contents
        })
    }

    fn validate(&self) -> Option<&'static str> {
        if self.contents.len() == 0 {
            return Some("The file was empty");
        }

        if !self.contents.starts_with("doctype") && !self.contents.starts_with("extends") {
            return Some("The document must start with a 'doctype' or 'extends'");
        }

        None
    }

    fn compile(self) -> String {
        let nodes = parse(self.contents);

        let mut parent_stack: Vec<&DocumentNode> = Vec::new();
        let mut output = String::new();
        let len = nodes.len();
        let mut i = 0;

        for n in &nodes {
            if i == 0 {
                if n.tokens[0] == "doctype" {
                    if let Some(doctype) = generate_doctype(&n.content) {
                        output.push_str(&doctype.to_string());
                    } else {
                        // TODO: proper error handling
                        panic!("Unknown 'doctype' suppied");
                    }
                } /*else if n.tokens[0] == "extends" {
                    // TODO: when extends is added
                }*/

                i += 1;
                continue;
            }

            // TODO: sort this code nesting out, it's too deep
            let has_next = i + 1 < len;
            let has_sub = has_next && nodes[i + 1].depth > n.depth;

            if has_sub {
                output.push_str(&n.render_open().to_string());

                if has_sub {
                    parent_stack.push(n);
                }
            } else {
                output.push_str(&n.render().to_string());

                if has_next && nodes[i + 1].depth < n.depth {
                    loop {
                        match parent_stack.pop() {
                            None =>  { break; },
                            Some(p) => {
                                output.push_str(&p.render_end().to_string());

                                if p.depth == nodes[i + 1].depth {
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if !has_next && parent_stack.len() > 0 {
                loop {
                    match parent_stack.pop() {
                        None =>  { break; },
                        Some(p) => {
                            output.push_str(&p.render_end().to_string());
                        }
                    }
                }
            }

            i += 1;
        }

        output
    }
}

fn parse(content: String) -> Vec<DocumentNode> {
    let mut nodes: Vec<DocumentNode> = Vec::new();

    for line in content.lines() {
        if line.is_empty() {
            continue;
        }

        nodes.push(DocumentNode::new(line));
    }

    nodes
}

fn split_tokens(s: String) -> (Vec<String>, String) {
    let mut tokens: Vec<String> = Vec::new();

    let mut start = 0;
    let len = s.len();
    let mut mode = 0;
    let mut content = String::new();

    for (i, c) in s.chars().enumerate() {
        if c.is_whitespace() && mode == 0 {
            if start < i {
                tokens.push(s[start..i].to_string());
            }

            content.push_str(&s[i..len].trim().to_string());
            break;
        }

        if c == ')' {
            if mode != 1 {
                // TODO: proper error handling
                panic!("Invalid attribute closing brace");
            }

            tokens.push(s[start..i].to_string());

            mode = 0;
            start = i;
        } else {
            if (c == '#' || c == '.' || c == '(') || i == len - 1 {
                if i == len - 1 {
                    tokens.push(s[start..].to_string());
                } else if i > start {
                    tokens.push(s[start..i].to_string());
                }

                if c == '(' {
                    mode = 1;
                }

                start = i;
            }
        }
    }

    // TODO: pretty sure this can be done using a pattern in the starts_with
    if tokens.len() > 0 && (tokens[0].starts_with(".") || tokens[0].starts_with("#")) {
        tokens.insert(0, "div".to_string());
    }

    (tokens, content)
}

// TODO: need to abstract this stuff to support multiple doctypes
fn generate_doctype(content: &String) -> Option<String> {
    return match content.as_ref() {
        "html" => Some(format!("<!DOCTYPE {}>", content)),
        "xml" => Some("<?xml version=\"1.0\" encoding=\"utf-8\" ?>".to_string()),
        _ => None
    };
}
<|endoftext|>


<commit_before>//! Serde support for querystring-style strings
//!
//! Querystrings are not formally defined and loosely take the form of
//! _nested_ urlencoded queries.
//!
//! This library aims for compatability with the syntax of
//! [qs](https://github.com/ljharb/qs) and also of the
//! [`Rack::Utils::parse_nested_query`](http://www.rubydoc.info/github/rack/rack/Rack/Utils#parse_nested_query-class_method)
//! implementation.
//!
//! For users who do *not* require nested URL parameters, it is highly
//! recommended that the `serde_urlencoded` crate is used instead, which
//! will almost certainly perform better for deserializing simple inputs.
//!
//! ## Supported Types
//!
//! At the **top level**, `serde_qs` only supports `struct`, `map`, and `enum`.
//! These are the only top-level structs which can be de/serialized since
//! Querystrings rely on having a (key, value) pair for each field, which
//! necessitates this kind of structure.
//!
//! However, after the top level you should find all supported types can be
//! de/serialized.
//!
//! ## Usage
//!
//! See the examples folder for a more detailed introduction.
//!
//! Serializing/Deserializing is designed to work with maps and structs.
//!
//! ```
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate serde_qs as qs;
//!
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct Address {
//!     city: String,
//!     postcode: String,
//! }
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct QueryParams {
//!     id: u8,
//!     name: String,
//!     address: Address,
//!     phone: u32,
//!     user_ids: Vec<u8>,
//! }
//!
//! # fn main() {
//! let params = QueryParams {
//!     id: 42,
//!     name: "Acme".to_string(),
//!     phone: 12345,
//!     address: Address {
//!         city: "Carrot City".to_string(),
//!         postcode: "12345".to_string(),
//!     },
//!     user_ids: vec![1, 2, 3, 4],
//! };
//! let rec_params: QueryParams = qs::from_str("\
//!     name=Acme&id=42&phone=12345&address[postcode]=12345&\
//!     address[city]=Carrot+City&user_ids[0]=1&user_ids[1]=2&\
//!     user_ids[2]=3&user_ids[3]=4")
//!     .unwrap();
//! assert_eq!(rec_params, params);
//!
//! # }

#![allow(
)]
#![deny(
    const_err,
    dead_code,
    deprecated,
    exceeding_bitshifts,
    fat_ptr_transmutes,
    improper_ctypes,
    missing_docs,
    mutable_transmutes,
    no_mangle_const_items,
    non_camel_case_types,
    non_shorthand_field_patterns,
    non_snake_case,
    non_upper_case_globals,
    overflowing_literals,
    path_statements,
    plugin_as_library,
    private_no_mangle_fns,
    private_no_mangle_statics,
    stable_features,
    trivial_casts,
    trivial_numeric_casts,
    unconditional_recursion,
    unknown_crate_types,
    unknown_lints,
    unreachable_code,
    unsafe_code,
    unstable_features,
    unused_allocation,
    unused_assignments,
    unused_attributes,
    unused_comparisons,
    unused_extern_crates,
    unused_features,
    unused_imports,
    unused_import_braces,
    unused_must_use,
    unused_mut,
    unused_parens,
    unused_qualifications,
    unused_results,
    unused_unsafe,
    unused_variables,
    variant_size_differences,
    warnings,
    while_true,
)]

extern crate data_encoding;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde;
extern crate url;

mod de;
mod error;
mod ser;

pub use error::Error;

#[doc(inline)]
pub use de::{QsDeserializer, from_bytes, from_reader, from_str};
#[doc(inline)]
pub use de::Config;
#[doc(inline)]
pub use ser::{QsSerializer, to_string};

<commit_msg>Add note in docs about using integer keys.<commit_after>//! Serde support for querystring-style strings
//!
//! Querystrings are not formally defined and loosely take the form of
//! _nested_ urlencoded queries.
//!
//! This library aims for compatability with the syntax of
//! [qs](https://github.com/ljharb/qs) and also of the
//! [`Rack::Utils::parse_nested_query`](http://www.rubydoc.info/github/rack/rack/Rack/Utils#parse_nested_query-class_method)
//! implementation.
//!
//! For users who do *not* require nested URL parameters, it is highly
//! recommended that the `serde_urlencoded` crate is used instead, which
//! will almost certainly perform better for deserializing simple inputs.
//!
//! ## Supported Types
//!
//! At the **top level**, `serde_qs` only supports `struct`, `map`, and `enum`.
//! These are the only top-level structs which can be de/serialized since
//! Querystrings rely on having a (key, value) pair for each field, which
//! necessitates this kind of structure.
//!
//! However, after the top level you should find all supported types can be
//! de/serialized.
//!
//! Note that integer keys are reserved for array indices. That is, a string of
//! the form `a[0]=1&a[1]=3` will deserialize to the ordered sequence `a =
//! [1,3]`.
//!
//! ## Usage
//!
//! See the examples folder for a more detailed introduction.
//!
//! Serializing/Deserializing is designed to work with maps and structs.
//!
//! ```
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate serde_qs as qs;
//!
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct Address {
//!     city: String,
//!     postcode: String,
//! }
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct QueryParams {
//!     id: u8,
//!     name: String,
//!     address: Address,
//!     phone: u32,
//!     user_ids: Vec<u8>,
//! }
//!
//! # fn main() {
//! let params = QueryParams {
//!     id: 42,
//!     name: "Acme".to_string(),
//!     phone: 12345,
//!     address: Address {
//!         city: "Carrot City".to_string(),
//!         postcode: "12345".to_string(),
//!     },
//!     user_ids: vec![1, 2, 3, 4],
//! };
//! let rec_params: QueryParams = qs::from_str("\
//!     name=Acme&id=42&phone=12345&address[postcode]=12345&\
//!     address[city]=Carrot+City&user_ids[0]=1&user_ids[1]=2&\
//!     user_ids[2]=3&user_ids[3]=4")
//!     .unwrap();
//! assert_eq!(rec_params, params);
//!
//! # }

#![allow(
)]
#![deny(
    const_err,
    dead_code,
    deprecated,
    exceeding_bitshifts,
    fat_ptr_transmutes,
    improper_ctypes,
    missing_docs,
    mutable_transmutes,
    no_mangle_const_items,
    non_camel_case_types,
    non_shorthand_field_patterns,
    non_snake_case,
    non_upper_case_globals,
    overflowing_literals,
    path_statements,
    plugin_as_library,
    private_no_mangle_fns,
    private_no_mangle_statics,
    stable_features,
    trivial_casts,
    trivial_numeric_casts,
    unconditional_recursion,
    unknown_crate_types,
    unknown_lints,
    unreachable_code,
    unsafe_code,
    unstable_features,
    unused_allocation,
    unused_assignments,
    unused_attributes,
    unused_comparisons,
    unused_extern_crates,
    unused_features,
    unused_imports,
    unused_import_braces,
    unused_must_use,
    unused_mut,
    unused_parens,
    unused_qualifications,
    unused_results,
    unused_unsafe,
    unused_variables,
    variant_size_differences,
    warnings,
    while_true,
)]

extern crate data_encoding;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde;
extern crate url;

mod de;
mod error;
mod ser;

pub use error::Error;

#[doc(inline)]
pub use de::{QsDeserializer, from_bytes, from_reader, from_str};
#[doc(inline)]
pub use de::Config;
#[doc(inline)]
pub use ser::{QsSerializer, to_string};

<|endoftext|>


<commit_before>//! This crate parses and processes `hyper::server::Request` data
//! that contains `multipart/form-data` content.
//!
//! The main entry point is `parse_multipart`

extern crate hyper;
#[macro_use] extern crate mime;
extern crate httparse;
extern crate libc;
extern crate tempdir;
extern crate textnonce;

#[cfg(test)]
mod mock;
pub mod buf;
mod content_disposition;
pub mod error;

pub use error::Error;
pub use buf::BufReadPlus;

use std::path::PathBuf;
use std::fs::File;
use std::io::{BufReader,BufRead,Read};

use hyper::server::Request as HyperRequest;
use hyper::header::{Headers,ContentType};
use mime::{Mime,TopLevel,SubLevel,Attr,Value};
use tempdir::TempDir;
use textnonce::TextNonce;

pub use content_disposition::ContentDispositionFormData;

#[cfg(test)]
use std::net::SocketAddr;

/// This structure represents uploaded files which were received as
/// part of the `multipart/form-data` parsing.  They are streamed to
/// disk because they may not fit in memory.
pub struct UploadedFile {
    /// This is the temporary file where the data was saved.
    pub path: PathBuf,
    /// This is the filename that was specified in the data, unfiltered.  It may or may not
    /// be legal on the local filesystem.
    pub filename: Option<String>,
    /// This is the content-type that was specified in the data, unvalidated.
    pub content_type: Mime,
    /// This is the actual size of the file received
    pub size: usize,
}

/// This function parses and processes `hyper::server::Request` data
/// that contains `multipart/form-data` content.  It does this in a streaming
/// fashion, saving embedded uploaded files to disk as they are encountered by
/// the parser.
///
/// It returns two sets of data.  The first, `Vec<(String,String)>`, are the
/// variable-value pairs from the POST-ed form.  The second
/// `Vec<(String,UploadedFile)>` are the variable-file pairs from the POST-ed
/// form, where `UploadedFile` structures describe the uploaded file.
pub fn parse_multipart(
    request: &mut Request)
    -> Result< (Vec<(String,String)>, Vec<(String,UploadedFile)>), Error >
{
    let mut parameters: Vec<(String,String)> = Vec::new();
    let mut files: Vec<(String,UploadedFile)> = Vec::new();

    let string_boundary = try!( get_boundary(request) );
    let boundary: Vec<u8> = string_boundary.into_bytes();
    let mut crlf_boundary: Vec<u8> = Vec::with_capacity(2 + boundary.len());
    crlf_boundary.extend(b"\r\n".iter().map(|&i| i));
    crlf_boundary.extend(boundary.clone());

    // Request implements Read.  Internally it's a BufReader, but it's not
    // exposed that way.  We need to wrap it into a BufReader to get that
    // functionality ourselves.
    let mut r = BufReader::with_capacity(4096,request);

    enum State {
        Discarding, // Discard until after initial boundary and CRLF
        CapturingValue, // Capture value until boundary, then discard past CRLF
        CapturingFile, // Capture file until boundary, then discard past CRLF
        ReadingHeaders, // Capture headers to blank line
    }

    let mut state = State::Discarding;
    let mut headers = Headers::new();

    loop {
        let mut buf: Vec<u8> = Vec::new();

        match state {
            State::Discarding => {
                // Read up to and including the boundary
                let read = try!( r.stream_until_token( &*boundary, &mut buf ) );
                if read==0 { return Err(Error::Eof); }

                state = State::ReadingHeaders;
            },
            State::ReadingHeaders => {
                {
                    // IF the next two characters are '--' (look ahead), then we are finished
                    let peeker = try!( r.fill_buf() );
                    if peeker.len() >= 2 && &peeker[..2]==b"--" {
                        return Ok((parameters, files))
                    }
                } // drop peeker

                // Read up to and including the CRLF after the boundary
                let read = try!( r.stream_until_token( b"\r\n", &mut buf ) );
                if read==0 { return Err(Error::Eof); }

                buf.truncate(0);
                let read = try!( r.stream_until_token( b"\r\n\r\n", &mut buf ) );
                if read==0 { return Err(Error::Eof); }
                buf.extend(b"\r\n\r\n".iter().map(|&i| i)); // parse_headers() needs this token at the end

                // Parse the headers
                let mut header_memory = [httparse::EMPTY_HEADER; 4];
                match httparse::parse_headers( &*buf, &mut header_memory) {
                    Ok(httparse::Status::Complete((_,raw_headers))) => {
                        // Turn raw headers into hyper headers
                        headers = try!( Headers::from_raw(raw_headers) );

                        let cd: &ContentDispositionFormData = match headers.get() {
                            Some(x) => x,
                            None => return Err(Error::MissingDisposition),
                        };
                        let ct: Option<&ContentType> = headers.get();

                        state = if ct.is_some() || cd.filename.is_some() {
                            State::CapturingFile
                        } else {
                            State::CapturingValue
                        };
                    },
                    Ok(httparse::Status::Partial) => {
                        println!("Header Parsing was Partial");
                        return Err(Error::PartialHeaders);
                    },
                    Err(e) => return Err( From::from(e) ),
                }
            },
            State::CapturingValue => {
                buf.truncate(0);
                let _ = try!( r.stream_until_token( &*crlf_boundary, &mut buf ) );

                let cd: &ContentDispositionFormData = headers.get().unwrap();

                let key = match cd.name {
                    None => return Err(Error::NoName),
                    Some(ref name) => name.clone()
                };
                let value = try!( String::from_utf8(buf) );

                parameters.push( (key,value) );

                state = State::ReadingHeaders;
            },
            State::CapturingFile => {
                // Setup a file to capture the contents
                let mut temp = try!( TempDir::new("formdata") ).into_path();
                temp.push( TextNonce::sized_urlsafe(32).unwrap().into_string() );
                let mut tmpfile = try!( File::create(temp.clone()) );

                // Stream out the file
                let read = try!( r.stream_until_token( &*crlf_boundary, &mut tmpfile ) );

                let cd: &ContentDispositionFormData = headers.get().unwrap();
                let key = match cd.name {
                    None => return Err(Error::NoName),
                    Some(ref name) => name.clone()
                };

                let content_type = match headers.get::<ContentType>() {
                    Some(ct) => (**ct).clone(),
                    None => mime!(Text/Plain; Charset=Utf8)
                };

                // FIXME: handle content-type: multipart/mixed as multiple files
                // FIXME: handle content-transfer-encoding

                let ufile = UploadedFile {
                    path: temp,
                    filename: cd.filename.clone(),
                    content_type: content_type,
                    size: read - crlf_boundary.len()
                };
                files.push( (key,ufile) );

                state = State::ReadingHeaders;
            },
        }
    }
}

fn get_boundary(request: &Request) -> Result<String,Error>
{
    // Verify that the request is 'content-type: multipart/form-data'
    let content_type: &ContentType = match request.headers().get() {
        Some(h) => h,
        None => return Err(Error::NoRequestContentType),
    };
    let ContentType(ref mime) = *content_type;
    let Mime(ref top_level, ref sub_level, ref params) = *mime;
    if *top_level != TopLevel::Multipart {
        return Err(Error::NotMultipart);
    }
    if *sub_level != SubLevel::FormData {
        return Err(Error::NotFormData);
    }

    // Get the boundary token
    for &(ref attr,ref value) in params.iter() {
        match (attr,value) {
            (&Attr::Boundary, &Value::Ext(ref v)) => {
                return Ok( format!("--{}",v.clone()) )
            }
            _ => {}
        }
    }
    Err(Error::BoundaryNotSpecified)

}

/// A wrapper trait for `hyper::server::Request` data to provide parsing multipart requests to any
/// front-end that provides a `hyper::header::Headers` and a `std::io::Read` of the request's
/// entire body.
pub trait Request: Read {
    /// Returns a reference to the request's Hyper headers.
    fn headers(&self) -> &Headers;
}

impl<'a,'b> Request for HyperRequest<'a,'b> {
    fn headers(&self) -> &Headers {
        &self.headers
    }
}

#[test]
fn test1() {
    use mock::MockStream;
    use hyper::net::NetworkStream;
    use hyper::buffer::BufReader;

    let input=b"POST / HTTP/1.1\r\n\
                Host: example.domain\r\n\
                Content-Type: multipart/form-data; boundary=\"abcdefg\"\r\n\
                Content-Length: 217\r\n\
                \r\n\
                --abcdefg\r\n\
                Content-Disposition: form-data; name=\"field1\"\r\n\
                \r\n\
                data1\r\n\
                --abcdefg\r\n\
                Content-Disposition: form-data; name=\"field2\"; filename=\"image.gif\"\r\n\
                Content-Type: image/gif\r\n\
                \r\n\
                This is a file\r\n\
                with two lines\r\n\
                --abcdefg\r\n\
                Content-Disposition: form-data; name=\"field3\"; filename=\"file.txt\"\r\n\
                \r\n\
                This is a file\r\n\
                --abcdefg--";
    let mut mock = MockStream::with_input(input);

    let mock: &mut NetworkStream = &mut mock;
    let mut stream = BufReader::new(mock);
    let sock: SocketAddr = "127.0.0.1:80".parse().unwrap();

    let mut req = HyperRequest::new(&mut stream, sock).unwrap();

    match parse_multipart(&mut req) {
        Ok((fields,files)) => {
            assert_eq!(fields.len(),1);
            for (k,v) in fields {
                if &k=="field1" { assert_eq!( &v, "data1" ) }
            }
            assert_eq!(files.len(),2);
            for (k,file) in files {
                if &k=="field2" {
                    assert_eq!(file.size, 30);
                    assert!(file.filename.is_some());
                    assert_eq!(&file.filename.unwrap(), "image.gif");
                    assert_eq!(file.content_type, mime!(Image/Gif));
                } else if &k=="field3" {
                    assert_eq!(file.size, 14);
                    assert!(file.filename.is_some());
                    assert_eq!(&file.filename.unwrap(), "file.txt");
                    assert_eq!(file.content_type, mime!(Text/Plain; Charset=Utf8));
                }
            }

        }
        Err(e) => {
            let msg = format!("FAILED ON: {:?}",e);
            assert!(false, msg);
        }
    }
}
<commit_msg>UploadedFile derived traits<commit_after>//! This crate parses and processes `hyper::server::Request` data
//! that contains `multipart/form-data` content.
//!
//! The main entry point is `parse_multipart`

extern crate hyper;
#[macro_use] extern crate mime;
extern crate httparse;
extern crate libc;
extern crate tempdir;
extern crate textnonce;

#[cfg(test)]
mod mock;
pub mod buf;
mod content_disposition;
pub mod error;

pub use error::Error;
pub use buf::BufReadPlus;

use std::path::PathBuf;
use std::fs::File;
use std::io::{BufReader,BufRead,Read};

use hyper::server::Request as HyperRequest;
use hyper::header::{Headers,ContentType};
use mime::{Mime,TopLevel,SubLevel,Attr,Value};
use tempdir::TempDir;
use textnonce::TextNonce;

pub use content_disposition::ContentDispositionFormData;

#[cfg(test)]
use std::net::SocketAddr;

/// This structure represents uploaded files which were received as
/// part of the `multipart/form-data` parsing.  They are streamed to
/// disk because they may not fit in memory.
#[derive(Debug,PartialEq,Clone)]
pub struct UploadedFile {
    /// This is the temporary file where the data was saved.
    pub path: PathBuf,
    /// This is the filename that was specified in the data, unfiltered.  It may or may not
    /// be legal on the local filesystem.
    pub filename: Option<String>,
    /// This is the content-type that was specified in the data, unvalidated.
    pub content_type: Mime,
    /// This is the actual size of the file received
    pub size: usize,
}

/// This function parses and processes `hyper::server::Request` data
/// that contains `multipart/form-data` content.  It does this in a streaming
/// fashion, saving embedded uploaded files to disk as they are encountered by
/// the parser.
///
/// It returns two sets of data.  The first, `Vec<(String,String)>`, are the
/// variable-value pairs from the POST-ed form.  The second
/// `Vec<(String,UploadedFile)>` are the variable-file pairs from the POST-ed
/// form, where `UploadedFile` structures describe the uploaded file.
pub fn parse_multipart(
    request: &mut Request)
    -> Result< (Vec<(String,String)>, Vec<(String,UploadedFile)>), Error >
{
    let mut parameters: Vec<(String,String)> = Vec::new();
    let mut files: Vec<(String,UploadedFile)> = Vec::new();

    let string_boundary = try!( get_boundary(request) );
    let boundary: Vec<u8> = string_boundary.into_bytes();
    let mut crlf_boundary: Vec<u8> = Vec::with_capacity(2 + boundary.len());
    crlf_boundary.extend(b"\r\n".iter().map(|&i| i));
    crlf_boundary.extend(boundary.clone());

    // Request implements Read.  Internally it's a BufReader, but it's not
    // exposed that way.  We need to wrap it into a BufReader to get that
    // functionality ourselves.
    let mut r = BufReader::with_capacity(4096,request);

    enum State {
        Discarding, // Discard until after initial boundary and CRLF
        CapturingValue, // Capture value until boundary, then discard past CRLF
        CapturingFile, // Capture file until boundary, then discard past CRLF
        ReadingHeaders, // Capture headers to blank line
    }

    let mut state = State::Discarding;
    let mut headers = Headers::new();

    loop {
        let mut buf: Vec<u8> = Vec::new();

        match state {
            State::Discarding => {
                // Read up to and including the boundary
                let read = try!( r.stream_until_token( &*boundary, &mut buf ) );
                if read==0 { return Err(Error::Eof); }

                state = State::ReadingHeaders;
            },
            State::ReadingHeaders => {
                {
                    // IF the next two characters are '--' (look ahead), then we are finished
                    let peeker = try!( r.fill_buf() );
                    if peeker.len() >= 2 && &peeker[..2]==b"--" {
                        return Ok((parameters, files))
                    }
                } // drop peeker

                // Read up to and including the CRLF after the boundary
                let read = try!( r.stream_until_token( b"\r\n", &mut buf ) );
                if read==0 { return Err(Error::Eof); }

                buf.truncate(0);
                let read = try!( r.stream_until_token( b"\r\n\r\n", &mut buf ) );
                if read==0 { return Err(Error::Eof); }
                buf.extend(b"\r\n\r\n".iter().map(|&i| i)); // parse_headers() needs this token at the end

                // Parse the headers
                let mut header_memory = [httparse::EMPTY_HEADER; 4];
                match httparse::parse_headers( &*buf, &mut header_memory) {
                    Ok(httparse::Status::Complete((_,raw_headers))) => {
                        // Turn raw headers into hyper headers
                        headers = try!( Headers::from_raw(raw_headers) );

                        let cd: &ContentDispositionFormData = match headers.get() {
                            Some(x) => x,
                            None => return Err(Error::MissingDisposition),
                        };
                        let ct: Option<&ContentType> = headers.get();

                        state = if ct.is_some() || cd.filename.is_some() {
                            State::CapturingFile
                        } else {
                            State::CapturingValue
                        };
                    },
                    Ok(httparse::Status::Partial) => {
                        println!("Header Parsing was Partial");
                        return Err(Error::PartialHeaders);
                    },
                    Err(e) => return Err( From::from(e) ),
                }
            },
            State::CapturingValue => {
                buf.truncate(0);
                let _ = try!( r.stream_until_token( &*crlf_boundary, &mut buf ) );

                let cd: &ContentDispositionFormData = headers.get().unwrap();

                let key = match cd.name {
                    None => return Err(Error::NoName),
                    Some(ref name) => name.clone()
                };
                let value = try!( String::from_utf8(buf) );

                parameters.push( (key,value) );

                state = State::ReadingHeaders;
            },
            State::CapturingFile => {
                // Setup a file to capture the contents
                let mut temp = try!( TempDir::new("formdata") ).into_path();
                temp.push( TextNonce::sized_urlsafe(32).unwrap().into_string() );
                let mut tmpfile = try!( File::create(temp.clone()) );

                // Stream out the file
                let read = try!( r.stream_until_token( &*crlf_boundary, &mut tmpfile ) );

                let cd: &ContentDispositionFormData = headers.get().unwrap();
                let key = match cd.name {
                    None => return Err(Error::NoName),
                    Some(ref name) => name.clone()
                };

                let content_type = match headers.get::<ContentType>() {
                    Some(ct) => (**ct).clone(),
                    None => mime!(Text/Plain; Charset=Utf8)
                };

                // FIXME: handle content-type: multipart/mixed as multiple files
                // FIXME: handle content-transfer-encoding

                let ufile = UploadedFile {
                    path: temp,
                    filename: cd.filename.clone(),
                    content_type: content_type,
                    size: read - crlf_boundary.len()
                };
                files.push( (key,ufile) );

                state = State::ReadingHeaders;
            },
        }
    }
}

fn get_boundary(request: &Request) -> Result<String,Error>
{
    // Verify that the request is 'content-type: multipart/form-data'
    let content_type: &ContentType = match request.headers().get() {
        Some(h) => h,
        None => return Err(Error::NoRequestContentType),
    };
    let ContentType(ref mime) = *content_type;
    let Mime(ref top_level, ref sub_level, ref params) = *mime;
    if *top_level != TopLevel::Multipart {
        return Err(Error::NotMultipart);
    }
    if *sub_level != SubLevel::FormData {
        return Err(Error::NotFormData);
    }

    // Get the boundary token
    for &(ref attr,ref value) in params.iter() {
        match (attr,value) {
            (&Attr::Boundary, &Value::Ext(ref v)) => {
                return Ok( format!("--{}",v.clone()) )
            }
            _ => {}
        }
    }
    Err(Error::BoundaryNotSpecified)

}

/// A wrapper trait for `hyper::server::Request` data to provide parsing multipart requests to any
/// front-end that provides a `hyper::header::Headers` and a `std::io::Read` of the request's
/// entire body.
pub trait Request: Read {
    /// Returns a reference to the request's Hyper headers.
    fn headers(&self) -> &Headers;
}

impl<'a,'b> Request for HyperRequest<'a,'b> {
    fn headers(&self) -> &Headers {
        &self.headers
    }
}

#[test]
fn test1() {
    use mock::MockStream;
    use hyper::net::NetworkStream;
    use hyper::buffer::BufReader;

    let input=b"POST / HTTP/1.1\r\n\
                Host: example.domain\r\n\
                Content-Type: multipart/form-data; boundary=\"abcdefg\"\r\n\
                Content-Length: 217\r\n\
                \r\n\
                --abcdefg\r\n\
                Content-Disposition: form-data; name=\"field1\"\r\n\
                \r\n\
                data1\r\n\
                --abcdefg\r\n\
                Content-Disposition: form-data; name=\"field2\"; filename=\"image.gif\"\r\n\
                Content-Type: image/gif\r\n\
                \r\n\
                This is a file\r\n\
                with two lines\r\n\
                --abcdefg\r\n\
                Content-Disposition: form-data; name=\"field3\"; filename=\"file.txt\"\r\n\
                \r\n\
                This is a file\r\n\
                --abcdefg--";
    let mut mock = MockStream::with_input(input);

    let mock: &mut NetworkStream = &mut mock;
    let mut stream = BufReader::new(mock);
    let sock: SocketAddr = "127.0.0.1:80".parse().unwrap();

    let mut req = HyperRequest::new(&mut stream, sock).unwrap();

    match parse_multipart(&mut req) {
        Ok((fields,files)) => {
            assert_eq!(fields.len(),1);
            for (k,v) in fields {
                if &k=="field1" { assert_eq!( &v, "data1" ) }
            }
            assert_eq!(files.len(),2);
            for (k,file) in files {
                if &k=="field2" {
                    assert_eq!(file.size, 30);
                    assert!(file.filename.is_some());
                    assert_eq!(&file.filename.unwrap(), "image.gif");
                    assert_eq!(file.content_type, mime!(Image/Gif));
                } else if &k=="field3" {
                    assert_eq!(file.size, 14);
                    assert!(file.filename.is_some());
                    assert_eq!(&file.filename.unwrap(), "file.txt");
                    assert_eq!(file.content_type, mime!(Text/Plain; Charset=Utf8));
                }
            }

        }
        Err(e) => {
            let msg = format!("FAILED ON: {:?}",e);
            assert!(false, msg);
        }
    }
}
<|endoftext|>


<commit_before>extern crate futures;
extern crate inotify;
extern crate mio;
extern crate tokio_core;

mod wrap;

pub use wrap::AsyncINotify;
<commit_msg>Re-export inotify FFI symbols<commit_after>extern crate futures;
extern crate inotify;
extern crate mio;
extern crate tokio_core;

mod wrap;

pub use inotify::ffi::*;

pub use wrap::AsyncINotify;
<|endoftext|>


<commit_before>extern crate terminal_size;

use std::io::Write;
use std::ops::{AddAssign, SubAssign};

use terminal_size::{terminal_size, Height, Width};

pub mod builder;
pub use builder::ProgressBuilder as Builder;

/// Tracks progress of a task.
///
/// There should be not more than a single instance started at a given point in
/// time, it will mangle your terminal output.
pub struct Progress {
    current: usize,
    total: usize,

    caption: String,

    started: bool,
}

impl Default for Progress {
    fn default() -> Progress {
        builder::ProgressBuilder::default().build()
    }
}

impl Progress {
    /// Returns the current progress absolute value.
    ///
    /// # Example
    ///
    /// ```
    /// use progress::Progress;
    /// let p = Progress::default();
    /// assert_eq!(0, p.current());
    /// ```
    pub fn current(&self) -> usize {
        self.current
    }

    /// Returns the total value.
    ///
    /// # Example
    ///
    /// ```
    /// use progress::Progress;
    /// let p = Progress::default();
    /// assert_eq!(100, p.total());
    /// ```
    pub fn total(&self) -> usize {
        self.total
    }

    pub fn forward(&mut self, step: usize) -> &Self {
        *self += step;
        self
    }

    pub fn backward(&mut self, step: usize) -> &Self {
        *self -= step;
        self
    }

    /// Advances the Progress by exactly one.
    pub fn increment(&mut self) -> &Self {
        self.forward(1)
    }

    /// Does a step backwards at the Progress.
    pub fn decrement(&mut self) -> &Self {
        self.backward(1)
    }

    /// Determines wheter a Progress has finished (reached the total) or not.
    pub fn finished(&self) -> bool {
        self.current >= self.total
    }

    /// Returns the relative value of the Progress.
    pub fn process(&self) -> u8 {
        (self.current * 100 / self.total) as u8
    }

    /// Activates the Progress.
    pub fn start(&mut self) -> &Self {
        self.started = true;
        self
    }

    /// Returns the current caption.
    pub fn caption(&self) -> &String {
        &self.caption
    }
}

impl AddAssign<usize> for Progress {
    fn add_assign(&mut self, step: usize) {
        let new = self.current + step;
        if new > self.total {
            self.current = self.total;
        } else {
            self.current += step;
        }
        print_bar(self);
    }
}

impl SubAssign<usize> for Progress {
    fn sub_assign(&mut self, step: usize) {
        self.current = self.current.saturating_sub(step);
        print_bar(self);
    }
}

fn print_bar(p: &Progress) {
    let p_info = format!(
        "{current} / {total} ({process})",
        current = p.current(),
        total = p.total(),
        process = p.process()
    );
    let caption = p.caption();

    let (Width(terminal_width), _) = terminal_size().unwrap_or((Width(79), Height(0)));

    let bar_width = terminal_width as usize // Width of terminal
        - p_info.len()  // Width of right summary
        - caption.len() // Width of caption
        - 3  // Colon and spaces
        - 2; // vertical bars in the progress meter
    let done_width = (bar_width * p.process() as usize) / 100;
    let todo_width = bar_width - done_width;
    let done_bar = std::iter::repeat("#").take(done_width).collect::<String>();
    let todo_bar = std::iter::repeat("-").take(todo_width).collect::<String>();
    let bar = format!("|{}{}|", done_bar, todo_bar);

    print!(
        "{caption}: {bar} {info}\r",
        caption = caption,
        bar = bar,
        info = p_info
    );
    std::io::stdout().flush().unwrap();
}
<commit_msg>Documentation<commit_after>extern crate terminal_size;

use std::io::Write;
use std::ops::{AddAssign, SubAssign};

use terminal_size::{terminal_size, Height, Width};

pub mod builder;
pub use builder::ProgressBuilder as Builder;

/// Tracks progress of a task.
///
/// There should be not more than a single instance started at a given point in
/// time, it will mangle your terminal output.
pub struct Progress {
    current: usize,
    total: usize,

    caption: String,

    started: bool,
}

impl Default for Progress {
    fn default() -> Progress {
        builder::ProgressBuilder::default().build()
    }
}

impl Progress {
    /// Returns the current progress absolute value.
    ///
    /// # Example
    ///
    /// ```
    /// use progress::Progress;
    /// let p = Progress::default();
    /// assert_eq!(0, p.current());
    /// ```
    pub fn current(&self) -> usize {
        self.current
    }

    /// Returns the total value.
    ///
    /// # Example
    ///
    /// ```
    /// use progress::Progress;
    /// let p = Progress::default();
    /// assert_eq!(100, p.total());
    /// ```
    pub fn total(&self) -> usize {
        self.total
    }

    /// Advances the Progress by a certain amount.
    ///
    /// # Examplw
    ///
    /// ```
    /// use progress::Progress;
    /// let mut p = Progress::default();
    /// assert_eq!(0, p.current());
    /// p.forward(10);
    /// assert_eq!(10, p.current());
    /// p += 20;
    /// assert_eq!(30, p.current());
    /// ```
    pub fn forward(&mut self, step: usize) -> &Self {
        *self += step;
        self
    }

    /// Advances the Progress by a certain amount.
    ///
    /// # Examplw
    ///
    /// ```
    /// use progress::Builder;
    /// let mut p = Builder::new().set_start(30).build();
    /// assert_eq!(30, p.current());
    /// p.backward(10);
    /// assert_eq!(20, p.current());
    /// p -= 20;
    /// assert_eq!(0, p.current());
    /// ```
    pub fn backward(&mut self, step: usize) -> &Self {
        *self -= step;
        self
    }

    /// Advances the Progress by exactly one.
    pub fn increment(&mut self) -> &Self {
        self.forward(1)
    }

    /// Does a step backwards at the Progress.
    pub fn decrement(&mut self) -> &Self {
        self.backward(1)
    }

    /// Determines wheter a Progress has finished (reached the total) or not.
    pub fn finished(&self) -> bool {
        self.current >= self.total
    }

    /// Returns the relative value of the Progress.
    pub fn process(&self) -> u8 {
        (self.current * 100 / self.total) as u8
    }

    /// Activates the Progress.
    pub fn start(&mut self) -> &Self {
        self.started = true;
        self
    }

    /// Returns the current caption.
    pub fn caption(&self) -> &String {
        &self.caption
    }
}

impl AddAssign<usize> for Progress {
    fn add_assign(&mut self, step: usize) {
        let new = self.current + step;
        if new > self.total {
            self.current = self.total;
        } else {
            self.current += step;
        }
        print_bar(self);
    }
}

impl SubAssign<usize> for Progress {
    fn sub_assign(&mut self, step: usize) {
        self.current = self.current.saturating_sub(step);
        print_bar(self);
    }
}

fn print_bar(p: &Progress) {
    let p_info = format!(
        "{current} / {total} ({process})",
        current = p.current(),
        total = p.total(),
        process = p.process()
    );
    let caption = p.caption();

    let (Width(terminal_width), _) = terminal_size().unwrap_or((Width(79), Height(0)));

    let bar_width = terminal_width as usize // Width of terminal
        - p_info.len()  // Width of right summary
        - caption.len() // Width of caption
        - 3  // Colon and spaces
        - 2; // vertical bars in the progress meter
    let done_width = (bar_width * p.process() as usize) / 100;
    let todo_width = bar_width - done_width;
    let done_bar = std::iter::repeat("#").take(done_width).collect::<String>();
    let todo_bar = std::iter::repeat("-").take(todo_width).collect::<String>();
    let bar = format!("|{}{}|", done_bar, todo_bar);

    print!(
        "{caption}: {bar} {info}\r",
        caption = caption,
        bar = bar,
        info = p_info
    );
    std::io::stdout().flush().unwrap();
}
<|endoftext|>


<commit_before>
use std::ops::Range;

pub struct BitField(u32);

impl BitField {
    pub fn get_bit(&self, bit: u32) -> bool {
        assert!(bit < 32);
        self.get_range(bit..(bit+1)) == 1
    }

    pub fn get_range(&self, range: Range<u32>) -> u32 {
        assert!(range.start < 32);
        assert!(range.end <= 32);
        assert!(range.start < range.end);

        // shift away high bits
        let bits = self.0 << (32 - range.end) >> (32 - range.end);
        // shift away low bits
        bits >> range.start
    }

    pub fn set_bit(&mut self, bit: u32) {
        assert!(bit < 32);
        self.0 |= 1 << bit;
    }

    pub fn reset_bit(&mut self, bit: u32) {
        assert!(bit < 32);
        self.0 &= !(1 << bit);
    }

    pub fn set_range(&mut self, range: Range<u32>, value: u32) {
        assert!(range.start < 32);
        assert!(range.end <= 32);
        assert!(range.start < range.end);
        assert!(value << (32 - (range.end - range.start)) >> (32 - (range.end - range.start)) == value, "value too big");

        let bitmask = !(!0 << (32 - range.end) >> (32 - range.end) >> range.start << range.start);

        let bits = self.0 & bitmask;
        // set bits
        self.0 = bits | (value << range.start);
    }
}

#[cfg(test)]
mod tests {
    use BitField;

    #[test]
    fn test_read() {
        let field = BitField(0b1111111111010110);
        assert_eq!(field.get_bit(0), false);
        assert_eq!(field.get_bit(1), true);
        assert_eq!(field.get_bit(2), true);
        assert_eq!(field.get_bit(3), false);
        assert_eq!(field.get_bit(4), true);
        assert_eq!(field.get_bit(5), false);
        for i in 6..16 {
            assert_eq!(field.get_bit(i), true);
        }
        for i in 16..32 {
            assert_eq!(field.get_bit(i), false);
        }

        assert_eq!(field.get_range(16..32), 0);
        assert_eq!(field.get_range(6..16), 0b1111111111);
        assert_eq!(field.get_range(0..6), 0b010110);
        assert_eq!(field.get_range(0..10), 0b1111010110);
        assert_eq!(field.get_range(5..12), 0b1111110);
    }

    #[test]
    fn test_set_reset() {
        let mut field = BitField(0b1111111111010110);
        let mut bit_i = |i| {
            field.set_bit(i);
            assert_eq!(field.get_bit(i), true);
            field.reset_bit(i);
            assert_eq!(field.get_bit(i), false);
            field.set_bit(i);
            assert_eq!(field.get_bit(i), true);
        };
        for i in 0..32 {
            bit_i(i);
        }
    }

    #[test]
    fn test_set_range() {
        let mut field = BitField(0b1111111111010110);
        field.set_range(10..15, 0b00000);
        assert_eq!(field.get_range(10..15), 0b00000);
        field.set_range(10..15, 0b10101);
        assert_eq!(field.get_range(10..15), 0b10101);
        field.set_range(10..15, 0b01010);
        assert_eq!(field.get_range(10..15), 0b01010);
        field.set_range(10..15, 0b11111);
        assert_eq!(field.get_range(10..15), 0b11111);

        field.set_range(0..16, 0xdead);
        field.set_range(14..32, 0xbeaf);
        assert_eq!(field.get_range(0..16), 0xdead);
        assert_eq!(field.get_range(14..32), 0xbeaf);
    }
}
<commit_msg>Make it #![no_std]<commit_after>#![no_std]

use core::ops::Range;

pub struct BitField(u32);

impl BitField {
    pub fn get_bit(&self, bit: u32) -> bool {
        assert!(bit < 32);
        self.get_range(bit..(bit+1)) == 1
    }

    pub fn get_range(&self, range: Range<u32>) -> u32 {
        assert!(range.start < 32);
        assert!(range.end <= 32);
        assert!(range.start < range.end);

        // shift away high bits
        let bits = self.0 << (32 - range.end) >> (32 - range.end);
        // shift away low bits
        bits >> range.start
    }

    pub fn set_bit(&mut self, bit: u32) {
        assert!(bit < 32);
        self.0 |= 1 << bit;
    }

    pub fn reset_bit(&mut self, bit: u32) {
        assert!(bit < 32);
        self.0 &= !(1 << bit);
    }

    pub fn set_range(&mut self, range: Range<u32>, value: u32) {
        assert!(range.start < 32);
        assert!(range.end <= 32);
        assert!(range.start < range.end);
        assert!(value << (32 - (range.end - range.start)) >> (32 - (range.end - range.start)) == value, "value too big");

        let bitmask = !(!0 << (32 - range.end) >> (32 - range.end) >> range.start << range.start);

        let bits = self.0 & bitmask;
        // set bits
        self.0 = bits | (value << range.start);
    }
}

#[cfg(test)]
mod tests {
    use BitField;

    #[test]
    fn test_read() {
        let field = BitField(0b1111111111010110);
        assert_eq!(field.get_bit(0), false);
        assert_eq!(field.get_bit(1), true);
        assert_eq!(field.get_bit(2), true);
        assert_eq!(field.get_bit(3), false);
        assert_eq!(field.get_bit(4), true);
        assert_eq!(field.get_bit(5), false);
        for i in 6..16 {
            assert_eq!(field.get_bit(i), true);
        }
        for i in 16..32 {
            assert_eq!(field.get_bit(i), false);
        }

        assert_eq!(field.get_range(16..32), 0);
        assert_eq!(field.get_range(6..16), 0b1111111111);
        assert_eq!(field.get_range(0..6), 0b010110);
        assert_eq!(field.get_range(0..10), 0b1111010110);
        assert_eq!(field.get_range(5..12), 0b1111110);
    }

    #[test]
    fn test_set_reset() {
        let mut field = BitField(0b1111111111010110);
        let mut bit_i = |i| {
            field.set_bit(i);
            assert_eq!(field.get_bit(i), true);
            field.reset_bit(i);
            assert_eq!(field.get_bit(i), false);
            field.set_bit(i);
            assert_eq!(field.get_bit(i), true);
        };
        for i in 0..32 {
            bit_i(i);
        }
    }

    #[test]
    fn test_set_range() {
        let mut field = BitField(0b1111111111010110);
        field.set_range(10..15, 0b00000);
        assert_eq!(field.get_range(10..15), 0b00000);
        field.set_range(10..15, 0b10101);
        assert_eq!(field.get_range(10..15), 0b10101);
        field.set_range(10..15, 0b01010);
        assert_eq!(field.get_range(10..15), 0b01010);
        field.set_range(10..15, 0b11111);
        assert_eq!(field.get_range(10..15), 0b11111);

        field.set_range(0..16, 0xdead);
        field.set_range(14..32, 0xbeaf);
        assert_eq!(field.get_range(0..16), 0xdead);
        assert_eq!(field.get_range(14..32), 0xbeaf);
    }
}
<|endoftext|>


<commit_before>//! redis-rs is a rust implementation of a Redis client library.  It exposes
//! a general purpose interface to Redis and also provides specific helpers for
//! commonly used functionality.
//!
//! The crate is called `redis` and you can depend on it via cargo:
//!
//! ```ini
//! [dependencies.redis]
//! git = "https://github.com/mitsuhiko/redis-rs.git"
//! ```
//!
//! # Basic Operation
//!
//! redis-rs exposes to API levels: a low- and a high-level part.  The high-level
//! part does not expose all the functionality of redis and might take some
//! liberties in how it speaks the protocol.  The low-level part of the API
//! allows you to express any request on the redis level.  You can fluently
//! switch between both API levels at any point.
//!
//! ## Connection Handling
//!
//! For connecting to redis you can use a client object which then can produce
//! actual connections.  Connections and clients as well as results of
//! connections and clients are considered `ConnectionLike` objects and
//! can be used anywhere a request is made.
//!
//! The full canonical way to get a connection is to create a client and
//! to ask for a connection from it:
//!
//! ```rust,no_run
//! extern crate redis;
//!
//! fn do_something() -> redis::RedisResult<()> {
//!     let client = try!(redis::Client::open("redis://127.0.0.1/"));
//!     let con = try!(client.get_connection());
//!
//!     /* do something here */
//!
//!     Ok(())
//! }
//! # fn main() {}
//! ```
//!
//! ## Connection Parameters
//!
//! redis-rs knows different ways to define where a connection should
//! go.  The parameter to `Client::open` needs to implement the
//! `IntoConnectionInfo` trait of which there are three implementations:
//!
//! * string slices in `redis://` URL format.
//! * URL objects from the redis-url crate.
//! * `ConnectionInfo` objects.
//!
//! The URL format is `redis://[:<passwd>@]<hostname>[:port][/<db>]`
//!
//! ## Executing Low-Level Commands
//!
//! To execute low-level commands you can use the `cmd` function which allows
//! you to build redis requests.  Once you have configured a command object
//! to your liking you can send a query into any `ConnectionLike` object:
//!
//! ```rust,no_run
//! fn do_something(con: &redis::Connection) -> redis::RedisResult<()> {
//!     let _ : () = try!(redis::cmd("SET").arg("my_key").arg(42i).query(con));
//!     Ok(())
//! }
//! ```
//!
//! Upon querying the return value is a result object.  If you do not care
//! about the actual return value (other than that it is not a failure)
//! you can always type annotate it to the unit type `()`.
//!
//! ## Executing High-Level Commands
//!
//! The high-level interface is similar.  For it to become available you
//! need to use the `Commands` trait in which case all `ConnectionLike`
//! objects the library provides will also have high-level methods which
//! make working with the protocol easier:
//!
//! ```rust,no_run
//! extern crate redis;
//! use redis::Commands;
//!
//! fn do_something(con: &redis::Connection) -> redis::RedisResult<()> {
//!     let _ : () = try!(con.set("my_key", 42i));
//!     Ok(())
//! }
//! # fn main() {}
//! ```
//!
//! Note that high-level commands are work in progress and many are still
//! missing!
//!
//! ## Type Conversions
//!
//! Because redis inherently is mostly type-less and the protocol is not
//! exactly friendly to developers, this library provides flexible support
//! for casting values to the intended results.  This is driven through the
//! `FromRedisValue` and `ToRedisArgs` traits.
//!
//! The `arg` method of the command will accept a wide range of types through
//! the `ToRedisArgs` trait and the `query` method of a command can convert the
//! value to what you expect the function to return through the `FromRedisValue`
//! trait.  This is quite flexible and allows vectors, tuples, hashsets, hashmaps
//! as well as optional values:
//!
//! ```rust,no_run
//! # use redis::Commands;
//! # use std::collections::{HashMap, HashSet};
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let count : i32 = try!(con.get("my_counter"));
//! let count = con.get("my_counter").unwrap_or(0i32);
//! let k : Option<String> = try!(con.get("missing_key"));
//! let name : String = try!(con.get("my_name"));
//! let bin : Vec<u8> = try!(con.get("my_binary"));
//! let map : HashMap<String, i32> = try!(con.hgetall("my_hash"));
//! let keys : Vec<String> = try!(con.hkeys("my_hash"));
//! let mems : HashSet<i32> = try!(con.smembers("my_set"));
//! let (k1, k2) : (String, String) = try!(con.get(&["k1", "k2"]));
//! # Ok(())
//! # }
//! ```
//!
//! # Iteration Protocol
//!
//! In addition to sending a single query you iterators are also supported.  When
//! used with regular bulk responses they don't give you much over querying and
//! converting into a vector (both use a vector internally) but they can also
//! be used with `SCAN` like commands in which case iteration will send more
//! queries until the cursor is exhausted:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let mut iter : redis::Iter<int> = try!(redis::cmd("SSCAN").arg("my_set")
//!     .cursor_arg(0).iter(&con));
//! for x in iter {
//!     // do something with the item
//! }
//! # Ok(()) }
//! ```
//!
//! As you can see the cursor argument needs to be defined with `cursor_arg`
//! instead of `arg` so that the library knows which argument needs updating
//! as the query is run for more items.
//!
//! # Pipelining
//!
//! In addition to simple queries you can also send command pipelines.  This
//! is provided through the `pipe` function.  It works very similar to sending
//! individual commands but you can send more than one in one go.  This also
//! allows you to ignore individual results so that matching on the end result
//! is easier:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = try!(redis::pipe()
//!     .cmd("SET").arg("key_1").arg(42i).ignore()
//!     .cmd("SET").arg("key_2").arg(43i).ignore()
//!     .cmd("GET").arg("key_1")
//!     .cmd("GET").arg("key_2").query(&con));
//! # Ok(()) }
//! ```
//!
//! If you want the pipeline to be wrapped in a `MULTI`/`EXEC` block you can
//! easily do that by switching the pipeline into `atomic` mode.  From the
//! caller's point of view nothing changes, the pipeline itself will take
//! care of the rest for you:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = try!(redis::pipe()
//!     .atomic()
//!     .cmd("SET").arg("key_1").arg(42i).ignore()
//!     .cmd("SET").arg("key_2").arg(43i).ignore()
//!     .cmd("GET").arg("key_1")
//!     .cmd("GET").arg("key_2").query(&con));
//! # Ok(()) }
//! ```
//!
//! You can also use high-level commands on pipelines through the
//! `PipelineCommands` trait:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! use redis::PipelineCommands;
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = try!(redis::pipe()
//!     .atomic()
//!     .set("key_1", 42i).ignore()
//!     .set("key_2", 43i).ignore()
//!     .get("key_1")
//!     .get("key_2").query(&con));
//! # Ok(()) }
//! ```
//!
//! # Transactions
//!
//! Transactions are available through atomic pipelines.  In order to use
//! them in a more simple way you can use the `transaction` function of a
//! connection:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! use redis::{Commands, PipelineCommands};
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let key = "the_key";
//! let (new_val,) : (int,) = try!(redis::transaction(&con, &[key], |pipe| {
//!     let old_val : int = try!(con.get(key));
//!     pipe
//!         .set(key, old_val + 1).ignore()
//!         .get(key).query(&con)
//! }));
//! println!("The incremented number is: {}", new_val);
//! # Ok(()) }
//! ```
//!
//! For more information see the `transaction` function.
//!
//! # PubSub
//!
//! Pubsub is currently work in progress but provided through the `PubSub`
//! connection object.  Due to the fact that Rust does not have support
//! for async IO in libnative yet, the API does not provide a way to
//! read messages with any form of timeout yet.
//!
//! Example usage:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! let client = try!(redis::Client::open("redis://127.0.0.1/"));
//! let mut pubsub = try!(client.get_pubsub());
//! try!(pubsub.subscribe("channel_1"));
//! try!(pubsub.subscribe("channel_2"));
//!
//! loop {
//!     let msg = try!(pubsub.get_message());
//!     let payload : String = try!(msg.get_payload());
//!     println!("channel '{}': {}", msg.get_channel_name(), payload);
//! }
//! # }
//! ```
//!
//! # Scripts
//!
//! Lua scripts are supported through the `Script` type in a convenient
//! way (it does not support pipelining currently).  It will automatically
//! load the script if it does not exist and invoke it.
//!
//! Example:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let script = redis::Script::new(r"
//!     return tonumber(ARGV[1]) + tonumber(ARGV[2]);
//! ");
//! let result : int = try!(script.arg(1i).arg(2i).invoke(&con));
//! assert_eq!(result, 3);
//! # Ok(()) }
//! ```

#![deny(non_camel_case_types)]

#![feature(collections, core, io, net, plugin)]

extern crate url;
extern crate "rustc-serialize" as serialize;
extern crate sha1;

/* public api */
pub use parser::{parse_redis_value, Parser};
pub use client::Client;
pub use script::{Script, ScriptInvocation};
pub use connection::{Connection, ConnectionLike, ConnectionInfo,
                     IntoConnectionInfo, PubSub, Msg, transaction,
                     parse_redis_url};
pub use cmd::{cmd, Cmd, pipe, Pipeline, Iter, pack_command};
pub use commands::{
    Commands,
    PipelineCommands,
};

#[doc(hidden)]
pub use types::{
    /* low level values */
    Value,

    /* error and result types */
    RedisError,
    RedisResult,

    /* error kinds */
    ErrorKind,

    /* utility types */
    InfoDict,
    NumericBehavior,

    /* conversion traits */
    FromRedisValue,
    ToRedisArgs,

    /* utility functions */
    from_redis_value,
};

mod macros;

mod parser;
mod client;
mod connection;
mod types;
mod script;
mod cmd;
mod commands;
<commit_msg>Use updated crate name<commit_after>//! redis-rs is a rust implementation of a Redis client library.  It exposes
//! a general purpose interface to Redis and also provides specific helpers for
//! commonly used functionality.
//!
//! The crate is called `redis` and you can depend on it via cargo:
//!
//! ```ini
//! [dependencies.redis]
//! git = "https://github.com/mitsuhiko/redis-rs.git"
//! ```
//!
//! # Basic Operation
//!
//! redis-rs exposes to API levels: a low- and a high-level part.  The high-level
//! part does not expose all the functionality of redis and might take some
//! liberties in how it speaks the protocol.  The low-level part of the API
//! allows you to express any request on the redis level.  You can fluently
//! switch between both API levels at any point.
//!
//! ## Connection Handling
//!
//! For connecting to redis you can use a client object which then can produce
//! actual connections.  Connections and clients as well as results of
//! connections and clients are considered `ConnectionLike` objects and
//! can be used anywhere a request is made.
//!
//! The full canonical way to get a connection is to create a client and
//! to ask for a connection from it:
//!
//! ```rust,no_run
//! extern crate redis;
//!
//! fn do_something() -> redis::RedisResult<()> {
//!     let client = try!(redis::Client::open("redis://127.0.0.1/"));
//!     let con = try!(client.get_connection());
//!
//!     /* do something here */
//!
//!     Ok(())
//! }
//! # fn main() {}
//! ```
//!
//! ## Connection Parameters
//!
//! redis-rs knows different ways to define where a connection should
//! go.  The parameter to `Client::open` needs to implement the
//! `IntoConnectionInfo` trait of which there are three implementations:
//!
//! * string slices in `redis://` URL format.
//! * URL objects from the redis-url crate.
//! * `ConnectionInfo` objects.
//!
//! The URL format is `redis://[:<passwd>@]<hostname>[:port][/<db>]`
//!
//! ## Executing Low-Level Commands
//!
//! To execute low-level commands you can use the `cmd` function which allows
//! you to build redis requests.  Once you have configured a command object
//! to your liking you can send a query into any `ConnectionLike` object:
//!
//! ```rust,no_run
//! fn do_something(con: &redis::Connection) -> redis::RedisResult<()> {
//!     let _ : () = try!(redis::cmd("SET").arg("my_key").arg(42i).query(con));
//!     Ok(())
//! }
//! ```
//!
//! Upon querying the return value is a result object.  If you do not care
//! about the actual return value (other than that it is not a failure)
//! you can always type annotate it to the unit type `()`.
//!
//! ## Executing High-Level Commands
//!
//! The high-level interface is similar.  For it to become available you
//! need to use the `Commands` trait in which case all `ConnectionLike`
//! objects the library provides will also have high-level methods which
//! make working with the protocol easier:
//!
//! ```rust,no_run
//! extern crate redis;
//! use redis::Commands;
//!
//! fn do_something(con: &redis::Connection) -> redis::RedisResult<()> {
//!     let _ : () = try!(con.set("my_key", 42i));
//!     Ok(())
//! }
//! # fn main() {}
//! ```
//!
//! Note that high-level commands are work in progress and many are still
//! missing!
//!
//! ## Type Conversions
//!
//! Because redis inherently is mostly type-less and the protocol is not
//! exactly friendly to developers, this library provides flexible support
//! for casting values to the intended results.  This is driven through the
//! `FromRedisValue` and `ToRedisArgs` traits.
//!
//! The `arg` method of the command will accept a wide range of types through
//! the `ToRedisArgs` trait and the `query` method of a command can convert the
//! value to what you expect the function to return through the `FromRedisValue`
//! trait.  This is quite flexible and allows vectors, tuples, hashsets, hashmaps
//! as well as optional values:
//!
//! ```rust,no_run
//! # use redis::Commands;
//! # use std::collections::{HashMap, HashSet};
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let count : i32 = try!(con.get("my_counter"));
//! let count = con.get("my_counter").unwrap_or(0i32);
//! let k : Option<String> = try!(con.get("missing_key"));
//! let name : String = try!(con.get("my_name"));
//! let bin : Vec<u8> = try!(con.get("my_binary"));
//! let map : HashMap<String, i32> = try!(con.hgetall("my_hash"));
//! let keys : Vec<String> = try!(con.hkeys("my_hash"));
//! let mems : HashSet<i32> = try!(con.smembers("my_set"));
//! let (k1, k2) : (String, String) = try!(con.get(&["k1", "k2"]));
//! # Ok(())
//! # }
//! ```
//!
//! # Iteration Protocol
//!
//! In addition to sending a single query you iterators are also supported.  When
//! used with regular bulk responses they don't give you much over querying and
//! converting into a vector (both use a vector internally) but they can also
//! be used with `SCAN` like commands in which case iteration will send more
//! queries until the cursor is exhausted:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let mut iter : redis::Iter<int> = try!(redis::cmd("SSCAN").arg("my_set")
//!     .cursor_arg(0).iter(&con));
//! for x in iter {
//!     // do something with the item
//! }
//! # Ok(()) }
//! ```
//!
//! As you can see the cursor argument needs to be defined with `cursor_arg`
//! instead of `arg` so that the library knows which argument needs updating
//! as the query is run for more items.
//!
//! # Pipelining
//!
//! In addition to simple queries you can also send command pipelines.  This
//! is provided through the `pipe` function.  It works very similar to sending
//! individual commands but you can send more than one in one go.  This also
//! allows you to ignore individual results so that matching on the end result
//! is easier:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = try!(redis::pipe()
//!     .cmd("SET").arg("key_1").arg(42i).ignore()
//!     .cmd("SET").arg("key_2").arg(43i).ignore()
//!     .cmd("GET").arg("key_1")
//!     .cmd("GET").arg("key_2").query(&con));
//! # Ok(()) }
//! ```
//!
//! If you want the pipeline to be wrapped in a `MULTI`/`EXEC` block you can
//! easily do that by switching the pipeline into `atomic` mode.  From the
//! caller's point of view nothing changes, the pipeline itself will take
//! care of the rest for you:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = try!(redis::pipe()
//!     .atomic()
//!     .cmd("SET").arg("key_1").arg(42i).ignore()
//!     .cmd("SET").arg("key_2").arg(43i).ignore()
//!     .cmd("GET").arg("key_1")
//!     .cmd("GET").arg("key_2").query(&con));
//! # Ok(()) }
//! ```
//!
//! You can also use high-level commands on pipelines through the
//! `PipelineCommands` trait:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! use redis::PipelineCommands;
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let (k1, k2) : (i32, i32) = try!(redis::pipe()
//!     .atomic()
//!     .set("key_1", 42i).ignore()
//!     .set("key_2", 43i).ignore()
//!     .get("key_1")
//!     .get("key_2").query(&con));
//! # Ok(()) }
//! ```
//!
//! # Transactions
//!
//! Transactions are available through atomic pipelines.  In order to use
//! them in a more simple way you can use the `transaction` function of a
//! connection:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! use redis::{Commands, PipelineCommands};
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let key = "the_key";
//! let (new_val,) : (int,) = try!(redis::transaction(&con, &[key], |pipe| {
//!     let old_val : int = try!(con.get(key));
//!     pipe
//!         .set(key, old_val + 1).ignore()
//!         .get(key).query(&con)
//! }));
//! println!("The incremented number is: {}", new_val);
//! # Ok(()) }
//! ```
//!
//! For more information see the `transaction` function.
//!
//! # PubSub
//!
//! Pubsub is currently work in progress but provided through the `PubSub`
//! connection object.  Due to the fact that Rust does not have support
//! for async IO in libnative yet, the API does not provide a way to
//! read messages with any form of timeout yet.
//!
//! Example usage:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! let client = try!(redis::Client::open("redis://127.0.0.1/"));
//! let mut pubsub = try!(client.get_pubsub());
//! try!(pubsub.subscribe("channel_1"));
//! try!(pubsub.subscribe("channel_2"));
//!
//! loop {
//!     let msg = try!(pubsub.get_message());
//!     let payload : String = try!(msg.get_payload());
//!     println!("channel '{}': {}", msg.get_channel_name(), payload);
//! }
//! # }
//! ```
//!
//! # Scripts
//!
//! Lua scripts are supported through the `Script` type in a convenient
//! way (it does not support pipelining currently).  It will automatically
//! load the script if it does not exist and invoke it.
//!
//! Example:
//!
//! ```rust,no_run
//! # fn do_something() -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://127.0.0.1/").unwrap();
//! # let con = client.get_connection().unwrap();
//! let script = redis::Script::new(r"
//!     return tonumber(ARGV[1]) + tonumber(ARGV[2]);
//! ");
//! let result : int = try!(script.arg(1i).arg(2i).invoke(&con));
//! assert_eq!(result, 3);
//! # Ok(()) }
//! ```

#![deny(non_camel_case_types)]

#![feature(collections, core, io, net, plugin)]

extern crate url;
extern crate rustc_serialize as serialize;
extern crate sha1;

/* public api */
pub use parser::{parse_redis_value, Parser};
pub use client::Client;
pub use script::{Script, ScriptInvocation};
pub use connection::{Connection, ConnectionLike, ConnectionInfo,
                     IntoConnectionInfo, PubSub, Msg, transaction,
                     parse_redis_url};
pub use cmd::{cmd, Cmd, pipe, Pipeline, Iter, pack_command};
pub use commands::{
    Commands,
    PipelineCommands,
};

#[doc(hidden)]
pub use types::{
    /* low level values */
    Value,

    /* error and result types */
    RedisError,
    RedisResult,

    /* error kinds */
    ErrorKind,

    /* utility types */
    InfoDict,
    NumericBehavior,

    /* conversion traits */
    FromRedisValue,
    ToRedisArgs,

    /* utility functions */
    from_redis_value,
};

mod macros;

mod parser;
mod client;
mod connection;
mod types;
mod script;
mod cmd;
mod commands;
<|endoftext|>


<commit_before>use std::default::Default;

pub struct State{
  pub name: String,
  pub enter: Option<fn()>,
  pub leave: Option<fn()>
}

pub struct Event{
  pub name: String,
  pub from_state: Vec<String>,
  pub to_state: String,
  pub before: Option<fn()>,
  pub after: Option<fn()>
}

pub struct Machine{
  pub name: String,
  pub initial_state: Option<String>,
  pub final_state: Option<String>,
  current_state: Option<String>,
  pub states: Vec<State>,
  pub events: Vec<Event>,
  ready: bool
}

impl Default for State{
  fn default() -> State{
    State{
      name: "".to_string(),
      enter: None,
      leave: None
    }
  }
}

impl Default for Event{
  fn default() -> Event{
    Event{
      name: "".to_string(),
      from_state: Vec::new(),
      to_state: "".to_string(),
      before: None,
      after: None
    }
  }
}

impl Default for Machine{
  fn default() -> Machine{
    Machine{
      name: "".to_string(),
      initial_state: None,
      final_state: None,
      current_state: None,
      states: Vec::new(),
      events: Vec::new(),
      ready: false
    }
  }
}

impl Machine{
  pub fn build(&mut self) -> Result<(), String>{
    /*
    check initial_state not null
    check state not null
    check state not duplicate
    check event not null
    check event not duplicate
    if final_state yes , check event to_state == final_state >= 1
    */
    if self.initial_state.is_none() { return Err("Initial state cannot be none.".to_string()); }
    if self.states.len() == 0 { return Err("No State is defined.".to_string()); }
    for s in self.states.iter(){
      let mut count = 0i;
      for sl in self.states.iter(){
        if s.name == sl.name {count+=1}
      }
      if count != 1 { return Err(format!("Duplicate state definition: {}.",s.name)); }
    }
    if self.events.len() == 0 { return Err("No Event is defined.".to_string()); }
    {
      let state_exists = |state: String| -> bool {
        for s in self.states.iter(){
          if s.name == state { return true; }
        }
        false
      };
      for e in self.events.iter(){
        let mut count = 0i;
        for el in self.events.iter(){
          if e.name == el.name {count+=1}
        }
        if count != 1 { return Err(format!("Duplicate event definition: {}.",e.name)); }
        if e.from_state.len() == 0 { return Err(format!("No from state is defined in Event {}.", e.name));}
        for fs in e.from_state.iter(){
          if state_exists(fs.clone()) == false { return Err(format!("State {} is not defined.", fs)); }
        }
        if state_exists(e.to_state.clone()) == false { return Err(format!("State {} is not defined.", e.to_state)); }
      }
    }
    if self.final_state.is_some() {
      let final_state = self.final_state.clone().unwrap();
      let mut count = 0i;
      for e in self.events.iter(){
        if e.to_state == final_state {count+=1}
      }
      if count == 0 { return Err("No event is connected to final state.".to_string()); }
    }
    //after checks
    self.current_state = self.initial_state.clone();
    self.ready = true;
    Ok(())
  }

  pub fn fire(&mut self, event: &str) -> Result<(),String>{
    //before > leave > enter > after
    if self.can_fire(event) {
      let current = self.current_state();
      let mut c_event: &Event;
      let mut c_from_state: &State;
      let mut c_to_state: &State;
      for e in self.events.iter() {
        if e.name.as_slice() == event {
          c_event = e; //get event obj
          match c_event.before { //fire before event
            Some(x) => x(),
            None => {}
          }
          for s in self.states.iter(){
            if s.name == current {
              c_from_state = s; //get current state obj
              match c_from_state.leave { //fire leave event
                Some(x) => x(),
                None => {}
              }
              break;
            }
          }
          for s in self.states.iter(){
            if s.name == c_event.to_state {
              c_to_state = s; //get to state obj
              match c_to_state.enter { //fire enter event
                Some(x) => x(),
                None => {}
              }
              break;
            }
          }
          match c_event.after { //fire after event
            Some(x) => x(),
            None => {}
          }
          self.current_state = Some(c_event.to_state.clone());
          break;
        }
      }
      return Ok(());
    }

    if self.ready == false { return Err("State machine is not ready.".to_string()); }
    if self.is_finished() { return Err("State machine is finished.".to_string()); }
    Err(format!("Event {} cannot be fired.", event))
  }

  pub fn can_fire(&mut self, event: &str) -> bool{
    if self.ready == false { return false; }
    if self.is_finished() { return false; }
    let current = self.current_state();
    for e in self.events.iter() {
      if e.name.as_slice() == event {
        for fs in e.from_state.iter(){
          if fs == &current { return true; }
        }
      }
    }
    false
  }

  pub fn current_state(&mut self) -> String{
    match self.current_state{
      Some(ref x) => x.clone(),
      None => "".to_string(),
    }
  }

  pub fn is_finished(&mut self) -> bool{
    match self.current_state{
      Some(ref cs) => {
          match self.final_state{
            Some(ref fs) => {
                if cs.as_slice() == "" { false }
                else if cs == fs { true }
                else { false }
              },
            None => false
          }
        },
      None => false
    }
  }
}
<commit_msg>Update comments<commit_after>/*
A Rust State Machine Library
Copyright (c) 2014 Chong Cheung
Licensed under the MIT license https://github.com/tomcheung789/rust-fsmlite/blob/master/LICENSE
*/

use std::default::Default;

pub struct State{
  pub name: String,
  pub enter: Option<fn()>,
  pub leave: Option<fn()>
}

pub struct Event{
  pub name: String,
  pub from_state: Vec<String>,
  pub to_state: String,
  pub before: Option<fn()>,
  pub after: Option<fn()>
}

pub struct Machine{
  pub name: String,
  pub initial_state: Option<String>,
  pub final_state: Option<String>,
  current_state: Option<String>,
  pub states: Vec<State>,
  pub events: Vec<Event>,
  ready: bool
}

impl Default for State{
  fn default() -> State{
    State{
      name: "".to_string(),
      enter: None,
      leave: None
    }
  }
}

impl Default for Event{
  fn default() -> Event{
    Event{
      name: "".to_string(),
      from_state: Vec::new(),
      to_state: "".to_string(),
      before: None,
      after: None
    }
  }
}

impl Default for Machine{
  fn default() -> Machine{
    Machine{
      name: "".to_string(),
      initial_state: None,
      final_state: None,
      current_state: None,
      states: Vec::new(),
      events: Vec::new(),
      ready: false
    }
  }
}

impl Machine{
  pub fn build(&mut self) -> Result<(), String>{
    //check initial_state not null
    if self.initial_state.is_none() { return Err("Initial state cannot be none.".to_string()); }
    //check state not null
    if self.states.len() == 0 { return Err("No State is defined.".to_string()); }
    //check state not duplicate
    for s in self.states.iter(){
      let mut count = 0i;
      for sl in self.states.iter(){
        if s.name == sl.name {count+=1}
      }
      if count != 1 { return Err(format!("Duplicate state definition: {}.",s.name)); }
    }
    //check event not null
    if self.events.len() == 0 { return Err("No Event is defined.".to_string()); }
    {
      let state_exists = |state: String| -> bool {
        for s in self.states.iter(){
          if s.name == state { return true; }
        }
        false
      };
      //check event not duplicate
      for e in self.events.iter(){
        let mut count = 0i;
        for el in self.events.iter(){
          if e.name == el.name {count+=1}
        }
        if count != 1 { return Err(format!("Duplicate event definition: {}.",e.name)); }
        if e.from_state.len() == 0 { return Err(format!("No from state is defined in Event {}.", e.name));}
        for fs in e.from_state.iter(){
          if state_exists(fs.clone()) == false { return Err(format!("State {} is not defined.", fs)); }
        }
        if state_exists(e.to_state.clone()) == false { return Err(format!("State {} is not defined.", e.to_state)); }
      }
    }
    //if final_state yes , check event to_state == final_state != 0
    if self.final_state.is_some() {
      let final_state = self.final_state.clone().unwrap();
      let mut count = 0i;
      for e in self.events.iter(){
        if e.to_state == final_state {count+=1}
      }
      if count == 0 { return Err("No event is connected to final state.".to_string()); }
    }
    //after checks
    self.current_state = self.initial_state.clone();
    self.ready = true;
    Ok(())
  }

  pub fn fire(&mut self, event: &str) -> Result<(),String>{
    //before > leave > enter > after
    if self.can_fire(event) {
      let current = self.current_state();
      let mut c_event: &Event;
      let mut c_from_state: &State;
      let mut c_to_state: &State;
      for e in self.events.iter() {
        if e.name.as_slice() == event {
          c_event = e; //get event obj
          match c_event.before { //fire before event
            Some(x) => x(),
            None => {}
          }
          for s in self.states.iter(){
            if s.name == current {
              c_from_state = s; //get current state obj
              match c_from_state.leave { //fire leave event
                Some(x) => x(),
                None => {}
              }
              break;
            }
          }
          for s in self.states.iter(){
            if s.name == c_event.to_state {
              c_to_state = s; //get to state obj
              match c_to_state.enter { //fire enter event
                Some(x) => x(),
                None => {}
              }
              break;
            }
          }
          match c_event.after { //fire after event
            Some(x) => x(),
            None => {}
          }
          self.current_state = Some(c_event.to_state.clone());
          break;
        }
      }
      return Ok(());
    }

    if self.ready == false { return Err("State machine is not ready.".to_string()); }
    if self.is_finished() { return Err("State machine is finished.".to_string()); }
    Err(format!("Event {} cannot be fired.", event))
  }

  pub fn can_fire(&mut self, event: &str) -> bool{
    if self.ready == false { return false; }
    if self.is_finished() { return false; }
    let current = self.current_state();
    for e in self.events.iter() {
      if e.name.as_slice() == event {
        for fs in e.from_state.iter(){
          if fs == &current { return true; }
        }
      }
    }
    false
  }

  pub fn current_state(&mut self) -> String{
    match self.current_state{
      Some(ref x) => x.clone(),
      None => "".to_string(),
    }
  }

  pub fn is_finished(&mut self) -> bool{
    match self.current_state{
      Some(ref cs) => {
          match self.final_state{
            Some(ref fs) => {
                if cs.as_slice() == "" { false }
                else if cs == fs { true }
                else { false }
              },
            None => false
          }
        },
      None => false
    }
  }
}
<|endoftext|>