<commit_before>use crate::{config::Config, env::Env, file_saver::save_to_file, nameutil, version::Version};
use log::info;
use std::{fs::File, io::prelude::*};
use toml::{self, value::Table, Value};

pub fn generate(env: &Env) -> String {
    info!("Generating sys Cargo.toml for {}", env.config.library_name);

    let path = env.config.target_path.join("Cargo.toml");

    let mut toml_str = String::new();
    if let Ok(mut file) = File::open(&path) {
        file.read_to_string(&mut toml_str).unwrap();
    }
    let empty = toml_str.trim().is_empty();
    let mut root_table = toml::from_str(&toml_str).unwrap_or_else(|_| Table::new());
    let crate_name = get_crate_name(&env.config, &root_table);

    if empty {
        fill_empty(&mut root_table, env, &crate_name);
    }
    fill_in(&mut root_table, env);

    save_to_file(&path, env.config.make_backup, |w| {
        w.write_all(toml::to_string(&root_table).unwrap().as_bytes())
    });

    crate_name
}

fn fill_empty(root: &mut Table, env: &Env, crate_name: &str) {
    let package_name = nameutil::exported_crate_name(crate_name);

    {
        let package = upsert_table(root, "package");
        set_string(package, "name", package_name);
        set_string(package, "version", "0.0.1");
        set_string(
            package,
            "links",
            nameutil::crate_name(&env.config.library_name),
        );
    }

    {
        let lib = upsert_table(root, "lib");
        set_string(lib, "name", crate_name);
    }

    let deps = upsert_table(root, "dependencies");
    for ext_lib in &env.config.external_libraries {
        let ext_package = if ext_lib.crate_name == "cairo" {
            format!("{}-sys-rs", ext_lib.crate_name)
        } else if ext_lib.crate_name == "gdk_pixbuf" {
            "gdk-pixbuf-sys".into()
        } else {
            format!("{}-sys", ext_lib.crate_name)
        };
        let dep = upsert_table(deps, &*ext_package);
        if ext_lib.crate_name == "cairo" {
            set_string(dep, "git", "https://github.com/gtk-rs/cairo");
        } else if ext_package.starts_with("sourceview") {
            set_string(dep, "git", "https://github.com/gtk-rs/sourceview");
        } else {
            set_string(dep, "git", "https://github.com/gtk-rs/sys");
        }
    }
}

fn fill_in(root: &mut Table, env: &Env) {
    {
        let package = upsert_table(root, "package");
        set_string(package, "build", "build.rs");
        //set_string(package, "version", "0.2.0");
    }

    {
        let deps = upsert_table(root, "dependencies");
        set_string(deps, "libc", "0.2");
    }

    {
        let build_deps = upsert_table(root, "build-dependencies");
        set_string(build_deps, "pkg-config", "0.3.7");
    }

    {
        let dev_deps = upsert_table(root, "dev-dependencies");
        set_string(dev_deps, "shell-words", "0.1.0");
        set_string(dev_deps, "tempdir", "0.3");
    }

    {
        let features = upsert_table(root, "features");
        let mut versions = env
            .namespaces
            .main()
            .versions
            .iter()
            .filter(|&&v| v > env.config.min_cfg_version)
            .collect::<Vec<_>>();
        versions.sort_unstable();
        let max_version = versions.last().copied();
        versions
            .into_iter()
            .fold(None::<Version>, |prev, &version| {
                let prev_array: Vec<Value> =
                    prev.iter().map(|v| Value::String(v.to_feature())).collect();
                features.insert(version.to_feature(), Value::Array(prev_array));
                Some(version)
            });
        features.insert("dox".to_string(), Value::Array(Vec::new()));

        let docs_rs_metadata = upsert_table(root, "package.metadata.docs.rs");
        let mut docs_rs_features = env.config.docs_rs_features.clone();
        docs_rs_features.push("dox".to_owned());
        if let Some(version) = max_version {
            docs_rs_features.push(version.to_feature());
        }
        docs_rs_features.sort_unstable();
        docs_rs_features.dedup(); // we remove duplicates if there is any
        docs_rs_metadata.insert(
            "features".to_string(),
            Value::Array(
                docs_rs_features
                    .into_iter()
                    .map(Value::String)
                    .collect::<Vec<_>>(),
            ),
        );
    }
}

/// Returns the name of crate being currently generated.
fn get_crate_name(config: &Config, root: &Table) -> String {
    if let Some(&Value::Table(ref lib)) = root.get("lib") {
        if let Some(&Value::String(ref lib_name)) = lib.get("name") {
            //Converting don't needed as library target names cannot contain hyphens
            return lib_name.to_owned();
        }
    }
    if let Some(&Value::Table(ref package)) = root.get("package") {
        if let Some(&Value::String(ref package_name)) = package.get("name") {
            return nameutil::crate_name(package_name);
        }
    }
    return format!("{}_sys", nameutil::crate_name(&config.library_name));
}

fn set_string<S: Into<String>>(table: &mut Table, name: &str, new_value: S) {
    if let Some(v) = table.get_mut(name) {
        *v = Value::String(new_value.into());
        return;
    }
    table.insert(name.into(), Value::String(new_value.into()));
}

fn upsert_table<S: Into<String>>(parent: &mut Table, name: S) -> &mut Table {
    if let Value::Table(ref mut table) = *parent
        .entry(name.into())
        .or_insert_with(|| Value::Table(toml::map::Map::new()))
    {
        table
    } else {
        unreachable!()
    }
}
<commit_msg>Don't provide version in dox generation<commit_after>use crate::{config::Config, env::Env, file_saver::save_to_file, nameutil, version::Version};
use log::info;
use std::{fs::File, io::prelude::*};
use toml::{self, value::Table, Value};

pub fn generate(env: &Env) -> String {
    info!("Generating sys Cargo.toml for {}", env.config.library_name);

    let path = env.config.target_path.join("Cargo.toml");

    let mut toml_str = String::new();
    if let Ok(mut file) = File::open(&path) {
        file.read_to_string(&mut toml_str).unwrap();
    }
    let empty = toml_str.trim().is_empty();
    let mut root_table = toml::from_str(&toml_str).unwrap_or_else(|_| Table::new());
    let crate_name = get_crate_name(&env.config, &root_table);

    if empty {
        fill_empty(&mut root_table, env, &crate_name);
    }
    fill_in(&mut root_table, env);

    save_to_file(&path, env.config.make_backup, |w| {
        w.write_all(toml::to_string(&root_table).unwrap().as_bytes())
    });

    crate_name
}

fn fill_empty(root: &mut Table, env: &Env, crate_name: &str) {
    let package_name = nameutil::exported_crate_name(crate_name);

    {
        let package = upsert_table(root, "package");
        set_string(package, "name", package_name);
        set_string(package, "version", "0.0.1");
        set_string(
            package,
            "links",
            nameutil::crate_name(&env.config.library_name),
        );
    }

    {
        let lib = upsert_table(root, "lib");
        set_string(lib, "name", crate_name);
    }

    let deps = upsert_table(root, "dependencies");
    for ext_lib in &env.config.external_libraries {
        let ext_package = if ext_lib.crate_name == "cairo" {
            format!("{}-sys-rs", ext_lib.crate_name)
        } else if ext_lib.crate_name == "gdk_pixbuf" {
            "gdk-pixbuf-sys".into()
        } else {
            format!("{}-sys", ext_lib.crate_name)
        };
        let dep = upsert_table(deps, &*ext_package);
        if ext_lib.crate_name == "cairo" {
            set_string(dep, "git", "https://github.com/gtk-rs/cairo");
        } else if ext_package.starts_with("sourceview") {
            set_string(dep, "git", "https://github.com/gtk-rs/sourceview");
        } else {
            set_string(dep, "git", "https://github.com/gtk-rs/sys");
        }
    }
}

fn fill_in(root: &mut Table, env: &Env) {
    {
        let package = upsert_table(root, "package");
        set_string(package, "build", "build.rs");
        //set_string(package, "version", "0.2.0");
    }

    {
        let deps = upsert_table(root, "dependencies");
        set_string(deps, "libc", "0.2");
    }

    {
        let build_deps = upsert_table(root, "build-dependencies");
        set_string(build_deps, "pkg-config", "0.3.7");
    }

    {
        let dev_deps = upsert_table(root, "dev-dependencies");
        set_string(dev_deps, "shell-words", "0.1.0");
        set_string(dev_deps, "tempdir", "0.3");
    }

    {
        let features = upsert_table(root, "features");
        let versions = env
            .namespaces
            .main()
            .versions
            .iter()
            .filter(|&&v| v > env.config.min_cfg_version);
        versions.fold(None::<Version>, |prev, &version| {
            let prev_array: Vec<Value> =
                prev.iter().map(|v| Value::String(v.to_feature())).collect();
            features.insert(version.to_feature(), Value::Array(prev_array));
            Some(version)
        });
        features.insert("dox".to_string(), Value::Array(Vec::new()));
    }

    {
        let docs_rs_metadata = upsert_table(root, "package.metadata.docs.rs");
        let mut docs_rs_features = env.config.docs_rs_features.clone();
        docs_rs_features.push("dox".to_owned());
        docs_rs_metadata.insert(
            "features".to_string(),
            Value::Array(
                docs_rs_features
                    .into_iter()
                    .map(Value::String)
                    .collect::<Vec<_>>(),
            ),
        );
    }
}

/// Returns the name of crate being currently generated.
fn get_crate_name(config: &Config, root: &Table) -> String {
    if let Some(&Value::Table(ref lib)) = root.get("lib") {
        if let Some(&Value::String(ref lib_name)) = lib.get("name") {
            //Converting don't needed as library target names cannot contain hyphens
            return lib_name.to_owned();
        }
    }
    if let Some(&Value::Table(ref package)) = root.get("package") {
        if let Some(&Value::String(ref package_name)) = package.get("name") {
            return nameutil::crate_name(package_name);
        }
    }
    return format!("{}_sys", nameutil::crate_name(&config.library_name));
}

fn set_string<S: Into<String>>(table: &mut Table, name: &str, new_value: S) {
    if let Some(v) = table.get_mut(name) {
        *v = Value::String(new_value.into());
        return;
    }
    table.insert(name.into(), Value::String(new_value.into()));
}

