<commit_before>// This example uses fds() to find out which file descriptors c-ares
// wants us to listen on, and uses select() to satisfy those requirements.
extern crate c_ares;

use winapi::winsock2::{fd_set, timeval, FD_SETSIZE, SOCKET_ERROR, WSADATA};
use ws2_32::{select, WSACleanup, WSAStartup};
use std::error::Error;
use std::mem;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::ptr;

fn print_soa_result(result: &c_ares::Result<c_ares::SOAResult>) {
    match *result {
        Err(ref e) => {
            println!("SOA lookup failed with error '{}'", e.description());
        }
        Ok(ref soa_result) => {
            println!("Successful SOA lookup...");
            println!("Name server: {}", soa_result.name_server());
            println!("Hostmaster: {}", soa_result.hostmaster());
            println!("Serial: {}", soa_result.serial());
            println!("Retry: {}", soa_result.retry());
            println!("Expire: {}", soa_result.expire());
            println!("Min TTL: {}", soa_result.min_ttl());
        }
    }
}

fn print_name_info_result(result: &c_ares::Result<c_ares::NameInfoResult>) {
    match *result {
        Err(ref e) => {
            println!("Name info lookup failed with error '{}'", e.description());
        }
        Ok(ref name_info_result) => {
            println!("Successful name info lookup...");
            println!("Node: {}", name_info_result.node().unwrap_or("<None>"));
            println!(
                "Service: {}",
                name_info_result.service().unwrap_or("<None>")
            );
        }
    }
}

pub fn main() {
    // Windows peculiarities.
    unsafe {
        let mut wsadata: WSADATA = mem::uninitialized();
        WSAStartup(0x101, &mut wsadata);
    }

    // Create the c_ares::Channel.
    let mut options = c_ares::Options::new();
    options
        .set_domains(&["example.com"])
        .set_flags(c_ares::Flags::STAYOPEN)
        .set_timeout(500)
        .set_tries(3);
    let mut ares_channel =
        c_ares::Channel::with_options(options).expect("Failed to create channel");
    ares_channel
        .set_servers(&["8.8.8.8"])
        .expect("Failed to set servers");

    // Set up some queries.
    ares_channel.query_soa("google.com", move |result| {
        println!();
        print_soa_result(&result);
    });

    let ipv4 = "216.58.210.14".parse::<Ipv4Addr>().unwrap();
    let sock = SocketAddr::V4(SocketAddrV4::new(ipv4, 80));
    ares_channel.get_name_info(
        &sock,
        c_ares::NIFlags::LOOKUPHOST | c_ares::NIFlags::LOOKUPSERVICE,
        move |result| {
            println!();
            print_name_info_result(&result);
        },
    );

    let ipv6 = "2a00:1450:4009:80a::200e".parse::<Ipv6Addr>().unwrap();
    let sock = SocketAddr::V6(SocketAddrV6::new(ipv6, 80, 0, 0));
    ares_channel.get_name_info(
        &sock,
        c_ares::NIFlags::LOOKUPHOST | c_ares::NIFlags::LOOKUPSERVICE,
        move |result| {
            println!();
            print_name_info_result(result);
        },
    );

    // While c-ares wants us to listen for events, do so..
    loop {
        let mut read_fds = fd_set {
            fd_count: 0,
            fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
        };
        let mut write_fds = fd_set {
            fd_count: 0,
            fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
        };
        let count = ares_channel.fds(&mut read_fds, &mut write_fds);
        if count == 0 {
            break;
        }

        // Wait for something to happen.
        let timeout = timeval {
            tv_sec: 0,
            tv_usec: 500000,
        };
        let results =
            unsafe { select(0, &mut read_fds, &mut write_fds, ptr::null_mut(), &timeout) };

        // Process whatever happened.
        match results {
            SOCKET_ERROR => panic!("Socket error"),
            _ => ares_channel.process(&mut read_fds, &mut write_fds),
        }
    }
    unsafe {
        WSACleanup();
    }
}
<commit_msg>fix windows examples build<commit_after>// This example uses fds() to find out which file descriptors c-ares
// wants us to listen on, and uses select() to satisfy those requirements.
extern crate c_ares;

use winapi::winsock2::{fd_set, timeval, FD_SETSIZE, SOCKET_ERROR, WSADATA};
use ws2_32::{select, WSACleanup, WSAStartup};
use std::error::Error;
use std::mem;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::ptr;

fn print_soa_result(result: &c_ares::Result<c_ares::SOAResult>) {
    match *result {
        Err(ref e) => {
            println!("SOA lookup failed with error '{}'", e.description());
        }
        Ok(ref soa_result) => {
            println!("Successful SOA lookup...");
            println!("Name server: {}", soa_result.name_server());
            println!("Hostmaster: {}", soa_result.hostmaster());
            println!("Serial: {}", soa_result.serial());
            println!("Retry: {}", soa_result.retry());
            println!("Expire: {}", soa_result.expire());
            println!("Min TTL: {}", soa_result.min_ttl());
        }
    }
}

fn print_name_info_result(result: &c_ares::Result<c_ares::NameInfoResult>) {
    match *result {
        Err(ref e) => {
            println!("Name info lookup failed with error '{}'", e.description());
        }
        Ok(ref name_info_result) => {
            println!("Successful name info lookup...");
            println!("Node: {}", name_info_result.node().unwrap_or("<None>"));
            println!(
                "Service: {}",
                name_info_result.service().unwrap_or("<None>")
            );
        }
    }
}

pub fn main() {
    // Windows peculiarities.
    unsafe {
        let mut wsadata: WSADATA = mem::uninitialized();
        WSAStartup(0x101, &mut wsadata);
    }

    // Create the c_ares::Channel.
    let mut options = c_ares::Options::new();
    options
        .set_domains(&["example.com"])
        .set_flags(c_ares::Flags::STAYOPEN)
        .set_timeout(500)
        .set_tries(3);
    let mut ares_channel =
        c_ares::Channel::with_options(options).expect("Failed to create channel");
    ares_channel
        .set_servers(&["8.8.8.8"])
        .expect("Failed to set servers");

    // Set up some queries.
    ares_channel.query_soa("google.com", move |result| {
        println!();
        print_soa_result(&result);
    });

    let ipv4 = "216.58.210.14".parse::<Ipv4Addr>().unwrap();
    let sock = SocketAddr::V4(SocketAddrV4::new(ipv4, 80));
    ares_channel.get_name_info(
        &sock,
        c_ares::NIFlags::LOOKUPHOST | c_ares::NIFlags::LOOKUPSERVICE,
        move |result| {
            println!();
            print_name_info_result(&result);
        },
    );

    let ipv6 = "2a00:1450:4009:80a::200e".parse::<Ipv6Addr>().unwrap();
    let sock = SocketAddr::V6(SocketAddrV6::new(ipv6, 80, 0, 0));
    ares_channel.get_name_info(
        &sock,
        c_ares::NIFlags::LOOKUPHOST | c_ares::NIFlags::LOOKUPSERVICE,
        move |result| {
            println!();
            print_name_info_result(&result);
        },
    );

    // While c-ares wants us to listen for events, do so..
    loop {
        let mut read_fds = fd_set {
            fd_count: 0,
            fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
        };
        let mut write_fds = fd_set {
            fd_count: 0,
            fd_array: [c_ares::SOCKET_BAD; FD_SETSIZE],
        };
        let count = ares_channel.fds(&mut read_fds, &mut write_fds);
        if count == 0 {
            break;
        }

        // Wait for something to happen.
        let timeout = timeval {
            tv_sec: 0,
            tv_usec: 500000,
        };
        let results =
            unsafe { select(0, &mut read_fds, &mut write_fds, ptr::null_mut(), &timeout) };

        // Process whatever happened.
        match results {
            SOCKET_ERROR => panic!("Socket error"),
            _ => ares_channel.process(&mut read_fds, &mut write_fds),
        }
    }
    unsafe {
        WSACleanup();
    }
}
<|endoftext|>


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

//! Command line commands utilities.

use std::str::FromStr;
use std::error::Error;
use std::collections::BTreeMap;

use clap;
use toml::Value;
use serde::{Serialize, Deserialize};

use blockchain::Service;
use self::internal::NotFoundInMap;

pub use self::builder::NodeBuilder;
pub use self::details::{Run, Finalize, GenerateNodeConfig, GenerateCommonConfig, GenerateTestnet};
pub use self::shared::{AbstractConfig, NodePublicConfig, CommonConfigTemplate, NodePrivateConfig};
pub use self::context_key::ContextKey;

mod shared;
mod builder;
mod details;
mod internal;
mod clap_backend;
#[macro_use]
mod context_key;

/// Default port value.
pub const DEFAULT_EXONUM_LISTEN_PORT: u16 = 6333;

/// Name of the `Command`.
pub type CommandName = &'static str;

/// `Argument` with name.
#[derive(Clone, Copy, Debug)]
pub struct NamedArgument {
    /// Short argument name, for example `-a`.
    pub short_name: Option<&'static str>,
    /// Long argument name, for example `--long-arg`.
    pub long_name: &'static str,
    /// If `multiple` is true, then argument has more than one value.
    pub multiple: bool,
}

/// Possible types of the arguments.
#[derive(Clone, Copy, Debug)]
pub enum ArgumentType {
    /// Unnamed positional argument.
    Positional,
    /// Named argument.
    Named(NamedArgument),
}

/// Abstraction to represent arguments in command line.
#[derive(Clone, Copy, Debug)]
pub struct Argument {
    /// Name of the current argument. This name is used in `context.arg(name)`.
    pub name: &'static str,
    /// Explains how this argument is represented.
    pub argument_type: ArgumentType,
    /// Explains if the argument required or not.
    pub required: bool,
    /// Help message.
    pub help: &'static str,
}

impl Argument {
    /// Creates a new argument with `long` and optionally `short` names.
    pub fn new_named<T>(
        name: &'static str,
        required: bool,
        help: &'static str,
        short_name: T,
        long_name: &'static str,
        multiple: bool,
    ) -> Argument
    where
        T: Into<Option<&'static str>>,
    {
        Argument {
            argument_type: ArgumentType::Named(NamedArgument {
                short_name: short_name.into(),
                long_name,
                multiple,
            }),
            name,
            help,
            required,
        }
    }

    /// Creates a new positional argument.
    pub fn new_positional(name: &'static str, required: bool, help: &'static str) -> Argument {
        Argument {
            argument_type: ArgumentType::Positional,
            name,
            help,
            required,
        }
    }
}

/// Keys describing various pieces of data one can get from `Context`.
pub mod keys {
    use std::collections::BTreeMap;

    use toml;

    use node::NodeConfig;
    use super::shared::{AbstractConfig, CommonConfigTemplate, NodePublicConfig};
    use super::ContextKey;

    /// Configuration for this node.
    /// Set by `finalize` and `run` commands.
    pub const NODE_CONFIG: ContextKey<NodeConfig> = context_key!("node_config");

    /// Configurations for all nodes.
    /// Set by `generate-testnet` command.
    pub const CONFIGS: ContextKey<Vec<NodeConfig>> = context_key!("configs");

    /// Services configuration.
    /// Set by `generate-testnet` command.
    pub const SERVICES_CONFIG: ContextKey<AbstractConfig> = context_key!("services_config");

    /// Common configuration.
    /// Set by `generate-config` and `finalize` commands.
    pub const COMMON_CONFIG: ContextKey<CommonConfigTemplate> = context_key!("common_config");

    /// Services public configuration.
    /// Set by `generate-config` command.
    pub const SERVICES_PUBLIC_CONFIGS: ContextKey<BTreeMap<String, toml::Value>> =
        context_key!("services_public_configs");

