<commit_before>// Copyright 2013-2018, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! # GTK+ 3 bindings
//!
//! This library contains safe Rust bindings for [GTK+ 3](http://www.gtk.org), a
//! multi-platform GUI toolkit. It's a part of [Gtk-rs](http://gtk-rs.org/).
//!
//! The library is a work in progress: expect missing bindings and breaking
//! changes. A steadily increasing share of the code is machine-generated from
//! `GObject` introspection metadata. The API docs were converted from the
//! upstream ones so until they've all been reviewed there will be incongruities
//! with actual Rust APIs.
//!
//! See also:
//!
//! - [Gtk-rs documentation overview](http://gtk-rs.org/docs/)
//!
//! - [General `GLib` family types and object system overview](../glib/index.html)
//!
//! - [GTK+ documentation](http://www.gtk.org/documentation.php)
//!
//! # Hello World
//!
//! ```no_run
//! extern crate gtk;
//! use gtk::prelude::*;
//! use gtk::{ButtonsType, DialogFlags, MessageType, MessageDialog, Window};
//!
//! fn main() {
//!     if gtk::init().is_err() {
//!         println!("Failed to initialize GTK.");
//!         return;
//!     }
//!     MessageDialog::new(None::<&Window>,
//!                        DialogFlags::empty(),
//!                        MessageType::Info,
//!                        ButtonsType::Ok,
//!                        "Hello World").run();
//! }
//! ```
//!
//! # Initialization
//!
//! GTK+ needs to be initialized before use by calling [`init`](fn.init.html) or
//! [`Application::new`](struct.Application.html#method.new). You only need to
//! do it once and there is no 'finalize'.
//!
//! # The main loop
//!
//! In a typical GTK+ application you set up the UI, assign signal handlers
//! and run the main event loop:
//!
//! ```no_run
//! # extern crate gtk;
//! # use gtk::prelude::*;
//! # use gtk::{Window, WindowType};
//! fn main() {
//!     gtk::init().unwrap();
//!     // Create the main window.
//!     let window = Window::new(WindowType::Toplevel);
//!     // UI initialization.
//!     // ...
//!     // Don't forget to make all widgets visible.
//!     window.show_all();
//!     // Handle closing of the window.
//!     window.connect_delete_event(|_, _| {
//!         // Stop the main loop.
//!         gtk::main_quit();
//!         // Let the default handler destroy the window.
//!         Inhibit(false)
//!     });
//!     // Run the main loop.
//!     gtk::main();
//! }
//! ```
//!
//! # Threads
//!
//! GTK+ is not thread-safe. Accordingly, none of this crate's structs implement
//! `Send` or `Sync`.
//!
//! The thread where `init` was called is considered the main thread. OS X has
//! its own notion of the main thread and `init` must be called on that thread.
//! After successful initialization, calling any `gtk` or `gdk` functions
//! (including `init`) from other threads will `panic`.
//!
//! Any thread can schedule a closure to be run by the main loop on the main
//! thread via [`glib::idle_add`](../glib/source/fn.idle_add.html) or
//! [`glib::timeout_add`](../glib/source/fn.timeout_add.html). This crate has
//! versions of those functions without the `Send` bound, which may only be
//! called from the main thread: [`idle_add`](fn.idle_add.html),
//! [`timeout_add`](fn.timeout_add.html).
//!
//! # Panics
//!
//! This and the `gdk` crate have some run-time safety and contract checks:
//!
//! - Any constructor or free function will panic if called before `init` or on
//! a non-main thread.
//!
//! - Any `&str` or `&Path` parameter with an interior null (`\0`) character will
//! cause a panic.
//!
//! - Some functions will panic if supplied out-of-range integer parameters. All
//! such cases will be documented individually but they're not yet.
//!
//! **A panic in a closure will abort the process.**
//!
//! # Crate features
//!
//! ## Library versions
//!
//! By default this crate provides only GTK+ 3.4 APIs. You can access more
//! modern APIs by selecting one of the following features: `v3_6`, `v3_8`,
//! `v3_10`, `v3_12`, `v3_14`, `v3_16`.
//!
//! `Cargo.toml` example:
//!
//! ```toml
//! [dependencies.gtk]
//! version = "0.x.y"
//! features = ["v3_16"]
//! ```
//!
//! **Take care when choosing the version to target: some of your users might
//! not have easy access to the latest ones.** The higher the version, the fewer
//! users will have it installed.
//!
//! ## Lgpl-docs
//!
//! The Gtk-rs crates come with API docs missing because of licensing
//! incompatibilty. You can embed those docs locally via the `embed-lgpl-docs`
//! feature, e.g.
//!
//! ```shell
//! > cargo doc --features embed-lgpl-docs
//! ```
//!
//! Its counterpart `purge-lgpl-docs` removes those docs regardless of edits.
//!
//! These features **rewrite the crate sources** so it's sufficient to enable
//! them once. **Omitting them in the following cargo invocations will not undo
//! their effects!**

#![cfg_attr(feature = "cargo-clippy", allow(let_unit_value))]
#![cfg_attr(feature = "cargo-clippy", allow(new_without_default))]
#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
#![cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
#![cfg_attr(feature = "cargo-clippy", allow(trivially_copy_pass_by_ref))]
#![allow(deprecated)]

extern crate libc;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate lazy_static;

extern crate glib_sys as glib_ffi;
extern crate gio_sys as gio_ffi;
extern crate gdk_sys as gdk_ffi;
extern crate gdk_pixbuf_sys as gdk_pixbuf_ffi;
extern crate gobject_sys as gobject_ffi;
extern crate gtk_sys as ffi;
extern crate cairo_sys as cairo_ffi;
#[macro_use]
extern crate glib;
extern crate gio;
extern crate gdk;
extern crate gdk_pixbuf;
extern crate cairo;
extern crate pango;

#[cfg(feature = "futures")]
extern crate send_cell;
#[cfg(feature = "futures")]
extern crate futures_core;

pub use glib::{
    Cast,
    Continue,
    Error,
    IsA,
    Object,
    StaticType,
    ToValue,
    Type,
    TypedValue,
    Value,
};

pub mod xlib;

pub const STYLE_PROVIDER_PRIORITY_FALLBACK: u32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_FALLBACK as u32;
pub const STYLE_PROVIDER_PRIORITY_THEME: u32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_THEME as u32;
pub const STYLE_PROVIDER_PRIORITY_SETTINGS: u32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_SETTINGS as u32;
pub const STYLE_PROVIDER_PRIORITY_APPLICATION: u32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32;
pub const STYLE_PROVIDER_PRIORITY_USER: u32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_USER as u32;

#[macro_use]
mod rt;

#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
#[cfg_attr(feature = "cargo-clippy", allow(let_and_return))]
#[cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))]
#[cfg_attr(feature = "cargo-clippy", allow(wrong_self_convention))]
mod auto;

mod app_chooser;
mod application;
mod application_window;
mod assistant;
mod buildable;
mod builder;
mod border;
mod clipboard;
mod color_button;
mod color_chooser;
mod dialog;
mod drag_context;
mod entry_buffer;
mod entry_completion;
mod enums;
mod file_chooser_dialog;
mod fixed;
mod im_context_simple;
mod invisible;
#[cfg(any(feature = "v3_10", feature = "dox"))]
mod list_box;
mod list_store;
mod menu;
mod message_dialog;
mod notebook;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod pad_action_entry;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod pad_controller;
mod page_range;
mod print_settings;
mod radio_button;
mod radio_menu_item;
mod radio_tool_button;
mod recent_chooser_dialog;
mod recent_data;
mod requisition;
mod signal;
#[cfg(any(target_os = "linux", feature = "dox"))]
mod socket;
mod switch;
mod target_entry;
mod target_list;
mod text_buffer;
mod text_iter;
mod tree_model_filter;
mod tree_row_reference;
mod tree_sortable;
mod tree_path;
mod tree_store;
mod widget;
mod window;

pub mod prelude;

pub use auto::*;
pub use auto::functions::*;
pub use rt::*;
pub use signal::*;
pub use prelude::*;

pub use gdk::Rectangle as Allocation;
pub use gdk::Rectangle;

pub use app_chooser::AppChooser;
pub use border::Border;
pub use entry_buffer::EntryBuffer;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use pad_action_entry::PadActionEntry;
pub use page_range::PageRange;
pub use recent_data::RecentData;
pub use requisition::Requisition;
#[cfg(any(target_os = "linux", feature = "dox"))]
pub use socket::Socket;
pub use target_entry::TargetEntry;
pub use tree_sortable::SortColumn;
<commit_msg>remove more clippy warnings<commit_after>// Copyright 2013-2018, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! # GTK+ 3 bindings
//!
//! This library contains safe Rust bindings for [GTK+ 3](http://www.gtk.org), a
//! multi-platform GUI toolkit. It's a part of [Gtk-rs](http://gtk-rs.org/).
//!
//! The library is a work in progress: expect missing bindings and breaking
//! changes. A steadily increasing share of the code is machine-generated from
//! `GObject` introspection metadata. The API docs were converted from the
//! upstream ones so until they've all been reviewed there will be incongruities
//! with actual Rust APIs.
//!
//! See also:
//!
//! - [Gtk-rs documentation overview](http://gtk-rs.org/docs/)
//!
//! - [General `GLib` family types and object system overview](../glib/index.html)
//!
//! - [GTK+ documentation](http://www.gtk.org/documentation.php)
//!
//! # Hello World
//!
//! ```no_run
//! extern crate gtk;
//! use gtk::prelude::*;
//! use gtk::{ButtonsType, DialogFlags, MessageType, MessageDialog, Window};
//!
//! fn main() {
//!     if gtk::init().is_err() {
//!         println!("Failed to initialize GTK.");
//!         return;
//!     }
//!     MessageDialog::new(None::<&Window>,
//!                        DialogFlags::empty(),
//!                        MessageType::Info,
//!                        ButtonsType::Ok,
//!                        "Hello World").run();
//! }
//! ```
//!
//! # Initialization
//!
//! GTK+ needs to be initialized before use by calling [`init`](fn.init.html) or
//! [`Application::new`](struct.Application.html#method.new). You only need to
//! do it once and there is no 'finalize'.
//!
//! # The main loop
//!
//! In a typical GTK+ application you set up the UI, assign signal handlers
//! and run the main event loop:
//!
//! ```no_run
//! # extern crate gtk;
//! # use gtk::prelude::*;
//! # use gtk::{Window, WindowType};
//! fn main() {
//!     gtk::init().unwrap();
//!     // Create the main window.
//!     let window = Window::new(WindowType::Toplevel);
//!     // UI initialization.
//!     // ...
//!     // Don't forget to make all widgets visible.
//!     window.show_all();
//!     // Handle closing of the window.
//!     window.connect_delete_event(|_, _| {
//!         // Stop the main loop.
//!         gtk::main_quit();
//!         // Let the default handler destroy the window.
//!         Inhibit(false)
//!     });
//!     // Run the main loop.
//!     gtk::main();
//! }
//! ```
//!
//! # Threads
//!
//! GTK+ is not thread-safe. Accordingly, none of this crate's structs implement
//! `Send` or `Sync`.
//!
//! The thread where `init` was called is considered the main thread. OS X has
//! its own notion of the main thread and `init` must be called on that thread.
//! After successful initialization, calling any `gtk` or `gdk` functions
//! (including `init`) from other threads will `panic`.
//!
//! Any thread can schedule a closure to be run by the main loop on the main
//! thread via [`glib::idle_add`](../glib/source/fn.idle_add.html) or
//! [`glib::timeout_add`](../glib/source/fn.timeout_add.html). This crate has
//! versions of those functions without the `Send` bound, which may only be
//! called from the main thread: [`idle_add`](fn.idle_add.html),
//! [`timeout_add`](fn.timeout_add.html).
//!
//! # Panics
//!
//! This and the `gdk` crate have some run-time safety and contract checks:
//!
//! - Any constructor or free function will panic if called before `init` or on
//! a non-main thread.
//!
//! - Any `&str` or `&Path` parameter with an interior null (`\0`) character will
//! cause a panic.
//!
//! - Some functions will panic if supplied out-of-range integer parameters. All
//! such cases will be documented individually but they're not yet.
//!
//! **A panic in a closure will abort the process.**
//!
//! # Crate features
//!
//! ## Library versions
//!
//! By default this crate provides only GTK+ 3.4 APIs. You can access more
//! modern APIs by selecting one of the following features: `v3_6`, `v3_8`,
//! `v3_10`, `v3_12`, `v3_14`, `v3_16`.
//!
//! `Cargo.toml` example:
//!
//! ```toml
//! [dependencies.gtk]
//! version = "0.x.y"
//! features = ["v3_16"]
//! ```
//!
//! **Take care when choosing the version to target: some of your users might
//! not have easy access to the latest ones.** The higher the version, the fewer
//! users will have it installed.
//!
//! ## Lgpl-docs
//!
//! The Gtk-rs crates come with API docs missing because of licensing
//! incompatibilty. You can embed those docs locally via the `embed-lgpl-docs`
//! feature, e.g.
//!
//! ```shell
//! > cargo doc --features embed-lgpl-docs
//! ```
//!
//! Its counterpart `purge-lgpl-docs` removes those docs regardless of edits.
//!
//! These features **rewrite the crate sources** so it's sufficient to enable
//! them once. **Omitting them in the following cargo invocations will not undo
//! their effects!**

