<commit_before>// Copyright (c) 2018 Chef Software Inc. and/or applicable contributors
//
// 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.

use clap::ArgMatches;
use std::str::FromStr;

use error::Error;

#[derive(Debug, Clone)]
pub struct Bind {
    pub name: String,
    pub service: String,
    pub group: String,
}

impl FromStr for Bind {
    type Err = Error;

    fn from_str(bind_spec: &str) -> Result<Self, Error> {
        let split: Vec<&str> = bind_spec.split(":").collect();
        if split.len() != 3 || split[0] == "" || split[1] == "" || split[2] == "" {
            return Err(Error::InvalidBindSpec(bind_spec.to_owned()));
        }

        Ok(Bind {
            name: split[0].to_owned(),
            service: split[1].to_owned(),
            group: split[2].to_owned(),
        })
    }
}

pub fn parse_bind_args(matches: &ArgMatches) -> Result<Vec<Bind>, Error> {
    let mut binds = Vec::new();

    if let Some(bind_args) = matches.values_of("BIND") {
        for arg in bind_args {
            let b = arg.parse::<Bind>()?;

            binds.push(b);
        }
    };

    Ok(binds)
}
<commit_msg>pkg-export-k8s: Add docs to Bind<commit_after>// Copyright (c) 2018 Chef Software Inc. and/or applicable contributors
//
// 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.

use clap::ArgMatches;
use std::str::FromStr;

use error::Error;

/// A Habitat service bind inside a Kubernetes cluster.
#[derive(Debug, Clone)]
pub struct Bind {
    pub name: String,
    pub service: String,
    pub group: String,
}

impl FromStr for Bind {
    type Err = Error;

    /// Create a `Bind` from a string.
    ///
    /// # Errors
    ///
    /// * `bind_spec` is not in the form `"name:service:group"`
    ///
    /// # Examples
    ///
    /// ```
    /// use habitat_pkg_export_kubernetes::{Bind, Error};
    ///
    /// let b = "n:s:g".parse::<Bind>().unwrap();
    ///
    /// assert_eq!(b.name, "n");
    /// assert_eq!(b.service, "s");
    /// assert_eq!(b.group, "g");
    ///
    /// for s in ["ns:g", "nsg", ":nsg:"].iter() {
    ///     if let Err(e) = s.parse::<Bind>() {
    ///         match e {
    ///             Error::InvalidBindSpec(_) => (),
    ///             _ => panic!("Unexpected error type"),
    ///        }
    ///     }
    /// }
    /// ```
    fn from_str(bind_spec: &str) -> Result<Self, Error> {
        let split: Vec<&str> = bind_spec.split(":").collect();
        if split.len() != 3 || split[0] == "" || split[1] == "" || split[2] == "" {
            return Err(Error::InvalidBindSpec(bind_spec.to_owned()));
        }

        Ok(Bind {
            name: split[0].to_owned(),
            service: split[1].to_owned(),
            group: split[2].to_owned(),
        })
    }
}

/// Helper function to parse CLI arguments into [`Bind`] instances.
///
/// [`Bind`]: ../bind/struct.Bind.html
pub fn parse_bind_args(matches: &ArgMatches) -> Result<Vec<Bind>, Error> {
    let mut binds = Vec::new();

    if let Some(bind_args) = matches.values_of("BIND") {
        for arg in bind_args {
            let b = arg.parse::<Bind>()?;

            binds.push(b);
        }
    };

    Ok(binds)
}
<|endoftext|>


<commit_before>//! # OpenTelemetry Span interface
//!
//! A `Span` represents a single operation within a trace. `Span`s can be nested to form a trace
//! tree. Each trace contains a root span, which typically describes the end-to-end latency and,
//! optionally, one or more sub-spans for its sub-operations.
//!
//! The `Span`'s start and end timestamps reflect the elapsed real time of the operation. A `Span`'s
//! start time SHOULD be set to the current time on span creation. After the `Span` is created, it
//! SHOULD be possible to change its name, set its `Attributes`, and add `Links` and `Events`.
//! These MUST NOT be changed after the `Span`'s end time has been set.
//!
//! `Spans` are not meant to be used to propagate information within a process. To prevent misuse,
//! implementations SHOULD NOT provide access to a `Span`'s attributes besides its `SpanContext`.
//!
//! Vendors may implement the `Span` interface to effect vendor-specific logic. However, alternative
//! implementations MUST NOT allow callers to create Spans directly. All `Span`s MUST be created
//! via a Tracer.
use crate::api;
use std::time::SystemTime;

/// Interface for a single operation within a trace.
pub trait Span: std::fmt::Debug {
    /// An API to record events in the context of a given `Span`.
    ///
    /// Events have a time associated with the moment when they are
    /// added to the `Span`.
    ///
    /// Events SHOULD preserve the order in which they're set. This will typically match
    /// the ordering of the events' timestamps.
    ///
    /// Note that the OpenTelemetry project documents certain ["standard event names and
    /// keys"](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md)
    /// which have prescribed semantic meanings.
    fn add_event(&mut self, message: String) {
        self.add_event_with_timestamp(message, SystemTime::now())
    }

    /// An API to record events at a specific time in the context of a given `Span`.
    ///
    /// Events SHOULD preserve the order in which they're set. This will typically match
    /// the ordering of the events' timestamps.
    ///
    /// Note that the OpenTelemetry project documents certain ["standard event names and
    /// keys"](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md)
    /// which have prescribed semantic meanings.
    fn add_event_with_timestamp(&mut self, message: String, timestamp: SystemTime);

    /// An API to add links to a given `Span`.
    ///
    /// Linked Spans can be from the same or a different trace.
    ///
    /// Links SHOULD preserve the order in which they're set.
    fn add_link(&mut self, link: api::SpanContext);

    /// Returns the `SpanContext` for the given `Span`. The returned value may be used even after
    /// the `Span is finished. The returned value MUST be the same for the entire `Span` lifetime.
    fn get_context(&self) -> api::SpanContext;

    /// Returns true if this `Span` is recording information like events with the `add_event`
    /// operation, attributes using `set_attributes`, status with `set_status`, etc.
    ///
    /// This flag SHOULD be used to avoid expensive computations of a `Span` attributes or events in
    /// case when a `Span` is definitely not recorded. Note that any child span's recording is
    /// determined independently from the value of this flag (typically based on the sampled flag of
    /// a `TraceFlag` on `SpanContext`).
    ///
    /// This flag may be true despite the entire trace being sampled out. This allows to record and
    /// process information about the individual Span without sending it to the backend. An example
    /// of this scenario may be recording and processing of all incoming requests for the processing
    /// and building of SLA/SLO latency charts while sending only a subset - sampled spans - to the
    /// backend. See also the sampling section of SDK design.
    ///
    /// Users of the API should only access the `is_recording` property when instrumenting code and
    /// never access `SampledFlag` unless used in context propagators.
    fn is_recording(&self) -> bool;

    /// An API to set a single `Attribute` where the attribute properties are passed
    /// as arguments. To avoid extra allocations some implementations may offer a separate API for
    /// each of the possible value types.
    ///
    /// An `Attribute` is defined as a `KeyValue` pair.
    ///
    /// Attributes SHOULD preserve the order in which they're set. Setting an attribute
    /// with the same key as an existing attribute SHOULD overwrite the existing
    /// attribute's value.
    ///
    /// Note that the OpenTelemetry project documents certain ["standard
    /// attributes"](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md)
    /// that have prescribed semantic meanings.
    fn set_attribute(&mut self, attribute: api::KeyValue);

    /// Sets the status of the `Span`. If used, this will override the default `Span`
    /// status, which is `OK`.
    ///
    /// Only the value of the last call will be recorded, and implementations are free
    /// to ignore previous calls.
    fn set_status(&mut self, status: String);

    /// Updates the `Span`'s name. After this update, any sampling behavior based on the
    /// name will depend on the implementation.
    ///
    /// It is highly discouraged to update the name of a `Span` after its creation.
    /// `Span` name is often used to group, filter and identify the logical groups of
    /// spans. Often, filtering logic will be implemented before the `Span` creation
    /// for performance reasons, and the name update may interfere with this logic.
    ///
    /// The method name is called `update_name` to differentiate this method from the
    /// regular property. It emphasizes that this operation signifies a
    /// major change for a `Span` and may lead to re-calculation of sampling or
    /// filtering decisions made previously depending on the implementation.
    fn update_name(&mut self, new_name: String);

    /// Finishes the `Span`.
    ///
    /// Implementations MUST ignore all subsequent calls to `end` (there might be
    /// exceptions when the tracer is streaming events and has no mutable state
    /// associated with the Span).
    ///
    /// Calls to `end` a Span MUST not have any effects on child `Span`s as they may
    /// still be running and can be ended later.
    ///
    ///This API MUST be non-blocking.
    fn end(&mut self);