fn upsert_table<S: Into<String>>(parent: &mut Table, name: S) -> &mut Table {
    if let Value::Table(ref mut table) = *parent
        .entry(name.into())
        .or_insert_with(|| Value::Table(toml::map::Map::new()))
    {
        table
    } else {
        unreachable!()
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*!
A GPU based renderer for the web.

It serves as an experimental render backend for [Servo](https://servo.org/),
but it can also be used as such in a standalone application.

# External dependencies
WebRender currently depends on [FreeType](https://www.freetype.org/)

# Api Structure
The main entry point to WebRender is the `webrender::Renderer`.

By calling `Renderer::new(...)` you get a `Renderer`, as well as a `RenderApiSender`.
Your `Renderer` is responsible to render the previously processed frames onto the screen.

By calling `yourRenderApiSender.create_api()`, you'll get a `RenderApi` instance,
which is responsible for managing resources and documents. A worker thread is used internally
to untie the workload from the application thread and therefore be able to make better use of
multicore systems.

## Frame

What is referred to as a `frame`, is the current geometry on the screen.
A new Frame is created by calling [`set_display_list()`][newframe] on the `RenderApi`.
When the geometry is processed, the application will be informed via a `RenderNotifier`,
a callback which you employ with [set_render_notifier][notifier] on the `Renderer`
More information about [stacking contexts][stacking_contexts].

`set_display_list()` also needs to be supplied with `BuiltDisplayList`s.
These are obtained by finalizing a `DisplayListBuilder`. These are used to draw your geometry.
But it doesn't only contain trivial geometry, it can also store another StackingContext, as
they're nestable.

[stacking_contexts]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
[newframe]: ../webrender_api/struct.RenderApi.html#method.set_display_list
[notifier]: renderer/struct.Renderer.html#method.set_render_notifier
*/

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate thread_profiler;

mod border;
mod clip_scroll_node;
mod clip_scroll_tree;
mod debug_colors;
mod debug_font_data;
mod debug_render;
#[cfg(feature = "debugger")]
mod debug_server;
mod device;
mod ellipse;
mod frame;
mod frame_builder;
mod freelist;
mod geometry;
mod glyph_cache;
mod glyph_rasterizer;
mod gpu_cache;
mod internal_types;
mod mask_cache;
mod prim_store;
mod print_tree;
mod profiler;
mod record;
mod render_backend;
mod render_task;
mod renderer;
mod resource_cache;
mod scene;
mod spring;
mod texture_allocator;
mod texture_cache;
mod tiling;
mod util;

mod shader_source {
    include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
}

pub use record::{ApiRecordingReceiver, BinaryRecorder, WEBRENDER_RECORDING_HEADER};

mod platform {
    #[cfg(target_os="macos")]
    pub use platform::macos::font;
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub use platform::unix::font;
    #[cfg(target_os = "windows")]
    pub use platform::windows::font;

    #[cfg(target_os="macos")]
    pub mod macos {
        pub mod font;
    }
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub mod unix {
        pub mod font;
    }
    #[cfg(target_os = "windows")]
    pub mod windows {
        pub mod font;
    }
}

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

#[cfg(all(unix, not(target_os="macos")))]
extern crate freetype;

#[cfg(target_os = "windows")]
extern crate dwrote;

extern crate app_units;
extern crate bincode;
extern crate euclid;
extern crate fxhash;
extern crate gleam;
extern crate num_traits;
//extern crate notify;
extern crate time;
pub extern crate webrender_api;
extern crate byteorder;
extern crate rayon;
extern crate plane_split;
#[cfg(feature = "debugger")]
extern crate ws;
#[cfg(feature = "debugger")]
extern crate serde_json;
#[cfg(feature = "debugger")]
#[macro_use]
extern crate serde_derive;

#[cfg(any(target_os="macos", target_os="windows"))]
extern crate gamma_lut;

pub use renderer::{ExternalImage, ExternalImageSource, ExternalImageHandler};
pub use renderer::{GraphicsApi, GraphicsApiInfo, ReadPixelsFormat, Renderer, RendererOptions};
pub use renderer::{CpuProfile, GpuProfile, DebugFlags};
pub use renderer::{MAX_VERTEX_TEXTURE_WIDTH, PROFILER_DBG, RENDER_TARGET_DBG, TEXTURE_CACHE_DBG};

pub use webrender_api as api;

#[doc(hidden)]
pub use device::build_shader_strings;
<commit_msg>Make RendererKind public since Servo needs that enum.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*!
A GPU based renderer for the web.

It serves as an experimental render backend for [Servo](https://servo.org/),
but it can also be used as such in a standalone application.

# External dependencies
WebRender currently depends on [FreeType](https://www.freetype.org/)

# Api Structure
The main entry point to WebRender is the `webrender::Renderer`.

By calling `Renderer::new(...)` you get a `Renderer`, as well as a `RenderApiSender`.
Your `Renderer` is responsible to render the previously processed frames onto the screen.

By calling `yourRenderApiSender.create_api()`, you'll get a `RenderApi` instance,
which is responsible for managing resources and documents. A worker thread is used internally
to untie the workload from the application thread and therefore be able to make better use of
multicore systems.

## Frame

What is referred to as a `frame`, is the current geometry on the screen.
A new Frame is created by calling [`set_display_list()`][newframe] on the `RenderApi`.
When the geometry is processed, the application will be informed via a `RenderNotifier`,
a callback which you employ with [set_render_notifier][notifier] on the `Renderer`
More information about [stacking contexts][stacking_contexts].

`set_display_list()` also needs to be supplied with `BuiltDisplayList`s.
These are obtained by finalizing a `DisplayListBuilder`. These are used to draw your geometry.
But it doesn't only contain trivial geometry, it can also store another StackingContext, as
they're nestable.

[stacking_contexts]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
[newframe]: ../webrender_api/struct.RenderApi.html#method.set_display_list
[notifier]: renderer/struct.Renderer.html#method.set_render_notifier
*/

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate thread_profiler;

mod border;
mod clip_scroll_node;
mod clip_scroll_tree;
mod debug_colors;
mod debug_font_data;
mod debug_render;
#[cfg(feature = "debugger")]
mod debug_server;
mod device;
mod ellipse;
mod frame;
mod frame_builder;
mod freelist;
mod geometry;
mod glyph_cache;
mod glyph_rasterizer;
mod gpu_cache;
mod internal_types;
mod mask_cache;
mod prim_store;
mod print_tree;
mod profiler;
mod record;
mod render_backend;
mod render_task;
mod renderer;
mod resource_cache;
mod scene;
mod spring;
mod texture_allocator;
mod texture_cache;
mod tiling;
mod util;

mod shader_source {
    include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
}

pub use record::{ApiRecordingReceiver, BinaryRecorder, WEBRENDER_RECORDING_HEADER};

mod platform {
    #[cfg(target_os="macos")]
    pub use platform::macos::font;
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub use platform::unix::font;
    #[cfg(target_os = "windows")]
    pub use platform::windows::font;

    #[cfg(target_os="macos")]
    pub mod macos {
        pub mod font;
    }
    #[cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))]
    pub mod unix {
        pub mod font;
    }
    #[cfg(target_os = "windows")]
    pub mod windows {
        pub mod font;
    }
}

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

#[cfg(all(unix, not(target_os="macos")))]
extern crate freetype;

#[cfg(target_os = "windows")]
extern crate dwrote;

extern crate app_units;
extern crate bincode;
extern crate euclid;
extern crate fxhash;
extern crate gleam;
extern crate num_traits;
//extern crate notify;
extern crate time;
pub extern crate webrender_api;
extern crate byteorder;
extern crate rayon;
extern crate plane_split;
#[cfg(feature = "debugger")]
extern crate ws;
#[cfg(feature = "debugger")]
extern crate serde_json;
#[cfg(feature = "debugger")]
#[macro_use]
extern crate serde_derive;

#[cfg(any(target_os="macos", target_os="windows"))]
extern crate gamma_lut;

pub use renderer::{ExternalImage, ExternalImageSource, ExternalImageHandler};
pub use renderer::{GraphicsApi, GraphicsApiInfo, ReadPixelsFormat, Renderer, RendererOptions};
pub use renderer::{CpuProfile, GpuProfile, DebugFlags, RendererKind};
pub use renderer::{MAX_VERTEX_TEXTURE_WIDTH, PROFILER_DBG, RENDER_TARGET_DBG, TEXTURE_CACHE_DBG};

pub use webrender_api as api;

#[doc(hidden)]
pub use device::build_shader_strings;
<|endoftext|>


<commit_before>//! The system which routes IRC messages to the proper places.
//!
//! This is surprisingly complicated :(

use irc::client::prelude::*;

use common::line::{Sender, User};
use common::types::Nick;

/// Cleaned up forms of channel-specific IRC commands and response codes.
#[derive(Debug, Clone)]
// We allow this so we can match variant names to their associated IRC message
// names.
#[allow(non_camel_case_types)]
pub enum BufferCmd {
    JOIN(User),
    PART(User, Option<String>),
    // QUIT(User, Option<String>),
    KICK { by: User, targ: Nick, reason: Option<String> },

    PRIVMSG(User, String),
    NOTICE(User, String),

    RPL_NAMREPLY(String),
    RPL_ENDOFNAMES,
}

/// Represents IRC commands handled by the network object.
#[derive(Debug, Clone)]
pub enum NetworkCmd {
    // NOTE: Quit is in here and `BufferMsg` because the network has to handle
    // it and send it to all the buffers with the quitting user present.
    QUIT(User, Option<String>),

    /// Represents an unknown response code.
    ///
    /// Since, by definition, we don't know what to do with these, we just send
    /// them off to the network object as is.
    UnknownCode(Response, Vec<String>, Option<String>),
}

/// Represents specialized forms of IRC commands targeted to a specific handler
/// like a buffer or the network.
#[derive(Debug, Clone)]
pub enum RoutedMsg {
    Channel(String, BufferCmd),
    Private(User, BufferCmd),
    Network(NetworkCmd),
}

/// Logs an error and returns if the given sender isn't a user.
///
/// The second argument is used as a message name for logging the error message.
macro_rules! try_user {
    ( $sender: expr, $name: expr ) => {
        match $sender {
            Some(Sender::User(ref user)) => user,
            Some(Sender::Server(_)) => {
                error!("Expected user prefix for {} command, but got a server prefix", $name);
                return None;
            },
            None => {
                error!("Expected user prefix for {} command, but found no prefix", $name);
                return None;
            },
        }
    }
}

/// This function handles routing an IRC message to the proper destinations.
pub fn route_message(msg: Message, cur_nick: &str) -> Option<RoutedMsg> {
    trace!("Routing {:?}", msg);
    // Parse the prefix first, as we'll need it later.
    let sender = msg.prefix.as_ref().map(|p| Sender::parse_prefix(&p));

    match msg.command {
        Command::JOIN(chan, _, _) => {
            let user = try_user!(sender, "JOIN").clone();
            let bc = BufferCmd::JOIN(user.clone());
            route_target(chan, user, cur_nick, bc)
        },
        Command::PART(chan, msg) => {
            let user = try_user!(sender, "PART").clone();
            let bc = BufferCmd::PART(user.clone(), msg.clone());
            route_target(chan, user, cur_nick, bc)
        },
        Command::KICK(chan, targ, msg) => {
            let user = try_user!(sender, "KICK").clone();
            let bc = BufferCmd::KICK {
                by: user.clone(),
                targ: targ.clone(),
                reason: msg.clone(),
            };
            route_target(chan, user, cur_nick, bc)
        },

        Command::PRIVMSG(dest, msg) => {
            let user = try_user!(sender, "PRIVMSG").clone();
            let bc = BufferCmd::PRIVMSG(user.clone(), msg.clone());
            route_target(dest, user, cur_nick, bc)
        },
        Command::NOTICE(dest, msg) => {
            let user = try_user!(sender, "NOTICE").clone();
            let bc = BufferCmd::NOTICE(user.clone(), msg.clone());
            route_target(dest, user, cur_nick, bc)
        },

        Command::QUIT(msg) => {
            let user = try_user!(sender, "QUIT").clone();
            // The network has to handle routing QUITs, as their routing depends
            // on which channels the quitting user is in.
            Some(RoutedMsg::Network(NetworkCmd::QUIT(user, msg.clone())))
        },

        Command::Response(Response::RPL_NAMREPLY, args, Some(body)) => {
            if args.len() < 3 {
                error!("Expected 3 args to RPL_NAMREPLY. Got: {:?}", args);
                return None;
            }
            // The channel is the third arg. I don't know what the other args
            // are...
            let ref chan = args[2];
            let bc = BufferCmd::RPL_NAMREPLY(body);
            Some(RoutedMsg::Channel(chan.clone(), bc))
        },
        Command::Response(Response::RPL_ENDOFNAMES, args, _) => {
            if args.len() < 1 {
                error!("Expected 1 arg to RPL_ENDOFNAMES. Got: {:?}", args);
                return None;
            }
            // The channel is the third arg.
            let ref chan = args[1];
            let bc = BufferCmd::RPL_ENDOFNAMES;
            Some(RoutedMsg::Channel(chan.clone(), bc))
        },

        Command::Response(code, args, body) => {
            let cmd = NetworkCmd::UnknownCode(code, args, body);
            Some(RoutedMsg::Network(cmd))
        },

        _ => {
            error!("Ignoring unrouted message: {:?}", msg);
            None
        },
    }
}

/// Routes a message to private or channel based on the given target string,
/// sender, and current nick.
fn route_target(targ: String, user: User, cur_nick: &str, msg: BufferCmd) -> Option<RoutedMsg> {
    if cur_nick == targ  {
        // NOTE: We don't do anything about the case where the server sends us a
        // JOIN with our nick as target. This shouldn't happen, but it's not
        // inconceivable. Regardless, we'll continue to ignore it for now.
        trace!("Routed private message from {}", user.nick);
        Some(RoutedMsg::Private(user.clone(), msg))
    } else {
        trace!("Routed channel message to {}", targ);
        Some(RoutedMsg::Channel(targ, msg))
    }
}
<commit_msg>Don't log errors for unhandled PINGs<commit_after>//! The system which routes IRC messages to the proper places.
//!
//! This is surprisingly complicated :(

use irc::client::prelude::*;

use common::line::{Sender, User};
use common::types::Nick;

/// Cleaned up forms of channel-specific IRC commands and response codes.
#[derive(Debug, Clone)]
// We allow this so we can match variant names to their associated IRC message
// names.
#[allow(non_camel_case_types)]
pub enum BufferCmd {
    JOIN(User),
    PART(User, Option<String>),
    // QUIT(User, Option<String>),
    KICK { by: User, targ: Nick, reason: Option<String> },

    PRIVMSG(User, String),
    NOTICE(User, String),

    RPL_NAMREPLY(String),
    RPL_ENDOFNAMES,
}

/// Represents IRC commands handled by the network object.
#[derive(Debug, Clone)]
pub enum NetworkCmd {
    // NOTE: Quit is in here and `BufferMsg` because the network has to handle
    // it and send it to all the buffers with the quitting user present.
    QUIT(User, Option<String>),

    /// Represents an unknown response code.
    ///
    /// Since, by definition, we don't know what to do with these, we just send
    /// them off to the network object as is.
    UnknownCode(Response, Vec<String>, Option<String>),
}

/// Represents specialized forms of IRC commands targeted to a specific handler
/// like a buffer or the network.
#[derive(Debug, Clone)]
pub enum RoutedMsg {
    Channel(String, BufferCmd),
    Private(User, BufferCmd),
    Network(NetworkCmd),
}

/// Logs an error and returns if the given sender isn't a user.
///
/// The second argument is used as a message name for logging the error message.
macro_rules! try_user {
    ( $sender: expr, $name: expr ) => {
        match $sender {
            Some(Sender::User(ref user)) => user,
            Some(Sender::Server(_)) => {
                error!("Expected user prefix for {} command, but got a server prefix", $name);
                return None;
            },
            None => {
                error!("Expected user prefix for {} command, but found no prefix", $name);
                return None;
            },
        }
    }
}

/// This function handles routing an IRC message to the proper destinations.
pub fn route_message(msg: Message, cur_nick: &str) -> Option<RoutedMsg> {
    trace!("Routing {:?}", msg);
    // Parse the prefix first, as we'll need it later.
    let sender = msg.prefix.as_ref().map(|p| Sender::parse_prefix(&p));

    match msg.command {
        Command::JOIN(chan, _, _) => {
            let user = try_user!(sender, "JOIN").clone();
            let bc = BufferCmd::JOIN(user.clone());
            route_target(chan, user, cur_nick, bc)
        },
        Command::PART(chan, msg) => {
            let user = try_user!(sender, "PART").clone();
            let bc = BufferCmd::PART(user.clone(), msg.clone());
            route_target(chan, user, cur_nick, bc)
        },
        Command::KICK(chan, targ, msg) => {
            let user = try_user!(sender, "KICK").clone();
            let bc = BufferCmd::KICK {
                by: user.clone(),
                targ: targ.clone(),
                reason: msg.clone(),
            };
            route_target(chan, user, cur_nick, bc)
        },

        Command::PRIVMSG(dest, msg) => {
            let user = try_user!(sender, "PRIVMSG").clone();
            let bc = BufferCmd::PRIVMSG(user.clone(), msg.clone());
            route_target(dest, user, cur_nick, bc)
        },
        Command::NOTICE(dest, msg) => {
            let user = try_user!(sender, "NOTICE").clone();
            let bc = BufferCmd::NOTICE(user.clone(), msg.clone());
            route_target(dest, user, cur_nick, bc)
        },

        Command::QUIT(msg) => {
            let user = try_user!(sender, "QUIT").clone();
            // The network has to handle routing QUITs, as their routing depends
            // on which channels the quitting user is in.
            Some(RoutedMsg::Network(NetworkCmd::QUIT(user, msg.clone())))
        },

        Command::Response(Response::RPL_NAMREPLY, args, Some(body)) => {
            if args.len() < 3 {
                error!("Expected 3 args to RPL_NAMREPLY. Got: {:?}", args);
                return None;
            }
            // The channel is the third arg. I don't know what the other args
            // are...
            let ref chan = args[2];
            let bc = BufferCmd::RPL_NAMREPLY(body);
            Some(RoutedMsg::Channel(chan.clone(), bc))
        },
        Command::Response(Response::RPL_ENDOFNAMES, args, _) => {
            if args.len() < 1 {
                error!("Expected 1 arg to RPL_ENDOFNAMES. Got: {:?}", args);
                return None;
            }
            // The channel is the third arg.
            let ref chan = args[1];
            let bc = BufferCmd::RPL_ENDOFNAMES;
            Some(RoutedMsg::Channel(chan.clone(), bc))
        },

        Command::Response(code, args, body) => {
            let cmd = NetworkCmd::UnknownCode(code, args, body);
            Some(RoutedMsg::Network(cmd))
        },

        // Ignore pings -- the IRC library responds to them for us.
        Command::PING(_, _) => None,
        _ => {
            error!("Ignoring unrouted message: {:?}", msg);
            None
        },
    }
}

/// Routes a message to private or channel based on the given target string,
/// sender, and current nick.
fn route_target(targ: String, user: User, cur_nick: &str, msg: BufferCmd) -> Option<RoutedMsg> {
    if cur_nick == targ  {
        // NOTE: We don't do anything about the case where the server sends us a
        // JOIN with our nick as target. This shouldn't happen, but it's not
        // inconceivable. Regardless, we'll continue to ignore it for now.
        trace!("Routed private message from {}", user.nick);
        Some(RoutedMsg::Private(user.clone(), msg))
    } else {
        trace!("Routed channel message to {}", targ);
        Some(RoutedMsg::Channel(targ, msg))
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use font::{Font, FontDescriptor, FontGroup, FontStyle, SelectorPlatformIdentifier};
use font::{SpecifiedFontStyle, UsedFontStyle};
use font_list::FontList;
use servo_util::cache::Cache;
use servo_util::cache::MonoCache;
use servo_util::time::ProfilerChan;

use platform::font::FontHandle;
use platform::font_context::FontContextHandle;

use azure::azure_hl::BackendType;
use core::hashmap::HashMap;

// TODO(Rust #3934): creating lots of new dummy styles is a workaround
// for not being able to store symbolic enums in top-level constants.
pub fn dummy_style() -> FontStyle {
    use font::FontWeight300;
    return FontStyle {
        pt_size: 20f,
        weight: FontWeight300,
        italic: false,
        oblique: false,
        families: ~"serif, sans-serif",
    }
}

pub trait FontContextHandleMethods {
    fn clone(&self) -> FontContextHandle;
    fn create_font_from_identifier(&self, ~str, UsedFontStyle) -> Result<FontHandle, ()>;
}

#[allow(non_implicitly_copyable_typarams)]
pub struct FontContext {
    instance_cache: MonoCache<FontDescriptor, @mut Font>,
    font_list: Option<FontList>, // only needed by layout
    handle: FontContextHandle,
    backend: BackendType,
    generic_fonts: HashMap<~str,~str>,
    profiler_chan: ProfilerChan,
}

#[allow(non_implicitly_copyable_typarams)]
pub impl<'self> FontContext {
    fn new(backend: BackendType,
           needs_font_list: bool,
           profiler_chan: ProfilerChan)
           -> FontContext {
        let handle = FontContextHandle::new();
        let font_list = if needs_font_list {
                            Some(FontList::new(&handle, profiler_chan.clone())) }
                        else { None };

        // TODO: Allow users to specify these.
        let mut generic_fonts = HashMap::with_capacity(5);
        generic_fonts.insert(~"serif", ~"Times New Roman");
        generic_fonts.insert(~"sans-serif", ~"Arial");
        generic_fonts.insert(~"cursive", ~"Apple Chancery");
        generic_fonts.insert(~"fantasy", ~"Papyrus");
        generic_fonts.insert(~"monospace", ~"Menlo");

        FontContext {
            // TODO(Rust #3902): remove extraneous type parameters once they are inferred correctly.
            instance_cache:
                Cache::new::<FontDescriptor,@mut Font,MonoCache<FontDescriptor,@mut Font>>(10),
            font_list: font_list,
            handle: handle,
            backend: backend,
            generic_fonts: generic_fonts,
            profiler_chan: profiler_chan,
        }
    }

    priv fn get_font_list(&'self self) -> &'self FontList {
        self.font_list.get_ref()
    }

    fn get_resolved_font_for_style(@mut self, style: &SpecifiedFontStyle) -> @FontGroup {
        // TODO(Issue #178, E): implement a cache of FontGroup instances.
        self.create_font_group(style)
    }

    fn get_font_by_descriptor(&mut self, desc: &FontDescriptor) -> Result<@mut Font, ()> {
        match self.instance_cache.find(desc) {
            Some(f) => Ok(f),
            None => {
                let result = self.create_font_instance(desc);
                match result {
                    Ok(font) => {
                        self.instance_cache.insert(desc, font);
                    }, _ => {}
                };
                result
            }
        }
    }

    priv fn transform_family(&self, family: &str) -> ~str {
        // FIXME: Need a find_like() in HashMap.
        let family = family.to_str();
        debug!("(transform family) searching for `%s`", family);
        match self.generic_fonts.find(&family) {
            None => family,
            Some(mapped_family) => copy *mapped_family
        }
    }

    // TODO:(Issue #196): cache font groups on the font context.
    priv fn create_font_group(@mut self, style: &SpecifiedFontStyle) -> @FontGroup {
        let mut fonts = ~[];

        debug!("(create font group) --- starting ---");

        let list = self.get_font_list();

        // TODO(Issue #193): make iteration over 'font-family' more robust.
        for str::each_split_char(style.families, ',') |family| {
            let family_name = str::trim(family);
            let transformed_family_name = self.transform_family(family_name);
            debug!("(create font group) transformed family is `%s`", transformed_family_name);

            let result = list.find_font_in_family(transformed_family_name, style);
            let mut found = false;
            for result.each |font_entry| {
                found = true;
                // TODO(Issue #203): route this instantion through FontContext's Font instance cache.
                let instance = Font::new_from_existing_handle(self, &font_entry.handle, style, self.backend,
                                                              self.profiler_chan.clone());
                do result::iter(&instance) |font: &@mut Font| { fonts.push(*font); }
            };

            if !found {
                debug!("(create font group) didn't find `%s`", transformed_family_name);
            }
        }

        let last_resort = FontList::get_last_resort_font_families();

        for last_resort.each |family| {
            let result = list.find_font_in_family(*family,style);
            for result.each |font_entry| {
                let instance = Font::new_from_existing_handle(self, &font_entry.handle, style, self.backend);
                do result::iter(&instance) |font: &@mut Font| { fonts.push(*font); }
            }
        }

        assert!(fonts.len() > 0);
        // TODO(Issue #179): Split FontStyle into specified and used styles
        let used_style = copy *style;

        debug!("(create font group) --- finished ---");

        @FontGroup::new(style.families.to_managed(), &used_style, fonts)
    }

    priv fn create_font_instance(&self, desc: &FontDescriptor) -> Result<@mut Font, ()> {
        return match &desc.selector {
            // TODO(Issue #174): implement by-platform-name font selectors.
            &SelectorPlatformIdentifier(ref identifier) => {
                let result_handle = self.handle.create_font_from_identifier(copy *identifier,
                                                                            copy desc.style);
                result::chain(result_handle, |handle| {
                    Ok(Font::new_from_adopted_handle(self,
                                                     handle,
                                                     &desc.style,
                                                     self.backend,
                                                     self.profiler_chan.clone()))
                })
            }
        };
    }
}
<commit_msg>Fix merge fallout<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use font::{Font, FontDescriptor, FontGroup, FontStyle, SelectorPlatformIdentifier};
use font::{SpecifiedFontStyle, UsedFontStyle};
use font_list::FontList;
use servo_util::cache::Cache;
use servo_util::cache::MonoCache;
use servo_util::time::ProfilerChan;

use platform::font::FontHandle;
use platform::font_context::FontContextHandle;

use azure::azure_hl::BackendType;
use core::hashmap::HashMap;

// TODO(Rust #3934): creating lots of new dummy styles is a workaround
// for not being able to store symbolic enums in top-level constants.
pub fn dummy_style() -> FontStyle {
    use font::FontWeight300;
    return FontStyle {
        pt_size: 20f,
        weight: FontWeight300,
        italic: false,
        oblique: false,
        families: ~"serif, sans-serif",
    }
}

pub trait FontContextHandleMethods {
    fn clone(&self) -> FontContextHandle;
    fn create_font_from_identifier(&self, ~str, UsedFontStyle) -> Result<FontHandle, ()>;
}

#[allow(non_implicitly_copyable_typarams)]
pub struct FontContext {
    instance_cache: MonoCache<FontDescriptor, @mut Font>,
    font_list: Option<FontList>, // only needed by layout
    handle: FontContextHandle,
    backend: BackendType,
    generic_fonts: HashMap<~str,~str>,
    profiler_chan: ProfilerChan,
}

#[allow(non_implicitly_copyable_typarams)]
pub impl<'self> FontContext {
    fn new(backend: BackendType,
           needs_font_list: bool,
           profiler_chan: ProfilerChan)
           -> FontContext {
        let handle = FontContextHandle::new();
        let font_list = if needs_font_list {
                            Some(FontList::new(&handle, profiler_chan.clone())) }
                        else { None };

        // TODO: Allow users to specify these.
        let mut generic_fonts = HashMap::with_capacity(5);
        generic_fonts.insert(~"serif", ~"Times New Roman");
        generic_fonts.insert(~"sans-serif", ~"Arial");
        generic_fonts.insert(~"cursive", ~"Apple Chancery");
        generic_fonts.insert(~"fantasy", ~"Papyrus");
        generic_fonts.insert(~"monospace", ~"Menlo");

        FontContext {
            // TODO(Rust #3902): remove extraneous type parameters once they are inferred correctly.
            instance_cache:
                Cache::new::<FontDescriptor,@mut Font,MonoCache<FontDescriptor,@mut Font>>(10),
            font_list: font_list,
            handle: handle,
            backend: backend,
            generic_fonts: generic_fonts,
            profiler_chan: profiler_chan,
        }
    }

    priv fn get_font_list(&'self self) -> &'self FontList {
        self.font_list.get_ref()
    }

    fn get_resolved_font_for_style(@mut self, style: &SpecifiedFontStyle) -> @FontGroup {
        // TODO(Issue #178, E): implement a cache of FontGroup instances.
        self.create_font_group(style)
    }

    fn get_font_by_descriptor(&mut self, desc: &FontDescriptor) -> Result<@mut Font, ()> {
        match self.instance_cache.find(desc) {
            Some(f) => Ok(f),
            None => {
                let result = self.create_font_instance(desc);
                match result {
                    Ok(font) => {
                        self.instance_cache.insert(desc, font);
                    }, _ => {}
                };
                result
            }
        }
    }

    priv fn transform_family(&self, family: &str) -> ~str {
        // FIXME: Need a find_like() in HashMap.
        let family = family.to_str();
        debug!("(transform family) searching for `%s`", family);
        match self.generic_fonts.find(&family) {
            None => family,
            Some(mapped_family) => copy *mapped_family
        }
    }

    // TODO:(Issue #196): cache font groups on the font context.
    priv fn create_font_group(@mut self, style: &SpecifiedFontStyle) -> @FontGroup {
        let mut fonts = ~[];

        debug!("(create font group) --- starting ---");

        let list = self.get_font_list();

        // TODO(Issue #193): make iteration over 'font-family' more robust.
        for str::each_split_char(style.families, ',') |family| {
            let family_name = str::trim(family);
            let transformed_family_name = self.transform_family(family_name);
            debug!("(create font group) transformed family is `%s`", transformed_family_name);

            let result = list.find_font_in_family(transformed_family_name, style);
            let mut found = false;
            for result.each |font_entry| {
                found = true;
                // TODO(Issue #203): route this instantion through FontContext's Font instance cache.
                let instance = Font::new_from_existing_handle(self, &font_entry.handle, style, self.backend,
                                                              self.profiler_chan.clone());
                do result::iter(&instance) |font: &@mut Font| { fonts.push(*font); }
            };

            if !found {
                debug!("(create font group) didn't find `%s`", transformed_family_name);
            }
        }

        let last_resort = FontList::get_last_resort_font_families();

        for last_resort.each |family| {
            let result = list.find_font_in_family(*family,style);
            for result.each |font_entry| {
                let instance = Font::new_from_existing_handle(self,
                                                              &font_entry.handle,
                                                              style,
                                                              self.backend,
                                                              self.profiler_chan.clone());
                do result::iter(&instance) |font: &@mut Font| {
                    fonts.push(*font);
                }
            }
        }

        assert!(fonts.len() > 0);
        // TODO(Issue #179): Split FontStyle into specified and used styles
        let used_style = copy *style;

        debug!("(create font group) --- finished ---");

        @FontGroup::new(style.families.to_managed(), &used_style, fonts)
    }

    priv fn create_font_instance(&self, desc: &FontDescriptor) -> Result<@mut Font, ()> {
        return match &desc.selector {
            // TODO(Issue #174): implement by-platform-name font selectors.
            &SelectorPlatformIdentifier(ref identifier) => {
                let result_handle = self.handle.create_font_from_identifier(copy *identifier,
                                                                            copy desc.style);
                result::chain(result_handle, |handle| {
                    Ok(Font::new_from_adopted_handle(self,
                                                     handle,
                                                     &desc.style,
                                                     self.backend,
                                                     self.profiler_chan.clone()))
                })
            }
        };
    }
}
<|endoftext|>


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

use redis::Value;

use serde::{self, de};

/// Error that can be produced during deserialization
#[derive(Debug)]
pub enum Error {
    Custom(String),
    TypeMismatch(String),
    EndOfStream,
    UnknownField(String),
    MissingField(&'static str),
    DeserializeNotSupported,
    WrongValue(String),
    FromUtf8(string::FromUtf8Error),
    ParseInt(num::ParseIntError),
    ParseFloat(num::ParseFloatError),
}

impl Error {
    pub fn wrong_value<S>(msg: S) -> Error
        where S: Into<String>
    {
        Error::WrongValue(msg.into())
    }
}

pub type Result<T> = ::std::result::Result<T, Error>;

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Custom(_) => "custom error when decoding redis values",
            Error::TypeMismatch(_) => "type mismatch when decoding redis values",
            Error::EndOfStream => "end of redis value stream",
            Error::UnknownField(_) => "unknown field",
            Error::MissingField(_) => "missing field",
            Error::DeserializeNotSupported => "unsupported deserialization operation",
            Error::WrongValue(_) => "expected value of different type",
            Error::FromUtf8(ref err) => err.description(),
            Error::ParseInt(ref err) => err.description(),
            Error::ParseFloat(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::FromUtf8(ref err) => Some(err),
            Error::ParseInt(ref err) => Some(err),
            Error::ParseFloat(ref err) => Some(err),
            _ => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Custom(ref reason) => write!(f, "CustomError({})", reason),
            Error::TypeMismatch(ref t) => write!(f, "TypeMismatch(expected: {})", t),
            Error::EndOfStream => write!(f, "Reached end of stream"),
            Error::UnknownField(ref field) => write!(f, "got unexpected field: {}", field),
            Error::MissingField(ref field) => write!(f, "missing field: {}", field),
            Error::DeserializeNotSupported => write!(f, "Deserialization option not supported"),
            Error::WrongValue(ref value_type) => write!(f, "Got unexpected value: {}", value_type),
            Error::FromUtf8(ref e) => write!(f, "{}", e),
            Error::ParseInt(ref e) => write!(f, "{}", e),
            Error::ParseFloat(ref e) => write!(f, "{}", e),
        }
    }
}

impl de::Error for Error {
    /// Raised when there is general error when deserializing a type.
    fn custom<T: Into<String>>(msg: T) -> Self {
        Error::Custom(msg.into())
    }

    /// Raised when a `Deserialize` type unexpectedly hit the end of the stream.
    fn end_of_stream() -> Self {
        Error::EndOfStream
    }

    /// Raised when a `Deserialize` was passed an incorrect value.
    fn invalid_value(msg: &str) -> Self {
        Error::custom(format!("Invalid value: {}", msg))
    }

    /// Raised when a fixed sized sequence or map was passed in the wrong amount of arguments.
    fn invalid_length(len: usize) -> Self {
        Error::custom(format!("Invalid length: {}", len))
    }

    /// Raised when a `Deserialize` enum type received an unexpected variant.
    fn unknown_variant(field: &str) -> Self {
        Error::custom(format!("Unknown variant `{}`", field))
    }

    fn unknown_field(field: &str) -> Error {
        Error::UnknownField(field.into())
    }

    fn missing_field(field: &'static str) -> Error {
        Error::MissingField(field)
    }

    fn invalid_type(t: ::serde::de::Type) -> Error {
        Error::TypeMismatch(format!("{:?}", t))
    }
}

impl From<string::FromUtf8Error> for Error {
    fn from(err: string::FromUtf8Error) -> Error {
        Error::FromUtf8(err)
    }
}

impl From<num::ParseIntError> for Error {
    fn from(err: num::ParseIntError) -> Error {
        Error::ParseInt(err)
    }
}

impl From<num::ParseFloatError> for Error {
    fn from(err: num::ParseFloatError) -> Error {
        Error::ParseFloat(err)
    }
}

/// deserializes Redis `Value`s
#[derive(Debug)]
pub struct Deserializer {
    root_values: Vec<Value>,
    nested_values: Vec<Value>,
    processing_nested_values: bool
}

impl Deserializer {
    pub fn new(redis_value: Value) -> Result<Deserializer> {
        let mut values = match redis_value {
            Value::Data(bytes) => vec![Value::Data(bytes)],
            Value::Bulk(bulk) => bulk,
            Value::Int(i) => vec![Value::Int(i)],
            Value::Nil => vec![Value::Nil],
            _ => return Err(Error::wrong_value("must be a redis value type"))
        };

        // TODO: would be better to turn this into an iterator than have to reverse and use the
        // vector.
        values.reverse();

        Ok(Deserializer {
            root_values: values,
            nested_values: Vec::new(),
            processing_nested_values: false
        })
    }

    /// Returns a reference to the next value
    ///
    /// Some qualification is required on "next value". If processing a subsequence (eg a hashmap
    /// returned in a pipeline), and the subsequence has come to an end, None will be returned even
    /// though the pipeline itself has additional data. This signals to the current visitor that
    /// there are no more values for it. The sequence visitor will continue using the pipeline data.
    pub fn peek(&self) -> Option<&Value> {
        if self.processing_nested_values {
            self.nested_values.last()
        } else {
            self.root_values.last()
        }
    }

    /// Return the next value
    ///
    /// See the qualification in the `peek` documentation as to the meaning of "next value".
    ///
    /// Unlike peek, this function will continue iterating on values. A value will be returned as
    /// long as the current subsequence or root sequence still has Values.
    pub fn next(&mut self) -> Result<Value> {
        // Work in the nested set if it's available
        if self.nested_values.len() != 0 {
            return match self.nested_values.pop() {
                Some(v) =>  Ok(v),
                None => Err(serde::de::Error::end_of_stream())
            };
        }

        // Otherwise, pop off the main list. If it's a bulk value, it becomes the new nested list,
        // and a value is returned from there.
        match self.root_values.pop() {
            Some(v) => {
                match v {
                    Value::Bulk(vals) => {
                        // descend into subsequence
                        self.set_subsequence(vals);
                        self.next()
                    },
                    _ => {
                        // Not processing nested values if this branch is reached.
                        self.processing_nested_values = false;
                        Ok(v)
                    }
                }
            },
            None => Err(serde::de::Error::end_of_stream())
        }
    }

    /// Sets a new subsequence
    fn set_subsequence(&mut self, mut values: Vec<Value>) {
        values.reverse();
        self.nested_values = values;
        self.processing_nested_values = true;
    }

    /// Notify that current bulk item has been completed (eg map, sequence)
    ///
    /// Visitors use this to update the deserializer state.
    pub fn completed_set(&mut self) {
        self.processing_nested_values = false;
    }

    pub fn read_string(&mut self) -> Result<String> {
        let redis_value = try!(self.next());
        Ok(match redis_value {
            Value::Data(bytes) => try!(String::from_utf8(bytes)),
            _ => {
                let msg = format!("Expected Data, got {:?}", &redis_value);
                return Err(Error::wrong_value(msg));
            }
        })
    }
}

macro_rules! impl_num {
    ($ty:ty, $deserialize_method:ident, $visitor_method:ident) => {
        #[inline]
        fn $deserialize_method<V>(&mut self, mut visitor: V) -> Result<V::Value>
            where V: serde::de::Visitor,
        {
            let redis_value = try!(self.next());
            let value = match redis_value {
                Value::Data(bytes) => {
                    let s = try!(String::from_utf8(bytes));
                    try!(s.parse::<$ty>())
                },
                Value::Int(i) => i as $ty,
                _ => {
                    let msg = format!("Expected Data or Int, got {:?}", &redis_value);
                    return Err(Error::wrong_value(msg));
                }
            };

            visitor.$visitor_method(value)
        }
    }
}

impl serde::Deserializer for Deserializer {
    type Error = Error;

    #[inline]
    fn deserialize<V>(&mut self, _visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        Err(Error::DeserializeNotSupported)
    }

    #[inline]
    fn deserialize_string<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        let s = try!(self.read_string());
        visitor.visit_string(s)
    }

    impl_num!(u8, deserialize_u8, visit_u8);
    impl_num!(u16, deserialize_u16, visit_u16);
    impl_num!(u32, deserialize_u32, visit_u32);
    impl_num!(u64, deserialize_u64, visit_u64);
    impl_num!(usize, deserialize_usize, visit_usize);

    impl_num!(i8, deserialize_i8, visit_i8);
    impl_num!(i16, deserialize_i16, visit_i16);
    impl_num!(i32, deserialize_i32, visit_i32);
    impl_num!(i64, deserialize_i64, visit_i64);
    impl_num!(isize, deserialize_isize, visit_isize);

    impl_num!(f32, deserialize_f32, visit_f32);
    impl_num!(f64, deserialize_f64, visit_f64);

    #[inline]
    fn deserialize_seq<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor
    {
        visitor.visit_seq(SeqVisitor { de: self })
    }

    #[inline]
    fn deserialize_map<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor,
    {
        visitor.visit_map(MapVisitor { de: self })
    }

    #[inline]
    fn deserialize_struct_field<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor,
    {
        let s = try!(self.read_string());
        visitor.visit_str(&s[..])
    }

    #[inline]
    fn deserialize_ignored_any<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor,
    {
        let s = try!(self.read_string());
        visitor.visit_str(&s[..])
    }

    #[inline]
    fn deserialize_enum<V>(&mut self,
                     _enum: &'static str,
                     _variants: &'static [&'static str],
                     mut visitor: V) -> Result<V::Value>
        where V: serde::de::EnumVisitor,
    {
        visitor.visit(VariantVisitor { de: self })
    }

    #[inline]
    fn deserialize_option<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor
    {
        let maybe = match self.peek() {
            Some(v) => {
                match *v {
                    Value::Data(_) => Some(()),
                    Value::Int(_) => Some(()),
                    Value::Nil => None,
                    _ => {
                        let msg = format!("Expected Data, Int, or Nil");
                        return Err(Error::wrong_value(msg));
                    }
                }
            },
            None => None,
        };

        if maybe.is_some() {
            visitor.visit_some(self)
        } else {
            visitor.visit_none()
        }
    }

    #[inline]
    fn deserialize_newtype_struct<V>(&mut self,
                                     _name: &'static str,
                                     mut visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor
    {
        visitor.visit_newtype_struct(self)
    }
}

struct SeqVisitor<'a> {
    de: &'a mut Deserializer,
}

impl<'a> de::SeqVisitor for SeqVisitor<'a> {
    type Error = Error;

    fn visit<T>(&mut self) -> Result<Option<T>>
        where T: de::Deserialize
    {
        if self.de.peek().is_some() {
            let value = try!(serde::Deserialize::deserialize(self.de));
            Ok(Some(value))
        } else {
            Ok(None)
        }
    }

    fn end(&mut self) -> Result<()> {
        self.de.completed_set();
        Ok(())
    }
}

struct MapVisitor<'a> {
    de: &'a mut Deserializer
}

impl<'a> serde::de::MapVisitor for MapVisitor<'a> {
    type Error = Error;

    fn visit_key<K>(&mut self) -> Result<Option<K>>
        where K: de::Deserialize,
    {
        if self.de.peek().is_some() {
            let key = try!(serde::Deserialize::deserialize(self.de));
            Ok(Some(key))
        } else {
            Ok(None)
        }
    }

    #[inline]
    fn visit_value<V>(&mut self) -> Result<V>
        where V: de::Deserialize,
    {
        serde::Deserialize::deserialize(self.de)
    }

    #[inline]
    fn end(&mut self) -> Result<()> {
        // ignore any unused values since keys can randomly be added in Redis
        self.de.completed_set();
        Ok(())
    }

    fn missing_field<V>(&mut self, _field: &'static str) -> Result<V>
        where V: de::Deserialize,
    {

        let mut de = de::value::ValueDeserializer::into_deserializer(());
        de::Deserialize::deserialize(&mut de)
    }
}

struct VariantVisitor<'a> {
    de: &'a mut Deserializer
}

impl<'a> serde::de::VariantVisitor for VariantVisitor<'a> {
    type Error = Error;

    fn visit_variant<V>(&mut self) -> Result<V>
        where V: serde::Deserialize,
    {
        let value = try!(serde::Deserialize::deserialize(self.de));
        Ok(value)
    }

    fn visit_unit(&mut self) -> Result<()> {
        Ok(())
    }

    fn visit_newtype<T>(&mut self) -> Result<T>
        where T: serde::de::Deserialize,
    {
        Err(de::Error::custom("newtype variants are not supported"))
    }

    fn visit_tuple<V>(&mut self,
                      _len: usize,
                      _visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor,
    {
        Err(de::Error::custom("tuple variants are not supported"))
    }

    fn visit_struct<V>(&mut self,
                       _fields: &'static [&'static str],
                       _visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor,
    {
        Err(de::Error::custom("struct variants are not supported"))
    }
}

<commit_msg>Support generic deserialize<commit_after>use std::error;
use std::fmt;
use std::string;
use std::num;

use redis::Value;

use serde::{self, de};

/// Error that can be produced during deserialization
#[derive(Debug)]
pub enum Error {
    Custom(String),
    TypeMismatch(String),
    EndOfStream,
    UnknownField(String),
    MissingField(&'static str),
    DeserializeNotSupported,
    WrongValue(String),
    FromUtf8(string::FromUtf8Error),
    ParseInt(num::ParseIntError),
    ParseFloat(num::ParseFloatError),
}

impl Error {
    pub fn wrong_value<S>(msg: S) -> Error
        where S: Into<String>
    {
        Error::WrongValue(msg.into())
    }
}

pub type Result<T> = ::std::result::Result<T, Error>;

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Custom(_) => "custom error when decoding redis values",
            Error::TypeMismatch(_) => "type mismatch when decoding redis values",
            Error::EndOfStream => "end of redis value stream",
            Error::UnknownField(_) => "unknown field",
            Error::MissingField(_) => "missing field",
            Error::DeserializeNotSupported => "unsupported deserialization operation",
            Error::WrongValue(_) => "expected value of different type",
            Error::FromUtf8(ref err) => err.description(),
            Error::ParseInt(ref err) => err.description(),
            Error::ParseFloat(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::FromUtf8(ref err) => Some(err),
            Error::ParseInt(ref err) => Some(err),
            Error::ParseFloat(ref err) => Some(err),
            _ => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Custom(ref reason) => write!(f, "CustomError({})", reason),
            Error::TypeMismatch(ref t) => write!(f, "TypeMismatch(expected: {})", t),
            Error::EndOfStream => write!(f, "Reached end of stream"),
            Error::UnknownField(ref field) => write!(f, "got unexpected field: {}", field),
            Error::MissingField(ref field) => write!(f, "missing field: {}", field),
            Error::DeserializeNotSupported => write!(f, "Deserialization option not supported"),
            Error::WrongValue(ref value_type) => write!(f, "Got unexpected value: {}", value_type),
            Error::FromUtf8(ref e) => write!(f, "{}", e),
            Error::ParseInt(ref e) => write!(f, "{}", e),
            Error::ParseFloat(ref e) => write!(f, "{}", e),
        }
    }
}

impl de::Error for Error {
    /// Raised when there is general error when deserializing a type.
    fn custom<T: Into<String>>(msg: T) -> Self {
        Error::Custom(msg.into())
    }

    /// Raised when a `Deserialize` type unexpectedly hit the end of the stream.
    fn end_of_stream() -> Self {
        Error::EndOfStream
    }

    /// Raised when a `Deserialize` was passed an incorrect value.
    fn invalid_value(msg: &str) -> Self {
        Error::custom(format!("Invalid value: {}", msg))
    }

    /// Raised when a fixed sized sequence or map was passed in the wrong amount of arguments.
    fn invalid_length(len: usize) -> Self {
        Error::custom(format!("Invalid length: {}", len))
    }

    /// Raised when a `Deserialize` enum type received an unexpected variant.
    fn unknown_variant(field: &str) -> Self {
        Error::custom(format!("Unknown variant `{}`", field))
    }

    fn unknown_field(field: &str) -> Error {
        Error::UnknownField(field.into())
    }

    fn missing_field(field: &'static str) -> Error {
        Error::MissingField(field)
    }

    fn invalid_type(t: ::serde::de::Type) -> Error {
        Error::TypeMismatch(format!("{:?}", t))
    }
}

impl From<string::FromUtf8Error> for Error {
    fn from(err: string::FromUtf8Error) -> Error {
        Error::FromUtf8(err)
    }
}

impl From<num::ParseIntError> for Error {
    fn from(err: num::ParseIntError) -> Error {
        Error::ParseInt(err)
    }
}

impl From<num::ParseFloatError> for Error {
    fn from(err: num::ParseFloatError) -> Error {
        Error::ParseFloat(err)
    }
}

/// deserializes Redis `Value`s
#[derive(Debug)]
pub struct Deserializer {
    root_values: Vec<Value>,
    nested_values: Vec<Value>,
    processing_nested_values: bool
}

impl Deserializer {
    pub fn new(redis_value: Value) -> Result<Deserializer> {
        let mut values = match redis_value {
            Value::Data(bytes) => vec![Value::Data(bytes)],
            Value::Bulk(bulk) => bulk,
            Value::Int(i) => vec![Value::Int(i)],
            Value::Nil => vec![Value::Nil],
            _ => return Err(Error::wrong_value("must be a redis value type"))
        };

        // TODO: would be better to turn this into an iterator than have to reverse and use the
        // vector.
        values.reverse();

        Ok(Deserializer {
            root_values: values,
            nested_values: Vec::new(),
            processing_nested_values: false
        })
    }

    /// Returns a reference to the next value
    ///
    /// Some qualification is required on "next value". If processing a subsequence (eg a hashmap
    /// returned in a pipeline), and the subsequence has come to an end, None will be returned even
    /// though the pipeline itself has additional data. This signals to the current visitor that
    /// there are no more values for it. The sequence visitor will continue using the pipeline data.
    pub fn peek(&self) -> Option<&Value> {
        if self.processing_nested_values {
            self.nested_values.last()
        } else {
            self.root_values.last()
        }
    }

    /// Return the next value
    ///
    /// See the qualification in the `peek` documentation as to the meaning of "next value".
    ///
    /// Unlike peek, this function will continue iterating on values. A value will be returned as
    /// long as the current subsequence or root sequence still has Values.
    pub fn next(&mut self) -> Result<Value> {
        // Work in the nested set if it's available
        if self.nested_values.len() != 0 {
            return match self.nested_values.pop() {
                Some(v) =>  Ok(v),
                None => Err(serde::de::Error::end_of_stream())
            };
        }

        // Otherwise, pop off the main list. If it's a bulk value, it becomes the new nested list,
        // and a value is returned from there.
        match self.root_values.pop() {
            Some(v) => {
                match v {
                    Value::Bulk(vals) => {
                        // descend into subsequence
                        self.set_subsequence(vals);
                        self.next()
                    },
                    _ => {
                        // Not processing nested values if this branch is reached.
                        self.processing_nested_values = false;
                        Ok(v)
                    }
                }
            },
            None => Err(serde::de::Error::end_of_stream())
        }
    }

    /// Sets a new subsequence
    fn set_subsequence(&mut self, mut values: Vec<Value>) {
        values.reverse();
        self.nested_values = values;
        self.processing_nested_values = true;
    }

    /// Notify that current bulk item has been completed (eg map, sequence)
    ///
    /// Visitors use this to update the deserializer state.
    pub fn completed_set(&mut self) {
        self.processing_nested_values = false;
    }

    pub fn read_string(&mut self) -> Result<String> {
        let redis_value = try!(self.next());
        Ok(match redis_value {
            Value::Data(bytes) => try!(String::from_utf8(bytes)),
            _ => {
                let msg = format!("Expected Data, got {:?}", &redis_value);
                return Err(Error::wrong_value(msg));
            }
        })
    }
}

macro_rules! impl_num {
    ($ty:ty, $deserialize_method:ident, $visitor_method:ident) => {
        #[inline]
        fn $deserialize_method<V>(&mut self, mut visitor: V) -> Result<V::Value>
            where V: serde::de::Visitor,
        {
            let redis_value = try!(self.next());
            let value = match redis_value {
                Value::Data(bytes) => {
                    let s = try!(String::from_utf8(bytes));
                    try!(s.parse::<$ty>())
                },
                Value::Int(i) => i as $ty,
                _ => {
                    let msg = format!("Expected Data or Int, got {:?}", &redis_value);
                    return Err(Error::wrong_value(msg));
                }
            };

            visitor.$visitor_method(value)
        }
    }
}

impl serde::Deserializer for Deserializer {
    type Error = Error;

    #[inline]
    fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        let s = try!(self.read_string());
        visitor.visit_str(&s[..])
    }

    #[inline]
    fn deserialize_string<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        let s = try!(self.read_string());
        visitor.visit_string(s)
    }

    impl_num!(u8, deserialize_u8, visit_u8);
    impl_num!(u16, deserialize_u16, visit_u16);
    impl_num!(u32, deserialize_u32, visit_u32);
    impl_num!(u64, deserialize_u64, visit_u64);
    impl_num!(usize, deserialize_usize, visit_usize);

    impl_num!(i8, deserialize_i8, visit_i8);
    impl_num!(i16, deserialize_i16, visit_i16);
    impl_num!(i32, deserialize_i32, visit_i32);
    impl_num!(i64, deserialize_i64, visit_i64);
    impl_num!(isize, deserialize_isize, visit_isize);

    impl_num!(f32, deserialize_f32, visit_f32);
    impl_num!(f64, deserialize_f64, visit_f64);

    #[inline]
    fn deserialize_seq<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor
    {
        visitor.visit_seq(SeqVisitor { de: self })
    }

    #[inline]
    fn deserialize_map<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor,
    {
        visitor.visit_map(MapVisitor { de: self })
    }

    #[inline]
    fn deserialize_struct_field<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor,
    {
        let s = try!(self.read_string());
        visitor.visit_str(&s[..])
    }

    #[inline]
    fn deserialize_ignored_any<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor,
    {
        let s = try!(self.read_string());
        visitor.visit_str(&s[..])
    }

    #[inline]
    fn deserialize_enum<V>(&mut self,
                     _enum: &'static str,
                     _variants: &'static [&'static str],
                     mut visitor: V) -> Result<V::Value>
        where V: serde::de::EnumVisitor,
    {
        visitor.visit(VariantVisitor { de: self })
    }

    #[inline]
    fn deserialize_option<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor
    {
        let maybe = match self.peek() {
            Some(v) => {
                match *v {
                    Value::Data(_) => Some(()),
                    Value::Int(_) => Some(()),
                    Value::Nil => None,
                    _ => {
                        let msg = format!("Expected Data, Int, or Nil");
                        return Err(Error::wrong_value(msg));
                    }
                }
            },
            None => None,
        };

        if maybe.is_some() {
            visitor.visit_some(self)
        } else {
            visitor.visit_none()
        }
    }

    #[inline]
    fn deserialize_newtype_struct<V>(&mut self,
                                     _name: &'static str,
                                     mut visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor
    {
        visitor.visit_newtype_struct(self)
    }
}

struct SeqVisitor<'a> {
    de: &'a mut Deserializer,
}

impl<'a> de::SeqVisitor for SeqVisitor<'a> {
    type Error = Error;

    fn visit<T>(&mut self) -> Result<Option<T>>
        where T: de::Deserialize
    {
        if self.de.peek().is_some() {
            let value = try!(serde::Deserialize::deserialize(self.de));
            Ok(Some(value))
        } else {
            Ok(None)
        }
    }

    fn end(&mut self) -> Result<()> {
        self.de.completed_set();
        Ok(())
    }
}

struct MapVisitor<'a> {
    de: &'a mut Deserializer
}