#![cfg_attr(feature = "cargo-clippy", allow(let_unit_value))]
#![cfg_attr(feature = "cargo-clippy", allow(new_without_default))]
#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
#![cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
#![cfg_attr(feature = "cargo-clippy", allow(trivially_copy_pass_by_ref))]
#![cfg_attr(feature = "cargo-clippy", allow(derive_hash_xor_eq))]
#![allow(deprecated)]

extern crate libc;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate lazy_static;

extern crate glib_sys as glib_ffi;
extern crate gio_sys as gio_ffi;
extern crate gdk_sys as gdk_ffi;
extern crate gdk_pixbuf_sys as gdk_pixbuf_ffi;
extern crate gobject_sys as gobject_ffi;
extern crate gtk_sys as ffi;
extern crate cairo_sys as cairo_ffi;
#[macro_use]
extern crate glib;
extern crate gio;
extern crate gdk;
extern crate gdk_pixbuf;
extern crate cairo;
extern crate pango;

#[cfg(feature = "futures")]
extern crate send_cell;
#[cfg(feature = "futures")]
extern crate futures_core;

pub use glib::{
    Cast,
    Continue,
    Error,
    IsA,
    Object,
    StaticType,
    ToValue,
    Type,
    TypedValue,
    Value,
};

pub mod xlib;

pub const STYLE_PROVIDER_PRIORITY_FALLBACK: u32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_FALLBACK as u32;
pub const STYLE_PROVIDER_PRIORITY_THEME: u32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_THEME as u32;
pub const STYLE_PROVIDER_PRIORITY_SETTINGS: u32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_SETTINGS as u32;
pub const STYLE_PROVIDER_PRIORITY_APPLICATION: u32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32;
pub const STYLE_PROVIDER_PRIORITY_USER: u32 = ffi::GTK_STYLE_PROVIDER_PRIORITY_USER as u32;

#[macro_use]
mod rt;

#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
#[cfg_attr(feature = "cargo-clippy", allow(let_and_return))]
#[cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))]
#[cfg_attr(feature = "cargo-clippy", allow(wrong_self_convention))]
mod auto;

mod app_chooser;
mod application;
mod application_window;
mod assistant;
mod buildable;
mod builder;
mod border;
mod clipboard;
mod color_button;
mod color_chooser;
mod dialog;
mod drag_context;
mod entry_buffer;
mod entry_completion;
mod enums;
mod file_chooser_dialog;
mod fixed;
mod im_context_simple;
mod invisible;
#[cfg(any(feature = "v3_10", feature = "dox"))]
mod list_box;
mod list_store;
mod menu;
mod message_dialog;
mod notebook;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod pad_action_entry;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod pad_controller;
mod page_range;
mod print_settings;
mod radio_button;
mod radio_menu_item;
mod radio_tool_button;
mod recent_chooser_dialog;
mod recent_data;
mod requisition;
mod signal;
#[cfg(any(target_os = "linux", feature = "dox"))]
mod socket;
mod switch;
mod target_entry;
mod target_list;
mod text_buffer;
mod text_iter;
mod tree_model_filter;
mod tree_row_reference;
mod tree_sortable;
mod tree_path;
mod tree_store;
mod widget;
mod window;

pub mod prelude;

pub use auto::*;
pub use auto::functions::*;
pub use rt::*;
pub use signal::*;
pub use prelude::*;

pub use gdk::Rectangle as Allocation;
pub use gdk::Rectangle;

pub use app_chooser::AppChooser;
pub use border::Border;
pub use entry_buffer::EntryBuffer;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use pad_action_entry::PadActionEntry;
pub use page_range::PageRange;
pub use recent_data::RecentData;
pub use requisition::Requisition;
#[cfg(any(target_os = "linux", feature = "dox"))]
pub use socket::Socket;
pub use target_entry::TargetEntry;
pub use tree_sortable::SortColumn;
<|endoftext|>


<commit_before>//!
//! ### Namespaces
//!
//! The XPath specification assumes that the XML being processed has a
//! prefix defined for every namespace present in the document. If you
//! are processing XML that was parsed from text, this will be true by
//! construction.
//!
//! If you have programmatically created XML with namespaces but not
//! defined prefixes, some XPath behavior may be confusing:
//!
//! 1. The `name` method will not include a prefix, even if the
//! element or attribute has a namespace.
//! 2. The `namespace` axis will not include namespaces without
//! prefixes.
//!

#![cfg_attr(feature = "unstable", feature(iter_cmp))]

#[macro_use]
extern crate peresil;
extern crate sxd_document;

use std::borrow::ToOwned;
use std::collections::HashMap;
use std::{iter,string};

use self::Value::{Boolean,Number,String};

use nodeset::{Nodeset,Node};
use parser::Parser;
use tokenizer::{Tokenizer,TokenDeabbreviator};

pub use function::Function;
pub use expression::Expression;

#[macro_use]
pub mod macros;
pub mod nodeset;
pub mod axis;
mod expression;
pub mod function;
mod node_test;
pub mod parser;
mod token;
pub mod tokenizer;

// TODO - this doesn't need to be public, figure out how to make it so
#[derive(PartialEq,Debug,Clone)]
pub enum LiteralValue {
    Boolean(bool),
    Number(f64),
    String(string::String),
}

impl LiteralValue {
    fn into_value<'d>(self) -> Value<'d> {
        match self {
            LiteralValue::Boolean(v) => Boolean(v),
            LiteralValue::Number(v)  => Number(v),
            LiteralValue::String(v)  => String(v),
        }
    }
}

#[derive(PartialEq,Debug,Clone)]
pub enum Value<'d> {
    Boolean(bool),
    Number(f64),
    String(string::String),
    Nodeset(Nodeset<'d>),
}

fn str_to_num(s: &str) -> f64 {
    s.trim().parse().unwrap_or(::std::f64::NAN)
}

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

    pub fn number(&self) -> f64 {
        use Value::*;
        match *self {
            Boolean(val) => if val { 1.0 } else { 0.0 },
            Number(val) => val,
            String(ref s) => str_to_num(s),
            Nodeset(..) => str_to_num(&self.string()),
        }
    }

    pub fn string(&self) -> string::String {
        use Value::*;
        match *self {
            Boolean(v) => v.to_string(),
            Number(n) => {
                if n.is_infinite() {
                    if n.signum() < 0.0 {
                        "-Infinity".to_owned()
                    } else {
                        "Infinity".to_owned()
                    }
                } else {
                    n.to_string()
                }
            },
            String(ref val) => val.clone(),
            Nodeset(ref ns) => match ns.document_order_first() {
                Some(n) => n.string_value(),
                None => "".to_owned(),
            },
        }
    }

    #[allow(dead_code)]
    fn into_literal_value(self) -> LiteralValue {
        use Value::*;
        match self {
            Boolean(v) => LiteralValue::Boolean(v),
            Number(v)  => LiteralValue::Number(v),
            String(v)  => LiteralValue::String(v),
            Nodeset(_) => panic!("Cannot convert a nodeset to a literal"),
        }
    }
}

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

#[derive(Copy,Clone)]
pub struct EvaluationContext<'a, 'd : 'a> {
    node: Node<'d>,
    functions: &'a Functions,
    variables: &'a Variables<'d>,
    namespaces: &'a Namespaces,
    position: usize,
    size: usize,
}

impl<'a, 'd> EvaluationContext<'a, 'd> {
    pub fn new<N>(node: N,
                  functions: &'a Functions,
                  variables: &'a Variables<'d>,
                  namespaces: &'a Namespaces)
                  -> EvaluationContext<'a, 'd>
        where N: Into<Node<'d>>
    {
        EvaluationContext {
            node: node.into(),
            functions: functions,
            variables: variables,
            namespaces: namespaces,
            position: 1,
            size: 1,
        }
    }

    fn new_context_for<N>(&self, node: N) -> EvaluationContext<'a, 'd>
        where N: Into<Node<'d>>
    {
        EvaluationContext {
            node: node.into(),
            .. *self
        }
    }

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

    fn size(&self) -> usize {
        self.size
    }

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

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

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

    fn predicate_iter<'p>(&'p self, nodes: Nodeset<'d>)
                          -> EvaluationContextPredicateIter<'a, 'd, 'p>
    {
        let sz = nodes.size();
        EvaluationContextPredicateIter {
            parent: self,
            nodes: nodes.into_iter().enumerate(),
            size: sz,
        }
    }
}

struct EvaluationContextPredicateIter<'a : 'p, 'd : 'a + 'p, 'p> {
    parent: &'p EvaluationContext<'a, 'd>,
    nodes: iter::Enumerate<nodeset::IntoIter<'d>>,
    size: usize,
}

impl<'a, 'd, 'p> Iterator for EvaluationContextPredicateIter<'a, 'd, 'p> {
    type Item = EvaluationContext<'a, 'd>;