    /// Used by global tracer to downcast to specific span type.
    fn as_any(&self) -> &dyn std::any::Any;
}
<commit_msg>Ensure spans are always send and sync<commit_after>//! # OpenTelemetry Span interface
//!
//! A `Span` represents a single operation within a trace. `Span`s can be nested to form a trace
//! tree. Each trace contains a root span, which typically describes the end-to-end latency and,
//! optionally, one or more sub-spans for its sub-operations.
//!
//! The `Span`'s start and end timestamps reflect the elapsed real time of the operation. A `Span`'s
//! start time SHOULD be set to the current time on span creation. After the `Span` is created, it
//! SHOULD be possible to change its name, set its `Attributes`, and add `Links` and `Events`.
//! These MUST NOT be changed after the `Span`'s end time has been set.
//!
//! `Spans` are not meant to be used to propagate information within a process. To prevent misuse,
//! implementations SHOULD NOT provide access to a `Span`'s attributes besides its `SpanContext`.
//!
//! Vendors may implement the `Span` interface to effect vendor-specific logic. However, alternative
//! implementations MUST NOT allow callers to create Spans directly. All `Span`s MUST be created
//! via a Tracer.
use crate::api;
use std::time::SystemTime;

/// Interface for a single operation within a trace.
pub trait Span: Send + Sync + std::fmt::Debug {
    /// An API to record events in the context of a given `Span`.
    ///
    /// Events have a time associated with the moment when they are
    /// added to the `Span`.
    ///
    /// Events SHOULD preserve the order in which they're set. This will typically match
    /// the ordering of the events' timestamps.
    ///
    /// Note that the OpenTelemetry project documents certain ["standard event names and
    /// keys"](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md)
    /// which have prescribed semantic meanings.
    fn add_event(&mut self, message: String) {
        self.add_event_with_timestamp(message, SystemTime::now())
    }

    /// An API to record events at a specific time in the context of a given `Span`.
    ///
    /// Events SHOULD preserve the order in which they're set. This will typically match
    /// the ordering of the events' timestamps.
    ///
    /// Note that the OpenTelemetry project documents certain ["standard event names and
    /// keys"](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md)
    /// which have prescribed semantic meanings.
    fn add_event_with_timestamp(&mut self, message: String, timestamp: SystemTime);

    /// An API to add links to a given `Span`.
    ///
    /// Linked Spans can be from the same or a different trace.
    ///
    /// Links SHOULD preserve the order in which they're set.
    fn add_link(&mut self, link: api::SpanContext);

    /// Returns the `SpanContext` for the given `Span`. The returned value may be used even after
    /// the `Span is finished. The returned value MUST be the same for the entire `Span` lifetime.
    fn get_context(&self) -> api::SpanContext;

    /// Returns true if this `Span` is recording information like events with the `add_event`
    /// operation, attributes using `set_attributes`, status with `set_status`, etc.
    ///
    /// This flag SHOULD be used to avoid expensive computations of a `Span` attributes or events in
    /// case when a `Span` is definitely not recorded. Note that any child span's recording is
    /// determined independently from the value of this flag (typically based on the sampled flag of
    /// a `TraceFlag` on `SpanContext`).
    ///
    /// This flag may be true despite the entire trace being sampled out. This allows to record and
    /// process information about the individual Span without sending it to the backend. An example
    /// of this scenario may be recording and processing of all incoming requests for the processing
    /// and building of SLA/SLO latency charts while sending only a subset - sampled spans - to the
    /// backend. See also the sampling section of SDK design.
    ///
    /// Users of the API should only access the `is_recording` property when instrumenting code and
    /// never access `SampledFlag` unless used in context propagators.
    fn is_recording(&self) -> bool;

    /// An API to set a single `Attribute` where the attribute properties are passed
    /// as arguments. To avoid extra allocations some implementations may offer a separate API for
    /// each of the possible value types.
    ///
    /// An `Attribute` is defined as a `KeyValue` pair.
    ///
    /// Attributes SHOULD preserve the order in which they're set. Setting an attribute
    /// with the same key as an existing attribute SHOULD overwrite the existing
    /// attribute's value.
    ///
    /// Note that the OpenTelemetry project documents certain ["standard
    /// attributes"](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md)
    /// that have prescribed semantic meanings.
    fn set_attribute(&mut self, attribute: api::KeyValue);

    /// Sets the status of the `Span`. If used, this will override the default `Span`
    /// status, which is `OK`.
    ///
    /// Only the value of the last call will be recorded, and implementations are free
    /// to ignore previous calls.
    fn set_status(&mut self, status: String);

    /// Updates the `Span`'s name. After this update, any sampling behavior based on the
    /// name will depend on the implementation.
    ///
    /// It is highly discouraged to update the name of a `Span` after its creation.
    /// `Span` name is often used to group, filter and identify the logical groups of
    /// spans. Often, filtering logic will be implemented before the `Span` creation
    /// for performance reasons, and the name update may interfere with this logic.
    ///
    /// The method name is called `update_name` to differentiate this method from the
    /// regular property. It emphasizes that this operation signifies a
    /// major change for a `Span` and may lead to re-calculation of sampling or
    /// filtering decisions made previously depending on the implementation.
    fn update_name(&mut self, new_name: String);

    /// Finishes the `Span`.
    ///
    /// Implementations MUST ignore all subsequent calls to `end` (there might be
    /// exceptions when the tracer is streaming events and has no mutable state
    /// associated with the Span).
    ///
    /// Calls to `end` a Span MUST not have any effects on child `Span`s as they may
    /// still be running and can be ended later.
    ///
    ///This API MUST be non-blocking.
    fn end(&mut self);

    /// Used by global tracer to downcast to specific span type.
    fn as_any(&self) -> &dyn std::any::Any;
}
<|endoftext|>


<commit_before>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{self, Serialize};

use imp_prelude::*;

use super::arraytraits::ARRAY_FORMAT_VERSION;
use super::Elements;

impl<A, D, S> Serialize for ArrayBase<S, D>
    where A: Serialize,
          D: Dimension + Serialize,
          S: Data<Elem = A>

{
    fn serialize<Se>(&self, serializer: &mut Se) -> Result<(), Se::Error>
        where Se: serde::Serializer
    {
        let mut struct_state = try!(serializer.serialize_struct("Array", 3));
        try!(serializer.serialize_struct_elt(&mut struct_state, "v", ARRAY_FORMAT_VERSION));
        try!(serializer.serialize_struct_elt(&mut struct_state, "dim", self.dim()));
        try!(serializer.serialize_struct_elt(&mut struct_state, "data", self.iter()));
        serializer.serialize_struct_end(struct_state)
    }
}

impl<'a, A, D> Serialize for Elements<'a, A, D>
    where A: Serialize,
          D: Dimension + Serialize
{
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer
    {
        let mut seq_state = try!(serializer.serialize_seq(Some(self.len())));
        for elt in self.clone() {
            try!(serializer.serialize_seq_elt(&mut seq_state, elt));
        }
        serializer.serialize_seq_end(seq_state)
    }
}
<commit_msg>serde: Make iterator implementation of serialize private<commit_after>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{self, Serialize};

use imp_prelude::*;

use super::arraytraits::ARRAY_FORMAT_VERSION;
use super::Elements;

impl<A, D, S> Serialize for ArrayBase<S, D>
    where A: Serialize,
          D: Dimension + Serialize,
          S: Data<Elem = A>

{
    fn serialize<Se>(&self, serializer: &mut Se) -> Result<(), Se::Error>
        where Se: serde::Serializer
    {
        let mut struct_state = try!(serializer.serialize_struct("Array", 3));
        try!(serializer.serialize_struct_elt(&mut struct_state, "v", ARRAY_FORMAT_VERSION));
        try!(serializer.serialize_struct_elt(&mut struct_state, "dim", self.dim()));
        try!(serializer.serialize_struct_elt(&mut struct_state, "data", Sequence(self.iter())));
        serializer.serialize_struct_end(struct_state)
    }
}

// private iterator wrapper
struct Sequence<'a, A: 'a, D>(Elements<'a, A, D>);

impl<'a, A, D> Serialize for Sequence<'a, A, D>
    where A: Serialize,
          D: Dimension + Serialize
{
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer
    {
        let iter = &self.0;
        let mut seq_state = try!(serializer.serialize_seq(Some(iter.len())));
        for elt in iter.clone() {
            try!(serializer.serialize_seq_elt(&mut seq_state, elt));
        }
        serializer.serialize_seq_end(seq_state)
    }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Display, Formatter};
use std::default::Default;
use rlua::{self, Table, Lua, UserData, ToLua, Value};
use super::object::{Object, Objectable};
use super::signal;
use super::property::Property;
use super::class::{self, Class};
use rustwlc::types::KeyMod;
use xcb::ffi::xproto::xcb_button_t;

#[derive(Clone, Debug)]
pub struct ButtonState {
    button: xcb_button_t,
    modifiers: KeyMod
}

#[derive(Clone, Debug)]
pub struct Button<'lua>(Table<'lua>);

impl Display for ButtonState {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Button: {:p}", self)
    }
}

impl Default for ButtonState {
    fn default() -> Self {
        ButtonState {
            button: xcb_button_t::default(),
            modifiers: KeyMod::empty()
        }
    }
}

impl UserData for ButtonState {}

impl <'lua> Button<'lua> {
    fn new(lua: &'lua Lua, args: rlua::Table) -> rlua::Result<Object<'lua>> {
        let class = class::class_setup(lua, "button")?;
        Ok(Button::allocate(lua, class)?
           .handle_constructor_argument(args)?
           .build())
    }

    pub fn button(&self) -> rlua::Result<Value<'lua>> {
        let button = self.state()?;
        Ok(Value::Integer(button.button as _))
    }

    pub fn set_button(&self, new_val: xcb_button_t) -> rlua::Result<()> {
        let mut button = self.state()?;
        button.button = new_val;
        self.set_state(button)?;
        Ok(())
    }