impl<'a> serde::de::MapVisitor for MapVisitor<'a> {
    type Error = Error;

    fn visit_key<K>(&mut self) -> Result<Option<K>>
        where K: de::Deserialize,
    {
        if self.de.peek().is_some() {
            let key = try!(serde::Deserialize::deserialize(self.de));
            Ok(Some(key))
        } else {
            Ok(None)
        }
    }

    #[inline]
    fn visit_value<V>(&mut self) -> Result<V>
        where V: de::Deserialize,
    {
        serde::Deserialize::deserialize(self.de)
    }

    #[inline]
    fn end(&mut self) -> Result<()> {
        // ignore any unused values since keys can randomly be added in Redis
        self.de.completed_set();
        Ok(())
    }

    fn missing_field<V>(&mut self, _field: &'static str) -> Result<V>
        where V: de::Deserialize,
    {

        let mut de = de::value::ValueDeserializer::into_deserializer(());
        de::Deserialize::deserialize(&mut de)
    }
}

struct VariantVisitor<'a> {
    de: &'a mut Deserializer
}

impl<'a> serde::de::VariantVisitor for VariantVisitor<'a> {
    type Error = Error;

    fn visit_variant<V>(&mut self) -> Result<V>
        where V: serde::Deserialize,
    {
        let value = try!(serde::Deserialize::deserialize(self.de));
        Ok(value)
    }