    /// Services secret configuration.
    /// Set by `generate-config` command.
    pub const SERVICES_SECRET_CONFIGS: ContextKey<BTreeMap<String, toml::Value>> =
        context_key!("services_secret_configs");

    /// Public configurations for all nodes.
    /// Set by `finalize` command.
    pub const PUBLIC_CONFIG_LIST: ContextKey<Vec<NodePublicConfig>> =
        context_key!("public_config_list");

    /// Auditor mode.
    /// Set by `finalize` command.
    pub const AUDITOR_MODE: ContextKey<bool> = context_key!("auditor_mode");
}

/// `Context` is a type, used to keep some values from `Command` into
/// `CommandExtension` and vice verse.
/// To access values stored inside Context, use `ContextKey`.
///
/// # Examples
///
/// ```
/// use exonum::node::NodeConfig;
/// use exonum::helpers::fabric::{keys, Context};
///
/// fn get_node_config(context: &Context) -> NodeConfig {
///     context.get(keys::NODE_CONFIG).unwrap()
/// }
/// ```
#[derive(PartialEq, Debug, Clone, Default)]
pub struct Context {
    args: BTreeMap<String, String>,
    multiple_args: BTreeMap<String, Vec<String>>,
    variables: BTreeMap<String, Value>,
}

impl Context {
    fn new_from_args(args: &[Argument], matches: &clap::ArgMatches) -> Context {
        let mut context = Context::default();
        for arg in args {
            // processing multiple value arguments make code ugly =(
            match arg.argument_type {
                ArgumentType::Named(detail) if detail.multiple => {
                    if let Some(values) = matches.values_of(&arg.name) {
                        let values: Vec<String> = values.map(|e| e.to_owned()).collect();
                        if context
                            .multiple_args
                            .insert(arg.name.to_owned(), values)
                            .is_some()
                        {
                            panic!("Duplicated argument: {}", arg.name);
                        }
                        continue;
                    }
                }
                _ => (),
            };

            if let Some(value) = matches.value_of(&arg.name) {
                if context
                    .args
                    .insert(arg.name.to_owned(), value.to_string())
                    .is_some()
                {
                    panic!("Duplicated argument: {}", arg.name);
                }

            } else if arg.required {
                panic!("Required argument is not found: {}", arg.name)
            }
        }
        context
    }

    /// Gets value of the command line argument.
    pub fn arg<T: FromStr>(&self, key: &str) -> Result<T, Box<Error>>
    where
        <T as FromStr>::Err: Error + 'static,
    {
        if let Some(v) = self.args.get(key) {
            Ok(v.parse()?)
        } else {
            Err(Box::new(NotFoundInMap))
        }
    }

    /// Gets multiple values of the command line argument.
    pub fn arg_multiple<T: FromStr>(&self, key: &str) -> Result<Vec<T>, Box<Error>>
    where
        <T as FromStr>::Err: Error + 'static,
    {
        if let Some(values) = self.multiple_args.get(key) {
            values.iter().map(|v| Ok(v.parse()?)).collect()
        } else {
            Err(Box::new(NotFoundInMap))
        }
    }

    /// Gets the variable from the context.
    pub fn get<'de, T: Deserialize<'de>>(&self, key: ContextKey<T>) -> Result<T, Box<Error>> {
        self.get_raw(key.name())
    }

    /// Sets the variable in the context and returns the previous value.
    ///
    /// # Panic
    ///
    /// Panics if value could not be serialized as TOML.
    pub fn set<T: Serialize>(&mut self, key: ContextKey<T>, value: T) -> Option<Value> {
        self.set_raw(key.name(), value)
    }

    fn get_raw<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T, Box<Error>> {
        if let Some(v) = self.variables.get(key) {
            Ok(v.clone().try_into()?)
        } else {
            Err(Box::new(NotFoundInMap))
        }
    }

    fn set_raw<T: Serialize>(&mut self, key: &str, value: T) -> Option<Value> {
        let value: Value = Value::try_from(value).expect("could not convert value into toml");
        self.variables.insert(key.to_owned(), value)
    }
}

/// `CommandExtension` is used for extending the existing commands.
pub trait CommandExtension {
    /// Returns arguments of the command.
    fn args(&self) -> Vec<Argument>;
    /// Executes command.
    fn execute(&self, context: Context) -> Result<Context, Box<Error>>;
}

/// Factory for service creation.
///
/// Services should provide implementation of this trait.
pub trait ServiceFactory: 'static {
    //TODO: we could move
    // `service_name` and `service_id` from `Service` trait into this one
    //fn name() -> &'static str;
    // ECR-76?

    /// Returns `CommandExtension` for the specific `CommandName`.
    #[allow(unused_variables)]
    fn command(&mut self, command: CommandName) -> Option<Box<CommandExtension>> {
        None
    }

    /// Creates a new service instance from the context returned by the `Run` command.
    fn make_service(&mut self, run_context: &Context) -> Box<Service>;
}
<commit_msg>Extend Context to have setters for args<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Command line commands utilities.

use std::str::FromStr;
use std::error::Error;
use std::collections::BTreeMap;

use clap;
use toml::Value;
use serde::{Serialize, Deserialize};

use blockchain::Service;
use self::internal::NotFoundInMap;

pub use self::builder::NodeBuilder;
pub use self::details::{Run, Finalize, GenerateNodeConfig, GenerateCommonConfig, GenerateTestnet};
pub use self::shared::{AbstractConfig, NodePublicConfig, CommonConfigTemplate, NodePrivateConfig};
pub use self::context_key::ContextKey;

mod shared;
mod builder;
mod details;
mod internal;
mod clap_backend;
#[macro_use]
mod context_key;

/// Default port value.
pub const DEFAULT_EXONUM_LISTEN_PORT: u16 = 6333;

/// Name of the `Command`.
pub type CommandName = &'static str;

/// `Argument` with name.
#[derive(Clone, Copy, Debug)]
pub struct NamedArgument {
    /// Short argument name, for example `-a`.
    pub short_name: Option<&'static str>,
    /// Long argument name, for example `--long-arg`.
    pub long_name: &'static str,
    /// If `multiple` is true, then argument has more than one value.
    pub multiple: bool,
}

/// Possible types of the arguments.
#[derive(Clone, Copy, Debug)]
pub enum ArgumentType {
    /// Unnamed positional argument.
    Positional,
    /// Named argument.
    Named(NamedArgument),
}

/// Abstraction to represent arguments in command line.
#[derive(Clone, Copy, Debug)]
pub struct Argument {
    /// Name of the current argument. This name is used in `context.arg(name)`.
    pub name: &'static str,
    /// Explains how this argument is represented.
    pub argument_type: ArgumentType,
    /// Explains if the argument required or not.
    pub required: bool,
    /// Help message.
    pub help: &'static str,
}

impl Argument {
    /// Creates a new argument with `long` and optionally `short` names.
    pub fn new_named<T>(
        name: &'static str,
        required: bool,
        help: &'static str,
        short_name: T,
        long_name: &'static str,
        multiple: bool,
    ) -> Argument
    where
        T: Into<Option<&'static str>>,
    {
        Argument {
            argument_type: ArgumentType::Named(NamedArgument {
                short_name: short_name.into(),
                long_name,
                multiple,
            }),
            name,
            help,
            required,
        }
    }

    /// Creates a new positional argument.
    pub fn new_positional(name: &'static str, required: bool, help: &'static str) -> Argument {
        Argument {
            argument_type: ArgumentType::Positional,
            name,
            help,
            required,
        }
    }
}

/// Keys describing various pieces of data one can get from `Context`.
pub mod keys {
    use std::collections::BTreeMap;

    use toml;

    use node::NodeConfig;
    use super::shared::{AbstractConfig, CommonConfigTemplate, NodePublicConfig};
    use super::ContextKey;

    /// Configuration for this node.
    /// Set by `finalize` and `run` commands.
    pub const NODE_CONFIG: ContextKey<NodeConfig> = context_key!("node_config");

    /// Configurations for all nodes.
    /// Set by `generate-testnet` command.
    pub const CONFIGS: ContextKey<Vec<NodeConfig>> = context_key!("configs");

    /// Services configuration.
    /// Set by `generate-testnet` command.
    pub const SERVICES_CONFIG: ContextKey<AbstractConfig> = context_key!("services_config");

    /// Common configuration.
    /// Set by `generate-config` and `finalize` commands.
    pub const COMMON_CONFIG: ContextKey<CommonConfigTemplate> = context_key!("common_config");

    /// Services public configuration.
    /// Set by `generate-config` command.
    pub const SERVICES_PUBLIC_CONFIGS: ContextKey<BTreeMap<String, toml::Value>> =
        context_key!("services_public_configs");

    /// Services secret configuration.
    /// Set by `generate-config` command.
    pub const SERVICES_SECRET_CONFIGS: ContextKey<BTreeMap<String, toml::Value>> =
        context_key!("services_secret_configs");

    /// Public configurations for all nodes.
    /// Set by `finalize` command.
    pub const PUBLIC_CONFIG_LIST: ContextKey<Vec<NodePublicConfig>> =
        context_key!("public_config_list");

    /// Auditor mode.
    /// Set by `finalize` command.
    pub const AUDITOR_MODE: ContextKey<bool> = context_key!("auditor_mode");
}

/// `Context` is a type, used to keep some values from `Command` into
/// `CommandExtension` and vice verse.
/// To access values stored inside Context, use `ContextKey`.
///
/// # Examples
///
/// ```
/// use exonum::node::NodeConfig;
/// use exonum::helpers::fabric::{keys, Context};
///
/// fn get_node_config(context: &Context) -> NodeConfig {
///     context.get(keys::NODE_CONFIG).unwrap()
/// }
/// ```
#[derive(PartialEq, Debug, Clone, Default)]
pub struct Context {
    args: BTreeMap<String, String>,
    multiple_args: BTreeMap<String, Vec<String>>,
    variables: BTreeMap<String, Value>,
}

impl Context {
    fn new_from_args(args: &[Argument], matches: &clap::ArgMatches) -> Context {
        let mut context = Context::default();
        for arg in args {
            // processing multiple value arguments make code ugly =(
            match arg.argument_type {
                ArgumentType::Named(detail) if detail.multiple => {
                    if let Some(values) = matches.values_of(&arg.name) {
                        let values: Vec<String> = values.map(|e| e.to_owned()).collect();
                        if context
                            .multiple_args
                            .insert(arg.name.to_owned(), values)
                            .is_some()
                        {
                            panic!("Duplicated argument: {}", arg.name);
                        }
                        continue;
                    }
                }
                _ => (),
            };

            if let Some(value) = matches.value_of(&arg.name) {
                if context
                    .args
                    .insert(arg.name.to_owned(), value.to_string())
                    .is_some()
                {
                    panic!("Duplicated argument: {}", arg.name);
                }

            } else if arg.required {
                panic!("Required argument is not found: {}", arg.name)
            }
        }
        context
    }

    /// Gets value of the command line argument.
    pub fn arg<T: FromStr>(&self, key: &str) -> Result<T, Box<Error>>
    where
        <T as FromStr>::Err: Error + 'static,
    {
        if let Some(v) = self.args.get(key) {
            Ok(v.parse()?)
        } else {
            Err(Box::new(NotFoundInMap))
        }
    }

    /// Inserts value to the command line arguments map.
    pub fn set_arg(&mut self, key: &str, value: String) {
        self.args.insert(String::from(key), value);
    }

    /// Gets multiple values of the command line argument.
    pub fn arg_multiple<T: FromStr>(&self, key: &str) -> Result<Vec<T>, Box<Error>>
    where
        <T as FromStr>::Err: Error + 'static,
    {
        if let Some(values) = self.multiple_args.get(key) {
            values.iter().map(|v| Ok(v.parse()?)).collect()
        } else {
            Err(Box::new(NotFoundInMap))
        }
    }