    pub fn modifiers(&self) -> rlua::Result<KeyMod> {
        let button = self.state()?;
        Ok(button.modifiers)
    }

    pub fn set_modifiers(&self, mods: Table<'lua>) -> rlua::Result<()> {
        use ::lua::mods_to_rust;
        let mut button = self.state()?;
        button.modifiers = mods_to_rust(mods)?;
        self.set_state(button)?;
        Ok(())
    }
}

impl <'lua> ToLua<'lua> for Button<'lua> {
    fn to_lua(self, lua: &'lua Lua) -> rlua::Result<Value<'lua>> {
        self.0.to_lua(lua)
    }
}

impl_objectable!(Button, ButtonState);

pub fn init(lua: &Lua) -> rlua::Result<Class> {
    Class::builder(lua, "button", None, None, None)?
        .method("__call".into(),
                lua.create_function(|lua, (_, args): (rlua::Value, rlua::Table)| Button::new(lua, args)))?
        .property(Property::new("button".into(),
                                Some(lua.create_function(set_button)),
                                Some(lua.create_function(get_button)),
                                Some(lua.create_function(set_button))))?
        .property(Property::new("modifiers".into(),
                                Some(lua.create_function(set_modifiers)),
                                Some(lua.create_function(get_modifiers)),
                                Some(lua.create_function(set_modifiers))))?
        .save_class("button")?
        .build()
}

fn set_button<'lua>(lua: &'lua Lua, (table, val): (Table, Value))
                    -> rlua::Result<Value<'lua>> {
    use rlua::Value::*;
    let button = Button::cast(table.clone().into())?;
    match val {
        Number(num) => button.set_button(num as _)?,
        Integer(num) => button.set_button(num as _)?,
        _ => button.set_button(xcb_button_t::default())?
    }
    signal::emit_signal(lua,
                        table.into(),
                        "property::button".into(),
                        val)?;
    Ok(Value::Nil)
}

fn get_button<'lua>(_: &'lua Lua, table: Table<'lua>)
                    -> rlua::Result<Value<'lua>> {
    Button::cast(table.into())?.button()
}

fn set_modifiers<'lua>(lua: &'lua Lua, (table, modifiers): (Table, Table))
                       -> rlua::Result<Value<'lua>> {
    let button = Button::cast(table.clone().into())?;
    button.set_modifiers(modifiers.clone())?;
    signal::emit_signal(lua,
                        table.into(),
                        "property::modifiers".into(),
                        modifiers)?;
    Ok(Value::Nil)
}

fn get_modifiers<'lua>(lua: &'lua Lua, table: Table<'lua>)
                    -> rlua::Result<Value<'lua>> {
    use ::lua::mods_to_lua;
    mods_to_lua(lua, Button::cast(table.into())?.modifiers()?).map(Value::Table)
}

#[cfg(test)]
mod test {
    use rlua::{Table, Lua};
    use super::super::button::{self, Button};
    use super::super::object;

    #[test]
    fn button_object_test() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.globals().set("button0", Button::new(&lua).unwrap())
            .unwrap();
        lua.globals().set("button1", Button::new(&lua).unwrap())
            .unwrap();
        lua.eval(r#"
assert(button0.button == 0)
assert(button1.button == 0)
button0:connect_signal("test", function(button) button.button = 3 end)
button0:emit_signal("test")
assert(button1.button == 0)
assert(button0.button == 3)
"#, None).unwrap()
    }

    #[test]
    fn button_class_test() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.eval(r#"
a_button = button()
assert(a_button.button == 0)
a_button:connect_signal("test", function(button) button.button = 2 end)
a_button:emit_signal("test")
assert(a_button.button == 2)
"#, None).unwrap()
    }

    #[test]
    fn button_property_test() {
        let lua = Lua::new();
        let button_class = button::init(&lua).unwrap();
        assert_eq!(button_class.properties().unwrap().len().unwrap(), 2);
        lua.eval(r#"
a_button = button()
assert(a_button.button == 0)
a_button.button = 5
assert(a_button.button == 5)
"#, None).unwrap()
    }

    #[test]
    fn button_remove_signal_test() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.eval(r#"
button0 = button()
assert(button0.button == 0)
button0:connect_signal("test", function(button) button.button = 3 end)
button0:emit_signal("test")
assert(button0.button == 3)
button0.button = 0
button0:disconnect_signal("test")
button0:emit_signal("test")
assert(button0.button == 0)
"#, None).unwrap()
    }

    #[test]
    fn button_emit_signal_multiple_args() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.globals().set("a_button", Button::new(&lua).unwrap())
            .unwrap();
        lua.eval(r#"
 assert(a_button.button == 0)
 a_button:connect_signal("test", function(button, num) button.button = num end)
 a_button:emit_signal("test", 5)
 assert(a_button.button == 5)
 a_button:emit_signal("test", 0)
 assert(a_button.button == 0)
 "#, None).unwrap()
    }

    #[test]
    fn button_modifiers_test() {
        use rustwlc::*;
        use self::button::Button;
        use self::object::Objectable;
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.globals().set("a_button", Button::new(&lua).unwrap())
            .unwrap();
        let button = Button::cast(lua.globals().get::<_, Table>("a_button")
                                  .unwrap().into()).unwrap();
        assert_eq!(button.modifiers().unwrap(), KeyMod::empty());
        lua.eval::<()>(r#"
a_button.modifiers = { "Caps" }
"#, None).unwrap();
        assert_eq!(button.modifiers().unwrap(), MOD_CAPS);
    }

    #[test]
    fn button_multiple_modifiers_test() {
        use rustwlc::*;
        use self::button::Button;
        use self::object::Objectable;
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.globals().set("a_button", Button::new(&lua).unwrap())
            .unwrap();
        let button = Button::cast(lua.globals().get::<_, Table>("a_button")
                                  .unwrap().into()).unwrap();
        assert_eq!(button.modifiers().unwrap(), KeyMod::empty());
        lua.eval::<()>(r#"
a_button.modifiers = { "Caps", "Mod2" }
"#, None).unwrap();
        assert_eq!(button.modifiers().unwrap(), MOD_CAPS | MOD_MOD2);
    }

    #[test]
    /// Tests that setting the button index property updates the
    /// callback for all instances of button
    fn button_index_property() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.globals().set("a_button", Button::new(&lua).unwrap())
            .unwrap();
        lua.eval::<()>(r#"
hit = false
button.set_index_miss_handler(function(button)
    hit = true
    return 5
end)
assert(not hit)
a = button.button
assert(a ~= 5)
assert(not hit)
a = a_button.aoeu
assert(hit)
assert(a == 5)
a = nil
hit = false
a = button().aoeu
assert(hit)
assert(a == 5)
"#, None).unwrap()
    }

    #[test]
    fn button_modifiers_signal_test() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.eval::<()>(r#"
a_button = button()
hit = false
a_button:connect_signal("property::modifiers", function(button) hit = true end)
a_button:emit_signal("property::modifiers")
assert(hit)
hit = false
assert(not hit)
button.button = nil
assert(not hit)
a_button.modifiers = { "Caps", "Mod2" }
assert(hit)
"#, None).unwrap()
    }

    #[test]
    fn button_button_signal_test() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.eval::<()>(r#"
a_button = button()
hit = false
a_button:connect_signal("property::button", function(button) hit = true end)
a_button:emit_signal("property::button")
assert(hit)
hit = false
assert(not hit)
a_button.button = nil
assert(hit)
"#, None).unwrap()
    }

    #[test]
    fn button_test_valid() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.eval::<()>(r#"
a_button = button()
assert(a_button.valid)
getmetatable(a_button).__class = nil
assert(not a_button.valid)
"#, None).unwrap();
    }
}

<commit_msg>awesome::button::test: Fix tests for recent API change<commit_after>use std::fmt::{self, Display, Formatter};
use std::default::Default;
use rlua::{self, Table, Lua, UserData, ToLua, Value};
use super::object::{Object, Objectable};
use super::signal;
use super::property::Property;
use super::class::{self, Class};
use rustwlc::types::KeyMod;
use xcb::ffi::xproto::xcb_button_t;

#[derive(Clone, Debug)]
pub struct ButtonState {
    button: xcb_button_t,
    modifiers: KeyMod
}

#[derive(Clone, Debug)]
pub struct Button<'lua>(Table<'lua>);

impl Display for ButtonState {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Button: {:p}", self)
    }
}

impl Default for ButtonState {
    fn default() -> Self {
        ButtonState {
            button: xcb_button_t::default(),
            modifiers: KeyMod::empty()
        }
    }
}

impl UserData for ButtonState {}

impl <'lua> Button<'lua> {
    fn new(lua: &'lua Lua, args: rlua::Table) -> rlua::Result<Object<'lua>> {
        let class = class::class_setup(lua, "button")?;
        Ok(Button::allocate(lua, class)?
           .handle_constructor_argument(args)?
           .build())
    }

    pub fn button(&self) -> rlua::Result<Value<'lua>> {
        let button = self.state()?;
        Ok(Value::Integer(button.button as _))
    }

    pub fn set_button(&self, new_val: xcb_button_t) -> rlua::Result<()> {
        let mut button = self.state()?;
        button.button = new_val;
        self.set_state(button)?;
        Ok(())
    }