    fn visit_unit(&mut self) -> Result<()> {
        Ok(())
    }

    fn visit_newtype<T>(&mut self) -> Result<T>
        where T: serde::de::Deserialize,
    {
        Err(de::Error::custom("newtype variants are not supported"))
    }

    fn visit_tuple<V>(&mut self,
                      _len: usize,
                      _visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor,
    {
        Err(de::Error::custom("tuple variants are not supported"))
    }

    fn visit_struct<V>(&mut self,
                       _fields: &'static [&'static str],
                       _visitor: V) -> Result<V::Value>
        where V: serde::de::Visitor,
    {
        Err(de::Error::custom("struct variants are not supported"))
    }
}

<|endoftext|>


<commit_before>use ::ffi;

/// Special data accessors

pub fn get_name(pnd: *mut ffi::nfc_device) -> &'static str {
    unsafe {
        let name = CStr::from_ptr(ffi::nfc_device_get_name(pnd)).to_str().unwrap();

        name
    }
}

pub fn get_connstring(pnd: *mut ffi::nfc_device) -> &'static str {
    unsafe {
        let connstring = CStr::from_ptr(ffi::nfc_device_get_connstring(pnd)).to_str().unwrap();

        connstring
    }
}

pub fn get_supported_modulation(pnd: *mut ffi::nfc_device, mode: ffi::nfc_mode, supported_mt: *mut *const ffi::nfc_modulation_type) -> i32 {
    unsafe { ffi::nfc_device_get_supported_modulation(pnd, mode, supported_mt) }
}