    /// Inserts multiple values to the command line arguments map.
    pub fn set_arg_multiple(&mut self, key: &str, values: Vec<String>) {
        self.multiple_args.insert(String::from(key), values);
    }

    /// Gets the variable from the context.
    pub fn get<'de, T: Deserialize<'de>>(&self, key: ContextKey<T>) -> Result<T, Box<Error>> {
        self.get_raw(key.name())
    }

    /// Sets the variable in the context and returns the previous value.
    ///
    /// # Panic
    ///
    /// Panics if value could not be serialized as TOML.
    pub fn set<T: Serialize>(&mut self, key: ContextKey<T>, value: T) -> Option<Value> {
        self.set_raw(key.name(), value)
    }

    fn get_raw<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T, Box<Error>> {
        if let Some(v) = self.variables.get(key) {
            Ok(v.clone().try_into()?)
        } else {
            Err(Box::new(NotFoundInMap))
        }
    }

    fn set_raw<T: Serialize>(&mut self, key: &str, value: T) -> Option<Value> {
        let value: Value = Value::try_from(value).expect("could not convert value into toml");
        self.variables.insert(key.to_owned(), value)
    }
}

/// `CommandExtension` is used for extending the existing commands.
pub trait CommandExtension {
    /// Returns arguments of the command.
    fn args(&self) -> Vec<Argument>;
    /// Executes command.
    fn execute(&self, context: Context) -> Result<Context, Box<Error>>;
}

/// Factory for service creation.
///
/// Services should provide implementation of this trait.
pub trait ServiceFactory: 'static {
    //TODO: we could move
    // `service_name` and `service_id` from `Service` trait into this one
    //fn name() -> &'static str;
    // ECR-76?

    /// Returns `CommandExtension` for the specific `CommandName`.
    #[allow(unused_variables)]
    fn command(&mut self, command: CommandName) -> Option<Box<CommandExtension>> {
        None
    }

    /// Creates a new service instance from the context returned by the `Run` command.
    fn make_service(&mut self, run_context: &Context) -> Box<Service>;
}
<|endoftext|>


<commit_before>// Finger client in Rust

use std::os;
use std::io::net::ip::{SocketAddr,IpAddr};
use std::io::net::tcp::TcpStream;
use std::time::duration::Duration;
use std::io::net::addrinfo;
use std::io::IoError;
use std::fmt;

static PORT_NUM: u16 = 79;

struct Options {
    short : bool,
    long : bool,
    no_plan : bool,
    no_matching : bool,
}

fn main() {
    let (opts, targets) = parse_arguments(os::args());
    for target in targets.iter() {
        finger(target,opts);
    }
}

fn finger(target : &String, opts : Options) -> Result<(), IoError> {
    let ts = (*target).as_slice();
    match ts.rfind('@') {
        None => finger_local(target,opts),
        Some(x) => finger_remote(ts.slice_to(x),ts.slice_from(x+1),opts),
    }
}

mod passwd;

fn finger_local(target:&String,opts:Options) -> Result<(), IoError> {
    println!("local {}",target);
    Ok(())
}

fn finger_remote(req:&str,hostname:&str,opts:Options) -> Result<(), IoError> {
    println!("remote {} from host {}",req,hostname);
    let mut ips : Vec<IpAddr>;
    match addrinfo::get_host_addresses(hostname) {
        Err(e) => return Err(e),
        Ok(v) => ips = v,
    }
    ips.dedup();
    for ip in ips.iter() {
        let addr = SocketAddr{ ip : *ip, port : PORT_NUM };
        match TcpStream::connect_timeout(addr,Duration::seconds(5)) {
            Ok(mut stream) => {
                stream.write(format!("{}\n\r",req).as_bytes());
            },
            Err(e) => match e.kind {
                std::io::IoErrorKind::TimedOut => continue,
                _ => panic!("Unexpected error on connect!"),
            }
        }
    }
    Ok(())
}

fn parse_arguments(arguments : Vec<String>) -> (Options, Vec<String>) {
    let mut targets: Vec<String> = Vec::new();
    let mut opts = Options {
        short : false,
        long : false,
        no_plan : false,
        no_matching : false,
    };

    let mut argiter = arguments.iter();
    argiter.next(); // skip first argument (app name)
    for arg in argiter {
        if arg.as_slice().starts_with("-") {
            // iterate over flags
            let mut it = arg.as_slice().graphemes(true);
            it.next(); // discard initial flag
            for g in it {
                match g {
                    "l" => opts.long = true,
                    "s" => opts.short = true,
                    "p" => opts.no_plan = true,
                    "m" => opts.no_matching = true,
                    _ => panic!("Unrecognized flag!"),
                }
            }
        } else {
            targets.push(String::from_str(arg.as_slice()))
        }
    }
    (opts, targets)
}
<commit_msg>moving report building to local finger command from fingerd<commit_after>// Finger client in Rust

use std::os;
use std::io::net::ip::{SocketAddr,IpAddr};
use std::io::net::tcp::TcpStream;
use std::time::duration::Duration;
use std::io::net::addrinfo;
use std::io::IoError;
use std::fmt;

static PORT_NUM: u16 = 79;

struct Options {
    short : bool,
    long : bool,
    no_plan : bool,
    no_matching : bool,
}

fn main() {
    let (opts, targets) = parse_arguments(os::args());
    if targets.len() == 0 {
        system_report();
    } else {
        for target in targets.iter() {
            finger(target,opts);
        }
    }
}

fn finger(target : &String, opts : Options) -> Result<(), IoError> {
    let ts = (*target).as_slice();
    match ts.rfind('@') {
        None => finger_local(target,opts),
        Some(x) => finger_remote(ts.slice_to(x),ts.slice_from(x+1),opts),
    }
}

mod passwd;

//Login: phooky         			Name: Adam Mayer
//Directory: /home/phooky             	Shell: /bin/bash
//On since Thu Dec  4 15:46 (EST) on tty2     2 days 23 hours idle
//     (messages off)
//On since Sat Nov 29 14:01 (EST) on :0 from :0 (messages off)
//On since Tue Dec  2 14:28 (EST) on pts/3 from :0
//    5 days 1 hour idle
//On since Thu Dec  4 16:05 (EST) on pts/1 from :0
//    45 seconds idle
//No mail.
//No Plan.
fn user_report_verbose(e : & passwd::Entry) {
    println!("Login: {: <33}Name: {: <33}",
             e.username,e.gecos.name);
    if e.gecos.location.len() > 0 ||
        e.gecos.telephone.len() > 0 {
        println!("Office: {: <30}Telephone: {: <30}",
                 e.gecos.location, e.gecos.telephone);
    }
    println!("Directory: {: <29}Shell: {: <33}",
             e.home,e.shell);
}

fn system_report() {
    println!("System report");
}

fn finger_local(target:&String,opts:Options) -> Result<(), IoError> {
    let uname = target.as_slice();
    match passwd::get_entry(String::from_str(uname)) {
        None => {println!("{}: no such user.",uname);}
        Some(e) => {user_report_verbose(&e);}
    };
    Ok(())
}

fn finger_remote(req:&str,hostname:&str,opts:Options) -> Result<(), IoError> {
    println!("remote {} from host {}",req,hostname);
    let mut ips : Vec<IpAddr>;
    match addrinfo::get_host_addresses(hostname) {
        Err(e) => return Err(e),
        Ok(v) => ips = v,
    }
    ips.dedup();
    for ip in ips.iter() {
        let addr = SocketAddr{ ip : *ip, port : PORT_NUM };
        match TcpStream::connect_timeout(addr,Duration::seconds(5)) {
            Ok(mut stream) => {
                stream.write(format!("{}\n\r",req).as_bytes());
            },
            Err(e) => match e.kind {
                std::io::IoErrorKind::TimedOut => continue,
                _ => panic!("Unexpected error on connect!"),
            }
        }
    }
    Ok(())
}

fn parse_arguments(arguments : Vec<String>) -> (Options, Vec<String>) {
    let mut targets: Vec<String> = Vec::new();
    let mut opts = Options {
        short : false,
        long : false,
        no_plan : false,
        no_matching : false,
    };

    let mut argiter = arguments.iter();
    argiter.next(); // skip first argument (app name)
    for arg in argiter {
        if arg.as_slice().starts_with("-") {
            // iterate over flags
            let mut it = arg.as_slice().graphemes(true);
            it.next(); // discard initial flag
            for g in it {
                match g {
                    "l" => opts.long = true,
                    "s" => opts.short = true,
                    "p" => opts.no_plan = true,
                    "m" => opts.no_matching = true,
                    _ => panic!("Unrecognized flag!"),
                }
            }
        } else {
            targets.push(String::from_str(arg.as_slice()))
        }
    }
    (opts, targets)
}
<|endoftext|>


<commit_before>//! Postfix completions, like `Ok(10).ifl<|>` => `if let Ok() = Ok(10) { <|> }`.

mod format_like;

use ide_db::ty_filter::TryEnum;
use syntax::{
    ast::{self, AstNode, AstToken},
    TextRange, TextSize,
};
use text_edit::TextEdit;

use self::format_like::add_format_like_completions;
use crate::{
    config::SnippetCap,
    context::CompletionContext,
    item::{Builder, CompletionKind},
    CompletionItem, CompletionItemKind, Completions,
};

pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
    if !ctx.config.enable_postfix_completions {
        return;
    }

    let dot_receiver = match &ctx.dot_receiver {
        Some(it) => it,
        None => return,
    };

    let receiver_text =
        get_receiver_text(dot_receiver, ctx.dot_receiver_is_ambiguous_float_literal);

    let receiver_ty = match ctx.sema.type_of_expr(&dot_receiver) {
        Some(it) => it,
        None => return,
    };

    let cap = match ctx.config.snippet_cap {
        Some(it) => it,
        None => return,
    };
    let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty);
    if let Some(try_enum) = &try_enum {
        match try_enum {
            TryEnum::Result => {
                postfix_snippet(
                    ctx,
                    cap,
                    &dot_receiver,
                    "ifl",
                    "if let Ok {}",
                    &format!("if let Ok($1) = {} {{\n    $0\n}}", receiver_text),
                )
                .add_to(acc);

                postfix_snippet(
                    ctx,
                    cap,
                    &dot_receiver,
                    "while",
                    "while let Ok {}",
                    &format!("while let Ok($1) = {} {{\n    $0\n}}", receiver_text),
                )
                .add_to(acc);
            }
            TryEnum::Option => {
                postfix_snippet(
                    ctx,
                    cap,
                    &dot_receiver,
                    "ifl",
                    "if let Some {}",
                    &format!("if let Some($1) = {} {{\n    $0\n}}", receiver_text),
                )
                .add_to(acc);

                postfix_snippet(
                    ctx,
                    cap,
                    &dot_receiver,
                    "while",
                    "while let Some {}",
                    &format!("while let Some($1) = {} {{\n    $0\n}}", receiver_text),
                )
                .add_to(acc);
            }
        }
    } else if receiver_ty.is_bool() || receiver_ty.is_unknown() {
        postfix_snippet(
            ctx,
            cap,
            &dot_receiver,
            "if",
            "if expr {}",
            &format!("if {} {{\n    $0\n}}", receiver_text),
        )
        .add_to(acc);
        postfix_snippet(
            ctx,
            cap,
            &dot_receiver,
            "while",
            "while expr {}",
            &format!("while {} {{\n    $0\n}}", receiver_text),
        )
        .add_to(acc);
        postfix_snippet(ctx, cap, &dot_receiver, "not", "!expr", &format!("!{}", receiver_text))
            .add_to(acc);
    }

    postfix_snippet(ctx, cap, &dot_receiver, "ref", "&expr", &format!("&{}", receiver_text))
        .add_to(acc);
    postfix_snippet(
        ctx,
        cap,
        &dot_receiver,
        "refm",
        "&mut expr",
        &format!("&mut {}", receiver_text),
    )
    .add_to(acc);

    // The rest of the postfix completions create an expression that moves an argument,
    // so it's better to consider references now to avoid breaking the compilation
    let dot_receiver = include_references(dot_receiver);
    let receiver_text =
        get_receiver_text(&dot_receiver, ctx.dot_receiver_is_ambiguous_float_literal);

    match try_enum {
        Some(try_enum) => match try_enum {
            TryEnum::Result => {
                postfix_snippet(
                    ctx,
                    cap,
                    &dot_receiver,
                    "match",
                    "match expr {}",
                    &format!("match {} {{\n    Ok(${{1:_}}) => {{$2}},\n    Err(${{3:_}}) => {{$0}},\n}}", receiver_text),
                )
                .add_to(acc);
            }
            TryEnum::Option => {
                postfix_snippet(
                    ctx,
                    cap,
                    &dot_receiver,
                    "match",
                    "match expr {}",
                    &format!(
                        "match {} {{\n    Some(${{1:_}}) => {{$2}},\n    None => {{$0}},\n}}",
                        receiver_text
                    ),
                )
                .add_to(acc);
            }
        },
        None => {
            postfix_snippet(
                ctx,
                cap,
                &dot_receiver,
                "match",
                "match expr {}",
                &format!("match {} {{\n    ${{1:_}} => {{$0}},\n}}", receiver_text),
            )
            .add_to(acc);
        }
    }

    postfix_snippet(
        ctx,
        cap,
        &dot_receiver,
        "box",
        "Box::new(expr)",
        &format!("Box::new({})", receiver_text),
    )
    .add_to(acc);

    postfix_snippet(ctx, cap, &dot_receiver, "ok", "Ok(expr)", &format!("Ok({})", receiver_text))
        .add_to(acc);

    postfix_snippet(
        ctx,
        cap,
        &dot_receiver,
        "some",
        "Some(expr)",
        &format!("Some({})", receiver_text),
    )
    .add_to(acc);

    postfix_snippet(
        ctx,
        cap,
        &dot_receiver,
        "dbg",
        "dbg!(expr)",
        &format!("dbg!({})", receiver_text),
    )
    .add_to(acc);

    postfix_snippet(
        ctx,
        cap,
        &dot_receiver,
        "dbgr",
        "dbg!(&expr)",
        &format!("dbg!(&{})", receiver_text),
    )
    .add_to(acc);

    postfix_snippet(
        ctx,
        cap,
        &dot_receiver,
        "call",
        "function(expr)",
        &format!("${{1}}({})", receiver_text),
    )
    .add_to(acc);

    if let ast::Expr::Literal(literal) = dot_receiver.clone() {
        if let Some(literal_text) = ast::String::cast(literal.token()) {
            add_format_like_completions(acc, ctx, &dot_receiver, cap, &literal_text);
        }
    }
}

fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal: bool) -> String {
    if receiver_is_ambiguous_float_literal {
        let text = receiver.syntax().text();
        let without_dot = ..text.len() - TextSize::of('.');
        text.slice(without_dot).to_string()
    } else {
        receiver.to_string()
    }
}

fn include_references(initial_element: &ast::Expr) -> ast::Expr {
    let mut resulting_element = initial_element.clone();
    while let Some(parent_ref_element) =
        resulting_element.syntax().parent().and_then(ast::RefExpr::cast)
    {
        resulting_element = ast::Expr::from(parent_ref_element);
    }
    resulting_element
}

fn postfix_snippet(
    ctx: &CompletionContext,
    cap: SnippetCap,
    receiver: &ast::Expr,
    label: &str,
    detail: &str,
    snippet: &str,
) -> Builder {
    let edit = {
        let receiver_syntax = receiver.syntax();
        let receiver_range = ctx.sema.original_range(receiver_syntax).range;
        let delete_range = TextRange::new(receiver_range.start(), ctx.source_range().end());
        TextEdit::replace(delete_range, snippet.to_string())
    };
    CompletionItem::new(CompletionKind::Postfix, ctx.source_range(), label)
        .detail(detail)
        .kind(CompletionItemKind::Snippet)
        .snippet_edit(cap, edit)
}

#[cfg(test)]
mod tests {
    use expect_test::{expect, Expect};

    use crate::{
        test_utils::{check_edit, completion_list},
        CompletionKind,
    };

    fn check(ra_fixture: &str, expect: Expect) {
        let actual = completion_list(ra_fixture, CompletionKind::Postfix);
        expect.assert_eq(&actual)
    }