    fn next(&mut self) -> Option<EvaluationContext<'a, 'd>> {
        self.nodes.next().map(|(idx, node)| {
            EvaluationContext {
                node: node,
                position: idx + 1,
                size: self.size,
                .. *self.parent
            }
        })
    }
}

pub struct Factory {
    parser: Parser,
}

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

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

        self.parser.parse(deabbreviator)
    }
}

#[cfg(test)]
mod test {
    use std::borrow::ToOwned;

    use sxd_document::Package;

    use super::Value;

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

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

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

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

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

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

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

        let c1 = doc.create_comment("42.42");
        let c2 = doc.create_comment("1234");
        doc.root().append_child(c1);
        doc.root().append_child(c2);

        let v = Value::Nodeset(nodeset![c2, c1]);
        assert_eq!(42.42, v.number());
    }

    #[test]
    fn string_of_true_is_true() {
        let v = Value::Boolean(true);
        assert_eq!("true", v.string());
    }

    #[test]
    fn string_of_false_is_false() {
        let v = Value::Boolean(false);
        assert_eq!("false", v.string());
    }

    #[test]
    fn string_of_nan_is_nan() {
        let v = Value::Number(::std::f64::NAN);
        assert_eq!("NaN", v.string());
    }

    #[test]
    fn string_of_positive_zero_is_zero() {
        let v = Value::Number(0.0);
        assert_eq!("0", v.string());
    }

    #[test]
    fn string_of_negative_zero_is_zero() {
        let v = Value::Number(-0.0);
        assert_eq!("0", v.string());
    }

    #[test]
    fn string_of_positive_infinity_is_infinity() {
        let v = Value::Number(::std::f64::INFINITY);
        assert_eq!("Infinity", v.string());
    }

    #[test]
    fn string_of_negative_infinity_is_minus_infinity() {
        let v = Value::Number(::std::f64::NEG_INFINITY);
        assert_eq!("-Infinity", v.string());
    }

    #[test]
    fn string_of_integer_has_no_decimal() {
        let v = Value::Number(-42.0);
        assert_eq!("-42", v.string());
    }

    #[test]
    fn string_of_decimal_has_fractional_part() {
        let v = Value::Number(1.2);
        assert_eq!("1.2", v.string());
    }

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

        let c1 = doc.create_comment("comment 1");
        let c2 = doc.create_comment("comment 2");
        doc.root().append_child(c1);
        doc.root().append_child(c2);

        let v = Value::Nodeset(nodeset![c2, c1]);
        assert_eq!("comment 1", v.string());
    }
}
<commit_msg>exported expression::Error (fixes #67)<commit_after>//!
//! ### Namespaces
//!
//! The XPath specification assumes that the XML being processed has a
//! prefix defined for every namespace present in the document. If you
//! are processing XML that was parsed from text, this will be true by
//! construction.
//!
//! If you have programmatically created XML with namespaces but not
//! defined prefixes, some XPath behavior may be confusing:
//!
//! 1. The `name` method will not include a prefix, even if the
//! element or attribute has a namespace.
//! 2. The `namespace` axis will not include namespaces without
//! prefixes.
//!

#![cfg_attr(feature = "unstable", feature(iter_cmp))]

#[macro_use]
extern crate peresil;
extern crate sxd_document;

use std::borrow::ToOwned;
use std::collections::HashMap;
use std::{iter,string};

use self::Value::{Boolean,Number,String};

use nodeset::{Nodeset,Node};
use parser::Parser;
use tokenizer::{Tokenizer,TokenDeabbreviator};

pub use function::Function;
pub use expression::Expression;
pub use expression::Error as ExpressionError;

#[macro_use]
pub mod macros;
pub mod nodeset;
pub mod axis;
mod expression;
pub mod function;
mod node_test;
pub mod parser;
mod token;
pub mod tokenizer;

// TODO - this doesn't need to be public, figure out how to make it so
#[derive(PartialEq,Debug,Clone)]
pub enum LiteralValue {
    Boolean(bool),
    Number(f64),
    String(string::String),
}

impl LiteralValue {
    fn into_value<'d>(self) -> Value<'d> {
        match self {
            LiteralValue::Boolean(v) => Boolean(v),
            LiteralValue::Number(v)  => Number(v),
            LiteralValue::String(v)  => String(v),
        }
    }
}

#[derive(PartialEq,Debug,Clone)]
pub enum Value<'d> {
    Boolean(bool),
    Number(f64),
    String(string::String),
    Nodeset(Nodeset<'d>),
}

fn str_to_num(s: &str) -> f64 {
    s.trim().parse().unwrap_or(::std::f64::NAN)
}

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

    pub fn number(&self) -> f64 {
        use Value::*;
        match *self {
            Boolean(val) => if val { 1.0 } else { 0.0 },
            Number(val) => val,
            String(ref s) => str_to_num(s),
            Nodeset(..) => str_to_num(&self.string()),
        }
    }

    pub fn string(&self) -> string::String {
        use Value::*;
        match *self {
            Boolean(v) => v.to_string(),
            Number(n) => {
                if n.is_infinite() {
                    if n.signum() < 0.0 {
                        "-Infinity".to_owned()
                    } else {
                        "Infinity".to_owned()
                    }
                } else {
                    n.to_string()
                }
            },
            String(ref val) => val.clone(),
            Nodeset(ref ns) => match ns.document_order_first() {
                Some(n) => n.string_value(),
                None => "".to_owned(),
            },
        }
    }

    #[allow(dead_code)]
    fn into_literal_value(self) -> LiteralValue {
        use Value::*;
        match self {
            Boolean(v) => LiteralValue::Boolean(v),
            Number(v)  => LiteralValue::Number(v),
            String(v)  => LiteralValue::String(v),
            Nodeset(_) => panic!("Cannot convert a nodeset to a literal"),
        }
    }
}

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

#[derive(Copy,Clone)]
pub struct EvaluationContext<'a, 'd : 'a> {
    node: Node<'d>,
    functions: &'a Functions,
    variables: &'a Variables<'d>,
    namespaces: &'a Namespaces,
    position: usize,
    size: usize,
}

impl<'a, 'd> EvaluationContext<'a, 'd> {
    pub fn new<N>(node: N,
                  functions: &'a Functions,
                  variables: &'a Variables<'d>,
                  namespaces: &'a Namespaces)
                  -> EvaluationContext<'a, 'd>
        where N: Into<Node<'d>>
    {
        EvaluationContext {
            node: node.into(),
            functions: functions,
            variables: variables,
            namespaces: namespaces,
            position: 1,
            size: 1,
        }
    }

    fn new_context_for<N>(&self, node: N) -> EvaluationContext<'a, 'd>
        where N: Into<Node<'d>>
    {
        EvaluationContext {
            node: node.into(),
            .. *self
        }
    }

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

    fn size(&self) -> usize {
        self.size
    }

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

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

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

    fn predicate_iter<'p>(&'p self, nodes: Nodeset<'d>)
                          -> EvaluationContextPredicateIter<'a, 'd, 'p>
    {
        let sz = nodes.size();
        EvaluationContextPredicateIter {
            parent: self,
            nodes: nodes.into_iter().enumerate(),
            size: sz,
        }
    }
}

struct EvaluationContextPredicateIter<'a : 'p, 'd : 'a + 'p, 'p> {
    parent: &'p EvaluationContext<'a, 'd>,
    nodes: iter::Enumerate<nodeset::IntoIter<'d>>,
    size: usize,
}

impl<'a, 'd, 'p> Iterator for EvaluationContextPredicateIter<'a, 'd, 'p> {
    type Item = EvaluationContext<'a, 'd>;

    fn next(&mut self) -> Option<EvaluationContext<'a, 'd>> {
        self.nodes.next().map(|(idx, node)| {
            EvaluationContext {
                node: node,
                position: idx + 1,
                size: self.size,
                .. *self.parent
            }
        })
    }
}

pub struct Factory {
    parser: Parser,
}

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

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

        self.parser.parse(deabbreviator)
    }
}

#[cfg(test)]
mod test {
    use std::borrow::ToOwned;

    use sxd_document::Package;

    use super::Value;

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

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

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

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

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

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

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

        let c1 = doc.create_comment("42.42");
        let c2 = doc.create_comment("1234");
        doc.root().append_child(c1);
        doc.root().append_child(c2);

        let v = Value::Nodeset(nodeset![c2, c1]);
        assert_eq!(42.42, v.number());
    }

    #[test]
    fn string_of_true_is_true() {
        let v = Value::Boolean(true);
        assert_eq!("true", v.string());
    }

    #[test]
    fn string_of_false_is_false() {
        let v = Value::Boolean(false);
        assert_eq!("false", v.string());
    }

    #[test]
    fn string_of_nan_is_nan() {
        let v = Value::Number(::std::f64::NAN);
        assert_eq!("NaN", v.string());
    }

    #[test]
    fn string_of_positive_zero_is_zero() {
        let v = Value::Number(0.0);
        assert_eq!("0", v.string());
    }

    #[test]
    fn string_of_negative_zero_is_zero() {
        let v = Value::Number(-0.0);
        assert_eq!("0", v.string());
    }

    #[test]
    fn string_of_positive_infinity_is_infinity() {
        let v = Value::Number(::std::f64::INFINITY);
        assert_eq!("Infinity", v.string());
    }

    #[test]
    fn string_of_negative_infinity_is_minus_infinity() {
        let v = Value::Number(::std::f64::NEG_INFINITY);
        assert_eq!("-Infinity", v.string());
    }

    #[test]
    fn string_of_integer_has_no_decimal() {
        let v = Value::Number(-42.0);
        assert_eq!("-42", v.string());
    }

    #[test]
    fn string_of_decimal_has_fractional_part() {
        let v = Value::Number(1.2);
        assert_eq!("1.2", v.string());
    }

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

        let c1 = doc.create_comment("comment 1");
        let c2 = doc.create_comment("comment 2");
        doc.root().append_child(c1);
        doc.root().append_child(c2);

        let v = Value::Nodeset(nodeset![c2, c1]);
        assert_eq!("comment 1", v.string());
    }
}
<|endoftext|>


<commit_before>//! Body Parser middleware for Iron
#![crate_id = "bodyparser"]
#![license = "MIT"]

extern crate iron;
extern crate serialize;

use iron::{Request, Response, Middleware, Alloy};
use iron::middleware::{Status, Continue, Unwind};

use serialize::json;
use serialize::json::Json;

#[deriving(Clone)]
struct Parsed(Json);

#[deriving(Clone)]
pub struct BodyParser;

impl BodyParser {
    pub fn new() -> BodyParser {
        BodyParser
    }
}