pub fn get_supported_baud_rate(pnd: *mut ffi::nfc_device, nmt: ffi::nfc_modulation_type, supported_br: *mut *const ffi::nfc_baud_rate) -> i32 {
    unsafe { ffi::nfc_device_get_supported_baud_rate(pnd, nmt, supported_br) }
}

/// Properties accessors

pub fn set_property_int(pnd: *mut ffi::nfc_device, property: ffi::nfc_property, value: i32) -> i32 {
    unsafe { ffi::nfc_device_set_property_int(pnd, property, value) }
}

pub fn set_property_bool(pnd: *mut ffi::nfc_device, property: ffi::nfc_property, bEnable: u8) -> i32 {
    unsafe { ffi::nfc_device_set_property_bool(pnd, property, bEnable) }
}
<commit_msg>Include CStr in device mod<commit_after>use ::ffi;
use std::ffi::CStr;

/// Special data accessors

pub fn get_name(pnd: *mut ffi::nfc_device) -> &'static str {
    unsafe {
        let name = CStr::from_ptr(ffi::nfc_device_get_name(pnd)).to_str().unwrap();

        name
    }
}

pub fn get_connstring(pnd: *mut ffi::nfc_device) -> &'static str {
    unsafe {
        let connstring = CStr::from_ptr(ffi::nfc_device_get_connstring(pnd)).to_str().unwrap();

        connstring
    }
}