    pub fn modifiers(&self) -> rlua::Result<KeyMod> {
        let button = self.state()?;
        Ok(button.modifiers)
    }

    pub fn set_modifiers(&self, mods: Table<'lua>) -> rlua::Result<()> {
        use ::lua::mods_to_rust;
        let mut button = self.state()?;
        button.modifiers = mods_to_rust(mods)?;
        self.set_state(button)?;
        Ok(())
    }
}

impl <'lua> ToLua<'lua> for Button<'lua> {
    fn to_lua(self, lua: &'lua Lua) -> rlua::Result<Value<'lua>> {
        self.0.to_lua(lua)
    }
}

impl_objectable!(Button, ButtonState);

pub fn init(lua: &Lua) -> rlua::Result<Class> {
    Class::builder(lua, "button", None, None, None)?
        .method("__call".into(),
                lua.create_function(|lua, (_, args): (rlua::Value, rlua::Table)| Button::new(lua, args)))?
        .property(Property::new("button".into(),
                                Some(lua.create_function(set_button)),
                                Some(lua.create_function(get_button)),
                                Some(lua.create_function(set_button))))?
        .property(Property::new("modifiers".into(),
                                Some(lua.create_function(set_modifiers)),
                                Some(lua.create_function(get_modifiers)),
                                Some(lua.create_function(set_modifiers))))?
        .save_class("button")?
        .build()
}

fn set_button<'lua>(lua: &'lua Lua, (table, val): (Table, Value))
                    -> rlua::Result<Value<'lua>> {
    use rlua::Value::*;
    let button = Button::cast(table.clone().into())?;
    match val {
        Number(num) => button.set_button(num as _)?,
        Integer(num) => button.set_button(num as _)?,
        _ => button.set_button(xcb_button_t::default())?
    }
    signal::emit_signal(lua,
                        table.into(),
                        "property::button".into(),
                        val)?;
    Ok(Value::Nil)
}

fn get_button<'lua>(_: &'lua Lua, table: Table<'lua>)
                    -> rlua::Result<Value<'lua>> {
    Button::cast(table.into())?.button()
}

fn set_modifiers<'lua>(lua: &'lua Lua, (table, modifiers): (Table, Table))
                       -> rlua::Result<Value<'lua>> {
    let button = Button::cast(table.clone().into())?;
    button.set_modifiers(modifiers.clone())?;
    signal::emit_signal(lua,
                        table.into(),
                        "property::modifiers".into(),
                        modifiers)?;
    Ok(Value::Nil)
}

fn get_modifiers<'lua>(lua: &'lua Lua, table: Table<'lua>)
                    -> rlua::Result<Value<'lua>> {
    use ::lua::mods_to_lua;
    mods_to_lua(lua, Button::cast(table.into())?.modifiers()?).map(Value::Table)
}

#[cfg(test)]
mod test {
    use rlua::{Table, Lua};
    use super::super::button::{self, Button};
    use super::super::object;

    #[test]
    fn button_object_test() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.globals().set("button0", Button::new(&lua, lua.create_table()).unwrap())
            .unwrap();
        lua.globals().set("button1", Button::new(&lua, lua.create_table()).unwrap())
            .unwrap();
        lua.eval(r#"
assert(button0.button == 0)
assert(button1.button == 0)
button0:connect_signal("test", function(button) button.button = 3 end)
button0:emit_signal("test")
assert(button1.button == 0)
assert(button0.button == 3)
"#, None).unwrap()
    }

    #[test]
    fn button_class_test() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.eval(r#"
a_button = button{}
assert(a_button.button == 0)
a_button:connect_signal("test", function(button) button.button = 2 end)
a_button:emit_signal("test")
assert(a_button.button == 2)
"#, None).unwrap()
    }