impl Middleware for BodyParser {
    fn enter(&mut self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status {
        if req.body.len() != 0 {
            let parse = json::from_str(req.body.as_slice());
            match parse {
                Ok(e) => {
                    alloy.insert::<Parsed>(Parsed(e));
                },
                Err(e) => {
                    return Continue;
                }
            }
        }
        Continue
    }
}<commit_msg>(refactor) Changed variable names<commit_after>//! Body Parser middleware for Iron
#![crate_id = "bodyparser"]
#![license = "MIT"]

extern crate iron;
extern crate serialize;

use iron::{Request, Response, Middleware, Alloy};
use iron::middleware::{Status, Continue, Unwind};

use serialize::json;
use serialize::json::Json;

#[deriving(Clone)]
struct Parsed(Json);

#[deriving(Clone)]
pub struct BodyParser;

impl BodyParser {
    pub fn new() -> BodyParser {
        BodyParser
    }
}

impl Middleware for BodyParser {
    fn enter(&mut self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status {
        if !req.body.is_empty() {
            let parse = json::from_str(req.body.as_slice());
            match parse {
                Ok(k) => {
                    alloy.insert::<Parsed>(Parsed(k));
                },
                Err(k) => {
                    return Continue;
                }
            }
        }
        Continue
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Token {
    Output,
    Input,
    Loop,
    EndLoop,
    Move(i32),
    Add(i32, i32),
    Set(i32, i32),
    MulCopy(i32, i32, i32),
    MulSet(i32, i32, i32),
    Scan(i32),
    LoadOut(i32, i32),
    LoadOutSet(i32),
    If(i32),
    EndIf,
}
use Token::*;

pub fn parse(code: &str) -> Vec<Token> {
    let mut tokens = Vec::with_capacity(code.len());
    for i in code.chars() {
        match i {
            '+' => tokens.push(Add(0, 1)),
            '-' => tokens.push(Add(0, -1)),
            '>' => tokens.push(Move(1)),
            '<' => tokens.push(Move(-1)),
            '[' => tokens.push(Loop),
            ']' => tokens.push(EndLoop),
            ',' => tokens.push(Input),
            '.' => {
                tokens.push(LoadOut(0, 0));
                tokens.push(Output);
            },
            _ => ()
        };
    }

    tokens
    }

pub fn optimize(tokens: Vec<Token>) -> Vec<Token> {
    let mut newtokens: Vec<Token> = Vec::with_capacity(tokens.len());
    let mut shift = 0;
    let mut do_output = false;
    // With HashMap, the order sometimes switches
    // in recursion, and the optimizer never exits.
    let mut adds: BTreeMap<i32, i32> = BTreeMap::new();
    let mut sets: BTreeMap<i32, i32> = BTreeMap::new();
    let mut pre_loop_sets: BTreeMap<i32, i32> = BTreeMap::new();

    for token in tokens.iter() {
        if *token == EndLoop && newtokens.last() == Some(&Loop) && shift == 0 && adds.contains_key(&0) {
            if adds.len() == 1 {
                newtokens.pop(); // Remove Loop
                if !sets.is_empty() {
                    newtokens.push(If(0));
                    for (offset, value) in sets.iter() {
                        newtokens.push(Set(*offset, *value));
                    }
                    sets.clear();
                    newtokens.push(Set(0, 0));
                    newtokens.push(EndIf);
                } else {
                    sets.insert(0, 0);
                }
                pre_loop_sets.clear();
                adds.clear();
                continue
            } else if adds.get(&0) == Some(&-1) {
                newtokens.pop(); // Remove Loop
                if !sets.is_empty() {
                    newtokens.push(If(0));
                    for (offset, value) in sets.iter() {
                        newtokens.push(Set(*offset, *value));
                    }
                }
                for (offset, value) in adds.iter() {
                    if *offset != 0 {
                        let src = 0;
                        let dest = *offset;
                        let mul = *value;
                        if pre_loop_sets.contains_key(&src) {
                            let val = pre_loop_sets.get(&src).unwrap() * mul;
                            newtokens.push(Add(dest, val));
                        } else {
                            newtokens.push(MulCopy(src, dest, mul));
                        }
                    }
                }
                if !sets.is_empty() {
                    newtokens.push(EndIf);
                }
                pre_loop_sets.clear();
                adds.clear();
                sets.clear();
                sets.insert(0, 0);
                continue
            }
        }

        match *token {
            Loop => {
                pre_loop_sets.clear();
                for (offset, value) in sets.iter() {
                    pre_loop_sets.insert(*offset+shift, *value);
                }
            },
            Set(_, _) | Add(_, _) | Move(_) => {},
            _ => pre_loop_sets.clear()
        }

        match *token {
            Set(_, _) | Add(_, _) | Move(_) | LoadOut(_, _) | LoadOutSet(_) | Output => {},
            _ => {
               if do_output {
                   newtokens.push(Output);
                   do_output = false;
               }

               for (offset, value) in sets.iter() {
                  newtokens.push(Set(*offset, *value));
               }
               for (offset, value) in adds.iter() {
                  newtokens.push(Add(*offset, *value));
               }
               sets.clear();
               adds.clear();
            }
        }

        if shift != 0 {
           match *token {
               Loop | Input | Scan(_) => {
                   newtokens.push(Move(shift));
                   shift = 0;
               },
               _ => {}
           }
        }

        match *token {
            Set(mut offset, val) => {
                offset += shift;
                // Add before Set does nothing; remove it
                adds.remove(&offset);
                sets.insert(offset, val);
            },
            Add(mut offset, mut val) => {
                offset += shift;
                if sets.contains_key(&offset) {
                    val = sets.get(&offset).unwrap() + val;
                    sets.insert(offset, val);
                } else {
                    val = adds.get(&offset).unwrap_or(&0) + val;
                    adds.insert(offset, val);
                }
            },
            MulCopy(src, dest, mul) => {
                if let Some(&Set(dest, 0)) = newtokens.last() {
                    newtokens.pop(); // Remove Set
                    newtokens.push(MulSet(src+shift, dest+shift, mul));
                } else {
                    newtokens.push(MulCopy(src+shift, dest+shift, mul));
                }
            },
            MulSet(src, dest, mul) =>
                newtokens.push(MulSet(src+shift, dest+shift, mul)),
            // XXX Deal with shift in if, if those are ever generated
            If(offset) =>
                newtokens.push(If(offset+shift)),
            Move(offset) =>
                shift += offset,
            Output =>
                do_output = true,
            LoadOut(mut offset, add) => {
                offset += shift;
                if sets.contains_key(&offset) {
                    newtokens.push(LoadOutSet(sets.get(&offset).unwrap() + add));
                } else {
                    newtokens.push(LoadOut(offset, adds.get(&offset).unwrap_or(&0) + add));
                }
            },
            EndLoop => {
                if newtokens.last() == Some(&Loop) && shift != 0 && sets.is_empty() && adds.is_empty() {
                    newtokens.pop(); // Remove StartLoop
                    newtokens.push(Scan(shift));
                } else {
                    if shift != 0 {
                        newtokens.push(Move(shift));
                    }
                    newtokens.push(EndLoop);
                }
                shift = 0;
            },
            EndIf | LoadOutSet(_) | Loop | Input | Scan(_) =>
                newtokens.push(*token),
        }
    }

    // Any remaining add/set/shift is ignored, as it would have no effect
    if do_output {
        newtokens.push(Output);
    }

    // Optimize recursively
    if newtokens != tokens {
        optimize(newtokens)
    } else {
        newtokens
    }
}
<commit_msg>Save a few characters<commit_after>use std::collections::BTreeMap;

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Token {
    Output,
    Input,
    Loop,
    EndLoop,
    Move(i32),
    Add(i32, i32),
    Set(i32, i32),
    MulCopy(i32, i32, i32),
    MulSet(i32, i32, i32),
    Scan(i32),
    LoadOut(i32, i32),
    LoadOutSet(i32),
    If(i32),
    EndIf,
}
use Token::*;

pub fn parse(code: &str) -> Vec<Token> {
    let mut tokens = Vec::with_capacity(code.len());
    for i in code.chars() {
        match i {
            '+' => tokens.push(Add(0, 1)),
            '-' => tokens.push(Add(0, -1)),
            '>' => tokens.push(Move(1)),
            '<' => tokens.push(Move(-1)),
            '[' => tokens.push(Loop),
            ']' => tokens.push(EndLoop),
            ',' => tokens.push(Input),
            '.' => {
                tokens.push(LoadOut(0, 0));
                tokens.push(Output);
            },
            _ => ()
        };
    }

    tokens
    }

pub fn optimize(tokens: Vec<Token>) -> Vec<Token> {
    let mut newtokens: Vec<Token> = Vec::with_capacity(tokens.len());
    let mut shift = 0;
    let mut do_output = false;
    // With HashMap, the order sometimes switches
    // in recursion, and the optimizer never exits.
    let mut adds: BTreeMap<i32, i32> = BTreeMap::new();
    let mut sets: BTreeMap<i32, i32> = BTreeMap::new();
    let mut pre_loop_sets: BTreeMap<i32, i32> = BTreeMap::new();

    for token in tokens.iter() {
        if *token == EndLoop && newtokens.last() == Some(&Loop) && shift == 0 && adds.contains_key(&0) {
            if adds.len() == 1 {
                newtokens.pop(); // Remove Loop
                if !sets.is_empty() {
                    newtokens.push(If(0));
                    for (offset, value) in sets.iter() {
                        newtokens.push(Set(*offset, *value));
                    }
                    sets.clear();
                    newtokens.push(Set(0, 0));
                    newtokens.push(EndIf);
                } else {
                    sets.insert(0, 0);
                }
                pre_loop_sets.clear();
                adds.clear();
                continue
            } else if adds.get(&0) == Some(&-1) {
                newtokens.pop(); // Remove Loop
                if !sets.is_empty() {
                    newtokens.push(If(0));
                    for (offset, value) in sets.iter() {
                        newtokens.push(Set(*offset, *value));
                    }
                }
                for (offset, value) in adds.iter() {
                    if *offset != 0 {
                        let src = 0;
                        let dest = *offset;
                        let mul = *value;
                        if pre_loop_sets.contains_key(&src) {
                            let val = pre_loop_sets.get(&src).unwrap() * mul;
                            newtokens.push(Add(dest, val));
                        } else {
                            newtokens.push(MulCopy(src, dest, mul));
                        }
                    }
                }
                if !sets.is_empty() {
                    newtokens.push(EndIf);
                }
                pre_loop_sets.clear();
                adds.clear();
                sets.clear();
                sets.insert(0, 0);
                continue
            }
        }

        match *token {
            Loop => {
                pre_loop_sets.clear();
                for (offset, value) in sets.iter() {
                    pre_loop_sets.insert(*offset+shift, *value);
                }
            },
            Set(..) | Add(..) | Move(_) => {},
            _ => pre_loop_sets.clear()
        }

        match *token {
            Set(..) | Add(..) | Move(_) | LoadOut(..) | LoadOutSet(_) | Output => {},
            _ => {
               if do_output {
                   newtokens.push(Output);
                   do_output = false;
               }

               for (offset, value) in sets.iter() {
                  newtokens.push(Set(*offset, *value));
               }
               for (offset, value) in adds.iter() {
                  newtokens.push(Add(*offset, *value));
               }
               sets.clear();
               adds.clear();
            }
        }

        if shift != 0 {
           match *token {
               Loop | Input | Scan(_) => {
                   newtokens.push(Move(shift));
                   shift = 0;
               },
               _ => {}
           }
        }

        match *token {
            Set(mut offset, val) => {
                offset += shift;
                // Add before Set does nothing; remove it
                adds.remove(&offset);
                sets.insert(offset, val);
            },
            Add(mut offset, mut val) => {
                offset += shift;
                if sets.contains_key(&offset) {
                    val = sets.get(&offset).unwrap() + val;
                    sets.insert(offset, val);
                } else {
                    val = adds.get(&offset).unwrap_or(&0) + val;
                    adds.insert(offset, val);
                }
            },
            MulCopy(src, dest, mul) => {
                if let Some(&Set(dest, 0)) = newtokens.last() {
                    newtokens.pop(); // Remove Set
                    newtokens.push(MulSet(src+shift, dest+shift, mul));
                } else {
                    newtokens.push(MulCopy(src+shift, dest+shift, mul));
                }
            },
            MulSet(src, dest, mul) =>
                newtokens.push(MulSet(src+shift, dest+shift, mul)),
            // XXX Deal with shift in if, if those are ever generated
            If(offset) =>
                newtokens.push(If(offset+shift)),
            Move(offset) =>
                shift += offset,
            Output =>
                do_output = true,
            LoadOut(mut offset, add) => {
                offset += shift;
                if sets.contains_key(&offset) {
                    newtokens.push(LoadOutSet(sets.get(&offset).unwrap() + add));
                } else {
                    newtokens.push(LoadOut(offset, adds.get(&offset).unwrap_or(&0) + add));
                }
            },
            EndLoop => {
                if newtokens.last() == Some(&Loop) && shift != 0 && sets.is_empty() && adds.is_empty() {
                    newtokens.pop(); // Remove StartLoop
                    newtokens.push(Scan(shift));
                } else {
                    if shift != 0 {
                        newtokens.push(Move(shift));
                    }
                    newtokens.push(EndLoop);
                }
                shift = 0;
            },
            EndIf | LoadOutSet(_) | Loop | Input | Scan(_) =>
                newtokens.push(*token),
        }
    }

    // Any remaining add/set/shift is ignored, as it would have no effect
    if do_output {
        newtokens.push(Output);
    }

    // Optimize recursively
    if newtokens != tokens {
        optimize(newtokens)
    } else {
        newtokens
    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]
#![feature(globs)]

extern crate semver;
extern crate conduit;

use std::iter;
use std::io::net::ip::IpAddr;
use std::collections::hash_map::{HashMap, Entries};

use conduit::{Method, Scheme, Host, Extensions, Headers, Request};

pub trait RequestDelegator {
    fn request<'a>(&'a self) -> &'a Request;
    fn mut_request<'a>(&'a mut self) -> &'a mut Request;

    fn http_version(&self) -> semver::Version {
        self.request().http_version()
    }

    fn conduit_version(&self) -> semver::Version {
        self.request().conduit_version()
    }

    fn method(&self) -> Method {
        self.request().method()
    }

    fn scheme(&self) -> Scheme {
        self.request().scheme()
    }

    fn host<'a>(&'a self) -> Host<'a> {
        self.request().host()
    }