    #[test]
    fn postfix_completion_works_for_trivial_path_expression() {
        check(
            r#"
fn main() {
    let bar = true;
    bar.<|>
}
"#,
            expect![[r#"
                sn box   Box::new(expr)
                sn call  function(expr)
                sn dbg   dbg!(expr)
                sn dbgr  dbg!(&expr)
                sn if    if expr {}
                sn match match expr {}
                sn not   !expr
                sn ok    Ok(expr)
                sn ref   &expr
                sn refm  &mut expr
                sn some  Some(expr)
                sn while while expr {}
            "#]],
        );
    }

    #[test]
    fn postfix_type_filtering() {
        check(
            r#"
fn main() {
    let bar: u8 = 12;
    bar.<|>
}
"#,
            expect![[r#"
                sn box   Box::new(expr)
                sn call  function(expr)
                sn dbg   dbg!(expr)
                sn dbgr  dbg!(&expr)
                sn match match expr {}
                sn ok    Ok(expr)
                sn ref   &expr
                sn refm  &mut expr
                sn some  Some(expr)
            "#]],
        )
    }

    #[test]
    fn option_iflet() {
        check_edit(
            "ifl",
            r#"
enum Option<T> { Some(T), None }

fn main() {
    let bar = Option::Some(true);
    bar.<|>
}
"#,
            r#"
enum Option<T> { Some(T), None }

fn main() {
    let bar = Option::Some(true);
    if let Some($1) = bar {
    $0
}
}
"#,
        );
    }

    #[test]
    fn result_match() {
        check_edit(
            "match",
            r#"
enum Result<T, E> { Ok(T), Err(E) }

fn main() {
    let bar = Result::Ok(true);
    bar.<|>
}
"#,
            r#"
enum Result<T, E> { Ok(T), Err(E) }

fn main() {
    let bar = Result::Ok(true);
    match bar {
    Ok(${1:_}) => {$2},
    Err(${3:_}) => {$0},
}
}
"#,
        );
    }

    #[test]
    fn postfix_completion_works_for_ambiguous_float_literal() {
        check_edit("refm", r#"fn main() { 42.<|> }"#, r#"fn main() { &mut 42 }"#)
    }

    #[test]
    fn works_in_simple_macro() {
        check_edit(
            "dbg",
            r#"
macro_rules! m { ($e:expr) => { $e } }
fn main() {
    let bar: u8 = 12;
    m!(bar.d<|>)
}
"#,
            r#"
macro_rules! m { ($e:expr) => { $e } }
fn main() {
    let bar: u8 = 12;
    m!(dbg!(bar))
}
"#,
        );
    }

    #[test]
    fn postfix_completion_for_references() {
        check_edit("dbg", r#"fn main() { &&42.<|> }"#, r#"fn main() { dbg!(&&42) }"#);
        check_edit("refm", r#"fn main() { &&42.<|> }"#, r#"fn main() { &&&mut 42 }"#);
    }

    #[test]
    fn postfix_completion_for_format_like_strings() {
        check_edit(
            "fmt",
            r#"fn main() { "{some_var:?}".<|> }"#,
            r#"fn main() { format!("{:?}", some_var) }"#,
        );
        check_edit(
            "panic",
            r#"fn main() { "Panic with {a}".<|> }"#,
            r#"fn main() { panic!("Panic with {}", a) }"#,
        );
        check_edit(
            "println",
            r#"fn main() { "{ 2+2 } { SomeStruct { val: 1, other: 32 } :?}".<|> }"#,
            r#"fn main() { println!("{} {:?}", 2+2, SomeStruct { val: 1, other: 32 }) }"#,
        );
        check_edit(
            "loge",
            r#"fn main() { "{2+2}".<|> }"#,
            r#"fn main() { log::error!("{}", 2+2) }"#,
        );
        check_edit(
            "logt",
            r#"fn main() { "{2+2}".<|> }"#,
            r#"fn main() { log::trace!("{}", 2+2) }"#,
        );
        check_edit(
            "logd",
            r#"fn main() { "{2+2}".<|> }"#,
            r#"fn main() { log::debug!("{}", 2+2) }"#,
        );
        check_edit(
            "logi",
            r#"fn main() { "{2+2}".<|> }"#,
            r#"fn main() { log::info!("{}", 2+2) }"#,
        );
        check_edit(
            "logw",
            r#"fn main() { "{2+2}".<|> }"#,
            r#"fn main() { log::warn!("{}", 2+2) }"#,
        );
        check_edit(
            "loge",
            r#"fn main() { "{2+2}".<|> }"#,
            r#"fn main() { log::error!("{}", 2+2) }"#,
        );
    }
}
<commit_msg>add let and letm postfix to turn expressions into variables<commit_after>//! Postfix completions, like `Ok(10).ifl<|>` => `if let Ok() = Ok(10) { <|> }`.

mod format_like;

use ide_db::ty_filter::TryEnum;
use syntax::{
    ast::{self, AstNode, AstToken},
    TextRange, TextSize,
};
use text_edit::TextEdit;

use self::format_like::add_format_like_completions;
use crate::{
    config::SnippetCap,
    context::CompletionContext,
    item::{Builder, CompletionKind},
    CompletionItem, CompletionItemKind, Completions,
};

pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
    if !ctx.config.enable_postfix_completions {
        return;
    }

    let dot_receiver = match &ctx.dot_receiver {
        Some(it) => it,
        None => return,
    };

    let receiver_text =
        get_receiver_text(dot_receiver, ctx.dot_receiver_is_ambiguous_float_literal);

    let receiver_ty = match ctx.sema.type_of_expr(&dot_receiver) {
        Some(it) => it,
        None => return,
    };

    let cap = match ctx.config.snippet_cap {
        Some(it) => it,
        None => return,
    };
    let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty);
    if let Some(try_enum) = &try_enum {
        match try_enum {
            TryEnum::Result => {
                postfix_snippet(
                    ctx,
                    cap,
                    &dot_receiver,
                    "ifl",
                    "if let Ok {}",
                    &format!("if let Ok($1) = {} {{\n    $0\n}}", receiver_text),
                )
                .add_to(acc);

                postfix_snippet(
                    ctx,
                    cap,
                    &dot_receiver,
                    "while",
                    "while let Ok {}",
                    &format!("while let Ok($1) = {} {{\n    $0\n}}", receiver_text),
                )
                .add_to(acc);
            }
            TryEnum::Option => {
                postfix_snippet(
                    ctx,
                    cap,
                    &dot_receiver,
                    "ifl",
                    "if let Some {}",
                    &format!("if let Some($1) = {} {{\n    $0\n}}", receiver_text),
                )
                .add_to(acc);

                postfix_snippet(
                    ctx,
                    cap,
                    &dot_receiver,
                    "while",
                    "while let Some {}",
                    &format!("while let Some($1) = {} {{\n    $0\n}}", receiver_text),
                )
                .add_to(acc);
            }
        }
    } else if receiver_ty.is_bool() || receiver_ty.is_unknown() {
        postfix_snippet(
            ctx,
            cap,
            &dot_receiver,
            "if",
            "if expr {}",
            &format!("if {} {{\n    $0\n}}", receiver_text),
        )
        .add_to(acc);
        postfix_snippet(
            ctx,
            cap,
            &dot_receiver,
            "while",
            "while expr {}",
            &format!("while {} {{\n    $0\n}}", receiver_text),
        )
        .add_to(acc);
        postfix_snippet(ctx, cap, &dot_receiver, "not", "!expr", &format!("!{}", receiver_text))
            .add_to(acc);
    }

    postfix_snippet(ctx, cap, &dot_receiver, "ref", "&expr", &format!("&{}", receiver_text))
        .add_to(acc);
    postfix_snippet(
        ctx,
        cap,
        &dot_receiver,
        "refm",
        "&mut expr",
        &format!("&mut {}", receiver_text),
    )
    .add_to(acc);

    // The rest of the postfix completions create an expression that moves an argument,
    // so it's better to consider references now to avoid breaking the compilation
    let dot_receiver = include_references(dot_receiver);
    let receiver_text =
        get_receiver_text(&dot_receiver, ctx.dot_receiver_is_ambiguous_float_literal);

    match try_enum {
        Some(try_enum) => match try_enum {
            TryEnum::Result => {
                postfix_snippet(
                    ctx,
                    cap,
                    &dot_receiver,
                    "match",
                    "match expr {}",
                    &format!("match {} {{\n    Ok(${{1:_}}) => {{$2}},\n    Err(${{3:_}}) => {{$0}},\n}}", receiver_text),
                )
                .add_to(acc);
            }
            TryEnum::Option => {
                postfix_snippet(
                    ctx,
                    cap,
                    &dot_receiver,
                    "match",
                    "match expr {}",
                    &format!(
                        "match {} {{\n    Some(${{1:_}}) => {{$2}},\n    None => {{$0}},\n}}",
                        receiver_text
                    ),
                )
                .add_to(acc);
            }
        },
        None => {
            postfix_snippet(
                ctx,
                cap,
                &dot_receiver,
                "match",
                "match expr {}",
                &format!("match {} {{\n    ${{1:_}} => {{$0}},\n}}", receiver_text),
            )
            .add_to(acc);
        }
    }

    postfix_snippet(
        ctx,
        cap,
        &dot_receiver,
        "box",
        "Box::new(expr)",
        &format!("Box::new({})", receiver_text),
    )
    .add_to(acc);

    postfix_snippet(ctx, cap, &dot_receiver, "ok", "Ok(expr)", &format!("Ok({})", receiver_text))
        .add_to(acc);

    postfix_snippet(
        ctx,
        cap,
        &dot_receiver,
        "some",
        "Some(expr)",
        &format!("Some({})", receiver_text),
    )
    .add_to(acc);

    postfix_snippet(
        ctx,
        cap,
        &dot_receiver,
        "dbg",
        "dbg!(expr)",
        &format!("dbg!({})", receiver_text),
    )
    .add_to(acc);

    postfix_snippet(
        ctx,
        cap,
        &dot_receiver,
        "dbgr",
        "dbg!(&expr)",
        &format!("dbg!(&{})", receiver_text),
    )
    .add_to(acc);

    postfix_snippet(
        ctx,
        cap,
        &dot_receiver,
        "call",
        "function(expr)",
        &format!("${{1}}({})", receiver_text),
    )
    .add_to(acc);

    postfix_snippet(ctx, cap, &dot_receiver, "let", "let", &format!("let $0 = {};", receiver_text))
        .add_to(acc);
    postfix_snippet(
        ctx,
        cap,
        &dot_receiver,
        "letm",
        "let mut",
        &format!("let mut $0 = {};", receiver_text),
    )
    .add_to(acc);

    if let ast::Expr::Literal(literal) = dot_receiver.clone() {
        if let Some(literal_text) = ast::String::cast(literal.token()) {
            add_format_like_completions(acc, ctx, &dot_receiver, cap, &literal_text);
        }
    }
}

fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal: bool) -> String {
    if receiver_is_ambiguous_float_literal {
        let text = receiver.syntax().text();
        let without_dot = ..text.len() - TextSize::of('.');
        text.slice(without_dot).to_string()
    } else {
        receiver.to_string()
    }
}

fn include_references(initial_element: &ast::Expr) -> ast::Expr {
    let mut resulting_element = initial_element.clone();
    while let Some(parent_ref_element) =
        resulting_element.syntax().parent().and_then(ast::RefExpr::cast)
    {
        resulting_element = ast::Expr::from(parent_ref_element);
    }
    resulting_element
}

fn postfix_snippet(
    ctx: &CompletionContext,
    cap: SnippetCap,
    receiver: &ast::Expr,
    label: &str,
    detail: &str,
    snippet: &str,
) -> Builder {
    let edit = {
        let receiver_syntax = receiver.syntax();
        let receiver_range = ctx.sema.original_range(receiver_syntax).range;
        let delete_range = TextRange::new(receiver_range.start(), ctx.source_range().end());
        TextEdit::replace(delete_range, snippet.to_string())
    };
    CompletionItem::new(CompletionKind::Postfix, ctx.source_range(), label)
        .detail(detail)
        .kind(CompletionItemKind::Snippet)
        .snippet_edit(cap, edit)
}

#[cfg(test)]
mod tests {
    use expect_test::{expect, Expect};

    use crate::{
        test_utils::{check_edit, completion_list},
        CompletionKind,
    };

    fn check(ra_fixture: &str, expect: Expect) {
        let actual = completion_list(ra_fixture, CompletionKind::Postfix);
        expect.assert_eq(&actual)
    }

    #[test]
    fn postfix_completion_works_for_trivial_path_expression() {
        check(
            r#"
fn main() {
    let bar = true;
    bar.<|>
}
"#,
            expect![[r#"
                sn box   Box::new(expr)
                sn call  function(expr)
                sn dbg   dbg!(expr)
                sn dbgr  dbg!(&expr)
                sn if    if expr {}
                sn let   let
                sn letm  let mut
                sn match match expr {}
                sn not   !expr
                sn ok    Ok(expr)
                sn ref   &expr
                sn refm  &mut expr
                sn some  Some(expr)
                sn while while expr {}
            "#]],
        );
    }

    #[test]
    fn postfix_type_filtering() {
        check(
            r#"
fn main() {
    let bar: u8 = 12;
    bar.<|>
}
"#,
            expect![[r#"
                sn box   Box::new(expr)
                sn call  function(expr)
                sn dbg   dbg!(expr)
                sn dbgr  dbg!(&expr)
                sn let   let
                sn letm  let mut
                sn match match expr {}
                sn ok    Ok(expr)
                sn ref   &expr
                sn refm  &mut expr
                sn some  Some(expr)
            "#]],
        )
    }

    #[test]
    fn option_iflet() {
        check_edit(
            "ifl",
            r#"
enum Option<T> { Some(T), None }

fn main() {
    let bar = Option::Some(true);
    bar.<|>
}
"#,
            r#"
enum Option<T> { Some(T), None }

fn main() {
    let bar = Option::Some(true);
    if let Some($1) = bar {
    $0
}
}
"#,
        );
    }

    #[test]
    fn result_match() {
        check_edit(
            "match",
            r#"
enum Result<T, E> { Ok(T), Err(E) }

fn main() {
    let bar = Result::Ok(true);
    bar.<|>
}
"#,
            r#"
enum Result<T, E> { Ok(T), Err(E) }

fn main() {
    let bar = Result::Ok(true);
    match bar {
    Ok(${1:_}) => {$2},
    Err(${3:_}) => {$0},
}
}
"#,
        );
    }

    #[test]
    fn postfix_completion_works_for_ambiguous_float_literal() {
        check_edit("refm", r#"fn main() { 42.<|> }"#, r#"fn main() { &mut 42 }"#)
    }

    #[test]
    fn works_in_simple_macro() {
        check_edit(
            "dbg",
            r#"
macro_rules! m { ($e:expr) => { $e } }
fn main() {
    let bar: u8 = 12;
    m!(bar.d<|>)
}
"#,
            r#"
macro_rules! m { ($e:expr) => { $e } }
fn main() {
    let bar: u8 = 12;
    m!(dbg!(bar))
}
"#,
        );
    }

    #[test]
    fn postfix_completion_for_references() {
        check_edit("dbg", r#"fn main() { &&42.<|> }"#, r#"fn main() { dbg!(&&42) }"#);
        check_edit("refm", r#"fn main() { &&42.<|> }"#, r#"fn main() { &&&mut 42 }"#);
    }

    #[test]
    fn postfix_completion_for_format_like_strings() {
        check_edit(
            "fmt",
            r#"fn main() { "{some_var:?}".<|> }"#,
            r#"fn main() { format!("{:?}", some_var) }"#,
        );
        check_edit(
            "panic",
            r#"fn main() { "Panic with {a}".<|> }"#,
            r#"fn main() { panic!("Panic with {}", a) }"#,
        );
        check_edit(
            "println",
            r#"fn main() { "{ 2+2 } { SomeStruct { val: 1, other: 32 } :?}".<|> }"#,
            r#"fn main() { println!("{} {:?}", 2+2, SomeStruct { val: 1, other: 32 }) }"#,
        );
        check_edit(
            "loge",
            r#"fn main() { "{2+2}".<|> }"#,
            r#"fn main() { log::error!("{}", 2+2) }"#,
        );
        check_edit(
            "logt",
            r#"fn main() { "{2+2}".<|> }"#,
            r#"fn main() { log::trace!("{}", 2+2) }"#,
        );
        check_edit(
            "logd",
            r#"fn main() { "{2+2}".<|> }"#,
            r#"fn main() { log::debug!("{}", 2+2) }"#,
        );
        check_edit(
            "logi",
            r#"fn main() { "{2+2}".<|> }"#,
            r#"fn main() { log::info!("{}", 2+2) }"#,
        );
        check_edit(
            "logw",
            r#"fn main() { "{2+2}".<|> }"#,
            r#"fn main() { log::warn!("{}", 2+2) }"#,
        );
        check_edit(
            "loge",
            r#"fn main() { "{2+2}".<|> }"#,
            r#"fn main() { log::error!("{}", 2+2) }"#,
        );
    }
}
<|endoftext|>


<commit_before>use prodbg_api::view::CViewCallbacks;
use libc::{c_void, c_uchar};
use std::rc::Rc;
use plugin::Plugin;
use plugins::PluginHandler;
use dynamic_reload::Lib;
use session::SessionHandle;
use std::ptr;
use prodbg_api::ui::Ui;

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct ViewHandle(pub u64);

pub struct ViewInstance {
    pub plugin_data: *mut c_void,
    pub ui: Ui,
    pub name: String,
    pub handle: ViewHandle,
    pub session_handle: SessionHandle,
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
    pub plugin_type: Rc<Plugin>,
}

#[derive(Clone)]
struct ReloadState {
    name: String,
    ui: Ui,
    handle: ViewHandle,
    session_handle: SessionHandle,
}

pub struct ViewPlugins {
    pub instances: Vec<ViewInstance>,
    plugin_types: Vec<Rc<Plugin>>,
    reload_state: Vec<ReloadState>,
    handle_counter: ViewHandle,
}

impl PluginHandler for ViewPlugins {
    fn is_correct_plugin_type(&self, plugin: &Plugin) -> bool {
        plugin.type_name.contains("View")
    }

    fn add_plugin(&mut self, plugin: &Rc<Plugin>) {
        println!("added plugin type {}", plugin.type_name);
        self.plugin_types.push(plugin.clone())
    }

    fn unload_plugin(&mut self, lib: &Rc<Lib>) {
        self.reload_state.clear();
        for i in (0..self.instances.len()).rev() {
            if &self.instances[i].plugin_type.lib == lib {
                let state = ReloadState {
                    ui: self.instances[i].ui,
                    name: self.instances[i].plugin_type.name.clone(),
                    handle: self.instances[i].handle,
                    session_handle: self.instances[i].session_handle,
                };

                self.reload_state.push(state);
                self.instances.swap_remove(i);
            }
        }

        for i in (0..self.plugin_types.len()).rev() {
            if &self.plugin_types[i].lib == lib {
                self.plugin_types.swap_remove(i);
            }
        }
    }

    fn reload_plugin(&mut self) {
        let t = self.reload_state.clone();
        for reload_plugin in &t {
            Self::create_instance(self, reload_plugin.ui, &reload_plugin.name, reload_plugin.session_handle);
        }
    }

    fn reload_failed(&mut self) {}
}

impl ViewPlugins {
    pub fn new() -> ViewPlugins {
        ViewPlugins {
            instances: Vec::new(),
            plugin_types: Vec::new(),
            reload_state: Vec::new(),
            handle_counter: ViewHandle(0),
        }
    }

    pub extern "C" fn service_fun(_name: *const c_uchar) -> *mut c_void {
        ptr::null_mut()
    }

    pub fn get_view(&mut self, view_handle: ViewHandle) -> Option<&mut ViewInstance> {
        for i in 0..self.instances.len() {
            if self.instances[i].handle == view_handle {
                return Some(&mut self.instances[i]);
            }
        }

        None
    }

    pub fn create_instance_from_index(&mut self, ui: Ui, index: usize, session_handle: SessionHandle) -> Option<ViewHandle> {
        let plugin_data = unsafe {
            let callbacks = self.plugin_types[index].plugin_funcs as *mut CViewCallbacks;
            (*callbacks).create_instance.unwrap()(ptr::null(), Self::service_fun)
        };

        let handle = self.handle_counter;

        let instance = ViewInstance {
            plugin_data: plugin_data,
            name: format!("Plugin {}", self.handle_counter.0),
            ui: ui,
            handle: handle,
            session_handle: session_handle,
            x: 0.0,
            y: 0.0,
            width: 0.0,
            height: 0.0,
            plugin_type: self.plugin_types[index].clone(),
        };

        self.handle_counter.0 += 1;
        self.instances.push(instance);

        Some(handle)
    }

    pub fn create_instance(&mut self, ui: Ui, plugin_type: &String, session_handle: SessionHandle) -> Option<ViewHandle> {
        for i in 0..self.plugin_types.len() {
            if self.plugin_types[i].name != *plugin_type {
                continue;
            }

            return Self::create_instance_from_index(self, ui, i, session_handle);
        }

        None
    }

    // TODO: Would be nice to use something stack-base instead or return an iterator to interate
    // over the data instead
    pub fn get_plugin_names(&self) -> Vec<String> {
        let mut names = Vec::new();

        for i in &self.plugin_types {
            names.push(i.name.clone());
        }

        names
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_search_paths_none() {
    }
}

<commit_msg>Allow plugins to use UI funcs during create<commit_after>use prodbg_api::view::CViewCallbacks;
use libc::{c_void, c_uchar};
use std::rc::Rc;
use plugin::Plugin;
use plugins::PluginHandler;
use dynamic_reload::Lib;
use session::SessionHandle;
use std::ptr;
use prodbg_api::ui::Ui;

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct ViewHandle(pub u64);

pub struct ViewInstance {
    pub plugin_data: *mut c_void,
    pub ui: Ui,
    pub name: String,
    pub handle: ViewHandle,
    pub session_handle: SessionHandle,
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
    pub plugin_type: Rc<Plugin>,
}

#[derive(Clone)]
struct ReloadState {
    name: String,
    ui: Ui,
    handle: ViewHandle,
    session_handle: SessionHandle,
}

pub struct ViewPlugins {
    pub instances: Vec<ViewInstance>,
    plugin_types: Vec<Rc<Plugin>>,
    reload_state: Vec<ReloadState>,
    handle_counter: ViewHandle,
}

impl PluginHandler for ViewPlugins {
    fn is_correct_plugin_type(&self, plugin: &Plugin) -> bool {
        plugin.type_name.contains("View")
    }

    fn add_plugin(&mut self, plugin: &Rc<Plugin>) {
        println!("added plugin type {}", plugin.type_name);
        self.plugin_types.push(plugin.clone())
    }

    fn unload_plugin(&mut self, lib: &Rc<Lib>) {
        self.reload_state.clear();
        for i in (0..self.instances.len()).rev() {
            if &self.instances[i].plugin_type.lib == lib {
                let state = ReloadState {
                    ui: self.instances[i].ui,
                    name: self.instances[i].plugin_type.name.clone(),
                    handle: self.instances[i].handle,
                    session_handle: self.instances[i].session_handle,
                };

                self.reload_state.push(state);
                self.instances.swap_remove(i);
            }
        }

        for i in (0..self.plugin_types.len()).rev() {
            if &self.plugin_types[i].lib == lib {
                self.plugin_types.swap_remove(i);
            }
        }
    }

    fn reload_plugin(&mut self) {
        let t = self.reload_state.clone();
        for reload_plugin in &t {
            Self::create_instance(self, reload_plugin.ui, &reload_plugin.name, reload_plugin.session_handle);
        }
    }

    fn reload_failed(&mut self) {}
}

impl ViewPlugins {
    pub fn new() -> ViewPlugins {
        ViewPlugins {
            instances: Vec::new(),
            plugin_types: Vec::new(),
            reload_state: Vec::new(),
            handle_counter: ViewHandle(0),
        }
    }

    pub extern "C" fn service_fun(_name: *const c_uchar) -> *mut c_void {
        ptr::null_mut()
    }

    pub fn get_view(&mut self, view_handle: ViewHandle) -> Option<&mut ViewInstance> {
        for i in 0..self.instances.len() {
            if self.instances[i].handle == view_handle {
                return Some(&mut self.instances[i]);
            }
        }

        None
    }

    pub fn create_instance_from_index(&mut self, ui: Ui, index: usize, session_handle: SessionHandle) -> Option<ViewHandle> {
        let plugin_data = unsafe {
            let callbacks = self.plugin_types[index].plugin_funcs as *mut CViewCallbacks;
            (*callbacks).create_instance.unwrap()(ui.api as *mut c_void, Self::service_fun)
        };

        let handle = self.handle_counter;

        let instance = ViewInstance {
            plugin_data: plugin_data,
            name: format!("Plugin {}", self.handle_counter.0),
            ui: ui,
            handle: handle,
            session_handle: session_handle,
            x: 0.0,
            y: 0.0,
            width: 0.0,
            height: 0.0,
            plugin_type: self.plugin_types[index].clone(),
        };

        self.handle_counter.0 += 1;
        self.instances.push(instance);

        Some(handle)
    }

    pub fn create_instance(&mut self, ui: Ui, plugin_type: &String, session_handle: SessionHandle) -> Option<ViewHandle> {
        for i in 0..self.plugin_types.len() {
            if self.plugin_types[i].name != *plugin_type {
                continue;
            }

            return Self::create_instance_from_index(self, ui, i, session_handle);
        }

        None
    }

    // TODO: Would be nice to use something stack-base instead or return an iterator to interate
    // over the data instead
    pub fn get_plugin_names(&self) -> Vec<String> {
        let mut names = Vec::new();

        for i in &self.plugin_types {
            names.push(i.name.clone());
        }

        names
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_search_paths_none() {
    }
}

<|endoftext|>


<commit_before>//! This module supports deserializing from primitives with the `ValueDeserializer` trait.

use std::collections::{
    BTreeMap,
    BTreeSet,
    HashMap,
    HashSet,
    btree_map,
    btree_set,
    hash_map,
    hash_set,
};
use std::hash::Hash;
use std::vec;

use de;
use bytes;

///////////////////////////////////////////////////////////////////////////////

/// This represents all the possible errors that can occur using the `ValueDeserializer`.
#[derive(Clone, Debug, PartialEq)]
pub enum Error {
    /// The value had some syntatic error.
    SyntaxError(String),

    /// The value had an incorrect type.
    TypeError(de::Type),

    /// The value had an invalid length.
    LengthError(usize),

    /// EOF while deserializing a value.
    EndOfStreamError,

    /// Unknown field in struct.
    UnknownFieldError(String),

    /// Struct is missing a field.
    MissingFieldError(&'static str),
}

impl de::Error for Error {
    fn syntax(msg: &str) -> Self { Error::SyntaxError(String::from(msg)) }
    fn type_mismatch(type_: de::Type) -> Self { Error::TypeError(type_) }
    fn length_mismatch(len: usize) -> Self { Error::LengthError(len) }
    fn end_of_stream() -> Self { Error::EndOfStreamError }
    fn unknown_field(field: &str) -> Self { Error::UnknownFieldError(String::from(field)) }
    fn missing_field(field: &'static str) -> Self { Error::MissingFieldError(field) }
}

///////////////////////////////////////////////////////////////////////////////

/// This trait converts primitive types into a deserializer.
pub trait ValueDeserializer {
    /// The actual deserializer type.
    type Deserializer: de::Deserializer<Error=Error>;

    /// Convert this value into a deserializer.
    fn into_deserializer(self) -> Self::Deserializer;
}

///////////////////////////////////////////////////////////////////////////////

impl ValueDeserializer for () {
    type Deserializer = UnitDeserializer;

    fn into_deserializer(self) -> UnitDeserializer {
        UnitDeserializer
    }
}

/// A helper deserializer that deserializes a `()`.
pub struct UnitDeserializer;

impl de::Deserializer for UnitDeserializer {
    type Error = Error;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
        where V: de::Visitor,
    {
        visitor.visit_unit()
    }

    fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
        where V: de::Visitor,
    {
        visitor.visit_none()
    }
}

///////////////////////////////////////////////////////////////////////////////

macro_rules! primitive_deserializer {
    ($ty:ty, $name:ident, $method:ident) => {
        /// A helper deserializer that deserializes a number.
        pub struct $name(Option<$ty>);

        impl ValueDeserializer for $ty {
            type Deserializer = $name;

            fn into_deserializer(self) -> $name {
                $name(Some(self))
            }
        }

        impl de::Deserializer for $name {
            type Error = Error;

            fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
                where V: de::Visitor,
            {
                match self.0.take() {
                    Some(v) => visitor.$method(v),
                    None => Err(de::Error::end_of_stream()),
                }
            }
        }
    }
}

primitive_deserializer!(bool, BoolDeserializer, visit_bool);
primitive_deserializer!(i8, I8Deserializer, visit_i8);
primitive_deserializer!(i16, I16Deserializer, visit_i16);
primitive_deserializer!(i32, I32Deserializer, visit_i32);
primitive_deserializer!(i64, I64Deserializer, visit_i64);
primitive_deserializer!(isize, IsizeDeserializer, visit_isize);
primitive_deserializer!(u8, U8Deserializer, visit_u8);
primitive_deserializer!(u16, U16Deserializer, visit_u16);
primitive_deserializer!(u32, U32Deserializer, visit_u32);
primitive_deserializer!(u64, U64Deserializer, visit_u64);
primitive_deserializer!(usize, UsizeDeserializer, visit_usize);
primitive_deserializer!(f32, F32Deserializer, visit_f32);
primitive_deserializer!(f64, F64Deserializer, visit_f64);
primitive_deserializer!(char, CharDeserializer, visit_char);

///////////////////////////////////////////////////////////////////////////////

/// A helper deserializer that deserializes a `&str`.
pub struct StrDeserializer<'a>(Option<&'a str>);

impl<'a> ValueDeserializer for &'a str {
    type Deserializer = StrDeserializer<'a>;

    fn into_deserializer(self) -> StrDeserializer<'a> {
        StrDeserializer(Some(self))
    }
}

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

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
        where V: de::Visitor,
    {
        match self.0.take() {
            Some(v) => visitor.visit_str(v),
            None => Err(de::Error::end_of_stream()),
        }
    }

    fn visit_enum<V>(&mut self,
                     _name: &str,
                     _variants: &'static [&'static str],
                     mut visitor: V) -> Result<V::Value, Error>
        where V: de::EnumVisitor,
    {
        visitor.visit(self)
    }
}

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

    fn visit_variant<T>(&mut self) -> Result<T, Error>
        where T: de::Deserialize,
    {
        de::Deserialize::deserialize(self)
    }

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

///////////////////////////////////////////////////////////////////////////////

/// A helper deserializer that deserializes a `String`.
pub struct StringDeserializer(Option<String>);

impl ValueDeserializer for String {
    type Deserializer = StringDeserializer;

    fn into_deserializer(self) -> StringDeserializer {
        StringDeserializer(Some(self))
    }
}

impl de::Deserializer for StringDeserializer {
    type Error = Error;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
        where V: de::Visitor,
    {
        match self.0.take() {
            Some(string) => visitor.visit_string(string),
            None => Err(de::Error::end_of_stream()),
        }
    }

    fn visit_enum<V>(&mut self,
                     _name: &str,
                     _variants: &'static [&'static str],
                     mut visitor: V) -> Result<V::Value, Error>
        where V: de::EnumVisitor,
    {
        visitor.visit(self)
    }
}

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

    fn visit_variant<T>(&mut self) -> Result<T, Error>
        where T: de::Deserialize,
    {
        de::Deserialize::deserialize(self)
    }

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

///////////////////////////////////////////////////////////////////////////////

/// A helper deserializer that deserializes a sequence.
pub struct SeqDeserializer<I> {
    iter: I,
    len: usize,
}

impl<I> SeqDeserializer<I> {
    /// Construct a new `SeqDeserializer<I>`.
    pub fn new(iter: I, len: usize) -> Self {
        SeqDeserializer {
            iter: iter,
            len: len,
        }
    }
}

impl<I, T> de::Deserializer for SeqDeserializer<I>
    where I: Iterator<Item=T>,
          T: ValueDeserializer,
{
    type Error = Error;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
        where V: de::Visitor,
    {
        visitor.visit_seq(self)
    }
}

impl<I, T> de::SeqVisitor for SeqDeserializer<I>
    where I: Iterator<Item=T>,
          T: ValueDeserializer,
{
    type Error = Error;

    fn visit<V>(&mut self) -> Result<Option<V>, Error>
        where V: de::Deserialize
    {
        match self.iter.next() {
            Some(value) => {
                self.len -= 1;
                let mut de = value.into_deserializer();
                Ok(Some(try!(de::Deserialize::deserialize(&mut de))))
            }
            None => Ok(None),
        }
    }

    fn end(&mut self) -> Result<(), Error> {
        if self.len == 0 {
            Ok(())
        } else {
            Err(de::Error::length_mismatch(self.len))
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len, Some(self.len))
    }
}

///////////////////////////////////////////////////////////////////////////////

impl<T> ValueDeserializer for Vec<T>
    where T: ValueDeserializer,
{
    type Deserializer = SeqDeserializer<vec::IntoIter<T>>;

    fn into_deserializer(self) -> SeqDeserializer<vec::IntoIter<T>> {
        let len = self.len();
        SeqDeserializer::new(self.into_iter(), len)
    }
}

impl<T> ValueDeserializer for BTreeSet<T>
    where T: ValueDeserializer + Eq + Ord,
{
    type Deserializer = SeqDeserializer<btree_set::IntoIter<T>>;

    fn into_deserializer(self) -> SeqDeserializer<btree_set::IntoIter<T>> {
        let len = self.len();
        SeqDeserializer::new(self.into_iter(), len)
    }
}

impl<T> ValueDeserializer for HashSet<T>
    where T: ValueDeserializer + Eq + Hash,
{
    type Deserializer = SeqDeserializer<hash_set::IntoIter<T>>;

    fn into_deserializer(self) -> SeqDeserializer<hash_set::IntoIter<T>> {
        let len = self.len();
        SeqDeserializer::new(self.into_iter(), len)
    }
}

///////////////////////////////////////////////////////////////////////////////

/// A helper deserializer that deserializes a map.
pub struct MapDeserializer<I, K, V>
    where I: Iterator<Item=(K, V)>,
          K: ValueDeserializer,
          V: ValueDeserializer,
{
    iter: I,
    value: Option<V>,
    len: usize,
}

impl<I, K, V> MapDeserializer<I, K, V>
    where I: Iterator<Item=(K, V)>,
          K: ValueDeserializer,
          V: ValueDeserializer,
{
    /// Construct a new `MapDeserializer<I, K, V>`.
    pub fn new(iter: I, len: usize) -> Self {
        MapDeserializer {
            iter: iter,
            value: None,
            len: len,
        }
    }
}

impl<I, K, V> de::Deserializer for MapDeserializer<I, K, V>
    where I: Iterator<Item=(K, V)>,
          K: ValueDeserializer,
          V: ValueDeserializer,
{
    type Error = Error;

    fn visit<V_>(&mut self, mut visitor: V_) -> Result<V_::Value, Error>
        where V_: de::Visitor,
    {
        visitor.visit_map(self)
    }
}

impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
    where I: Iterator<Item=(K, V)>,
          K: ValueDeserializer,
          V: ValueDeserializer,
{
    type Error = Error;

    fn visit_key<T>(&mut self) -> Result<Option<T>, Error>
        where T: de::Deserialize,
    {
        match self.iter.next() {
            Some((key, value)) => {
                self.len -= 1;
                self.value = Some(value);
                let mut de = key.into_deserializer();
                Ok(Some(try!(de::Deserialize::deserialize(&mut de))))
            }
            None => Ok(None),
        }
    }

    fn visit_value<T>(&mut self) -> Result<T, Error>
        where T: de::Deserialize,
    {
        match self.value.take() {
            Some(value) => {
                let mut de = value.into_deserializer();
                de::Deserialize::deserialize(&mut de)
            }
            None => Err(de::Error::syntax("expected a map value"))
        }
    }

    fn end(&mut self) -> Result<(), Error> {
        if self.len == 0 {
            Ok(())
        } else {
            Err(de::Error::length_mismatch(self.len))
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len, Some(self.len))
    }
}

///////////////////////////////////////////////////////////////////////////////

impl<K, V> ValueDeserializer for BTreeMap<K, V>
    where K: ValueDeserializer + Eq + Ord,
          V: ValueDeserializer,
{
    type Deserializer = MapDeserializer<btree_map::IntoIter<K, V>, K, V>;

    fn into_deserializer(self) -> MapDeserializer<btree_map::IntoIter<K, V>, K, V> {
        let len = self.len();
        MapDeserializer::new(self.into_iter(), len)
    }
}

impl<K, V> ValueDeserializer for HashMap<K, V>
    where K: ValueDeserializer + Eq + Hash,
          V: ValueDeserializer,
{
    type Deserializer = MapDeserializer<hash_map::IntoIter<K, V>, K, V>;

    fn into_deserializer(self) -> MapDeserializer<hash_map::IntoIter<K, V>, K, V> {
        let len = self.len();
        MapDeserializer::new(self.into_iter(), len)
    }
}

///////////////////////////////////////////////////////////////////////////////

impl<'a> ValueDeserializer for bytes::Bytes<'a>
{
    type Deserializer = BytesDeserializer<'a>;

    fn into_deserializer(self) -> BytesDeserializer<'a> {
        BytesDeserializer(Some(self.into()))
    }
}

/// A helper deserializer that deserializes a `&[u8]`.
pub struct BytesDeserializer<'a> (Option<&'a [u8]>);

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

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
        where V: de::Visitor,
    {
        match self.0.take() {
            Some(bytes) => visitor.visit_bytes(bytes),
            None => Err(de::Error::end_of_stream()),
        }
    }
}

///////////////////////////////////////////////////////////////////////////////

impl ValueDeserializer for bytes::ByteBuf
{
    type Deserializer = ByteBufDeserializer;

    fn into_deserializer(self) -> Self::Deserializer {
        ByteBufDeserializer(Some(self.into()))
    }
}

/// A helper deserializer that deserializes a `Vec<u8>`.
pub struct ByteBufDeserializer(Option<Vec<u8>>);

impl de::Deserializer for ByteBufDeserializer {
    type Error = Error;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
        where V: de::Visitor,
    {
        match self.0.take() {
            Some(bytes) => visitor.visit_byte_buf(bytes),
            None => Err(de::Error::end_of_stream()),
        }
    }
}
<commit_msg>feat: `ValueDeserializer`s are generic over the error type<commit_after>//! This module supports deserializing from primitives with the `ValueDeserializer` trait.

use std::collections::{
    BTreeMap,
    BTreeSet,
    HashMap,
    HashSet,
    btree_map,
    btree_set,
    hash_map,
    hash_set,
};
use std::hash::Hash;
use std::vec;
use std::marker::PhantomData;

use de;
use bytes;

///////////////////////////////////////////////////////////////////////////////

/// This represents all the possible errors that can occur using the `ValueDeserializer`.
#[derive(Clone, Debug, PartialEq)]
pub enum Error {
    /// The value had some syntatic error.
    SyntaxError(String),

    /// The value had an incorrect type.
    TypeError(de::Type),

    /// The value had an invalid length.
    LengthError(usize),

    /// EOF while deserializing a value.
    EndOfStreamError,

    /// Unknown field in struct.
    UnknownFieldError(String),

    /// Struct is missing a field.
    MissingFieldError(&'static str),
}

impl de::Error for Error {
    fn syntax(msg: &str) -> Self { Error::SyntaxError(String::from(msg)) }
    fn type_mismatch(type_: de::Type) -> Self { Error::TypeError(type_) }
    fn length_mismatch(len: usize) -> Self { Error::LengthError(len) }
    fn end_of_stream() -> Self { Error::EndOfStreamError }
    fn unknown_field(field: &str) -> Self { Error::UnknownFieldError(String::from(field)) }
    fn missing_field(field: &'static str) -> Self { Error::MissingFieldError(field) }
}

///////////////////////////////////////////////////////////////////////////////

/// This trait converts primitive types into a deserializer.
pub trait ValueDeserializer<E: de::Error = Error> {
    /// The actual deserializer type.
    type Deserializer: de::Deserializer<Error=E>;

    /// Convert this value into a deserializer.
    fn into_deserializer(self) -> Self::Deserializer;
}

///////////////////////////////////////////////////////////////////////////////

impl<E> ValueDeserializer<E> for ()
    where E: de::Error,
{
    type Deserializer = UnitDeserializer<E>;

    fn into_deserializer(self) -> UnitDeserializer<E> {
        UnitDeserializer(PhantomData)
    }
}

/// A helper deserializer that deserializes a `()`.
pub struct UnitDeserializer<E>(PhantomData<E>);

impl<E> de::Deserializer for UnitDeserializer<E>
    where E: de::Error
{
    type Error = E;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
        where V: de::Visitor,
    {
        visitor.visit_unit()
    }

    fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
        where V: de::Visitor,
    {
        visitor.visit_none()
    }
}

///////////////////////////////////////////////////////////////////////////////

macro_rules! primitive_deserializer {
    ($ty:ty, $name:ident, $method:ident) => {
        /// A helper deserializer that deserializes a number.
        pub struct $name<E>(Option<$ty>, PhantomData<E>);

        impl<E> ValueDeserializer<E> for $ty
            where E: de::Error,
        {
            type Deserializer = $name<E>;

            fn into_deserializer(self) -> $name<E> {
                $name(Some(self), PhantomData)
            }
        }

        impl<E> de::Deserializer for $name<E>
            where E: de::Error,
        {
            type Error = E;

            fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
                where V: de::Visitor,
            {
                match self.0.take() {
                    Some(v) => visitor.$method(v),
                    None => Err(de::Error::end_of_stream()),
                }
            }
        }
    }
}

primitive_deserializer!(bool, BoolDeserializer, visit_bool);
primitive_deserializer!(i8, I8Deserializer, visit_i8);
primitive_deserializer!(i16, I16Deserializer, visit_i16);
primitive_deserializer!(i32, I32Deserializer, visit_i32);
primitive_deserializer!(i64, I64Deserializer, visit_i64);
primitive_deserializer!(isize, IsizeDeserializer, visit_isize);
primitive_deserializer!(u8, U8Deserializer, visit_u8);
primitive_deserializer!(u16, U16Deserializer, visit_u16);
primitive_deserializer!(u32, U32Deserializer, visit_u32);
primitive_deserializer!(u64, U64Deserializer, visit_u64);
primitive_deserializer!(usize, UsizeDeserializer, visit_usize);
primitive_deserializer!(f32, F32Deserializer, visit_f32);
primitive_deserializer!(f64, F64Deserializer, visit_f64);
primitive_deserializer!(char, CharDeserializer, visit_char);

///////////////////////////////////////////////////////////////////////////////

/// A helper deserializer that deserializes a `&str`.
pub struct StrDeserializer<'a, E>(Option<&'a str>, PhantomData<E>);

impl<'a, E> ValueDeserializer<E> for &'a str
    where E: de::Error,
{
    type Deserializer = StrDeserializer<'a, E>;

    fn into_deserializer(self) -> StrDeserializer<'a, E> {
        StrDeserializer(Some(self), PhantomData)
    }
}

impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
    where E: de::Error,
{
    type Error = E;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
        where V: de::Visitor,
    {
        match self.0.take() {
            Some(v) => visitor.visit_str(v),
            None => Err(de::Error::end_of_stream()),
        }
    }

    fn visit_enum<V>(&mut self,
                     _name: &str,
                     _variants: &'static [&'static str],
                     mut visitor: V) -> Result<V::Value, Self::Error>
        where V: de::EnumVisitor,
    {
        visitor.visit(self)
    }
}

impl<'a, E> de::VariantVisitor for StrDeserializer<'a, E>
    where E: de::Error,
{
    type Error = E;

    fn visit_variant<T>(&mut self) -> Result<T, Self::Error>
        where T: de::Deserialize,
    {
        de::Deserialize::deserialize(self)
    }

    fn visit_unit(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }
}

///////////////////////////////////////////////////////////////////////////////

/// A helper deserializer that deserializes a `String`.
pub struct StringDeserializer<E>(Option<String>, PhantomData<E>);

impl<E> ValueDeserializer<E> for String
    where E: de::Error,
{
    type Deserializer = StringDeserializer<E>;

    fn into_deserializer(self) -> StringDeserializer<E> {
        StringDeserializer(Some(self), PhantomData)
    }
}

impl<E> de::Deserializer for StringDeserializer<E>
    where E: de::Error,
{
    type Error = E;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
        where V: de::Visitor,
    {
        match self.0.take() {
            Some(string) => visitor.visit_string(string),
            None => Err(de::Error::end_of_stream()),
        }
    }

    fn visit_enum<V>(&mut self,
                     _name: &str,
                     _variants: &'static [&'static str],
                     mut visitor: V) -> Result<V::Value, Self::Error>
        where V: de::EnumVisitor,
    {
        visitor.visit(self)
    }
}

impl<'a, E> de::VariantVisitor for StringDeserializer<E>
    where E: de::Error,
{
    type Error = E;

    fn visit_variant<T>(&mut self) -> Result<T, Self::Error>
        where T: de::Deserialize,
    {
        de::Deserialize::deserialize(self)
    }

    fn visit_unit(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }
}

///////////////////////////////////////////////////////////////////////////////

/// A helper deserializer that deserializes a sequence.
pub struct SeqDeserializer<I, E> {
    iter: I,
    len: usize,
    marker: PhantomData<E>,
}

impl<I, E> SeqDeserializer<I, E>
    where E: de::Error,
{
    /// Construct a new `SeqDeserializer<I>`.
    pub fn new(iter: I, len: usize) -> Self {
        SeqDeserializer {
            iter: iter,
            len: len,
            marker: PhantomData,
        }
    }
}

impl<I, T, E> de::Deserializer for SeqDeserializer<I, E>
    where I: Iterator<Item=T>,
          T: ValueDeserializer<E>,
          E: de::Error,
{
    type Error = E;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
        where V: de::Visitor,
    {
        visitor.visit_seq(self)
    }
}

impl<I, T, E> de::SeqVisitor for SeqDeserializer<I, E>
    where I: Iterator<Item=T>,
          T: ValueDeserializer<E>,
          E: de::Error,
{
    type Error = E;

    fn visit<V>(&mut self) -> Result<Option<V>, Self::Error>
        where V: de::Deserialize
    {
        match self.iter.next() {
            Some(value) => {
                self.len -= 1;
                let mut de = value.into_deserializer();
                Ok(Some(try!(de::Deserialize::deserialize(&mut de))))
            }
            None => Ok(None),
        }
    }

    fn end(&mut self) -> Result<(), Self::Error> {
        if self.len == 0 {
            Ok(())
        } else {
            Err(de::Error::length_mismatch(self.len))
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len, Some(self.len))
    }
}

///////////////////////////////////////////////////////////////////////////////

impl<T, E> ValueDeserializer<E> for Vec<T>
    where T: ValueDeserializer<E>,
          E: de::Error,
{
    type Deserializer = SeqDeserializer<vec::IntoIter<T>, E>;

    fn into_deserializer(self) -> Self::Deserializer {
        let len = self.len();
        SeqDeserializer::new(self.into_iter(), len)
    }
}

impl<T, E> ValueDeserializer<E> for BTreeSet<T>
    where T: ValueDeserializer<E> + Eq + Ord,
          E: de::Error,
{
    type Deserializer = SeqDeserializer<btree_set::IntoIter<T>, E>;

    fn into_deserializer(self) -> Self::Deserializer {
        let len = self.len();
        SeqDeserializer::new(self.into_iter(), len)
    }
}

impl<T, E> ValueDeserializer<E> for HashSet<T>
    where T: ValueDeserializer<E> + Eq + Hash,
          E: de::Error,
{
    type Deserializer = SeqDeserializer<hash_set::IntoIter<T>, E>;

    fn into_deserializer(self) -> Self::Deserializer {
        let len = self.len();
        SeqDeserializer::new(self.into_iter(), len)
    }
}

///////////////////////////////////////////////////////////////////////////////

/// A helper deserializer that deserializes a map.
pub struct MapDeserializer<I, K, V, E>
    where I: Iterator<Item=(K, V)>,
          K: ValueDeserializer<E>,
          V: ValueDeserializer<E>,
          E: de::Error,
{
    iter: I,
    value: Option<V>,
    len: usize,
    marker: PhantomData<E>,
}

impl<I, K, V, E> MapDeserializer<I, K, V, E>
    where I: Iterator<Item=(K, V)>,
          K: ValueDeserializer<E>,
          V: ValueDeserializer<E>,
          E: de::Error,
{
    /// Construct a new `MapDeserializer<I, K, V>`.
    pub fn new(iter: I, len: usize) -> Self {
        MapDeserializer {
            iter: iter,
            value: None,
            len: len,
            marker: PhantomData,
        }
    }
}

impl<I, K, V, E> de::Deserializer for MapDeserializer<I, K, V, E>
    where I: Iterator<Item=(K, V)>,
          K: ValueDeserializer<E>,
          V: ValueDeserializer<E>,
          E: de::Error,
{
    type Error = E;

    fn visit<V_>(&mut self, mut visitor: V_) -> Result<V_::Value, Self::Error>
        where V_: de::Visitor,
    {
        visitor.visit_map(self)
    }
}

impl<I, K, V, E> de::MapVisitor for MapDeserializer<I, K, V, E>
    where I: Iterator<Item=(K, V)>,
          K: ValueDeserializer<E>,
          V: ValueDeserializer<E>,
          E: de::Error,
{
    type Error = E;

    fn visit_key<T>(&mut self) -> Result<Option<T>, Self::Error>
        where T: de::Deserialize,
    {
        match self.iter.next() {
            Some((key, value)) => {
                self.len -= 1;
                self.value = Some(value);
                let mut de = key.into_deserializer();
                Ok(Some(try!(de::Deserialize::deserialize(&mut de))))
            }
            None => Ok(None),
        }
    }

    fn visit_value<T>(&mut self) -> Result<T, Self::Error>
        where T: de::Deserialize,
    {
        match self.value.take() {
            Some(value) => {
                let mut de = value.into_deserializer();
                de::Deserialize::deserialize(&mut de)
            }
            None => Err(de::Error::syntax("expected a map value"))
        }
    }

    fn end(&mut self) -> Result<(), Self::Error> {
        if self.len == 0 {
            Ok(())
        } else {
            Err(de::Error::length_mismatch(self.len))
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len, Some(self.len))
    }
}

///////////////////////////////////////////////////////////////////////////////

impl<K, V, E> ValueDeserializer<E> for BTreeMap<K, V>
    where K: ValueDeserializer<E> + Eq + Ord,
          V: ValueDeserializer<E>,
          E: de::Error,
{
    type Deserializer = MapDeserializer<btree_map::IntoIter<K, V>, K, V, E>;

    fn into_deserializer(self) -> Self::Deserializer {
        let len = self.len();
        MapDeserializer::new(self.into_iter(), len)
    }
}

impl<K, V, E> ValueDeserializer<E> for HashMap<K, V>
    where K: ValueDeserializer<E> + Eq + Hash,
          V: ValueDeserializer<E>,
          E: de::Error,
{
    type Deserializer = MapDeserializer<hash_map::IntoIter<K, V>, K, V, E>;

    fn into_deserializer(self) -> Self::Deserializer {
        let len = self.len();
        MapDeserializer::new(self.into_iter(), len)
    }
}

///////////////////////////////////////////////////////////////////////////////

impl<'a, E> ValueDeserializer<E> for bytes::Bytes<'a>
    where E: de::Error,
{
    type Deserializer = BytesDeserializer<'a, E>;

    fn into_deserializer(self) -> BytesDeserializer<'a, E> {
        BytesDeserializer(Some(self.into()), PhantomData)
    }
}

/// A helper deserializer that deserializes a `&[u8]`.
pub struct BytesDeserializer<'a, E> (Option<&'a [u8]>, PhantomData<E>);

impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
    where E: de::Error
{
    type Error = E;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
        where V: de::Visitor,
    {
        match self.0.take() {
            Some(bytes) => visitor.visit_bytes(bytes),
            None => Err(de::Error::end_of_stream()),
        }
    }
}

///////////////////////////////////////////////////////////////////////////////

impl<E> ValueDeserializer<E> for bytes::ByteBuf
    where E: de::Error,
{
    type Deserializer = ByteBufDeserializer<E>;

    fn into_deserializer(self) -> Self::Deserializer {
        ByteBufDeserializer(Some(self.into()), PhantomData)
    }
}

/// A helper deserializer that deserializes a `Vec<u8>`.
pub struct ByteBufDeserializer<E>(Option<Vec<u8>>, PhantomData<E>);

impl<E> de::Deserializer for ByteBufDeserializer<E>
    where E: de::Error,
{
    type Error = E;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
        where V: de::Visitor,
    {
        match self.0.take() {
            Some(bytes) => visitor.visit_byte_buf(bytes),
            None => Err(de::Error::end_of_stream()),
        }
    }
}
<|endoftext|>