    #[test]
    fn button_property_test() {
        let lua = Lua::new();
        let button_class = button::init(&lua).unwrap();
        assert_eq!(button_class.properties().unwrap().len().unwrap(), 2);
        lua.eval(r#"
a_button = button{}
assert(a_button.button == 0)
a_button.button = 5
assert(a_button.button == 5)
"#, None).unwrap()
    }

    #[test]
    fn button_remove_signal_test() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.eval(r#"
button0 = button{}
assert(button0.button == 0)
button0:connect_signal("test", function(button) button.button = 3 end)
button0:emit_signal("test")
assert(button0.button == 3)
button0.button = 0
button0:disconnect_signal("test")
button0:emit_signal("test")
assert(button0.button == 0)
"#, None).unwrap()
    }

    #[test]
    fn button_emit_signal_multiple_args() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.globals().set("a_button", Button::new(&lua, lua.create_table()).unwrap())
            .unwrap();
        lua.eval(r#"
 assert(a_button.button == 0)
 a_button:connect_signal("test", function(button, num) button.button = num end)
 a_button:emit_signal("test", 5)
 assert(a_button.button == 5)
 a_button:emit_signal("test", 0)
 assert(a_button.button == 0)
 "#, None).unwrap()
    }

    #[test]
    fn button_modifiers_test() {
        use rustwlc::*;
        use self::button::Button;
        use self::object::Objectable;
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.globals().set("a_button", Button::new(&lua, lua.create_table()).unwrap())
            .unwrap();
        let button = Button::cast(lua.globals().get::<_, Table>("a_button")
                                  .unwrap().into()).unwrap();
        assert_eq!(button.modifiers().unwrap(), KeyMod::empty());
        lua.eval::<()>(r#"
a_button.modifiers = { "Caps" }
"#, None).unwrap();
        assert_eq!(button.modifiers().unwrap(), MOD_CAPS);
    }

    #[test]
    fn button_multiple_modifiers_test() {
        use rustwlc::*;
        use self::button::Button;
        use self::object::Objectable;
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.globals().set("a_button", Button::new(&lua, lua.create_table()).unwrap())
            .unwrap();
        let button = Button::cast(lua.globals().get::<_, Table>("a_button")
                                  .unwrap().into()).unwrap();
        assert_eq!(button.modifiers().unwrap(), KeyMod::empty());
        lua.eval::<()>(r#"
a_button.modifiers = { "Caps", "Mod2" }
"#, None).unwrap();
        assert_eq!(button.modifiers().unwrap(), MOD_CAPS | MOD_MOD2);
    }

    #[test]
    /// Tests that setting the button index property updates the
    /// callback for all instances of button
    fn button_index_property() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.globals().set("a_button", Button::new(&lua, lua.create_table()).unwrap())
            .unwrap();
        lua.eval::<()>(r#"
hit = false
button.set_index_miss_handler(function(button)
    hit = true
    return 5
end)
assert(not hit)
a = button.button
assert(a ~= 5)
assert(not hit)
a = a_button.aoeu
assert(hit)
assert(a == 5)
a = nil
hit = false
a = button{}.aoeu
assert(hit)
assert(a == 5)
"#, None).unwrap()
    }

    #[test]
    fn button_modifiers_signal_test() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.eval::<()>(r#"
a_button = button{}
hit = false
a_button:connect_signal("property::modifiers", function(button) hit = true end)
a_button:emit_signal("property::modifiers")
assert(hit)
hit = false
assert(not hit)
button.button = nil
assert(not hit)
a_button.modifiers = { "Caps", "Mod2" }
assert(hit)
"#, None).unwrap()
    }

    #[test]
    fn button_button_signal_test() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.eval::<()>(r#"
a_button = button{}
hit = false
a_button:connect_signal("property::button", function(button) hit = true end)
a_button:emit_signal("property::button")
assert(hit)
hit = false
assert(not hit)
a_button.button = nil
assert(hit)
"#, None).unwrap()
    }

    #[test]
    fn button_test_valid() {
        let lua = Lua::new();
        button::init(&lua).unwrap();
        lua.eval::<()>(r#"
a_button = button{}
assert(a_button.valid)
getmetatable(a_button).__class = nil
assert(not a_button.valid)
"#, None).unwrap();
    }
}

<|endoftext|>


<commit_before>use quote::Tokens;
use syn;

// FIXME: Documenation

pub fn ber_choice_serialize(ast: &syn::MacroInput) -> Tokens {
  let name = &ast.ident;
  let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

  let fields = if let syn::Body::Enum(ref fields) = ast.body {
    fields
  } else {
    panic!("Expected an enum, but type {} was not an enum", name);
  };

  let match_pattern: Vec<_> = fields.iter().map(|v| {
    let ident = &v.ident;
    quote!(#name::#ident(ref item))
  }).collect();
  let match_action: Vec<_> = fields.iter().map(|_v| {
    // TODO: Handle asn1 attributes
    quote! {
      if false {
        // let mut bytes = Vec::new();
        // try!(item.serialize_enc(e, &mut bytes));
        // try!(tag.write_tag(writer));
        // let len: ::asn1_cereal::tag::Len = Some(bytes.len() as ::asn1_cereal::tag::LenNum).into();
        // try!(writer.write_all(&mut bytes));
      } else {
        // FIXME: Does implicit tagging + CHOICE mean always explicit tag?
        // Maybe not with context-specific tags?
        // FIXME: We should be conditionally setting the constructed flag.
        // if E::tag_rules() == ::asn1_cereal::ber::enc::TagEnc::Implicit {
        //   try!(item.serialize_value(e, writer));
        // } else {
          try!(item.serialize_enc(e, writer));
        // }
      }
    }
  }).collect();

  quote! {
    impl #impl_generics ::asn1_cereal::BerSerialize for #name #ty_generics #where_clause {
      fn serialize_value<E: ::asn1_cereal::BerEncRules, W: ::std::io::Write>
          (&self, e: E, writer: &mut W) -> Result<(), ::asn1_cereal::err::EncodeError> {
        match *self {
          #(#match_pattern => #match_action),*
        }
        Ok(())
      }
    }
  }
}

pub fn ber_choice_deserialize(ast: &syn::MacroInput) -> Tokens {
  let name = &ast.ident;
  let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

  let fields = if let syn::Body::Enum(ref fields) = ast.body {
    fields
  } else {
    panic!("Expected an enum, but type {} was not an enum", name);
  };

  let match_pattern: Vec<_> = fields.iter().map(|v| {
    let ident = &v.ident;
    let inner = if let syn::VariantData::Tuple(ref fields) = v.data {
      fields[0].clone()
    } else {
      panic!("Expected a tuple, but type {} variant {} was not a tuple", name, ident);
    };
    // TODO: Handle asn1 attributes
    quote! {
      tag @ ::asn1_cereal::tag::Tag { .. }
        if tag == <#inner as ::asn1_cereal::Asn1Info>::asn1_tag().unwrap()
    }
  }).collect();

  let match_action: Vec<_> = fields.iter().map(|v| {
    let ident = &v.ident;
    // TODO: Handle asn1 attributes
    quote! {
      Ok(#name::#ident(
        // FIXME: Does implicit tagging + CHOICE mean always explicit tag?
        // Maybe not with context-specific tags?
        // FIXME: We should be conditionally setting the constructed flag.
        // if E::tag_rules() == ::asn1_cereal::ber::enc::TagEnc::Implicit {
        //   try!(::asn1_cereal::BerDeserialize::deserialize_value(e, reader, len))
        // } else {
          try!(::asn1_cereal::BerDeserialize::deserialize_with_tag(e, reader, tag, len))
        // }
      ))
    }
  }).collect();

  quote! {
    impl #impl_generics ::asn1_cereal::BerDeserialize for #name #ty_generics #where_clause {
      fn deserialize_value<E: ::asn1_cereal::BerEncRules, I: Iterator<Item=::std::io::Result<u8>>>
          (e: E, reader: &mut I, _len: ::asn1_cereal::tag::Len) ->
          Result<Self, ::asn1_cereal::err::DecodeError> {
        let (tag, len) = ::asn1_cereal::tag::read_taglen(reader)?;
        match tag {
          #(#match_pattern => #match_action),*,
          _ => unimplemented!(),
        }
      }
    }
  }
}
<commit_msg>Reimplement _deserialize_with_tag for choice<commit_after>use quote::Tokens;
use syn;

// FIXME: Documenation

pub fn ber_choice_serialize(ast: &syn::MacroInput) -> Tokens {
  let name = &ast.ident;
  let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

  let fields = if let syn::Body::Enum(ref fields) = ast.body {
    fields
  } else {
    panic!("Expected an enum, but type {} was not an enum", name);
  };

  let match_pattern: Vec<_> = fields.iter().map(|v| {
    let ident = &v.ident;
    quote!(#name::#ident(ref item))
  }).collect();
  let match_action: Vec<_> = fields.iter().map(|_v| {
    // TODO: Handle asn1 attributes
    quote! {
      if false {
        // let mut bytes = Vec::new();
        // try!(item.serialize_enc(e, &mut bytes));
        // try!(tag.write_tag(writer));
        // let len: ::asn1_cereal::tag::Len = Some(bytes.len() as ::asn1_cereal::tag::LenNum).into();
        // try!(writer.write_all(&mut bytes));
      } else {
        // FIXME: Does implicit tagging + CHOICE mean always explicit tag?
        // Maybe not with context-specific tags?
        // FIXME: We should be conditionally setting the constructed flag.
        // if E::tag_rules() == ::asn1_cereal::ber::enc::TagEnc::Implicit {
        //   try!(item.serialize_value(e, writer));
        // } else {
          try!(item.serialize_enc(e, writer));
        // }
      }
    }
  }).collect();

  quote! {
    impl #impl_generics ::asn1_cereal::BerSerialize for #name #ty_generics #where_clause {
      fn serialize_value<E: ::asn1_cereal::BerEncRules, W: ::std::io::Write>
          (&self, e: E, writer: &mut W) -> Result<(), ::asn1_cereal::err::EncodeError> {
        match *self {
          #(#match_pattern => #match_action),*
        }
        Ok(())
      }
    }
  }
}

pub fn ber_choice_deserialize(ast: &syn::MacroInput) -> Tokens {
  let name = &ast.ident;
  let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

  let fields = if let syn::Body::Enum(ref fields) = ast.body {
    fields
  } else {
    panic!("Expected an enum, but type {} was not an enum", name);
  };

  let match_pattern: Vec<_> = fields.iter().map(|v| {
    let ident = &v.ident;
    let inner = if let syn::VariantData::Tuple(ref fields) = v.data {
      fields[0].clone()
    } else {
      panic!("Expected a tuple, but type {} variant {} was not a tuple", name, ident);
    };
    // TODO: Handle asn1 attributes
    quote! {
      tag @ ::asn1_cereal::tag::Tag { .. }
        if tag == <#inner as ::asn1_cereal::Asn1Info>::asn1_tag().unwrap()
    }
  }).collect();

  let match_action: Vec<_> = fields.iter().map(|v| {
    let ident = &v.ident;
    // TODO: Handle asn1 attributes
    quote! {
      Ok(#name::#ident(
        // FIXME: Does implicit tagging + CHOICE mean always explicit tag?
        // Maybe not with context-specific tags?
        // FIXME: We should be conditionally setting the constructed flag.
        // if E::tag_rules() == ::asn1_cereal::ber::enc::TagEnc::Implicit {
        //   try!(::asn1_cereal::BerDeserialize::deserialize_value(e, reader, len))
        // } else {
        try!(::asn1_cereal::BerDeserialize::deserialize_with_tag(e, reader, tag, len))
        // }
      ))
    }
  }).collect();

  quote! {
    impl #impl_generics ::asn1_cereal::BerDeserialize for #name #ty_generics #where_clause {
      fn _deserialize_with_tag<E: ::asn1_cereal::BerEncRules, I: Iterator<Item=::std::io::Result<u8>>>
          (e: E, reader: &mut I, tag: ::asn1_cereal::tag::Tag, len: ::asn1_cereal::tag::Len) ->
          Option<Result<Self, ::asn1_cereal::err::DecodeError>> {
        let mut res = ||
          match tag {
            #(#match_pattern => #match_action),*,
            _ => panic!("Choice: Unknown tag {}", tag),
          };
        Some(res())
      }

      fn deserialize_value<E: ::asn1_cereal::BerEncRules, I: Iterator<Item=::std::io::Result<u8>>>
          (e: E, reader: &mut I, _len: ::asn1_cereal::tag::Len) ->
          Result<Self, ::asn1_cereal::err::DecodeError> {
        let (tag, len) = ::asn1_cereal::tag::read_taglen(reader)?;
        Self::_deserialize_with_tag(e, reader, tag, len).unwrap()
      }
    }
  }
}
<|endoftext|>


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

extern crate router = "route_recognizer";
extern crate conduit;

use std::collections::HashMap;
use std::any::{Any, AnyRefExt};
use std::fmt::Show;

use router::{Router, Match};
use conduit::{Method, Handler, Request, Response};

pub struct RouteBuilder {
    routers: HashMap<Method, Router<Box<Handler + Send + Share>>>
}

impl RouteBuilder {
    pub fn new() -> RouteBuilder {
        RouteBuilder { routers: HashMap::new() }
    }

    pub fn recognize<'a>(&'a self, method: &Method, path: &str)
                         -> Result<Match<&'a Box<Handler + Send + Share>>, String>
    {
        match self.routers.find(method) {
            None => Err(format!("No router found for {}", method)),
            Some(router) => router.recognize(path)
        }
    }

    pub fn map<'a, H: Handler>(&'a mut self, method: Method, pattern: &str,
                               handler: H) -> &'a mut RouteBuilder {
        {
            let router = self.routers.find_or_insert_with(method, |_| Router::new());
            router.add(pattern, box handler as Box<Handler + Send + Share>);
        }
        self
    }

    pub fn get<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                               -> &'a mut RouteBuilder {
        self.map(conduit::Get, pattern, handler)
    }

    pub fn post<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                -> &'a mut RouteBuilder {
        self.map(conduit::Post, pattern, handler)
    }

    pub fn put<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                               -> &'a mut RouteBuilder {
        self.map(conduit::Put, pattern, handler)
    }

    pub fn delete<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                  -> &'a mut RouteBuilder {
        self.map(conduit::Delete, pattern, handler)
    }

    pub fn head<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                -> &'a mut RouteBuilder {
        self.map(conduit::Head, pattern, handler)
    }
}

impl conduit::Handler for RouteBuilder {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Show>> {
        let m = {
            let method = request.method();
            let path = request.path();

            match self.recognize(&method, path) {
                Ok(m) => m,
                Err(e) => return Err(box e as Box<Show>)
            }
        };

        {
            let extensions = request.mut_extensions();
            extensions.insert("router.params", box m.params.clone() as Box<Any>);
        }

        (*m.handler).call(request)
    }
}