    fn virtual_root<'a>(&'a self) -> Option<&'a str> {
        self.request().virtual_root()
    }

    fn path<'a>(&'a self) -> &'a str {
        self.request().path()
    }

    fn query_string<'a>(&'a self) -> Option<&'a str> {
        self.request().query_string()
    }

    fn remote_ip(&self) -> IpAddr {
        self.request().remote_ip()
    }

    fn content_length(&self) -> Option<uint> {
        self.request().content_length()
    }

    fn headers<'a>(&'a self) -> &'a Headers {
        self.request().headers()
    }

    fn body<'a>(&'a mut self) -> &'a mut Reader {
        self.mut_request().body()
    }

    fn extensions<'a>(&'a self) -> &'a Extensions {
        self.request().extensions()
    }

    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
        self.mut_request().mut_extensions()
    }
}

impl<'a> Request for &'a mut RequestDelegator + 'a {
    fn http_version(&self) -> semver::Version {
        self.http_version()
    }

    fn conduit_version(&self) -> semver::Version {
        self.conduit_version()
    }

    fn method(&self) -> Method {
        self.method()
    }

    fn scheme(&self) -> Scheme {
        self.scheme()
    }

    fn host<'a>(&'a self) -> Host<'a> {
        self.host()
    }

    fn virtual_root<'a>(&'a self) -> Option<&'a str> {
        self.virtual_root()
    }

    fn path<'a>(&'a self) -> &'a str {
        self.path()
    }

    fn query_string<'a>(&'a self) -> Option<&'a str> {
        self.query_string()
    }

    fn remote_ip(&self) -> IpAddr {
        self.remote_ip()
    }

    fn content_length(&self) -> Option<uint> {
        self.content_length()
    }

    fn headers<'a>(&'a self) -> &'a Headers {
        self.headers()
    }

    fn body<'a>(&'a mut self) -> &'a mut Reader {
        self.body()
    }

    fn extensions<'a>(&'a self) -> &'a Extensions {
        self.extensions()
    }

    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
        self.mut_extensions()
    }
}

type RawHeaders = HashMap<String, Vec<String>>;
type InHeader<'a> = (&'a String, &'a Vec<String>);
type OutHeader<'a> = (String, &'a Vec<String>);

#[deriving(PartialEq, Clone, Show)]
pub struct HeaderMap(HashMap<String, Vec<String>>);

impl HeaderMap {
    fn normalize(headers: HashMap<String, Vec<String>>) -> HeaderMap {
        let headers = headers.into_iter().map(|(k,v)| (to_lower(&k), v)).collect();
        HeaderMap(headers)
    }

    fn iter<'a>(&'a self) -> iter::Map<'a, InHeader<'a>, OutHeader<'a>, Entries<'a, String, Vec<String>>> {
        self.as_ref().iter().map(|(k,v)| (to_lower(k), v))
    }

    fn as_ref<'a>(&'a self) -> &'a HashMap<String, Vec<String>> {
        match *self {
            HeaderMap(ref map) => map
        }
    }

    fn as_mut<'a>(&'a mut self) -> &'a mut HashMap<String, Vec<String>> {
        match *self {
            HeaderMap(ref mut map) => map
        }
    }

    pub fn len(&self) -> uint {
        self.as_ref().len()
    }
    pub fn clear(&mut self) {
        self.as_mut().clear()
    }
    pub fn find<'a, S: Str>(&'a self, key: &S) -> Option<&'a Vec<String>> {
        self.as_ref().find(&to_lower(key))
    }
    pub fn insert<S: Str>(&mut self, k: S, v: Vec<String>) -> Option<Vec<String>> {
        self.as_mut().swap(to_lower(&k), v)
    }
    pub fn remove<S: Str>(&mut self, k: &S) -> Option<Vec<String>> {
        self.as_mut().pop(&to_lower(k))
    }

    pub fn find_mut<'a, S: Str>(&'a mut self, k: &S) -> Option<&'a mut Vec<String>> {
        self.as_mut().find_mut(&to_lower(k))
    }
}

fn to_lower<S: Str>(string: &S) -> String {
    string.as_slice().chars().map(|c| c.to_lowercase()).collect()
}

#[cfg(test)]
mod tests {
    extern crate "conduit-test" as test;

    use {RequestDelegator, HeaderMap};

    use std::collections::HashMap;
    use conduit;
    use conduit::{Request, Method};

    struct OverrideRequest<'a> {
        request: &'a mut Request + 'a
    }

    impl<'a> RequestDelegator for OverrideRequest<'a> {
        fn request<'a>(&'a self) -> &'a Request {
            let req: &Request = self.request; req
        }

        fn mut_request<'a>(&'a mut self) -> &'a mut Request {
            let req: &mut Request = self.request; req
        }

        fn method(&self) -> Method {
            conduit::Get
        }
    }

    #[test]
    fn test_delegate() {
        let request = &mut test::MockRequest::new(conduit::Head, "/hello") as &mut Request;
        let new = OverrideRequest { request: request };

        assert_eq!(new.method(), conduit::Get);
        assert_eq!(new.path(), "/hello");
    }

    #[test]
    fn test_header_map() {
        let mut map = HeaderMap(HashMap::new());
        map.insert("Content-Type".to_string(), vec!("text/html".to_string()));
        map.insert("location".to_string(), vec!("http://example.com".to_string()));

        assert_eq!(map.find(&"content-type".to_string()), Some(&vec!("text/html".to_string())))
        assert_eq!(map.find(&"Location".to_string()), Some(&vec!("http://example.com".to_string())))
        assert_eq!(map.find(&"content-type"), Some(&vec!("text/html".to_string())))
        assert_eq!(map.find(&"Location"), Some(&vec!("http://example.com".to_string())))
    }

    #[test]
    fn test_header_map_with_static_inserts() {
        let mut map = HeaderMap(HashMap::new());
        map.insert("Content-Type", vec!("text/html".to_string()));
        map.insert("location", vec!("http://example.com".to_string()));

        assert_eq!(map.find(&"content-type".to_string()), Some(&vec!("text/html".to_string())))
        assert_eq!(map.find(&"Location".to_string()), Some(&vec!("http://example.com".to_string())))
        assert_eq!(map.find(&"content-type"), Some(&vec!("text/html".to_string())))
        assert_eq!(map.find(&"Location"), Some(&vec!("http://example.com".to_string())))
    }

    #[test]
    fn test_normalize() {
        let mut map = HashMap::new();
        map.insert("Content-Type".to_string(), vec!("text/html".to_string()));

        let headers = HeaderMap::normalize(map);
        assert_eq!(headers.find(&"Content-Type".to_string()), Some(&vec!("text/html".to_string())))
        assert_eq!(headers.find(&"Content-Type"), Some(&vec!("text/html".to_string())))
        assert_eq!(headers.find(&"content-type".to_string()), Some(&vec!("text/html".to_string())))
        assert_eq!(headers.find(&"content-type"), Some(&vec!("text/html".to_string())))
    }

    #[test]
    fn test_iterate() {
        let mut headers = HeaderMap(HashMap::new());
        headers.insert("Content-Type", vec!("text/html".to_string()));
        headers.insert("location", vec!("http://example.com".to_string()));

        assert!(headers.iter().any(|t| t == ("content-type".to_string(), &vec!("text/html".to_string()))));
        assert!(headers.iter().any(|t| t == ("location".to_string(), &vec!("http://example.com".to_string()))));
        assert!(headers.iter().count() == 2);
    }
}
<commit_msg>Update to rust master<commit_after>#![feature(macro_rules)]
#![feature(globs)]

extern crate semver;
extern crate conduit;

use std::iter;
use std::io::net::ip::IpAddr;
use std::collections::hash_map::{HashMap, Entries};

use conduit::{Method, Scheme, Host, Extensions, Headers, Request};