pub fn get_supported_modulation(pnd: *mut ffi::nfc_device, mode: ffi::nfc_mode, supported_mt: *mut *const ffi::nfc_modulation_type) -> i32 {
    unsafe { ffi::nfc_device_get_supported_modulation(pnd, mode, supported_mt) }
}

pub fn get_supported_baud_rate(pnd: *mut ffi::nfc_device, nmt: ffi::nfc_modulation_type, supported_br: *mut *const ffi::nfc_baud_rate) -> i32 {
    unsafe { ffi::nfc_device_get_supported_baud_rate(pnd, nmt, supported_br) }
}

/// Properties accessors

pub fn set_property_int(pnd: *mut ffi::nfc_device, property: ffi::nfc_property, value: i32) -> i32 {
    unsafe { ffi::nfc_device_set_property_int(pnd, property, value) }
}

pub fn set_property_bool(pnd: *mut ffi::nfc_device, property: ffi::nfc_property, bEnable: u8) -> i32 {
    unsafe { ffi::nfc_device_set_property_bool(pnd, property, bEnable) }
}
<|endoftext|>


<commit_before>use byteorder;
use std::{fmt, io, string};

pub enum OscError {
    StringError(string::FromUtf8Error),
    ReadError(io::Error),
    ByteOrderError(byteorder::Error),
    BadOscPacket(String),
    BadOscAddress(String),
    BadOscMessage(String),
    BadOscString(String),
    BadOscBundle,
}