pub trait RequestParams<'a> {
    fn params(self) -> &'a router::Params;
}

pub fn params<'a>(req: &'a mut Request) -> &'a router::Params {
    req.extensions().find(&"router.params")
        .and_then(|a| a.as_ref::<router::Params>())
        .expect("Missing params")
}

impl<'a> RequestParams<'a> for &'a mut Request {
    fn params(self) -> &'a router::Params {
        params(self)
    }
}

#[cfg(test)]
mod tests {
    extern crate semver;
    use std::io::net::ip::IpAddr;
    use std::collections::HashMap;
    use std::io::MemReader;
    use super::*;

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

    struct RequestSentinel {
        method: Method,
        path: String,
        extensions: conduit::Extensions
    }

    impl RequestSentinel {
        fn new(method: Method, path: &'static str) -> RequestSentinel {
            RequestSentinel {
                path: path.to_str(),
                extensions: HashMap::new(),
                method: method
            }
        }
    }

    impl conduit::Request for RequestSentinel {
        fn http_version(&self) -> semver::Version { unimplemented!() }
        fn conduit_version(&self) -> semver::Version { unimplemented!() }
        fn method(&self) -> Method { self.method }
        fn scheme(&self) -> Scheme { unimplemented!() }
        fn host<'a>(&'a self) -> Host<'a> { unimplemented!() }
        fn virtual_root<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn path<'a>(&'a self) -> &'a str {
            self.path.as_slice()
        }
        fn query_string<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn remote_ip(&self) -> IpAddr { unimplemented!() }
        fn content_length(&self) -> Option<uint> { unimplemented!() }
        fn headers<'a>(&'a self) -> &'a Headers { unimplemented!() }
        fn body<'a>(&'a mut self) -> &'a mut Reader { unimplemented!() }
        fn extensions<'a>(&'a self) -> &'a Extensions {
            &self.extensions
        }
        fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
            &mut self.extensions
        }
    }

    #[test]
    fn as_conduit_handler() {
        let mut router = RouteBuilder::new();
        router.post("/posts/:id", handler1);
        router.get("/posts/:id", handler1);

        let mut req = RequestSentinel::new(conduit::Get, "/posts/1");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_str().unwrap(), "1, Get".to_str());

        let mut req = RequestSentinel::new(conduit::Post, "/posts/10");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_str().unwrap(), "10, Post".to_str());

        let mut req = RequestSentinel::new(conduit::Post, "/nonexistent");
        router.call(&mut req).err().expect("No response");
    }

    fn handler1(req: &mut conduit::Request) -> Result<conduit::Response, ()> {
        let mut res = vec!();
        res.push(req.params()["id"]);
        res.push(format!("{}", req.method()));

        Ok(conduit::Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: box MemReader::new(res.connect(", ").into_bytes())
        })
    }
}
<commit_msg>Split tests into units with helpers.<commit_after>#![feature(macro_rules)]
#![feature(globs)]

extern crate router = "route_recognizer";
extern crate conduit;

use std::collections::HashMap;
use std::any::{Any, AnyRefExt};
use std::fmt::Show;

use router::{Router, Match};
use conduit::{Method, Handler, Request, Response};

pub struct RouteBuilder {
    routers: HashMap<Method, Router<Box<Handler + Send + Share>>>
}

impl RouteBuilder {
    pub fn new() -> RouteBuilder {
        RouteBuilder { routers: HashMap::new() }
    }

    pub fn recognize<'a>(&'a self, method: &Method, path: &str)
                         -> Result<Match<&'a Box<Handler + Send + Share>>, String>
    {
        match self.routers.find(method) {
            None => Err(format!("No router found for {}", method)),
            Some(router) => router.recognize(path)
        }
    }

    pub fn map<'a, H: Handler>(&'a mut self, method: Method, pattern: &str,
                               handler: H) -> &'a mut RouteBuilder {
        {
            let router = self.routers.find_or_insert_with(method, |_| Router::new());
            router.add(pattern, box handler as Box<Handler + Send + Share>);
        }
        self
    }

    pub fn get<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                               -> &'a mut RouteBuilder {
        self.map(conduit::Get, pattern, handler)
    }

    pub fn post<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                -> &'a mut RouteBuilder {
        self.map(conduit::Post, pattern, handler)
    }

    pub fn put<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                               -> &'a mut RouteBuilder {
        self.map(conduit::Put, pattern, handler)
    }

    pub fn delete<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                  -> &'a mut RouteBuilder {
        self.map(conduit::Delete, pattern, handler)
    }

    pub fn head<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                -> &'a mut RouteBuilder {
        self.map(conduit::Head, pattern, handler)
    }
}

impl conduit::Handler for RouteBuilder {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Show>> {
        let m = {
            let method = request.method();
            let path = request.path();

            match self.recognize(&method, path) {
                Ok(m) => m,
                Err(e) => return Err(box e as Box<Show>)
            }
        };

        {
            let extensions = request.mut_extensions();
            extensions.insert("router.params", box m.params.clone() as Box<Any>);
        }

        (*m.handler).call(request)
    }
}

pub trait RequestParams<'a> {
    fn params(self) -> &'a router::Params;
}

pub fn params<'a>(req: &'a mut Request) -> &'a router::Params {
    req.extensions().find(&"router.params")
        .and_then(|a| a.as_ref::<router::Params>())
        .expect("Missing params")
}

impl<'a> RequestParams<'a> for &'a mut Request {
    fn params(self) -> &'a router::Params {
        params(self)
    }
}

#[cfg(test)]
mod tests {
    extern crate semver;
    use std::io::net::ip::IpAddr;
    use std::collections::HashMap;
    use std::io::MemReader;
    use super::*;

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

    struct RequestSentinel {
        method: Method,
        path: String,
        extensions: conduit::Extensions
    }

    impl RequestSentinel {
        fn new(method: Method, path: &'static str) -> RequestSentinel {
            RequestSentinel {
                path: path.to_str(),
                extensions: HashMap::new(),
                method: method
            }
        }
    }

    impl conduit::Request for RequestSentinel {
        fn http_version(&self) -> semver::Version { unimplemented!() }
        fn conduit_version(&self) -> semver::Version { unimplemented!() }
        fn method(&self) -> Method { self.method }
        fn scheme(&self) -> Scheme { unimplemented!() }
        fn host<'a>(&'a self) -> Host<'a> { unimplemented!() }
        fn virtual_root<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn path<'a>(&'a self) -> &'a str {
            self.path.as_slice()
        }
        fn query_string<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn remote_ip(&self) -> IpAddr { unimplemented!() }
        fn content_length(&self) -> Option<uint> { unimplemented!() }
        fn headers<'a>(&'a self) -> &'a Headers { unimplemented!() }
        fn body<'a>(&'a mut self) -> &'a mut Reader { unimplemented!() }
        fn extensions<'a>(&'a self) -> &'a Extensions {
            &self.extensions
        }
        fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
            &mut self.extensions
        }
    }

    #[test]
    fn basic_get() {
        let router = test_router();
        let mut req = RequestSentinel::new(conduit::Get, "/posts/1");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_str().unwrap(), "1, Get".to_str());
    }

    #[test]
    fn basic_post() {
        let router = test_router();
        let mut req = RequestSentinel::new(conduit::Post, "/posts/10");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_str().unwrap(), "10, Post".to_str());
    }

    #[test]
    fn nonexistent_route() {
        let router = test_router();
        let mut req = RequestSentinel::new(conduit::Post, "/nonexistent");
        router.call(&mut req).err().expect("No response");
    }

    fn test_router() -> RouteBuilder {
        let mut router = RouteBuilder::new();
        router.post("/posts/:id", test_handler);
        router.get("/posts/:id", test_handler);
        router
    }

    fn test_handler(req: &mut conduit::Request) -> Result<conduit::Response, ()> {
        let mut res = vec!();
        res.push(req.params()["id"]);
        res.push(format!("{}", req.method()));

        Ok(conduit::Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: box MemReader::new(res.connect(", ").into_bytes())
        })
    }
}
<|endoftext|>


<commit_before>//! A simple first program in rust, actually I plan to do something even
//! useful. Trying to find all my audiobooks on many machines, identify them,
//! find duplicates (later trying to solve the problem, also including their permissions,
//! different names, but same albums, etc, get all stats about it).
//! It acts as a wrapper around adbflib, which holds major parts of the implemention.
//!
//! Use ADBF_LOG = console, system, file for enabling logging according to your likes.

mod command_line;

use adbfbinlib::{
    common::{logit, paths::SearchPath},
    ctrl::{Ctrl, UiUpdateMsg},
    data::{
        collection::Collection,
        ipc::{IFCollectionOutputData, IPC},
    },
    net::subs::key_keeper,
    shared,
};
use async_std::task;
use crossbeam::{channel::unbounded, sync::WaitGroup};
use ctrlc;
use exitcode;
use log::{error, info, trace};
use num_cpus;
use std::{
    cmp, env, io, process,
    sync::{Arc as SArc, Mutex as SMutex},
};