pub trait RequestDelegator {
    fn request<'a>(&'a self) -> &'a Request;
    fn mut_request<'a>(&'a mut self) -> &'a mut Request;

    fn http_version(&self) -> semver::Version {
        self.request().http_version()
    }

    fn conduit_version(&self) -> semver::Version {
        self.request().conduit_version()
    }

    fn method(&self) -> Method {
        self.request().method()
    }

    fn scheme(&self) -> Scheme {
        self.request().scheme()
    }

    fn host<'a>(&'a self) -> Host<'a> {
        self.request().host()
    }

    fn virtual_root<'a>(&'a self) -> Option<&'a str> {
        self.request().virtual_root()
    }

    fn path<'a>(&'a self) -> &'a str {
        self.request().path()
    }

    fn query_string<'a>(&'a self) -> Option<&'a str> {
        self.request().query_string()
    }

    fn remote_ip(&self) -> IpAddr {
        self.request().remote_ip()
    }

    fn content_length(&self) -> Option<uint> {
        self.request().content_length()
    }

    fn headers<'a>(&'a self) -> &'a Headers {
        self.request().headers()
    }

    fn body<'a>(&'a mut self) -> &'a mut Reader {
        self.mut_request().body()
    }

    fn extensions<'a>(&'a self) -> &'a Extensions {
        self.request().extensions()
    }

    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
        self.mut_request().mut_extensions()
    }
}

impl<'a> Request for &'a mut RequestDelegator + 'a {
    fn http_version(&self) -> semver::Version {
        self.http_version()
    }

    fn conduit_version(&self) -> semver::Version {
        self.conduit_version()
    }

    fn method(&self) -> Method {
        self.method()
    }

    fn scheme(&self) -> Scheme {
        self.scheme()
    }

    fn host<'a>(&'a self) -> Host<'a> {
        self.host()
    }

    fn virtual_root<'a>(&'a self) -> Option<&'a str> {
        self.virtual_root()
    }

    fn path<'a>(&'a self) -> &'a str {
        self.path()
    }

    fn query_string<'a>(&'a self) -> Option<&'a str> {
        self.query_string()
    }

    fn remote_ip(&self) -> IpAddr {
        self.remote_ip()
    }

    fn content_length(&self) -> Option<uint> {
        self.content_length()
    }

    fn headers<'a>(&'a self) -> &'a Headers {
        self.headers()
    }

    fn body<'a>(&'a mut self) -> &'a mut Reader {
        self.body()
    }

    fn extensions<'a>(&'a self) -> &'a Extensions {
        self.extensions()
    }

    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
        self.mut_extensions()
    }
}

type RawHeaders = HashMap<String, Vec<String>>;
type InHeader<'a> = (&'a String, &'a Vec<String>);
type OutHeader<'a> = (String, &'a Vec<String>);

#[deriving(PartialEq, Clone, Show)]
pub struct HeaderMap(HashMap<String, Vec<String>>);

impl HeaderMap {
    fn normalize(headers: HashMap<String, Vec<String>>) -> HeaderMap {
        let headers = headers.into_iter().map(|(k,v)| (to_lower(&k), v)).collect();
        HeaderMap(headers)
    }

    fn iter<'a>(&'a self) -> iter::Map<'a, InHeader<'a>, OutHeader<'a>, Entries<'a, String, Vec<String>>> {
        self.as_ref().iter().map(|(k,v)| (to_lower(k), v))
    }

    fn as_ref<'a>(&'a self) -> &'a HashMap<String, Vec<String>> {
        match *self {
            HeaderMap(ref map) => map
        }
    }

    fn as_mut<'a>(&'a mut self) -> &'a mut HashMap<String, Vec<String>> {
        match *self {
            HeaderMap(ref mut map) => map
        }
    }

    pub fn len(&self) -> uint {
        self.as_ref().len()
    }
    pub fn clear(&mut self) {
        self.as_mut().clear()
    }
    pub fn find<'a, S: Str>(&'a self, key: &S) -> Option<&'a Vec<String>> {
        self.as_ref().get(&to_lower(key))
    }
    pub fn insert<S: Str>(&mut self, k: S, v: Vec<String>) -> Option<Vec<String>> {
        self.as_mut().insert(to_lower(&k), v)
    }
    pub fn remove<S: Str>(&mut self, k: &S) -> Option<Vec<String>> {
        self.as_mut().remove(&to_lower(k))
    }

    pub fn find_mut<'a, S: Str>(&'a mut self, k: &S) -> Option<&'a mut Vec<String>> {
        self.as_mut().get_mut(&to_lower(k))
    }
}

fn to_lower<S: Str>(string: &S) -> String {
    string.as_slice().chars().map(|c| c.to_lowercase()).collect()
}

#[cfg(test)]
mod tests {
    extern crate "conduit-test" as test;

    use {RequestDelegator, HeaderMap};

    use std::collections::HashMap;
    use conduit;
    use conduit::{Request, Method};