impl fmt::Display for OscError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            _ => write!(f, "{}", "TODO"),
        }
    }
}
<commit_msg>Add common error type for Osc arguments<commit_after>use byteorder;
use std::{fmt, io, string};

pub enum OscError {
    StringError(string::FromUtf8Error),
    ReadError(io::Error),
    ByteOrderError(byteorder::Error),
    BadOscPacket(String),
    BadOscAddress(String),
    BadOscMessage(String),
    BadOscString(String),
    BadOscArg(String),
    BadOscBundle,
}

impl fmt::Display for OscError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            _ => write!(f, "{}", "TODO"),
        }
    }
}
<|endoftext|>


<commit_before>
//! Repeat a stream multiple times.

use event;
use modifier;
use transform;
use template;
use builder;

/// A stored stream representing an element if the parent stream does.
pub type MaybeElementTemplate<D> = modifier::Derived<template::TemplateStream, D>;

/// Repeat a stream for each item of an iterator.
pub struct Repeat<S, I, B>
where
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
{
    state: modifier::State<State<S, I, B, MaybeElementTemplate<S>>>,
}

impl<S, I, B> Repeat<S, I, B>
where
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
{
    pub(crate) fn new(stream: S, iter: I, builder: B) -> Repeat<S, I, B> {
        Repeat {
            state: modifier::State::new(State::Collect { stream, iter, builder }),
        }
    }
}