/// The main application which is central part of communicating with
/// the adbflib, which is closely connected.
fn main() -> io::Result<()> {
    // get start values from the input parser!!!
    let (ui_paths, has_tui, has_webui, has_net, keep_alive, open_browser, web_port, has_ui) =
        command_line::get_start_values();

    // read into paths
    let cleaned_paths = SearchPath::new(&ui_paths);
    if cleaned_paths.len() != ui_paths.len() && !has_tui && !has_webui && !open_browser {
        println!("Some paths/folders intersect and will not be used!");
    }

    // only use the arc
    let search_path = SArc::new(SMutex::new(cleaned_paths));
    let search_path_ui = search_path.clone();

    // define collection thread pool
    let ctrlc_thread = 1;
    let assumed_number_of_threads_used = if has_webui { 1 } else { 0 }
        + if has_tui { 1 } else { 0 }
        + if has_net { 1 } else { 0 }
        + ctrlc_thread;
    let nr_cpus = num_cpus::get();
    let nr_threads_for_collection = if assumed_number_of_threads_used >= nr_cpus {
        1
    } else {
        nr_cpus - assumed_number_of_threads_used
    };
    rayon::ThreadPoolBuilder::new()
        .thread_name(|nr| format!("col_{}", nr))
        .num_threads(nr_threads_for_collection)
        .build_global()
        .unwrap();

    // for synced start of different threads
    let wait_collector = WaitGroup::new();
    let wait_ui = wait_collector.clone();
    let wait_net = wait_collector.clone();

    //
    // prepare the message system
    //
    let (tx, rx) = unbounded::<UiUpdateMsg>();

    // these will be taken directly
    let tx_net = tx.clone();

    // ui message from here (collection)
    let tx_col = tx.clone();

    // for now this will stay wrapped
    let tx_from_collector_to_ui = SArc::new(SMutex::new(tx.clone()));

    // start the logging
    logit::Logit::init(logit::read_env_level(
        &env::var("ADBF_LOG").unwrap_or("".into()),
    ));

    // all optional components are wrapped into threads
    // 1 - UI         ui_thread   (optional)
    // 2 - Net        net_thread  (optional)
    // 3 - Collector  no thread yet (uses multiple rayon worker threads)
    let ui_thread = std::thread::Builder::new()
        .name("ui".into())
        .spawn(move || {
            if has_ui {
                Ctrl::run(
                    key_keeper::get_p2p_server_id(),
                    search_path_ui,
                    rx,
                    has_net,
                    wait_ui,
                    has_webui,
                    has_tui,
                    open_browser,
                    web_port,
                )
            } else {
                info!("no ui was created!");
                drop(wait_ui);
                Ok::<(), std::io::Error>(())
            }
        })?;

    // create a crossbeam channel for massive data exchange
    // with data I called IPC ...
    // in contrast to normal channels crossbeam channels are
    // n:m, so senders can be cloned as well!
    let (ipc_send, ipc_receive) = unbounded::<IPC>();

    // 2 - Net Future
    let net_thread = std::thread::Builder::new()
        .name("net".into())
        .spawn(move || {
            if has_net {
                let sender = Some(tx_net);
                task::block_on(
                    async move { shared::net_search(wait_net, sender, ipc_receive).await },
                )
                .map_err(|error| {
                    std::io::Error::new(
                        std::io::ErrorKind::Other,
                        format!("network error: {}", error),
                    )
                })
            } else {
                info!("no net!");
                drop(wait_net);
                Ok::<(), std::io::Error>(())
            }
        })?;

    // CTRL-C exit handler (is wrapped inside a thread)
    ctrlc::set_handler(move || {
        println!("\n'{}' was manually exited!!!", env!("CARGO_PKG_NAME"));
        process::exit(exitcode::SOFTWARE);
    })
    .map_err(|error| {
        std::io::Error::new(
            std::io::ErrorKind::Other,
            format!(
                "{} terminate signal invokation doesn't work!({:?})",
                env!("CARGO_PKG_NAME"),
                error
            ),
        )
    })?;

    // finished ipc sender reserved before collector takes action
    let ipc_send_finished = ipc_send.clone();

    // the collector
    // but yet this simple bracket to enclose this a little
    {
        trace!("syncing with 2 other threads");
        wait_collector.wait();
        trace!("sync with net and ui done ... collector can start");

        let synced_to_ui_messages = tx_from_collector_to_ui.clone();

        // set up data
        let collection_protected = SArc::new(SMutex::new(Collection::new()));

        // search parallelly
        let output_data = shared::collection_search(
            collection_protected.clone(),
            search_path,
            synced_to_ui_messages,
            has_ui,
        );

        info!("collector finished!!");
        if has_ui || has_net {
            // send own peer and others that are finished
            let memory_used = collection_protected
                .lock()
                .and_then(|collection| Ok(collection.memory()))
                .unwrap_or_else(|_| {
                    error!("locking collection didn't work here!");
                    0
                });

            let mut collection_output = IFCollectionOutputData::from(&output_data);
            // to have not 0 as data size minimum
            collection_output.size_of_data_in_kb = cmp::max(1, (memory_used / 1000) as usize);

            // to others via IPC
            if has_net {
                ipc_send_finished
                    .send(IPC::DoneSearching(collection_output.clone()))
                    .unwrap_or_else(|_| {
                        error!("net has to be up and receiving this send!");
                    });
            }
            // to myself (ui) via UiUpdateMsg
            if has_ui {
                tx_col
                    .send(UiUpdateMsg::PeerSearchFinished(
                        key_keeper::get_p2p_server_id(),
                        collection_output,
                    ))
                    .unwrap_or_else(|e| error!("use one: {}", e));
            }
        }
        if !has_ui {
            collection_protected
                .lock()
                .and_then(|locked_collection| {
                    Ok(locked_collection
                        .print_stats(&key_keeper::get_p2p_server_id(), nr_threads_for_collection))
                })
                .unwrap_or(())
        }
    }

    // look for keeping alive argument if that was chosen
    if keep_alive {
        ui_thread
            .join()
            .unwrap_or_else(|_| {
                // it doesn't matter because we will terminate anyway
                error!("this should be result of ui thread!!");
                Ok(())
            })
            .unwrap();
        if has_ui {
            info!("Stopped ui thread");
        }
        // net thread
        if has_ui {
            // if had a ui , net_thread will stop also after ui quit
            drop(net_thread);
        } else {
            // if didn't have ui, net_thread will continue running
            println!(
                "Search is finished, but net thread is kept running!\nTo stop send break command (ctrl-c)!"
            );
            net_thread
                .join()
                .unwrap_or_else(|_| {
                    // it doesn't matter because we will terminate anyway
                    error!("is this normal when joining net thread???");
                    Ok(())
                })
                .unwrap();
            info!("Stopped net thread");
        }
    } else {
        drop(net_thread);
        drop(ui_thread);
    }
    Ok(())
}
<commit_msg>[refactor] fix logging example in main.rs<commit_after>//! A simple first program in rust, actually I plan to do something even
//! useful. Trying to find all my audiobooks on many machines, identify them,
//! find duplicates (later trying to solve the problem, also including their permissions,
//! different names, but same albums, etc, get all stats about it).
//! It acts as a wrapper around adbflib, which holds major parts of the implemention.
//!
//! Use e.g. ADBF_LOG_LVL=file RUST_BACKTRACE=full RUST_LOG=adbflib::webui=trace system,
//! file for enabling logging according to your likes.

mod command_line;

use adbfbinlib::{
    common::{logit, paths::SearchPath},
    ctrl::{Ctrl, UiUpdateMsg},
    data::{
        collection::Collection,
        ipc::{IFCollectionOutputData, IPC},
    },
    net::subs::key_keeper,
    shared,
};
use async_std::task;
use crossbeam::{channel::unbounded, sync::WaitGroup};
use ctrlc;
use exitcode;
use log::{error, info, trace};
use num_cpus;
use std::{
    cmp, env, io, process,
    sync::{Arc as SArc, Mutex as SMutex},
};