    struct OverrideRequest<'a> {
        request: &'a mut Request + 'a
    }

    impl<'a> RequestDelegator for OverrideRequest<'a> {
        fn request<'a>(&'a self) -> &'a Request {
            let req: &Request = self.request; req
        }

        fn mut_request<'a>(&'a mut self) -> &'a mut Request {
            let req: &mut Request = self.request; req
        }

        fn method(&self) -> Method {
            conduit::Get
        }
    }

    #[test]
    fn test_delegate() {
        let request = &mut test::MockRequest::new(conduit::Head, "/hello") as &mut Request;
        let new = OverrideRequest { request: request };

        assert_eq!(new.method(), conduit::Get);
        assert_eq!(new.path(), "/hello");
    }

    #[test]
    fn test_header_map() {
        let mut map = HeaderMap(HashMap::new());
        map.insert("Content-Type".to_string(), vec!("text/html".to_string()));
        map.insert("location".to_string(), vec!("http://example.com".to_string()));

        assert_eq!(map.find(&"content-type".to_string()), Some(&vec!("text/html".to_string())))
        assert_eq!(map.find(&"Location".to_string()), Some(&vec!("http://example.com".to_string())))
        assert_eq!(map.find(&"content-type"), Some(&vec!("text/html".to_string())))
        assert_eq!(map.find(&"Location"), Some(&vec!("http://example.com".to_string())))
    }

    #[test]
    fn test_header_map_with_static_inserts() {
        let mut map = HeaderMap(HashMap::new());
        map.insert("Content-Type", vec!("text/html".to_string()));
        map.insert("location", vec!("http://example.com".to_string()));

        assert_eq!(map.find(&"content-type".to_string()), Some(&vec!("text/html".to_string())))
        assert_eq!(map.find(&"Location".to_string()), Some(&vec!("http://example.com".to_string())))
        assert_eq!(map.find(&"content-type"), Some(&vec!("text/html".to_string())))
        assert_eq!(map.find(&"Location"), Some(&vec!("http://example.com".to_string())))
    }

    #[test]
    fn test_normalize() {
        let mut map = HashMap::new();
        map.insert("Content-Type".to_string(), vec!("text/html".to_string()));

        let headers = HeaderMap::normalize(map);
        assert_eq!(headers.find(&"Content-Type".to_string()), Some(&vec!("text/html".to_string())))
        assert_eq!(headers.find(&"Content-Type"), Some(&vec!("text/html".to_string())))
        assert_eq!(headers.find(&"content-type".to_string()), Some(&vec!("text/html".to_string())))
        assert_eq!(headers.find(&"content-type"), Some(&vec!("text/html".to_string())))
    }

    #[test]
    fn test_iterate() {
        let mut headers = HeaderMap(HashMap::new());
        headers.insert("Content-Type", vec!("text/html".to_string()));
        headers.insert("location", vec!("http://example.com".to_string()));

        assert!(headers.iter().any(|t| {
            t.0.as_slice() == "content-type" &&
            t.1.as_slice() == &["text/html".to_string()]
        }));
        assert!(headers.iter().any(|t| {
            t.0.as_slice() == "location" &&
            t.1.as_slice() == &["http://example.com".to_string()]
        }));
        assert!(headers.iter().count() == 2);
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;

#[derive(Default)]
pub struct Crate {
    pub include_prefix: Option<PathBuf>,
    pub links: Option<OsString>,
    pub crate_dir: Option<PathBuf>,
    pub include_dir: Option<PathBuf>,
}

impl Crate {
    pub fn print_to_cargo(&self) {
        if let Some(include_prefix) = &self.include_prefix {
            println!("cargo:CXXBRIDGE_PREFIX={}", include_prefix.to_string_lossy());
        }
        if let Some(links) = &self.links {
            println!("cargo:CXXBRIDGE_LINKS={}", links.to_string_lossy());
        }
        if let Some(crate_dir) = &self.crate_dir {
            println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
        }
        if let Some(include_dir) = &self.include_dir {
            println!("cargo:CXXBRIDGE_INCLUDE={}", include_dir.to_string_lossy());
        }
    }
}

pub fn direct_dependencies() -> Vec<Crate> {
    let mut crates: BTreeMap<String, Crate> = BTreeMap::new();

    for (k, v) in env::vars_os() {
        let mut k = k.to_string_lossy().into_owned();
        // Only variables set from a build script of direct dependencies are
        // observable. That's exactly what we want! Your crate needs to declare
        // a direct dependency on the other crate in order to be able to
        // #include its headers.
        //
        // Also, they're only observable if the dependency's manifest contains a
        // `links` key. This is important because Cargo imposes no ordering on
        // the execution of build scripts without a `links` key. When exposing a
        // generated header for the current crate to #include, we need to be
        // sure the dependency's build script has already executed and emitted
        // that generated header.
        //
        // References:
        //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
        //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
        if k.starts_with("DEP_") {
            if k.ends_with("_CXXBRIDGE_PREFIX") {
                k.truncate(k.len() - "_CXXBRIDGE_PREFIX".len());
                crates.entry(k).or_default().include_prefix = Some(PathBuf::from(v));
            } else if k.ends_with("_CXXBRIDGE_LINKS") {
                k.truncate(k.len() - "_CXXBRIDGE_LINKS".len());
                crates.entry(k).or_default().links = Some(v);
            } else if k.ends_with("_CXXBRIDGE_CRATE") {
                k.truncate(k.len() - "_CXXBRIDGE_CRATE".len());
                crates.entry(k).or_default().crate_dir = Some(PathBuf::from(v));
            } else if k.ends_with("_CXXBRIDGE_INCLUDE") {
                k.truncate(k.len() - "_CXXBRIDGE_INCLUDE".len());
                crates.entry(k).or_default().include_dir = Some(PathBuf::from(v));
            }
        }
    }

    crates.into_iter().map(|entry| entry.1).collect()
}
<commit_msg>Reduce nesting in direct_dependencies()<commit_after>use std::collections::BTreeMap;
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;

#[derive(Default)]
pub struct Crate {
    pub include_prefix: Option<PathBuf>,
    pub links: Option<OsString>,
    pub crate_dir: Option<PathBuf>,
    pub include_dir: Option<PathBuf>,
}

impl Crate {
    pub fn print_to_cargo(&self) {
        if let Some(include_prefix) = &self.include_prefix {
            println!("cargo:CXXBRIDGE_PREFIX={}", include_prefix.to_string_lossy());
        }
        if let Some(links) = &self.links {
            println!("cargo:CXXBRIDGE_LINKS={}", links.to_string_lossy());
        }
        if let Some(crate_dir) = &self.crate_dir {
            println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
        }
        if let Some(include_dir) = &self.include_dir {
            println!("cargo:CXXBRIDGE_INCLUDE={}", include_dir.to_string_lossy());
        }
    }
}

pub fn direct_dependencies() -> Vec<Crate> {
    let mut crates: BTreeMap<String, Crate> = BTreeMap::new();

    // Only variables set from a build script of direct dependencies are
    // observable. That's exactly what we want! Your crate needs to declare a
    // direct dependency on the other crate in order to be able to #include its
    // headers.
    //
    // Also, they're only observable if the dependency's manifest contains a
    // `links` key. This is important because Cargo imposes no ordering on the
    // execution of build scripts without a `links` key. When exposing a
    // generated header for the current crate to #include, we need to be sure
    // the dependency's build script has already executed and emitted that
    // generated header.
    //
    // References:
    //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
    //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
    for (k, v) in env::vars_os() {
        let mut k = k.to_string_lossy().into_owned();
        if !k.starts_with("DEP_") {
            continue;
        }

        if k.ends_with("_CXXBRIDGE_PREFIX") {
            k.truncate(k.len() - "_CXXBRIDGE_PREFIX".len());
            crates.entry(k).or_default().include_prefix = Some(PathBuf::from(v));
            continue;
        }

        if k.ends_with("_CXXBRIDGE_LINKS") {
            k.truncate(k.len() - "_CXXBRIDGE_LINKS".len());
            crates.entry(k).or_default().links = Some(v);
            continue;
        }

        if k.ends_with("_CXXBRIDGE_CRATE") {
            k.truncate(k.len() - "_CXXBRIDGE_CRATE".len());
            crates.entry(k).or_default().crate_dir = Some(PathBuf::from(v));
            continue;
        }

        if k.ends_with("_CXXBRIDGE_INCLUDE") {
            k.truncate(k.len() - "_CXXBRIDGE_INCLUDE".len());
            crates.entry(k).or_default().include_dir = Some(PathBuf::from(v));
            continue;
        }
    }

    crates.into_iter().map(|entry| entry.1).collect()
}
<|endoftext|>


<commit_before>#![feature(no_std)]
#![feature(core)]
#![feature(asm)]
#![no_std]

#![crate_name = "raw_cpuid"]
#![crate_type = "lib"]

#[macro_use]
extern crate core;

#[cfg(test)]
#[macro_use]
extern crate std;

const MAX_ENTRIES: usize = 32;

#[derive(Debug)]
pub struct CpuId {
    values: [CpuIdResult; MAX_ENTRIES]
}

#[derive(Debug, Copy)]
pub struct CpuIdResult {
    eax: u32,
    ebx: u32,
    ecx: u32,
    edx: u32
}

impl CpuId {
    pub fn new() -> CpuId {
        let mut cpu = CpuId{ values: [ CpuIdResult{ eax: 0, ebx: 0, ecx: 0, edx: 0}; MAX_ENTRIES] };

        unsafe {
            let mut res: CpuIdResult;
            res = cpuid(0x0);
            cpu.values[0] = res;
            assert!( (res.eax as usize) < MAX_ENTRIES);
            for i in 1..(res.eax as usize) {
                res = cpuid(i as u32);
                cpu.values[i] = res;
            }
        }

        cpu
    }
}

pub unsafe fn cpuid(eax: u32) -> CpuIdResult {
    asm!("movl $0, %eax" : : "r" (eax) : "eax");

    let mut res = CpuIdResult{eax: 0, ebx: 0, ecx: 0, edx: 0};
    asm!("cpuid" : "={eax}"(res.eax) "={ebx}"(res.ebx) "={ecx}"(res.ecx) "={edx}"(res.edx)
                 :
                 : "eax", "ebx", "ecx", "edx");

    res
}

fn to_bytes(val: u32) -> [u8; 4] {
    let mut res: [u8; 4] = [0; 4];

    res[0] = val as u8;
    res[1] = (val >> 8) as u8;
    res[2] = (val >> 16) as u8;
    res[3] = (val >> 24) as u8;
    res
}

fn to_str(t: [u8; 4]) -> [char; 4] {
    let mut arr: [char; 4] = ['\0'; 4];
    for i in 0..4 {
        arr[i] = t[i] as char;
    }

    arr
}

#[test]
fn genuine_intel() {
    let cpu: CpuId = CpuId::new();

    let b = to_str(to_bytes(cpu.values[0].ebx));
    assert!(b[0] == 'G');
    assert!(b[1] == 'e');
    assert!(b[2] == 'n');
    assert!(b[3] == 'u');
}<commit_msg>Expose result.<commit_after>#![feature(no_std)]
#![feature(core)]
#![feature(asm)]
#![no_std]

#![crate_name = "raw_cpuid"]
#![crate_type = "lib"]

#[macro_use]
extern crate core;

#[cfg(test)]
#[macro_use]
extern crate std;

const MAX_ENTRIES: usize = 32;

#[derive(Debug)]
pub struct CpuId {
    values: [CpuIdResult; MAX_ENTRIES]
}

#[derive(Debug, Copy)]
pub struct CpuIdResult {
    pub eax: u32,
    pub ebx: u32,
    pub ecx: u32,
    pub edx: u32
}

impl CpuId {
    pub fn new() -> CpuId {
        let mut cpu = CpuId{ values: [ CpuIdResult{ eax: 0, ebx: 0, ecx: 0, edx: 0}; MAX_ENTRIES] };

        unsafe {
            cpu.values[0] = cpuid(0x0);
            assert!( (cpu.values[0].eax as usize) < MAX_ENTRIES);
            for i in 1..(cpu.values[0].eax as usize) {
                cpu.values[i] = cpuid(i as u32);
            }
        }

        cpu
    }

    pub fn get(&self, eax: usize) -> &CpuIdResult {
        return &self.values[eax];
    }
}

pub unsafe fn cpuid(eax: u32) -> CpuIdResult {
    asm!("movl $0, %eax" : : "r" (eax) : "eax");

    let mut res = CpuIdResult{eax: 0, ebx: 0, ecx: 0, edx: 0};
    asm!("cpuid" : "={eax}"(res.eax) "={ebx}"(res.ebx) "={ecx}"(res.ecx) "={edx}"(res.edx)
                 :
                 : "eax", "ebx", "ecx", "edx");

    res
}

fn to_bytes(val: u32) -> [u8; 4] {
    let mut res: [u8; 4] = [0; 4];

    res[0] = val as u8;
    res[1] = (val >> 8) as u8;
    res[2] = (val >> 16) as u8;
    res[3] = (val >> 24) as u8;
    res
}

fn to_str(t: [u8; 4]) -> [char; 4] {
    let mut arr: [char; 4] = ['\0'; 4];
    for i in 0..4 {
        arr[i] = t[i] as char;
    }

    arr
}

#[test]
fn genuine_intel() {
    let cpu: CpuId = CpuId::new();

    let b = to_str(to_bytes(cpu.values[0].ebx));
    assert!(b[0] == 'G');
    assert!(b[1] == 'e');
    assert!(b[2] == 'n');
    assert!(b[3] == 'u');
}<|endoftext|>


<commit_before>/****************************************************************************
*
*   lib.rs
*   opter
*
*   Copyright (c) 2015 Tyler Cole
*
*   Details:
*   - options come in four flavors
*     - flag is name without value
*     - ordinal is value without name
*     - named is value with a name
*     - value is simply a raw value
*   - full names start with "--" and short names with "-"
*   - short name flags can be stacked with "-"
*     - "-abc" represents the flags a, b, and c
*   - "-" with no following characters is a value
*   - "--" signifies end of options and is not emitted
*     - all values following "--" are simply passed along
*
***/

use std::env;
use std::iter;

/****************************************************************************
*
*   Opt
*
***/

#[derive(Debug)]
#[derive(PartialEq)]
pub enum Opt {
    Flag(String),
    Named(String, String),
    Ordinal(String),
    Raw(String),
}

/****************************************************************************
*
*   OptIter
*
***/

pub struct OptIter<I> where I : Iterator<Item = String> {
    iter  : I,
    flags : Vec<char>,
    name  : String,
    raw   : bool,
    done  : bool,
}

impl<I> OptIter<I> where I : Iterator<Item = String> {
    fn next_opt (&mut self) -> Option<Opt> {
        // Check for done
        if self.done {
            return None;
        }

        // Process flags
        if let Some(c) = self.flags.pop() {
            return Some(Opt::Flag(c.to_string()));
        }

        // Get next
        let arg;
        match self.iter.next() {
            Some(a) => arg = a,
            None => {
                // Iterator is done
                self.done = true;

                if !self.name.is_empty() {
                    // Previous was a name so emit a flag
                    let temp = self.name.clone();
                    self.name.clear();
                    return Some(Opt::Flag(temp));
                }
                else {
                    // All done
                    return None;
                }
            }
        }

        // If raw just send it along
        if self.raw {
            return Some(Opt::Raw(arg));
        }

        // Handle --
        if arg == "--" {
            self.raw = true;
            return self.next_opt();
        }

        // Parse as name or flags
        let mut name = String::new();
        if arg.starts_with("--") {
            name.push_str(&arg[2..]);
        }
        else if arg.starts_with("-") {
            if arg.chars().count() > 2 {
                // Parse flags
                for c in arg.chars().skip(1) {
                    self.flags.push(c);
                }
                self.flags.reverse();
            }
            else {
                // Save single char name
                name.push_str(&arg[1..]);
            }
        }

        // Emit option
        if !self.name.is_empty() {
            // Named or flag
            if !name.is_empty() {
                // Previous was name, current is name, so previous as flag
                let temp = name;
                name = self.name.clone();
                self.name = temp;
                return Some(Opt::Flag(name));
            }
            else if !self.flags.is_empty() {
                // Previous was name, current is flags, so previous as flag
                name = self.name.clone();
                self.name.clear();
                return Some(Opt::Flag(name));
            }
            else {
                // Previous was name, current is ordinal, so current as named
                name = self.name.clone();
                self.name.clear();
                return Some(Opt::Named(name, arg));
            }
        }
        else if !name.is_empty() {
            // Previous was not name, current is name
            self.name = name;
            return self.next_opt();
        }
        else if !self.flags.is_empty() {
            // Previous was not name, current is flags
            return self.next_opt();
        }

        // Previous was not name, current is ordinal, so current as ordinal
        return Some(Opt::Ordinal(arg));
    }
}

impl<I> Iterator for OptIter<I> where I : Iterator<Item = String> {
    type Item = Opt;

    fn next (&mut self) -> Option<Opt> {
        return self.next_opt();
    }
}

/****************************************************************************
*
*   Public functions
*
***/

pub fn parse<I, II> (values : II) -> OptIter<II::IntoIter> where
    I : Iterator<Item = String>,
    II : IntoIterator<Item = String, IntoIter = I>
{
    return OptIter {
        iter  : values.into_iter(),
        flags : Vec::new(),
        name  : String::new(),
        raw   : false,
        done  : false,
    };
}

pub fn parse_env () -> OptIter<iter::Skip<env::Args>> {
    return parse(env::args().skip(1));
}

/****************************************************************************
*
*   Tests
*
***/

#[cfg(test)]
mod tests {
    use super::Opt;

    fn args_from_str (s : &str) -> Vec<String> {
        return s.split(" ").map(|s| s.to_string()).collect();
    }

    fn options_from_str (s : &str) -> Vec<Opt> {
        return super::parse(args_from_str(s)).collect();
    }

    fn flag_from_str (name : &str) -> Opt {
        return Opt::Flag(name.to_string());
    }

    fn named_from_str (name : &str, value : &str) -> Opt {
        return Opt::Named(name.to_string(), value.to_string());
    }

    fn ordinal_from_str (value : &str) -> Opt {
        return Opt::Ordinal(value.to_string());
    }

    fn raw_from_str (value : &str) -> Opt {
        return Opt::Raw(value.to_string());
    }

    #[test]
    fn full () {
        let actual = options_from_str("a -bc -d e --f g - h -- i -j --k");
        let spec = vec![
            ordinal_from_str("a"),
            flag_from_str("b"),
            flag_from_str("c"),
            named_from_str("d", "e"),
            named_from_str("f", "g"),
            ordinal_from_str("-"),
            ordinal_from_str("h"),
            raw_from_str("i"),
            raw_from_str("-j"),
            raw_from_str("--k"),
        ];

        assert_eq!(actual, spec);
    }

    #[test]
    fn trailing_flag () {
        let actual = options_from_str("a b -c");
        let spec = vec![
            ordinal_from_str("a"),
            ordinal_from_str("b"),
            flag_from_str("c"),
        ];

        assert_eq!(actual, spec);
    }
}
<commit_msg>Opt.iter -> Opt.args<commit_after>/****************************************************************************
*
*   lib.rs
*   opter
*
*   Copyright (c) 2015 Tyler Cole
*
*   Details:
*   - options come in four flavors
*     - flag is name without value
*     - ordinal is value without name
*     - named is value with a name
*     - value is simply a raw value
*   - full names start with "--" and short names with "-"
*   - short name flags can be stacked with "-"
*     - "-abc" represents the flags a, b, and c
*   - "-" with no following characters is a value
*   - "--" signifies end of options and is not emitted
*     - all values following "--" are simply passed along
*
***/

use std::env;
use std::iter;

/****************************************************************************
*
*   Opt
*
***/

#[derive(Debug)]
#[derive(PartialEq)]
pub enum Opt {
    Flag(String),
    Named(String, String),
    Ordinal(String),
    Raw(String),
}

/****************************************************************************
*
*   OptIter
*
***/

pub struct OptIter<I> where I : Iterator<Item = String> {
    args  : I,
    flags : Vec<char>,
    name  : String,
    raw   : bool,
    done  : bool,
}

impl<I> OptIter<I> where I : Iterator<Item = String> {
    fn next_opt (&mut self) -> Option<Opt> {
        // Check for done
        if self.done {
            return None;
        }

        // Process flags
        if let Some(c) = self.flags.pop() {
            return Some(Opt::Flag(c.to_string()));
        }

        // Get next
        let arg;
        match self.args.next() {
            Some(a) => arg = a,
            None => {
                // Iterator is done
                self.done = true;

                if !self.name.is_empty() {
                    // Previous was a name so emit a flag
                    let temp = self.name.clone();
                    self.name.clear();
                    return Some(Opt::Flag(temp));
                }
                else {
                    // All done
                    return None;
                }
            }
        }

        // If raw just send it along
        if self.raw {
            return Some(Opt::Raw(arg));
        }

        // Handle --
        if arg == "--" {
            self.raw = true;
            return self.next_opt();
        }

        // Parse as name or flags
        let mut name = String::new();
        if arg.starts_with("--") {
            name.push_str(&arg[2..]);
        }
        else if arg.starts_with("-") {
            if arg.chars().count() > 2 {
                // Parse flags
                for c in arg.chars().skip(1) {
                    self.flags.push(c);
                }
                self.flags.reverse();
            }
            else {
                // Save single char name
                name.push_str(&arg[1..]);
            }
        }

        // Emit option
        if !self.name.is_empty() {
            // Named or flag
            if !name.is_empty() {
                // Previous was name, current is name, so previous as flag
                let temp = name;
                name = self.name.clone();
                self.name = temp;
                return Some(Opt::Flag(name));
            }
            else if !self.flags.is_empty() {
                // Previous was name, current is flags, so previous as flag
                name = self.name.clone();
                self.name.clear();
                return Some(Opt::Flag(name));
            }
            else {
                // Previous was name, current is ordinal, so current as named
                name = self.name.clone();
                self.name.clear();
                return Some(Opt::Named(name, arg));
            }
        }
        else if !name.is_empty() {
            // Previous was not name, current is name
            self.name = name;
            return self.next_opt();
        }
        else if !self.flags.is_empty() {
            // Previous was not name, current is flags
            return self.next_opt();
        }

        // Previous was not name, current is ordinal, so current as ordinal
        return Some(Opt::Ordinal(arg));
    }
}

impl<I> Iterator for OptIter<I> where I : Iterator<Item = String> {
    type Item = Opt;

    fn next (&mut self) -> Option<Opt> {
        return self.next_opt();
    }
}

/****************************************************************************
*
*   Public functions
*
***/

pub fn parse<I, II> (values : II) -> OptIter<II::IntoIter> where
    I : Iterator<Item = String>,
    II : IntoIterator<Item = String, IntoIter = I>
{
    return OptIter {
        args  : values.into_iter(),
        flags : Vec::new(),
        name  : String::new(),
        raw   : false,
        done  : false,
    };
}

pub fn parse_env () -> OptIter<iter::Skip<env::Args>> {
    return parse(env::args().skip(1));
}

/****************************************************************************
*
*   Tests
*
***/

#[cfg(test)]
mod tests {
    use super::Opt;

    fn args_from_str (s : &str) -> Vec<String> {
        return s.split(" ").map(|s| s.to_string()).collect();
    }

    fn options_from_str (s : &str) -> Vec<Opt> {
        return super::parse(args_from_str(s)).collect();
    }

    fn flag_from_str (name : &str) -> Opt {
        return Opt::Flag(name.to_string());
    }

    fn named_from_str (name : &str, value : &str) -> Opt {
        return Opt::Named(name.to_string(), value.to_string());
    }

    fn ordinal_from_str (value : &str) -> Opt {
        return Opt::Ordinal(value.to_string());
    }

    fn raw_from_str (value : &str) -> Opt {
        return Opt::Raw(value.to_string());
    }

    #[test]
    fn full () {
        let actual = options_from_str("a -bc -d e --f g - h -- i -j --k");
        let spec = vec![
            ordinal_from_str("a"),
            flag_from_str("b"),
            flag_from_str("c"),
            named_from_str("d", "e"),
            named_from_str("f", "g"),
            ordinal_from_str("-"),
            ordinal_from_str("h"),
            raw_from_str("i"),
            raw_from_str("-j"),
            raw_from_str("--k"),
        ];

        assert_eq!(actual, spec);
    }

    #[test]
    fn trailing_flag () {
        let actual = options_from_str("a b -c");
        let spec = vec![
            ordinal_from_str("a"),
            ordinal_from_str("b"),
            flag_from_str("c"),
        ];

        assert_eq!(actual, spec);
    }
}
<|endoftext|>


<commit_before>
pub fn xor(source: &[u8], key: &[u8]) -> Vec<u8> {
    let key_iter = InfiniteByteIterator::new(key);
    source.iter().zip(key_iter).map(|(&a, b)| a ^ b).collect()
}

struct InfiniteByteIterator {
    bytes: Vec<u8>,
    index: uint
}

impl InfiniteByteIterator {
    pub fn new(bytes: &[u8]) -> InfiniteByteIterator {
        InfiniteByteIterator {
            bytes: bytes.to_vec(),
            index: 0
        }
    }
}

impl Iterator<u8> for InfiniteByteIterator {
    fn next(&mut self) -> Option<u8> {
        let byte = self.bytes[self.index];
        self.index = next_index(self.index, self.bytes.len());
        Some(byte)
    }
}

fn next_index(current: uint, count: uint) -> uint {
    let index = current + 1;
    if index < count {
        index
    } else {
        0
    }
}

#[cfg(test)]
mod test {

    use super::xor;

    #[test]
    fn test_xor_len() {
        let source = [0u8, 1, 2, 3];
        let key = [34u8, 52];
        assert!(xor(source, key).len() == source.len());
    }

    #[test]
    fn test_xor_result() {
        let source = [0u8, 1, 2, 3];
        let key = [34u8, 52];
        assert!(xor(source, key) == vec![34, 53, 32, 55]);
    }
}
<commit_msg>Added checks for empty source and key. Cleaned up tests.<commit_after>
pub fn xor(source: &[u8], key: &[u8]) -> Vec<u8> {
    if source.len() == 0 {
        return Vec::new();
    }
    if key.len() == 0 {
        return source.to_vec();
    }
    let key_iter = InfiniteByteIterator::new(key);
    source.iter().zip(key_iter).map(|(&a, b)| a ^ b).collect()
}

struct InfiniteByteIterator {
    bytes: Vec<u8>,
    index: uint
}

impl InfiniteByteIterator {
    pub fn new(bytes: &[u8]) -> InfiniteByteIterator {
        InfiniteByteIterator {
            bytes: bytes.to_vec(),
            index: 0
        }
    }
}

impl Iterator<u8> for InfiniteByteIterator {
    fn next(&mut self) -> Option<u8> {
        let byte = self.bytes[self.index];
        self.index = next_index(self.index, self.bytes.len());
        Some(byte)
    }
}

fn next_index(current: uint, count: uint) -> uint {
    let index = current + 1;
    if index < count {
        index
    } else {
        0
    }
}

#[cfg(test)]
mod test {

    use super::xor;

    #[test]
    fn test_len() {
        let source = [0, 1, 2, 3];
        let key = [34, 52];
        assert!(xor(source, key).len() == source.len());
    }

    #[test]
    fn test_result() {
        let source = [0, 1, 2, 3];
        let key = [34, 52];
        assert!(xor(source, key) == vec![34, 53, 32, 55]);
    }

    #[test]
    fn test_with_empty_key() {
        let source = [0, 1, 2, 3];
        let key = [];
        assert!(xor(source, key) == vec![0, 1, 2, 3]);
    }

    #[test]
    fn test_with_empty_source() {
        let source = [];
        let key = [45, 32, 56];
        assert!(xor(source, key) == vec![]);
    }
}
<|endoftext|>