impl<S, I, B> event::Stream for Repeat<S, I, B>
where
    S: event::Stream,
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.state.step(|state| state.step(modifier::Derived::new))
    }
}

enum State<S, I, B, SB>
where
    I: Iterator,
    B: builder::BuildMutMapped<SB, I::Item>,
{
    Collect {
        stream: S,
        builder: B,
        iter: I,
    },
    Next {
        template: template::Template,
        builder: B,
        iter: I,
    },
    Emit {
        template: template::Template,
        stream: B::Stream,
        builder: B,
        iter: I,
    },
}

impl<S, I, B, SB> State<S, I, B, SB>
where
    I: Iterator,
    B: builder::BuildMutMapped<SB, I::Item>,
    S: event::Stream,
    SB: event::Stream,
{
    fn step<F>(self, stepper: F) -> modifier::StateResult<State<S, I, B, SB>>
    where
        F: FnOnce(template::TemplateStream) -> SB,
    {
        use event::{ Stream };
        match self {
            State::Collect { stream, builder, iter } => {
                let template = template::Template::from_stream(stream)?;
                Ok(Some((event::noop(), Some(State::Next { template, builder, iter }))))
            },
            State::Next { template, mut builder, mut iter } => {
                let item = match iter.next() {
                    Some(value) => value,
                    None => return Ok(None),
                };
                let stream = stepper(template.to_stream());
                let stream = transform::build_mut_mapped(stream, &mut builder, item);
                Ok(Some((event::noop(), Some(State::Emit { template, stream, builder, iter }))))
            },
            State::Emit { template, builder, iter, mut stream } => match stream.next_event()? {
                Some(event) => Ok(Some((
                    event,
                    Some(State::Emit { template, builder, iter, stream }),
                ))),
                None => Ok(Some((
                    event::noop(),
                    Some(State::Next { template, builder, iter }),
                ))),
            },
        }
    }
}

struct RepeatContentStream<S, I, B>
where
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    state: modifier::State<State<S, I, B, template::TemplateStream>>,
}

impl<S, I, B> event::Stream for RepeatContentStream<S, I, B>
where
    S: event::Stream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.state.step(|state| state.step(|stream| stream))
    }
}

struct Builder {
    iter: I,
    builder: B,
}

impl<S, I, B> builder::BuildOnce<modifier::select::CurrentContent<S>> for Builder
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    type Stream = RepeatContentStream<modifier::select::CurrentContent<S>, I, B>;

    fn build_once(self, stream: transform::Api<modifier::select::CurrentContent<S>>)
    -> transform::Api<Self::Stream> {
        transform::Api::pack(RepeatContentStream {
            state: modifier::State::new(State::Collect {
                stream: stream.unpack(),
                iter: self.iter,
                builder: self.builder,
            }),
        })
    }
}

/// Repeat the contents of the current element for each item of an iterator.
pub struct RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    stream: modifier::select::SelectContent<S, Builder>,
}

impl<S, I, B> RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    pub(crate) fn new(stream: S, iter: I, builder: B) -> RepeatContent<S, I, B> {
        RepeatContent {
            stream: modifier::select::SelectContent::new(stream, Builder { iter, builder }),
        }
    }
}

impl<S, I, B> event::Stream for RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.stream.next_event()
    }
}

impl<S, I, B> event::ElementStream for RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{}

#[cfg(test)]
mod tests {
    use std::str::{ FromStr };

    #[test]
    fn repeat_contents() {
        test_transform!(
            Default::default(),
            "23<c></c>45",
            "23<c>3</c>4523<c>4</c>45",
            |html| html
                .select(::select::Tag::from_str("b").unwrap(), |html| html
                    .repeat_contents(3..5, |html, n| html
                        .select(::select::Tag::from_str("c").unwrap(), move |html| html
                            .replace_contents(n)
                        )
                    )
                )
        );
    }

    #[test]
    fn repeat() {
        test_transform!(
            Default::default(),
            "23<c></c>45",
            "23<c>3</c>4523<c>4</c>45",
            |html| html
                .select(::select::Tag::from_str("b").unwrap(), |html| html
                    .repeat(3..5, |html, n| html
                        .select(::select::Tag::from_str("c").unwrap(), move |html| html
                            .replace_contents(n)
                        )
                    )
                )
        );
    }
}
<commit_msg>moved repeat to new test structure<commit_after>
//! Repeat a stream multiple times.

use event;
use modifier;
use transform;
use template;
use builder;

/// A stored stream representing an element if the parent stream does.
pub type MaybeElementTemplate<D> = modifier::Derived<template::TemplateStream, D>;

/// Repeat a stream for each item of an iterator.
pub struct Repeat<S, I, B>
where
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
{
    state: modifier::State<State<S, I, B, MaybeElementTemplate<S>>>,
}

impl<S, I, B> Repeat<S, I, B>
where
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
{
    pub(crate) fn new(stream: S, iter: I, builder: B) -> Repeat<S, I, B> {
        Repeat {
            state: modifier::State::new(State::Collect { stream, iter, builder }),
        }
    }
}

impl<S, I, B> event::Stream for Repeat<S, I, B>
where
    S: event::Stream,
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.state.step(|state| state.step(modifier::Derived::new))
    }
}

enum State<S, I, B, SB>
where
    I: Iterator,
    B: builder::BuildMutMapped<SB, I::Item>,
{
    Collect {
        stream: S,
        builder: B,
        iter: I,
    },
    Next {
        template: template::Template,
        builder: B,
        iter: I,
    },
    Emit {
        template: template::Template,
        stream: B::Stream,
        builder: B,
        iter: I,
    },
}

impl<S, I, B, SB> State<S, I, B, SB>
where
    I: Iterator,
    B: builder::BuildMutMapped<SB, I::Item>,
    S: event::Stream,
    SB: event::Stream,
{
    fn step<F>(self, stepper: F) -> modifier::StateResult<State<S, I, B, SB>>
    where
        F: FnOnce(template::TemplateStream) -> SB,
    {
        use event::{ Stream };
        match self {
            State::Collect { stream, builder, iter } => {
                let template = template::Template::from_stream(stream)?;
                Ok(Some((event::noop(), Some(State::Next { template, builder, iter }))))
            },
            State::Next { template, mut builder, mut iter } => {
                let item = match iter.next() {
                    Some(value) => value,
                    None => return Ok(None),
                };
                let stream = stepper(template.to_stream());
                let stream = transform::build_mut_mapped(stream, &mut builder, item);
                Ok(Some((event::noop(), Some(State::Emit { template, stream, builder, iter }))))
            },
            State::Emit { template, builder, iter, mut stream } => match stream.next_event()? {
                Some(event) => Ok(Some((
                    event,
                    Some(State::Emit { template, builder, iter, stream }),
                ))),
                None => Ok(Some((
                    event::noop(),
                    Some(State::Next { template, builder, iter }),
                ))),
            },
        }
    }
}

struct RepeatContentStream<S, I, B>
where
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    state: modifier::State<State<S, I, B, template::TemplateStream>>,
}

impl<S, I, B> event::Stream for RepeatContentStream<S, I, B>
where
    S: event::Stream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.state.step(|state| state.step(|stream| stream))
    }
}

struct Builder {
    iter: I,
    builder: B,
}

impl<S, I, B> builder::BuildOnce<modifier::select::CurrentContent<S>> for Builder
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    type Stream = RepeatContentStream<modifier::select::CurrentContent<S>, I, B>;

    fn build_once(self, stream: transform::Api<modifier::select::CurrentContent<S>>)
    -> transform::Api<Self::Stream> {
        transform::Api::pack(RepeatContentStream {
            state: modifier::State::new(State::Collect {
                stream: stream.unpack(),
                iter: self.iter,
                builder: self.builder,
            }),
        })
    }
}

/// Repeat the contents of the current element for each item of an iterator.
pub struct RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    stream: modifier::select::SelectContent<S, Builder>,
}

impl<S, I, B> RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    pub(crate) fn new(stream: S, iter: I, builder: B) -> RepeatContent<S, I, B> {
        RepeatContent {
            stream: modifier::select::SelectContent::new(stream, Builder { iter, builder }),
        }
    }
}

impl<S, I, B> event::Stream for RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.stream.next_event()
    }
}

impl<S, I, B> event::ElementStream for RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{}

#[cfg(test)]
mod tests {
    use std::str::{ FromStr };

    test_group!(repeat_contents:
        "some integers" => transform_test!(
            "23<c></c>45",
            "23<c>3</c>4523<c>4</c>45",
            |html| html.select("b", |html| html.repeat_contents(3..5, |html, n| html
                .select("c", move |html| html.replace_contents(n))
            )),
        ),
        "empty iterator" => transform_test!(
            "23<c></c>45",
            "",
            |html| html.select("b", |html| html.repeat_contents(0..0, |html, n| html
                .select("c", move |html| html.replace_contents(n))
            )),
        ),
    );

    test_group!(repeat:
        "some integers" => transform_test!(
            "23<c></c>45",
            "23<c>3</c>4523<c>4</c>45",
            |html| html.select("b", |html| html.repeat(3..5, |html, n| html
                .select("c", move |html| html.replace_contents(n))
            )),
        ),
        "empty iterator" => transform_test!(
            "23<c></c>45",
            "",
            |html| html.select("b", |html| html.repeat(0..0, |html, n| html
                .select("c", move |html| html.replace_contents(n))
            )),
        ),
    );
}
<|endoftext|>