/// The main application which is central part of communicating with
/// the adbflib, which is closely connected.
fn main() -> io::Result<()> {
    // get start values from the input parser!!!
    let (ui_paths, has_tui, has_webui, has_net, keep_alive, open_browser, web_port, has_ui) =
        command_line::get_start_values();

    // read into paths
    let cleaned_paths = SearchPath::new(&ui_paths);
    if cleaned_paths.len() != ui_paths.len() && !has_tui && !has_webui && !open_browser {
        println!("Some paths/folders intersect and will not be used!");
    }

    // only use the arc
    let search_path = SArc::new(SMutex::new(cleaned_paths));
    let search_path_ui = search_path.clone();

    // define collection thread pool
    let ctrlc_thread = 1;
    let assumed_number_of_threads_used = if has_webui { 1 } else { 0 }
        + if has_tui { 1 } else { 0 }
        + if has_net { 1 } else { 0 }
        + ctrlc_thread;
    let nr_cpus = num_cpus::get();
    let nr_threads_for_collection = if assumed_number_of_threads_used >= nr_cpus {
        1
    } else {
        nr_cpus - assumed_number_of_threads_used
    };
    rayon::ThreadPoolBuilder::new()
        .thread_name(|nr| format!("col_{}", nr))
        .num_threads(nr_threads_for_collection)
        .build_global()
        .unwrap();

    // for synced start of different threads
    let wait_collector = WaitGroup::new();
    let wait_ui = wait_collector.clone();
    let wait_net = wait_collector.clone();

    //
    // prepare the message system
    //
    let (tx, rx) = unbounded::<UiUpdateMsg>();

    // these will be taken directly
    let tx_net = tx.clone();

    // ui message from here (collection)
    let tx_col = tx.clone();

    // for now this will stay wrapped
    let tx_from_collector_to_ui = SArc::new(SMutex::new(tx.clone()));

    // start the logging
    logit::Logit::init(logit::read_env_level(
        &env::var("ADBF_LOG").unwrap_or("".into()),
    ));

    // all optional components are wrapped into threads
    // 1 - UI         ui_thread   (optional)
    // 2 - Net        net_thread  (optional)
    // 3 - Collector  no thread yet (uses multiple rayon worker threads)
    let ui_thread = std::thread::Builder::new()
        .name("ui".into())
        .spawn(move || {
            if has_ui {
                Ctrl::run(
                    key_keeper::get_p2p_server_id(),
                    search_path_ui,
                    rx,
                    has_net,
                    wait_ui,
                    has_webui,
                    has_tui,
                    open_browser,
                    web_port,
                )
            } else {
                info!("no ui was created!");
                drop(wait_ui);
                Ok::<(), std::io::Error>(())
            }
        })?;

    // create a crossbeam channel for massive data exchange
    // with data I called IPC ...
    // in contrast to normal channels crossbeam channels are
    // n:m, so senders can be cloned as well!
    let (ipc_send, ipc_receive) = unbounded::<IPC>();

    // 2 - Net Future
    let net_thread = std::thread::Builder::new()
        .name("net".into())
        .spawn(move || {
            if has_net {
                let sender = Some(tx_net);
                task::block_on(
                    async move { shared::net_search(wait_net, sender, ipc_receive).await },
                )
                .map_err(|error| {
                    std::io::Error::new(
                        std::io::ErrorKind::Other,
                        format!("network error: {}", error),
                    )
                })
            } else {
                info!("no net!");
                drop(wait_net);
                Ok::<(), std::io::Error>(())
            }
        })?;

    // CTRL-C exit handler (is wrapped inside a thread)
    ctrlc::set_handler(move || {
        println!("\n'{}' was manually exited!!!", env!("CARGO_PKG_NAME"));
        process::exit(exitcode::SOFTWARE);
    })
    .map_err(|error| {
        std::io::Error::new(
            std::io::ErrorKind::Other,
            format!(
                "{} terminate signal invokation doesn't work!({:?})",
                env!("CARGO_PKG_NAME"),
                error
            ),
        )
    })?;

    // finished ipc sender reserved before collector takes action
    let ipc_send_finished = ipc_send.clone();

    // the collector
    // but yet this simple bracket to enclose this a little
    {
        trace!("syncing with 2 other threads");
        wait_collector.wait();
        trace!("sync with net and ui done ... collector can start");

        let synced_to_ui_messages = tx_from_collector_to_ui.clone();

        // set up data
        let collection_protected = SArc::new(SMutex::new(Collection::new()));

        // search parallelly
        let output_data = shared::collection_search(
            collection_protected.clone(),
            search_path,
            synced_to_ui_messages,
            has_ui,
        );

        info!("collector finished!!");
        if has_ui || has_net {
            // send own peer and others that are finished
            let memory_used = collection_protected
                .lock()
                .and_then(|collection| Ok(collection.memory()))
                .unwrap_or_else(|_| {
                    error!("locking collection didn't work here!");
                    0
                });

            let mut collection_output = IFCollectionOutputData::from(&output_data);
            // to have not 0 as data size minimum
            collection_output.size_of_data_in_kb = cmp::max(1, (memory_used / 1000) as usize);

            // to others via IPC
            if has_net {
                ipc_send_finished
                    .send(IPC::DoneSearching(collection_output.clone()))
                    .unwrap_or_else(|_| {
                        error!("net has to be up and receiving this send!");
                    });
            }
            // to myself (ui) via UiUpdateMsg
            if has_ui {
                tx_col
                    .send(UiUpdateMsg::PeerSearchFinished(
                        key_keeper::get_p2p_server_id(),
                        collection_output,
                    ))
                    .unwrap_or_else(|e| error!("use one: {}", e));
            }
        }
        if !has_ui {
            collection_protected
                .lock()
                .and_then(|locked_collection| {
                    Ok(locked_collection
                        .print_stats(&key_keeper::get_p2p_server_id(), nr_threads_for_collection))
                })
                .unwrap_or(())
        }
    }

    // look for keeping alive argument if that was chosen
    if keep_alive {
        ui_thread
            .join()
            .unwrap_or_else(|_| {
                // it doesn't matter because we will terminate anyway
                error!("this should be result of ui thread!!");
                Ok(())
            })
            .unwrap();
        if has_ui {
            info!("Stopped ui thread");
        }
        // net thread
        if has_ui {
            // if had a ui , net_thread will stop also after ui quit
            drop(net_thread);
        } else {
            // if didn't have ui, net_thread will continue running
            println!(
                "Search is finished, but net thread is kept running!\nTo stop send break command (ctrl-c)!"
            );
            net_thread
                .join()
                .unwrap_or_else(|_| {
                    // it doesn't matter because we will terminate anyway
                    error!("is this normal when joining net thread???");
                    Ok(())
                })
                .unwrap();
            info!("Stopped net thread");
        }
    } else {
        drop(net_thread);
        drop(ui_thread);
    }
    Ok(())
}
<|endoftext|>


<commit_before>use std::string::String;
use std::vec::Vec;
use std::io::TcpStream;

pub struct Clients
{
    destinations: Vec<String>,
}

pub trait ClientFunction
{
    fn new() -> Clients;
    fn add_client(&mut self, ip: String, port: String);
    fn remove_client(&mut self, index: uint);
    fn send_message(&mut self, message: String);
}

impl ClientFunction for Clients
{
    fn new() -> Clients
    {
        return Clients{destinations: Vec::new()};
    }

    fn add_client(&mut self, ip: String, port: String)
    {
        let mut port_ip = String::new();
        port_ip.push_str(ip.as_slice());
        port_ip.push_str(":");
        port_ip.push_str(port.as_slice());
        self.destinations.push(port_ip);
    }

    fn remove_client(&mut self, index: uint)
    {
        self.destinations.remove(index);
    }

    fn send_message(&mut self, message: String)
    {
        for dest in self.destinations.iter()
        {
            let mut tcp_stream = TcpStream::connect(dest.as_slice()).unwrap();
            let _ = tcp_stream.write(message.as_bytes());
        }
    }
}
<commit_msg>replaced usize.  Need to silence warnings.<commit_after>use std::string::String;
use std::vec::Vec;
use std::io::TcpStream;

pub struct Clients
{
    destinations: Vec<String>,
}

pub trait ClientFunction
{
    fn new() -> Clients;
    fn add_client(&mut self, ip: String, port: String);
    fn remove_client(&mut self, index: usize);
    fn send_message(&mut self, message: String);
}

impl ClientFunction for Clients
{
    fn new() -> Clients
    {
        return Clients{destinations: Vec::new()};
    }

    fn add_client(&mut self, ip: String, port: String)
    {
        let mut port_ip = String::new();
        port_ip.push_str(ip.as_slice());
        port_ip.push_str(":");
        port_ip.push_str(port.as_slice());
        self.destinations.push(port_ip);
    }

    fn remove_client(&mut self, index: usize)
    {
        self.destinations.remove(index);
    }

    fn send_message(&mut self, message: String)
    {
        for dest in self.destinations.iter()
        {
            let mut tcp_stream = TcpStream::connect(dest.as_slice()).unwrap();
            let _ = tcp_stream.write(message.as_bytes());
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code, unused_imports)]
use super::*;
use std::env;

const ENV_KEY: &str = "PROXER_API_KEY";

#[test]
fn api_response()
{
	// is the api structured as we want it to be?
	let client = Client::with_env_key(ENV_KEY).unwrap();

	let req = client
		.api()
		.info()
		.get_fullentry(parameter::InfoGetFullEntry { id: 53 });

	let res = client.execute(req);

	eprintln!();

	match res
	{
		Err(e) => {
			match e
			{
				error::Error::Api(e) => {
					match e.error()
					{
						error::api::Errcode::NoApiPermissions => return,
						_ => panic!("this error is not expected"),
					}
				}
				error::Error::Json(e) => panic!("can't parse json: {}", e),
				error::Error::Unknown => panic!("unknown error"),
				_ => return,
			}
		}

		Ok(r) => {
			assert_eq!(r.medium, "animeseries");
		}
	}
}
<commit_msg>print error on fail<commit_after>#![allow(dead_code, unused_imports)]
use super::*;
use std::env;

const ENV_KEY: &str = "PROXER_API_KEY";

#[test]
fn api_response()
{
	// is the api structured as we want it to be?
	let client = Client::with_env_key(ENV_KEY).unwrap();

	let req = client
		.api()
		.info()
		.get_fullentry(parameter::InfoGetFullEntry { id: 53 });

	let res = client.execute(req);

	eprintln!();

	match res
	{
		Err(e) => {
			match e
			{
				error::Error::Api(e) => {
					match e.error()
					{
						error::api::Errcode::NoApiPermissions => return,
						_ => panic!("this error is not expected: {}", e),
					}
				}
				error::Error::Json(e) => panic!("can't parse json: {}", e),
				error::Error::Unknown => panic!("unknown error"),
				_ => return,
			}
		}

		Ok(r) => {
			assert_eq!(r.medium, "animeseries");
		}
	}
}
<|endoftext|>