<commit_before>// Copyright 2018 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.

//! Private part of the Exonum REST API.
//!
//! Private API includes requests that are available only to the blockchain
//! administrators, e.g. view the list of services on the current node.

use std::{collections::HashMap, net::SocketAddr};

use api::{Error as ApiError, ServiceApiScope, ServiceApiState};
use blockchain::{Service, SharedNodeState};
use crypto::PublicKey;
use messages::PROTOCOL_MAJOR_VERSION;
use node::{ConnectInfo, ExternalMessage};

/// Short information about the service.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct ServiceInfo {
    /// Service name.
    pub name: String,
    /// Service identifier for database schema and service messages.
    pub id: u16,
}

/// Short information about the current node.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct NodeInfo {
    /// Version of the `exonum` crate.
    pub core_version: Option<String>,
    /// Version of the Exonum protocol.
    pub protocol_version: u8,
    /// List of services.
    pub services: Vec<ServiceInfo>,
}

impl NodeInfo {
    /// Creates new `NodeInfo` from services list.
    pub fn new<'a, I>(services: I) -> Self
    where
        I: IntoIterator<Item = &'a Box<dyn Service>>,
    {
        let core_version = option_env!("CARGO_PKG_VERSION").map(|ver| ver.to_owned());
        Self {
            core_version,
            protocol_version: PROTOCOL_MAJOR_VERSION,
            services: services
                .into_iter()
                .map(|s| ServiceInfo {
                    name: s.service_name().to_owned(),
                    id: s.service_id(),
                }).collect(),
        }
    }
}

#[derive(Serialize, Deserialize, Default)]
struct ReconnectInfo {
    delay: u64,
}

#[derive(Serialize, Deserialize)]
#[serde(tag = "type")]
enum IncomingConnectionState {
    Active,
    Reconnect(ReconnectInfo),
}

impl Default for IncomingConnectionState {
    fn default() -> Self {
        IncomingConnectionState::Active
    }
}

#[derive(Serialize, Deserialize, Default)]
struct IncomingConnection {
    public_key: Option<PublicKey>,
    state: IncomingConnectionState,
}

#[derive(Serialize, Deserialize)]
struct PeersInfo {
    incoming_connections: Vec<ConnectInfo>,
    outgoing_connections: HashMap<SocketAddr, IncomingConnection>,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
struct ConsensusEnabledQuery {
    enabled: bool,
}

/// Private system API.
#[derive(Clone, Debug)]
pub struct SystemApi {
    info: NodeInfo,
    shared_api_state: SharedNodeState,
}

impl SystemApi {
    /// Creates a new `private::SystemApi` instance.
    pub fn new(info: NodeInfo, shared_api_state: SharedNodeState) -> Self {
        Self {
            info,
            shared_api_state,
        }
    }

    /// Adds private system API endpoints to the corresponding scope.
    pub fn wire(self, api_scope: &mut ServiceApiScope) -> &mut ServiceApiScope {
        self.handle_peers_info("v1/peers", api_scope)
            .handle_peer_add("v1/peers", api_scope)
            .handle_network_info("v1/network", api_scope)
            .handle_is_consensus_enabled("v1/consensus_enabled", api_scope)
            .handle_set_consensus_enabled("v1/consensus_enabled", api_scope)
            .handle_shutdown("v1/shutdown", api_scope)
            .handle_rebroadcast("v1/rebroadcast", api_scope);
        api_scope
    }

    fn handle_peers_info(self, name: &'static str, api_scope: &mut ServiceApiScope) -> Self {
        let self_ = self.clone();
        api_scope.endpoint(name, move |_state: &ServiceApiState, _query: ()| {
            let mut outgoing_connections: HashMap<SocketAddr, IncomingConnection> = HashMap::new();

            for connect_info in self.shared_api_state.outgoing_connections() {
                outgoing_connections.insert(
                    connect_info.address.parse().unwrap(),
                    IncomingConnection {
                        public_key: Some(connect_info.public_key),
                        state: Default::default(),
                    },
                );
            }

            info!(
                "shared_api_state.reconnects_timeout() {:?}",
                self.shared_api_state.reconnects_timeout()
            );

            for (s, delay) in self.shared_api_state.reconnects_timeout() {
                outgoing_connections
                    .entry(s)
                    .or_insert_with(Default::default)
                    .state = IncomingConnectionState::Reconnect(ReconnectInfo { delay });
            }

            Ok(PeersInfo {
                incoming_connections: self.shared_api_state.incoming_connections(),
                outgoing_connections,
            })
        });
        self_
    }

    fn handle_peer_add(self, name: &'static str, api_scope: &mut ServiceApiScope) -> Self {
        api_scope.endpoint_mut(
            name,
            move |state: &ServiceApiState, connect_info: ConnectInfo| {
                state
                    .sender()
                    .peer_add(connect_info)
                    .map_err(ApiError::from)
            },
        );
        self
    }

    fn handle_network_info(self, name: &'static str, api_scope: &mut ServiceApiScope) -> Self {
        let self_ = self.clone();
        api_scope.endpoint(name, move |_state: &ServiceApiState, _query: ()| {
            Ok(self.info.clone())
        });
        self_
    }

    fn handle_is_consensus_enabled(
        self,
        name: &'static str,
        api_scope: &mut ServiceApiScope,
    ) -> Self {
        let self_ = self.clone();
        api_scope.endpoint(name, move |_state: &ServiceApiState, _query: ()| {
            Ok(self.shared_api_state.is_enabled())
        });
        self_
    }

    fn handle_set_consensus_enabled(
        self,
        name: &'static str,
        api_scope: &mut ServiceApiScope,
    ) -> Self {
        let self_ = self.clone();
        api_scope.endpoint_mut(
            name,
            move |state: &ServiceApiState, query: ConsensusEnabledQuery| {
                state
                    .sender()
                    .send_external_message(ExternalMessage::Enable(query.enabled))
                    .map_err(ApiError::from)
            },
        );
        self_
    }

    fn handle_shutdown(self, name: &'static str, api_scope: &mut ServiceApiScope) -> Self {
        api_scope.endpoint_mut(name, move |state: &ServiceApiState, _query: ()| {
            state
                .sender()
                .send_external_message(ExternalMessage::Shutdown)
                .map_err(ApiError::from)
        });
        self
    }

    fn handle_rebroadcast(self, name: &'static str, api_scope: &mut ServiceApiScope) -> Self {
        api_scope.endpoint_mut(name, move |state: &ServiceApiState, _query: ()| {
            state
                .sender()
                .send_external_message(ExternalMessage::Rebroadcast)
                .map_err(ApiError::from)
        });
        self
    }
}
<commit_msg>Remove unused logs from API. (#1092)<commit_after>// Copyright 2018 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.

//! Private part of the Exonum REST API.
//!
//! Private API includes requests that are available only to the blockchain
//! administrators, e.g. view the list of services on the current node.

use std::{collections::HashMap, net::SocketAddr};

use api::{Error as ApiError, ServiceApiScope, ServiceApiState};
use blockchain::{Service, SharedNodeState};
use crypto::PublicKey;
use messages::PROTOCOL_MAJOR_VERSION;
use node::{ConnectInfo, ExternalMessage};

/// Short information about the service.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct ServiceInfo {
    /// Service name.
    pub name: String,
    /// Service identifier for database schema and service messages.
    pub id: u16,
}

/// Short information about the current node.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct NodeInfo {
    /// Version of the `exonum` crate.
    pub core_version: Option<String>,
    /// Version of the Exonum protocol.
    pub protocol_version: u8,
    /// List of services.
    pub services: Vec<ServiceInfo>,
}

impl NodeInfo {
    /// Creates new `NodeInfo` from services list.
    pub fn new<'a, I>(services: I) -> Self
    where
        I: IntoIterator<Item = &'a Box<dyn Service>>,
    {
        let core_version = option_env!("CARGO_PKG_VERSION").map(|ver| ver.to_owned());
        Self {
            core_version,
            protocol_version: PROTOCOL_MAJOR_VERSION,
            services: services
                .into_iter()
                .map(|s| ServiceInfo {
                    name: s.service_name().to_owned(),
                    id: s.service_id(),
                }).collect(),
        }
    }
}

#[derive(Serialize, Deserialize, Default)]
struct ReconnectInfo {
    delay: u64,
}

#[derive(Serialize, Deserialize)]
#[serde(tag = "type")]
enum IncomingConnectionState {
    Active,
    Reconnect(ReconnectInfo),
}

impl Default for IncomingConnectionState {
    fn default() -> Self {
        IncomingConnectionState::Active
    }
}

#[derive(Serialize, Deserialize, Default)]
struct IncomingConnection {
    public_key: Option<PublicKey>,
    state: IncomingConnectionState,
}

#[derive(Serialize, Deserialize)]
struct PeersInfo {
    incoming_connections: Vec<ConnectInfo>,
    outgoing_connections: HashMap<SocketAddr, IncomingConnection>,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
struct ConsensusEnabledQuery {
    enabled: bool,
}

/// Private system API.
#[derive(Clone, Debug)]
pub struct SystemApi {
    info: NodeInfo,
    shared_api_state: SharedNodeState,
}

impl SystemApi {
    /// Creates a new `private::SystemApi` instance.
    pub fn new(info: NodeInfo, shared_api_state: SharedNodeState) -> Self {
        Self {
            info,
            shared_api_state,
        }
    }

    /// Adds private system API endpoints to the corresponding scope.
    pub fn wire(self, api_scope: &mut ServiceApiScope) -> &mut ServiceApiScope {
        self.handle_peers_info("v1/peers", api_scope)
            .handle_peer_add("v1/peers", api_scope)
            .handle_network_info("v1/network", api_scope)
            .handle_is_consensus_enabled("v1/consensus_enabled", api_scope)
            .handle_set_consensus_enabled("v1/consensus_enabled", api_scope)
            .handle_shutdown("v1/shutdown", api_scope)
            .handle_rebroadcast("v1/rebroadcast", api_scope);
        api_scope
    }

    fn handle_peers_info(self, name: &'static str, api_scope: &mut ServiceApiScope) -> Self {
        let self_ = self.clone();
        api_scope.endpoint(name, move |_state: &ServiceApiState, _query: ()| {
            let mut outgoing_connections: HashMap<SocketAddr, IncomingConnection> = HashMap::new();

            for connect_info in self.shared_api_state.outgoing_connections() {
                outgoing_connections.insert(
                    connect_info.address.parse().unwrap(),
                    IncomingConnection {
                        public_key: Some(connect_info.public_key),
                        state: Default::default(),
                    },
                );
            }

            for (s, delay) in self.shared_api_state.reconnects_timeout() {
                outgoing_connections
                    .entry(s)
                    .or_insert_with(Default::default)
                    .state = IncomingConnectionState::Reconnect(ReconnectInfo { delay });
            }

            Ok(PeersInfo {
                incoming_connections: self.shared_api_state.incoming_connections(),
                outgoing_connections,
            })
        });
        self_
    }

    fn handle_peer_add(self, name: &'static str, api_scope: &mut ServiceApiScope) -> Self {
        api_scope.endpoint_mut(
            name,
            move |state: &ServiceApiState, connect_info: ConnectInfo| {
                state
                    .sender()
                    .peer_add(connect_info)
                    .map_err(ApiError::from)
            },
        );
        self
    }

    fn handle_network_info(self, name: &'static str, api_scope: &mut ServiceApiScope) -> Self {
        let self_ = self.clone();
        api_scope.endpoint(name, move |_state: &ServiceApiState, _query: ()| {
            Ok(self.info.clone())
        });
        self_
    }

    fn handle_is_consensus_enabled(
        self,
        name: &'static str,
        api_scope: &mut ServiceApiScope,
    ) -> Self {
        let self_ = self.clone();
        api_scope.endpoint(name, move |_state: &ServiceApiState, _query: ()| {
            Ok(self.shared_api_state.is_enabled())
        });
        self_
    }

    fn handle_set_consensus_enabled(
        self,
        name: &'static str,
        api_scope: &mut ServiceApiScope,
    ) -> Self {
        let self_ = self.clone();
        api_scope.endpoint_mut(
            name,
            move |state: &ServiceApiState, query: ConsensusEnabledQuery| {
                state
                    .sender()
                    .send_external_message(ExternalMessage::Enable(query.enabled))
                    .map_err(ApiError::from)
            },
        );
        self_
    }

    fn handle_shutdown(self, name: &'static str, api_scope: &mut ServiceApiScope) -> Self {
        api_scope.endpoint_mut(name, move |state: &ServiceApiState, _query: ()| {
            state
                .sender()
                .send_external_message(ExternalMessage::Shutdown)
                .map_err(ApiError::from)
        });
        self
    }

    fn handle_rebroadcast(self, name: &'static str, api_scope: &mut ServiceApiScope) -> Self {
        api_scope.endpoint_mut(name, move |state: &ServiceApiState, _query: ()| {
            state
                .sender()
                .send_external_message(ExternalMessage::Rebroadcast)
                .map_err(ApiError::from)
        });
        self
    }
}
<|endoftext|>


<commit_before>use super::*;

impl Editor {
    /// Go to next char
    pub fn next(&mut self) {
        // TODO: Add numerals
        if self.x() == self.text[self.y()].len() {
            if self.y() >= self.text.len() {
                self.text.push_back(VecDeque::new())
            }
            if self.y() < self.text.len() - 1 {
                self.cursor_mut().x = 0;
                self.cursor_mut().y += 1;
            }
        } else {
            self.cursor_mut().x += 1;
        }
    }

    /// Go to previous char
    pub fn previous(&mut self) {
        if self.x() == 0 {
            if self.y() > 0 {
                self.cursor_mut().y -= 1;
                self.cursor_mut().x = self.text[self.y()].len();
            }
        } else {
            self.cursor_mut().x -= 1;
        }
    }

    /// Go right
    pub fn right(&mut self, n: usize) {
        let x = self.x() + n;
        let y = self.y();

        let text = self.text.clone();
        let curs = self.cursor_mut();

        curs.x += n;

        if x > text[y].len() {
            curs.x = text[y].len();
        }
    }

    /// Go left
    pub fn left(&mut self, n: usize) {
        let x = self.x();
        let y = self.y();

        let text = self.text.clone();
        let curs = self.cursor_mut();

        if n <= x {
            curs.x = x - n;
        } else {
            curs.x = 0;
        }

    }

    /// Go up
    pub fn up(&mut self, n: usize) {
        let y = self.y();
        let curs = self.cursor_mut();
        if n <= y {
            curs.y -= n;
        } else {
            curs.y = 0;
        }
    }

    /// Go down
    pub fn down(&mut self, n: usize) {
        let x = self.x();
        let y = self.y() + n;

        let text = self.text.clone();
        let curs = self.cursor_mut();

        curs.y += n;

        if y >= text.len() {
            curs.y = text.len() - 1;
        }
    }
}
<commit_msg>Refactor into methods returning the position<commit_after>use super::*;

impl Editor {
    /// Get pos of next char
    pub fn next_pos(&mut self) -> (usize, usize) {
        // TODO: Add numerals
        if self.x() == self.text[self.y()].len() {
            if self.y() < self.text.len() - 1 {
                (0, self.y() + 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() + 1, self.y())
        }
    }

    /// Get pos of previous char
    pub fn previous_pos(&mut self) -> (usize, usize) {
        if self.x() == 0 {
            if self.y() > 0 {
                (self.text[self.y()].len(), self.y() - 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() - 1, self.y())
        }
    }

    pub fn next(&mut self) {
        let (x, y) = self.next_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }
    pub fn previous(&mut self) {
        let (x, y) = self.previous_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

    /// Go right
    pub fn right(&mut self, n: usize) {
        let x = self.x() + n;
        let y = self.y();

        let text = self.text.clone();
        let curs = self.cursor_mut();

        curs.x += n;

        if x > text[y].len() {
            curs.x = text[y].len();
        }
    }

    /// Go left
    pub fn left(&mut self, n: usize) {
        let x = self.x();
        let y = self.y();

        let text = self.text.clone();
        let curs = self.cursor_mut();

        if n <= x {
            curs.x = x - n;
        } else {
            curs.x = 0;
        }

    }

    /// Go up
    pub fn up(&mut self, n: usize) {
        let y = self.y();
        let curs = self.cursor_mut();
        if n <= y {
            curs.y -= n;
        } else {
            curs.y = 0;
        }
    }

    /// Go down
    pub fn down(&mut self, n: usize) {
        let x = self.x();
        let y = self.y() + n;

        let text = self.text.clone();
        let curs = self.cursor_mut();

        curs.y += n;

        if y >= text.len() {
            curs.y = text.len() - 1;
        }
    }
}
<|endoftext|>


<commit_before>use Model;
use linear_algebra::Vector;
use num::{Float, One};
use std::marker::PhantomData;

/// Models the target as `c`
///
/// This model predicts a number. The cost function used during training decides
/// wether this number is a mean, median or something else.
///
/// # Examples
///
/// Estimate mean
///
/// ```
/// use vikos::model::Constant;
/// use vikos::cost::LeastSquares;
/// use vikos::gradient_descent_step;
///
/// let history = [1f64, 3.0, 4.0, 7.0, 8.0, 11.0, 29.0]; //mean is 9
/// let cost = LeastSquares{};
/// let mut model = Constant::new(0.0);
///
/// let learning_rate_start = 0.4;
/// let learning_rate_stop = 0.001;
/// let num_steps = 60;
///
/// let learning_rate_gradient = (learning_rate_start - learning_rate_stop) / (num_steps as f64);
///
/// for (count_step, &truth) in history.iter().cycle().take(num_steps).enumerate(){
///
///     let adapted_learning_rate = learning_rate_stop + learning_rate_gradient * (num_steps - count_step) as f64;
///     gradient_descent_step(&cost, & mut model, &(), truth, adapted_learning_rate);
/// }
/// ```
#[derive(Debug)]
pub struct Constant<Input>{
    /// Any prediction made by this model will have the value of `c`
    pub c: f64,
    _phantom: PhantomData<Input>
}

impl<I> Constant<I> {
    /// Creates a new Constant from a `f64`
    pub fn new(c: f64) -> Constant<I>{
        Constant{c: c, _phantom: PhantomData::<I>{}}
    }
}

impl<I> Clone for Constant<I>{
    fn clone(&self) -> Self{
        Constant::new(self.c)
    }
}

impl<I> Model for Constant<I>{
    type Input = I;
    type Target = f64;

    fn predict(&self, _: &I) -> f64{
        self.c
    }

    fn num_coefficents(&self) -> usize{
        1
    }

    fn gradient(&self, coefficent : usize, _ : &I) -> f64{
        match coefficent{
            0 => 1.0,
            _ => panic!("coefficent index out of range")
        }
    }

    fn coefficent(& mut self, coefficent : usize) -> & mut f64{
        match coefficent{
            0 => & mut self.c,
            _ => panic!("coefficent index out of range")
        }
    }
}

/// Models the target as `y = m * x + c`
#[derive(Debug, Clone)]
pub struct Linear<V : Vector>{
    /// Slope
    pub m : V,
    /// Offset
    pub c : V::Scalar
}

impl<V : Vector> Model for Linear<V> where V::Scalar : Float{

    type Input = V;
    type Target = V::Scalar;

    fn predict(&self, input : &V) -> V::Scalar{
        self.m.dot(input) + self.c
    }

    fn num_coefficents(&self) -> usize{
        self.m.dimension() + 1
    }

    fn gradient(&self, coefficent : usize, input : &V) -> V::Scalar{

        use num::One;

        if coefficent == self.m.dimension(){
            V::Scalar::one() //c
        } else {
            input.at(coefficent)
        }
    }

    fn coefficent(& mut self, coefficent : usize) -> & mut V::Scalar{
        if coefficent == self.m.dimension(){
            & mut self.c
        } else {
            self.m.mut_at(coefficent)
        }
    }
}

/// Models target as `y = 1/1+e^(m * x + c)`
#[derive(Clone)]
pub struct Logicstic<V: Vector>{
    /// Linear term of `Logistic` model
    pub linear : Linear<V>
}

impl<V : Vector> Model for Logicstic<V> where V::Scalar : Float{
    type Input = V;
    type Target = V::Scalar;

    fn predict(&self, input : &V) -> V::Scalar{
        V::Scalar::one() / (V::Scalar::one() + self.linear.predict(input).exp())
    }

    fn num_coefficents(&self) -> usize{
        self.linear.num_coefficents()
    }

    fn gradient(&self, coefficent : usize, input : &V) -> V::Scalar{
        let p = self.predict(input);
        - p * (V::Scalar::one() - p) * self.linear.gradient(coefficent, input)
    }

    fn coefficent(& mut self, coefficent : usize) -> & mut V::Scalar{
        self.linear.coefficent(coefficent)
    }
}<commit_msg>removed typo from logistic model<commit_after>use Model;
use linear_algebra::Vector;
use num::{Float, One};
use std::marker::PhantomData;

/// Models the target as `c`
///
/// This model predicts a number. The cost function used during training decides
/// wether this number is a mean, median or something else.
///
/// # Examples
///
/// Estimate mean
///
/// ```
/// use vikos::model::Constant;
/// use vikos::cost::LeastSquares;
/// use vikos::gradient_descent_step;
///
/// let history = [1f64, 3.0, 4.0, 7.0, 8.0, 11.0, 29.0]; //mean is 9
/// let cost = LeastSquares{};
/// let mut model = Constant::new(0.0);
///
/// let learning_rate_start = 0.4;
/// let learning_rate_stop = 0.001;
/// let num_steps = 60;
///
/// let learning_rate_gradient = (learning_rate_start - learning_rate_stop) / (num_steps as f64);
///
/// for (count_step, &truth) in history.iter().cycle().take(num_steps).enumerate(){
///
///     let adapted_learning_rate = learning_rate_stop + learning_rate_gradient * (num_steps - count_step) as f64;
///     gradient_descent_step(&cost, & mut model, &(), truth, adapted_learning_rate);
/// }
/// ```
#[derive(Debug)]
pub struct Constant<Input>{
    /// Any prediction made by this model will have the value of `c`
    pub c: f64,
    _phantom: PhantomData<Input>
}

impl<I> Constant<I> {
    /// Creates a new Constant from a `f64`
    pub fn new(c: f64) -> Constant<I>{
        Constant{c: c, _phantom: PhantomData::<I>{}}
    }
}

impl<I> Clone for Constant<I>{
    fn clone(&self) -> Self{
        Constant::new(self.c)
    }
}

impl<I> Model for Constant<I>{
    type Input = I;
    type Target = f64;

    fn predict(&self, _: &I) -> f64{
        self.c
    }

    fn num_coefficents(&self) -> usize{
        1
    }

    fn gradient(&self, coefficent : usize, _ : &I) -> f64{
        match coefficent{
            0 => 1.0,
            _ => panic!("coefficent index out of range")
        }
    }

    fn coefficent(& mut self, coefficent : usize) -> & mut f64{
        match coefficent{
            0 => & mut self.c,
            _ => panic!("coefficent index out of range")
        }
    }
}

/// Models the target as `y = m * x + c`
#[derive(Debug, Clone)]
pub struct Linear<V : Vector>{
    /// Slope
    pub m : V,
    /// Offset
    pub c : V::Scalar
}

impl<V : Vector> Model for Linear<V> where V::Scalar : Float{

    type Input = V;
    type Target = V::Scalar;

    fn predict(&self, input : &V) -> V::Scalar{
        self.m.dot(input) + self.c
    }

    fn num_coefficents(&self) -> usize{
        self.m.dimension() + 1
    }

    fn gradient(&self, coefficent : usize, input : &V) -> V::Scalar{

        use num::One;

        if coefficent == self.m.dimension(){
            V::Scalar::one() //c
        } else {
            input.at(coefficent)
        }
    }

    fn coefficent(& mut self, coefficent : usize) -> & mut V::Scalar{
        if coefficent == self.m.dimension(){
            & mut self.c
        } else {
            self.m.mut_at(coefficent)
        }
    }
}

/// Models target as `y = 1/1+e^(m * x + c)`
#[derive(Clone)]
pub struct Logistic<V: Vector>{
    /// Linear term of `Logistic` model
    pub linear : Linear<V>
}

impl<V : Vector> Model for Logistic<V> where V::Scalar : Float{
    type Input = V;
    type Target = V::Scalar;

    fn predict(&self, input : &V) -> V::Scalar{
        V::Scalar::one() / (V::Scalar::one() + self.linear.predict(input).exp())
    }

    fn num_coefficents(&self) -> usize{
        self.linear.num_coefficents()
    }

    fn gradient(&self, coefficent : usize, input : &V) -> V::Scalar{
        let p = self.predict(input);
        - p * (V::Scalar::one() - p) * self.linear.gradient(coefficent, input)
    }

    fn coefficent(& mut self, coefficent : usize) -> & mut V::Scalar{
        self.linear.coefficent(coefficent)
    }
}<|endoftext|>


<commit_before>use pb::ProgressBar;
use std::str::from_utf8;
use tty::move_cursor_up;
use std::io::{Stdout, Result, Write};
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};

pub struct MultiBar<T: Write> {
    nlines: usize,

    lines: Vec<String>,

    nbars: usize,

    chan: (Sender<WriteMsg>, Receiver<WriteMsg>),

    handle: T,
}

impl MultiBar<Stdout> {
    /// Create a new MultiBar with stdout as a writer.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::thread;
    /// use pbr::MultiBar;
    ///
    /// let mut mb = MultiBar::new();
    /// mb.println("Application header:");
    ///
    /// let mut p1 = mb.create_bar(count);
    /// let _ = thread::spawn(move || {
    ///     for _ in 0..count {
    ///         p1.inc();
    ///         thread::sleep(Duration::from_millis(100));
    ///     }
    ///     // notify the multibar that this bar finished.
    ///     p1.finish();
    /// });
    ///
    /// mb.println("add a separator between the two bars");
    ///
    /// let mut p2 = mb.create_bar(count * 2);
    /// let _ = thread::spawn(move || {
    ///     for _ in 0..count * 2 {
    ///         p2.inc();
    ///         thread::sleep(Duration::from_millis(100));
    ///     }
    ///     // notify the multibar that this bar finished.
    ///     p2.finish();
    /// });
    ///
    /// // start listen to all bars changes.
    /// // this is a blocking operation, until all bars will finish.
    /// // to ignore blocking, you can run it in a different thread.
    /// mb.listen();
    /// ```
    pub fn new() -> MultiBar<Stdout> {
        MultiBar::on(::std::io::stdout())
    }
}

impl<T: Write> MultiBar<T> {
    /// Create a new MultiBar with an arbitrary writer.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use pbr::MultiBar;
    /// use std::io::stderr;
    ///
    /// let mut mb = MultiBar::on(stderr());
    /// // ...
    /// // see full example in `MultiBar::new`
    /// // ...
    /// ```
    pub fn on(handle: T) -> MultiBar<T> {
        MultiBar {
            nlines: 0,
            nbars: 0,
            lines: Vec::new(),
            chan: mpsc::channel(),
            handle: handle,
        }
    }

    /// println used to add text lines between the bars.
    /// for example: you could add a header to your application,
    /// or text separators between bars.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use pbr::MultiBar;
    ///
    /// let mut mb = MultiBar::new();
    /// mb.println("Application header:");
    ///
    /// let mut p1 = MultiBar::create_bar(count);
    /// // ...
    ///
    /// mb.println("Text line between bar1 and bar2");
    ///
    /// let mut p2 = MultiBar::create_bar(count);
    /// // ...
    ///
    /// mb.println("Text line between bar2 and bar3");
    ///
    /// // ...
    /// // ...
    /// mb.listen();
    /// ```
    pub fn println(&mut self, s: &str) {
        self.lines.push(s.to_owned());
        self.nlines += 1;
    }

    /// create_bar creates new `ProgressBar` with `Pipe` as the writer.
    ///
    /// The ordering of the method calls is important. it means that in
    /// the first call, you get a progress bar in level 1, in the 2nd call,
    /// you get a progress bar in level 2, and so on.
    ///
    /// ProgressBar that finish its work, must call `finish()` (or `finish_print`)
    /// to notify the `MultiBar` about it.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use pbr::MultiBar;
    ///
    /// let mut mb = MultiBar::new();
    ///
    /// // progress bar in level 1
    /// let mut p1 = MultiBar::create_bar(count1);
    /// // ...
    ///
    /// // progress bar in level 2
    /// let mut p2 = MultiBar::create_bar(count2);
    /// // ...
    ///
    /// // progress bar in level 3
    /// let mut p3 = MultiBar::create_bar(count3);
    ///
    /// // ...
    /// mb.listen();
    /// ```
    pub fn create_bar(&mut self, total: u64) -> ProgressBar<Pipe> {
        self.println("");
        self.nbars += 1;
        let mut p = ProgressBar::on(Pipe {
                                        level: self.nlines - 1,
                                        chan: self.chan.0.clone(),
                                    },
                                    total);
        p.is_multibar = true;
        p.add(0);
        p
    }

    /// listen start listen to all bars changes.
    ///
    /// `ProgressBar` that finish its work, must call `finish()` (or `finish_print`)
    /// to notify the `MultiBar` about it.
    ///
    /// This is a blocking operation and blocks until all bars will
    /// finish.
    /// To ignore blocking, you can run it in a different thread.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use pbr::MultiBar;
    ///
    /// let mut mb = MultiBar::new();
    ///
    /// // ...
    /// // create some bars here
    /// // ...
    ///
    /// thread::spawn(move || {
    ///     mb.listen();
    ///     println!("all bars done!");
    /// });
    ///
    /// // ...
    /// ```
    pub fn listen(&mut self) {
        let mut first = true;
        let mut nbars = self.nbars;
        while nbars > 0 {

            // receive message
            let msg = self.chan.1.recv().unwrap();
            if msg.done {
                nbars -= 1;
                continue;
            }
            self.lines[msg.level] = msg.string;

            // and draw
            let mut out = String::new();
            if !first {
                out += &move_cursor_up(self.nlines);
            } else {
                first = false;
            }
            for l in self.lines.iter() {
                out.push_str(&format!("\r{}\n", l));
            }
            printfl!(self.handle, "{}", out);
        }
    }
}

pub struct Pipe {
    level: usize,
    chan: Sender<WriteMsg>,
}

impl Write for Pipe {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let s = from_utf8(buf).unwrap().to_owned();
        self.chan
            .send(WriteMsg {
                // finish method emit empty string
                done: s == "",
                level: self.level,
                string: s,
            })
            .unwrap();
        Ok(1)
    }

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

// WriteMsg is the message format used to communicate
// between MultiBar and its bars
struct WriteMsg {
    done: bool,
    level: usize,
    string: String,
}
<commit_msg>Fix doctests<commit_after>use pb::ProgressBar;
use std::str::from_utf8;
use tty::move_cursor_up;
use std::io::{Stdout, Result, Write};
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};

pub struct MultiBar<T: Write> {
    nlines: usize,

    lines: Vec<String>,

    nbars: usize,

    chan: (Sender<WriteMsg>, Receiver<WriteMsg>),

    handle: T,
}

impl MultiBar<Stdout> {
    /// Create a new MultiBar with stdout as a writer.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::thread;
    /// use pbr::MultiBar;
    /// use std::time::Duration;
    ///
    /// let mut mb = MultiBar::new();
    /// mb.println("Application header:");
    ///
    /// # let count = 250;
    /// let mut p1 = mb.create_bar(count);
    /// let _ = thread::spawn(move || {
    ///     for _ in 0..count {
    ///         p1.inc();
    ///         thread::sleep(Duration::from_millis(100));
    ///     }
    ///     // notify the multibar that this bar finished.
    ///     p1.finish();
    /// });
    ///
    /// mb.println("add a separator between the two bars");
    ///
    /// let mut p2 = mb.create_bar(count * 2);
    /// let _ = thread::spawn(move || {
    ///     for _ in 0..count * 2 {
    ///         p2.inc();
    ///         thread::sleep(Duration::from_millis(100));
    ///     }
    ///     // notify the multibar that this bar finished.
    ///     p2.finish();
    /// });
    ///
    /// // start listen to all bars changes.
    /// // this is a blocking operation, until all bars will finish.
    /// // to ignore blocking, you can run it in a different thread.
    /// mb.listen();
    /// ```
    pub fn new() -> MultiBar<Stdout> {
        MultiBar::on(::std::io::stdout())
    }
}

impl<T: Write> MultiBar<T> {
    /// Create a new MultiBar with an arbitrary writer.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use pbr::MultiBar;
    /// use std::io::stderr;
    ///
    /// let mut mb = MultiBar::on(stderr());
    /// // ...
    /// // see full example in `MultiBar::new`
    /// // ...
    /// ```
    pub fn on(handle: T) -> MultiBar<T> {
        MultiBar {
            nlines: 0,
            nbars: 0,
            lines: Vec::new(),
            chan: mpsc::channel(),
            handle: handle,
        }
    }

    /// println used to add text lines between the bars.
    /// for example: you could add a header to your application,
    /// or text separators between bars.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use pbr::MultiBar;
    ///
    /// let mut mb = MultiBar::new();
    /// mb.println("Application header:");
    ///
    /// # let count = 250;
    /// let mut p1 = mb.create_bar(count);
    /// // ...
    ///
    /// mb.println("Text line between bar1 and bar2");
    ///
    /// let mut p2 = mb.create_bar(count);
    /// // ...
    ///
    /// mb.println("Text line between bar2 and bar3");
    ///
    /// // ...
    /// // ...
    /// mb.listen();
    /// ```
    pub fn println(&mut self, s: &str) {
        self.lines.push(s.to_owned());
        self.nlines += 1;
    }

    /// create_bar creates new `ProgressBar` with `Pipe` as the writer.
    ///
    /// The ordering of the method calls is important. it means that in
    /// the first call, you get a progress bar in level 1, in the 2nd call,
    /// you get a progress bar in level 2, and so on.
    ///
    /// ProgressBar that finish its work, must call `finish()` (or `finish_print`)
    /// to notify the `MultiBar` about it.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use pbr::MultiBar;
    ///
    /// let mut mb = MultiBar::new();
    /// # let (count1, count2, count3) = (250, 62500, 15625000);
    ///
    /// // progress bar in level 1
    /// let mut p1 = mb.create_bar(count1);
    /// // ...
    ///
    /// // progress bar in level 2
    /// let mut p2 = mb.create_bar(count2);
    /// // ...
    ///
    /// // progress bar in level 3
    /// let mut p3 = mb.create_bar(count3);
    ///
    /// // ...
    /// mb.listen();
    /// ```
    pub fn create_bar(&mut self, total: u64) -> ProgressBar<Pipe> {
        self.println("");
        self.nbars += 1;
        let mut p = ProgressBar::on(Pipe {
                                        level: self.nlines - 1,
                                        chan: self.chan.0.clone(),
                                    },
                                    total);
        p.is_multibar = true;
        p.add(0);
        p
    }

    /// listen start listen to all bars changes.
    ///
    /// `ProgressBar` that finish its work, must call `finish()` (or `finish_print`)
    /// to notify the `MultiBar` about it.
    ///
    /// This is a blocking operation and blocks until all bars will
    /// finish.
    /// To ignore blocking, you can run it in a different thread.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::thread;
    /// use pbr::MultiBar;
    ///
    /// let mut mb = MultiBar::new();
    ///
    /// // ...
    /// // create some bars here
    /// // ...
    ///
    /// thread::spawn(move || {
    ///     mb.listen();
    ///     println!("all bars done!");
    /// });
    ///
    /// // ...
    /// ```
    pub fn listen(&mut self) {
        let mut first = true;
        let mut nbars = self.nbars;
        while nbars > 0 {

            // receive message
            let msg = self.chan.1.recv().unwrap();
            if msg.done {
                nbars -= 1;
                continue;
            }
            self.lines[msg.level] = msg.string;

            // and draw
            let mut out = String::new();
            if !first {
                out += &move_cursor_up(self.nlines);
            } else {
                first = false;
            }
            for l in self.lines.iter() {
                out.push_str(&format!("\r{}\n", l));
            }
            printfl!(self.handle, "{}", out);
        }
    }
}

pub struct Pipe {
    level: usize,
    chan: Sender<WriteMsg>,
}

impl Write for Pipe {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let s = from_utf8(buf).unwrap().to_owned();
        self.chan
            .send(WriteMsg {
                // finish method emit empty string
                done: s == "",
                level: self.level,
                string: s,
            })
            .unwrap();
        Ok(1)
    }

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

// WriteMsg is the message format used to communicate
// between MultiBar and its bars
struct WriteMsg {
    done: bool,
    level: usize,
    string: String,
}
<|endoftext|>


<commit_before>#![crate_name = "mv"]
#![feature(path_ext, slice_extras, slice_patterns, str_char)]
#![allow(deprecated)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Orvar Segerström <orvarsegerstrom@gmail.com>
 * (c) Sokovikov Evgeniy  <skv-headless@yandex.ru>
 *
 * For the full copyright and license information, please view the LICENSE file
 * that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;

use std::fs::{self, PathExt};
use std::io::{BufRead, BufReader, Result, stdin, Write};
use std::os::unix::fs::MetadataExt;
use std::path::{Path, PathBuf};

#[path = "../common/util.rs"]
#[macro_use]
mod util;

static NAME: &'static str = "mv";
static VERSION: &'static str = "0.0.1";

pub struct Behaviour {
    overwrite: OverwriteMode,
    backup: BackupMode,
    suffix: String,
    update: bool,
    target_dir: Option<String>,
    no_target_dir: bool,
    verbose: bool,
}

#[derive(Clone, Eq, PartialEq)]
pub enum OverwriteMode {
    NoClobber,
    Interactive,
    Force,
}

#[derive(Clone, Eq, PartialEq)]
pub enum BackupMode {
    NoBackup,
    SimpleBackup,
    NumberedBackup,
    ExistingBackup,
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optflagopt("",  "backup", "make a backup of each existing destination file", "CONTROL");
    opts.optflag("b", "", "like --backup but does not accept an argument");
    opts.optflag("f", "force", "do not prompt before overwriting");
    opts.optflag("i", "interactive", "prompt before override");
    opts.optflag("n", "no-clobber", "do not overwrite an existing file");
    opts.optflag("",  "strip-trailing-slashes", "remove any trailing slashes from each SOURCE\n \
                                                 argument");
    opts.optopt("S", "suffix", "override the usual backup suffix", "SUFFIX");
    opts.optopt("t", "target-directory", "move all SOURCE arguments into DIRECTORY", "DIRECTORY");
    opts.optflag("T", "no-target-directory", "treat DEST as a normal file");
    opts.optflag("u", "update", "move only when the SOURCE file is newer\n \
                                than the destination file or when the\n \
                                destination file is missing");
    opts.optflag("v", "verbose", "explain what is being done");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            show_error!("Invalid options\n{}", f);
            return 1;
        }
    };
    let usage = opts.usage("Move SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.");

    /* This does not exactly match the GNU implementation:
     * The GNU mv defaults to Force, but if more than one of the
     * overwrite options are supplied, only the last takes effect.
     * To default to no-clobber in that situation seems safer:
     */
    let overwrite_mode = if matches.opt_present("no-clobber") {
        OverwriteMode::NoClobber
    } else if matches.opt_present("interactive") {
        OverwriteMode::Interactive
    } else {
        OverwriteMode::Force
    };

    let backup_mode = if matches.opt_present("b") {
        BackupMode::SimpleBackup
    } else if matches.opt_present("backup") {
        match matches.opt_str("backup") {
            None => BackupMode::SimpleBackup,
            Some(mode) => match &mode[..] {
                "simple" | "never" => BackupMode::SimpleBackup,
                "numbered" | "t"   => BackupMode::NumberedBackup,
                "existing" | "nil" => BackupMode::ExistingBackup,
                "none" | "off"     => BackupMode::NoBackup,
                x => {
                    show_error!("invalid argument ‘{}’ for ‘backup type’\n\
                                Try '{} --help' for more information.", x, NAME);
                    return 1;
                }
            }
        }
    } else {
        BackupMode::NoBackup
    };

    if overwrite_mode == OverwriteMode::NoClobber && backup_mode != BackupMode::NoBackup {
        show_error!("options --backup and --no-clobber are mutually exclusive\n\
                    Try '{} --help' for more information.", NAME);
        return 1;
    }

    let backup_suffix = if matches.opt_present("suffix") {
        match matches.opt_str("suffix") {
            Some(x) => x,
            None => {
                show_error!("option '--suffix' requires an argument\n\
                            Try '{} --help' for more information.", NAME);
                return 1;
            }
        }
    } else {
        "~".to_string()
    };

    if matches.opt_present("T") && matches.opt_present("t") {
        show_error!("cannot combine --target-directory (-t) and --no-target-directory (-T)");
        return 1;
    }

    let behaviour = Behaviour {
        overwrite: overwrite_mode,
        backup: backup_mode,
        suffix: backup_suffix,
        update: matches.opt_present("u"),
        target_dir: matches.opt_str("t"),
        no_target_dir: matches.opt_present("T"),
        verbose: matches.opt_present("v"),
    };

    let paths: Vec<PathBuf> = {
        fn string_to_path<'a>(s: &'a String) -> &'a Path {
            Path::new(s)
        };
        fn strip_slashes<'a>(p: &'a Path) -> &'a Path {
            p.components().as_path()
        }
        let to_owned = |p: &Path| p.to_owned();
        let arguments = matches.free.iter().map(string_to_path);
        if matches.opt_present("strip-trailing-slashes") {
            arguments.map(strip_slashes).map(to_owned).collect()
        } else {
            arguments.map(to_owned).collect()
        }
    };

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        0
    } else if matches.opt_present("help") {
        help(&usage);
        0
    } else {
        exec(&paths[..], behaviour)
    }
}

fn help(usage: &str) {
    println!("a0{} {1}\n\n \
                       Usage: {0} SOURCE DEST\n  \
                         or:  {0} SOURCE... DIRECTORY \
                       \n\
                       {2}", NAME, VERSION, usage);
}

fn exec(files: &[PathBuf], b: Behaviour) -> i32 {
    match b.target_dir {
        Some(ref name) => return move_files_into_dir(files, &PathBuf::from(name), &b),
        None => {}
    }
    match files {
        [] | [_] => {
            show_error!("missing file operand\n\
                        Try '{} --help' for more information.", NAME);
            return 1;
        },
        [ref source, ref target] => {
            if !source.exists() {
                show_error!("cannot stat ‘{}’: No such file or directory", source.display());
                return 1;
            }

            if target.is_dir() {
                if b.no_target_dir {
                    if !source.is_dir() {
                        show_error!("cannot overwrite directory ‘{}’ with non-directory",
                            target.display());
                        return 1;
                    }

                    return match rename(source, target, &b) {
                        Err(e) => {
                            show_error!("{}", e);
                            1
                        },
                        _ => 0
                    }
                }

                return move_files_into_dir(&[source.clone()], target, &b);
            }

            match rename(source, target, &b) {
                Err(e) => {
                    show_error!("{}", e);
                    return 1;
                },
                _ => {}
            }
        }
        fs => {
            if b.no_target_dir {
                show_error!("mv: extra operand ‘{}’\n\
                            Try '{} --help' for more information.", fs[2].display(), NAME);
                return 1;
            }
            let target_dir = fs.last().unwrap();
            move_files_into_dir(fs.init(), target_dir, &b);
        }
    }
    0
}

fn move_files_into_dir(files: &[PathBuf], target_dir: &PathBuf, b: &Behaviour) -> i32 {
    if !target_dir.is_dir() {
        show_error!("target ‘{}’ is not a directory", target_dir.display());
        return 1;
    }

    let mut all_successful = true;
    for sourcepath in files.iter() {
        let targetpath = match sourcepath.as_os_str().to_str() {
            Some(name) => target_dir.join(name),
            None => {
                show_error!("cannot stat ‘{}’: No such file or directory",
                            sourcepath.display());

                all_successful = false;
                continue;
            }
        };

        match rename(sourcepath, &targetpath, b) {
            Err(e) => {
                show_error!("mv: cannot move ‘{}’ to ‘{}’: {}",
                            sourcepath.display(), targetpath.display(), e);
                all_successful = false;
            },
            _ => {}
        }
    };
    if all_successful { 0 } else { 1 }
}

fn rename(from: &PathBuf, to: &PathBuf, b: &Behaviour) -> Result<()> {
    let mut backup_path = None;

    if to.exists() {
        match b.overwrite {
            OverwriteMode::NoClobber => return Ok(()),
            OverwriteMode::Interactive => {
                print!("{}: overwrite ‘{}’? ", NAME, to.display());
                if !read_yes() {
                    return Ok(());
                }
            },
            OverwriteMode::Force => {}
        };

        backup_path = match b.backup {
            BackupMode::NoBackup => None,
            BackupMode::SimpleBackup => Some(simple_backup_path(to, &b.suffix)),
            BackupMode::NumberedBackup => Some(numbered_backup_path(to)),
            BackupMode::ExistingBackup => Some(existing_backup_path(to, &b.suffix))
        };
        if let Some(ref p) = backup_path {
            try!(fs::rename(to, p));
        }

        if b.update {
            if try!(fs::metadata(from)).mtime() <= try!(fs::metadata(to)).mtime() {
                return Ok(());
            }
        }
    }

    try!(fs::rename(from, to));

    if b.verbose {
        print!("‘{}’ -> ‘{}’", from.display(), to.display());
        match backup_path {
            Some(path) => println!(" (backup: ‘{}’)", path.display()),
            None => println!("")
        }
    }
    Ok(())
}

fn read_yes() -> bool {
    let mut s = String::new();
    match BufReader::new(stdin()).read_line(&mut s) {
        Ok(_) => match s.slice_shift_char() {
            Some((x, _)) => x == 'y' || x == 'Y',
            _ => false
        },
        _ => false
    }
}

fn simple_backup_path(path: &PathBuf, suffix: &String) -> PathBuf {
    let mut p = path.as_os_str().to_str().unwrap().to_string();
    p.push_str(suffix);
    return PathBuf::from(p);
}

fn numbered_backup_path(path: &PathBuf) -> PathBuf {
    let mut i: u64 = 1;
    loop {
        let new_path = simple_backup_path(path, &format!(".~{}~", i));
        if !new_path.exists() {
            return new_path;
        }
        i = i + 1;
    }
}

fn existing_backup_path(path: &PathBuf, suffix: &String) -> PathBuf {
    let test_path = simple_backup_path(path, &".~1~".to_string());
    if test_path.exists() {
        return numbered_backup_path(path);
    }
    simple_backup_path(path, suffix)
}
<commit_msg>Fix alignment of mv help.<commit_after>#![crate_name = "mv"]
#![feature(path_ext, slice_extras, slice_patterns, str_char)]
#![allow(deprecated)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Orvar Segerström <orvarsegerstrom@gmail.com>
 * (c) Sokovikov Evgeniy  <skv-headless@yandex.ru>
 *
 * For the full copyright and license information, please view the LICENSE file
 * that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;

use std::fs::{self, PathExt};
use std::io::{BufRead, BufReader, Result, stdin, Write};
use std::os::unix::fs::MetadataExt;
use std::path::{Path, PathBuf};

#[path = "../common/util.rs"]
#[macro_use]
mod util;

static NAME: &'static str = "mv";
static VERSION: &'static str = "0.0.1";

pub struct Behaviour {
    overwrite: OverwriteMode,
    backup: BackupMode,
    suffix: String,
    update: bool,
    target_dir: Option<String>,
    no_target_dir: bool,
    verbose: bool,
}

#[derive(Clone, Eq, PartialEq)]
pub enum OverwriteMode {
    NoClobber,
    Interactive,
    Force,
}

#[derive(Clone, Eq, PartialEq)]
pub enum BackupMode {
    NoBackup,
    SimpleBackup,
    NumberedBackup,
    ExistingBackup,
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optflagopt("",  "backup", "make a backup of each existing destination file", "CONTROL");
    opts.optflag("b", "", "like --backup but does not accept an argument");
    opts.optflag("f", "force", "do not prompt before overwriting");
    opts.optflag("i", "interactive", "prompt before override");
    opts.optflag("n", "no-clobber", "do not overwrite an existing file");
    opts.optflag("",  "strip-trailing-slashes", "remove any trailing slashes from each SOURCE\n \
                                                 argument");
    opts.optopt("S", "suffix", "override the usual backup suffix", "SUFFIX");
    opts.optopt("t", "target-directory", "move all SOURCE arguments into DIRECTORY", "DIRECTORY");
    opts.optflag("T", "no-target-directory", "treat DEST as a normal file");
    opts.optflag("u", "update", "move only when the SOURCE file is newer\n \
                                than the destination file or when the\n \
                                destination file is missing");
    opts.optflag("v", "verbose", "explain what is being done");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            show_error!("Invalid options\n{}", f);
            return 1;
        }
    };
    let usage = opts.usage("Move SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.");

    /* This does not exactly match the GNU implementation:
     * The GNU mv defaults to Force, but if more than one of the
     * overwrite options are supplied, only the last takes effect.
     * To default to no-clobber in that situation seems safer:
     */
    let overwrite_mode = if matches.opt_present("no-clobber") {
        OverwriteMode::NoClobber
    } else if matches.opt_present("interactive") {
        OverwriteMode::Interactive
    } else {
        OverwriteMode::Force
    };

    let backup_mode = if matches.opt_present("b") {
        BackupMode::SimpleBackup
    } else if matches.opt_present("backup") {
        match matches.opt_str("backup") {
            None => BackupMode::SimpleBackup,
            Some(mode) => match &mode[..] {
                "simple" | "never" => BackupMode::SimpleBackup,
                "numbered" | "t"   => BackupMode::NumberedBackup,
                "existing" | "nil" => BackupMode::ExistingBackup,
                "none" | "off"     => BackupMode::NoBackup,
                x => {
                    show_error!("invalid argument ‘{}’ for ‘backup type’\n\
                                Try '{} --help' for more information.", x, NAME);
                    return 1;
                }
            }
        }
    } else {
        BackupMode::NoBackup
    };

    if overwrite_mode == OverwriteMode::NoClobber && backup_mode != BackupMode::NoBackup {
        show_error!("options --backup and --no-clobber are mutually exclusive\n\
                    Try '{} --help' for more information.", NAME);
        return 1;
    }

    let backup_suffix = if matches.opt_present("suffix") {
        match matches.opt_str("suffix") {
            Some(x) => x,
            None => {
                show_error!("option '--suffix' requires an argument\n\
                            Try '{} --help' for more information.", NAME);
                return 1;
            }
        }
    } else {
        "~".to_string()
    };

    if matches.opt_present("T") && matches.opt_present("t") {
        show_error!("cannot combine --target-directory (-t) and --no-target-directory (-T)");
        return 1;
    }

    let behaviour = Behaviour {
        overwrite: overwrite_mode,
        backup: backup_mode,
        suffix: backup_suffix,
        update: matches.opt_present("u"),
        target_dir: matches.opt_str("t"),
        no_target_dir: matches.opt_present("T"),
        verbose: matches.opt_present("v"),
    };

    let paths: Vec<PathBuf> = {
        fn string_to_path<'a>(s: &'a String) -> &'a Path {
            Path::new(s)
        };
        fn strip_slashes<'a>(p: &'a Path) -> &'a Path {
            p.components().as_path()
        }
        let to_owned = |p: &Path| p.to_owned();
        let arguments = matches.free.iter().map(string_to_path);
        if matches.opt_present("strip-trailing-slashes") {
            arguments.map(strip_slashes).map(to_owned).collect()
        } else {
            arguments.map(to_owned).collect()
        }
    };

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        0
    } else if matches.opt_present("help") {
        help(&usage);
        0
    } else {
        exec(&paths[..], behaviour)
    }
}

fn help(usage: &str) {
    println!("{0} {1}\n\n\
    Usage: {0} SOURCE DEST\n   \
       or: {0} SOURCE... DIRECTORY\n\n\
    {2}", NAME, VERSION, usage);
}

fn exec(files: &[PathBuf], b: Behaviour) -> i32 {
    match b.target_dir {
        Some(ref name) => return move_files_into_dir(files, &PathBuf::from(name), &b),
        None => {}
    }
    match files {
        [] | [_] => {
            show_error!("missing file operand\n\
                        Try '{} --help' for more information.", NAME);
            return 1;
        },
        [ref source, ref target] => {
            if !source.exists() {
                show_error!("cannot stat ‘{}’: No such file or directory", source.display());
                return 1;
            }

            if target.is_dir() {
                if b.no_target_dir {
                    if !source.is_dir() {
                        show_error!("cannot overwrite directory ‘{}’ with non-directory",
                            target.display());
                        return 1;
                    }

                    return match rename(source, target, &b) {
                        Err(e) => {
                            show_error!("{}", e);
                            1
                        },
                        _ => 0
                    }
                }

                return move_files_into_dir(&[source.clone()], target, &b);
            }

            match rename(source, target, &b) {
                Err(e) => {
                    show_error!("{}", e);
                    return 1;
                },
                _ => {}
            }
        }
        fs => {
            if b.no_target_dir {
                show_error!("mv: extra operand ‘{}’\n\
                            Try '{} --help' for more information.", fs[2].display(), NAME);
                return 1;
            }
            let target_dir = fs.last().unwrap();
            move_files_into_dir(fs.init(), target_dir, &b);
        }
    }
    0
}

fn move_files_into_dir(files: &[PathBuf], target_dir: &PathBuf, b: &Behaviour) -> i32 {
    if !target_dir.is_dir() {
        show_error!("target ‘{}’ is not a directory", target_dir.display());
        return 1;
    }

    let mut all_successful = true;
    for sourcepath in files.iter() {
        let targetpath = match sourcepath.as_os_str().to_str() {
            Some(name) => target_dir.join(name),
            None => {
                show_error!("cannot stat ‘{}’: No such file or directory",
                            sourcepath.display());

                all_successful = false;
                continue;
            }
        };

        match rename(sourcepath, &targetpath, b) {
            Err(e) => {
                show_error!("mv: cannot move ‘{}’ to ‘{}’: {}",
                            sourcepath.display(), targetpath.display(), e);
                all_successful = false;
            },
            _ => {}
        }
    };
    if all_successful { 0 } else { 1 }
}

fn rename(from: &PathBuf, to: &PathBuf, b: &Behaviour) -> Result<()> {
    let mut backup_path = None;

    if to.exists() {
        match b.overwrite {
            OverwriteMode::NoClobber => return Ok(()),
            OverwriteMode::Interactive => {
                print!("{}: overwrite ‘{}’? ", NAME, to.display());
                if !read_yes() {
                    return Ok(());
                }
            },
            OverwriteMode::Force => {}
        };

        backup_path = match b.backup {
            BackupMode::NoBackup => None,
            BackupMode::SimpleBackup => Some(simple_backup_path(to, &b.suffix)),
            BackupMode::NumberedBackup => Some(numbered_backup_path(to)),
            BackupMode::ExistingBackup => Some(existing_backup_path(to, &b.suffix))
        };
        if let Some(ref p) = backup_path {
            try!(fs::rename(to, p));
        }

        if b.update {
            if try!(fs::metadata(from)).mtime() <= try!(fs::metadata(to)).mtime() {
                return Ok(());
            }
        }
    }

    try!(fs::rename(from, to));

    if b.verbose {
        print!("‘{}’ -> ‘{}’", from.display(), to.display());
        match backup_path {
            Some(path) => println!(" (backup: ‘{}’)", path.display()),
            None => println!("")
        }
    }
    Ok(())
}

fn read_yes() -> bool {
    let mut s = String::new();
    match BufReader::new(stdin()).read_line(&mut s) {
        Ok(_) => match s.slice_shift_char() {
            Some((x, _)) => x == 'y' || x == 'Y',
            _ => false
        },
        _ => false
    }
}

fn simple_backup_path(path: &PathBuf, suffix: &String) -> PathBuf {
    let mut p = path.as_os_str().to_str().unwrap().to_string();
    p.push_str(suffix);
    return PathBuf::from(p);
}

fn numbered_backup_path(path: &PathBuf) -> PathBuf {
    let mut i: u64 = 1;
    loop {
        let new_path = simple_backup_path(path, &format!(".~{}~", i));
        if !new_path.exists() {
            return new_path;
        }
        i = i + 1;
    }
}

fn existing_backup_path(path: &PathBuf, suffix: &String) -> PathBuf {
    let test_path = simple_backup_path(path, &".~1~".to_string());
    if test_path.exists() {
        return numbered_backup_path(path);
    }
    simple_backup_path(path, suffix)
}
<|endoftext|>


<commit_before>#![allow(missing_docs)] //TODO

use std::ops;

use cgmath::{ortho as cgmath_ortho, perspective as cgmath_perspective,
             Deg, Rad, Decomposed, Point3, Vector3, Quaternion,
             EuclideanSpace, InnerSpace, Rotation, Rotation3,
             Transform as Transform_};
use mint;

use {Camera, NodePointer, Object, Transform};
use input::{MOUSE_LEFT, Input, Button};

impl<P> AsRef<NodePointer> for Camera<P> {
    fn as_ref(&self) -> &NodePointer {
        &self.object.node
    }
}

impl<P> ops::Deref for Camera<P> {
    type Target = Object;
    fn deref(&self) -> &Object {
        &self.object
    }
}
impl<P> ops::DerefMut for Camera<P> {
    fn deref_mut(&mut self) -> &mut Object {
        &mut self.object
    }
}

/// Generic trait for different graphics projections.
pub trait Projection {
    /// Represents projection as projection matrix.
    fn get_matrix(&self, aspect: f32) -> mint::ColumnMatrix4<f32>;
}

/// Orthographic projection parameters.
/// See [`Orthographic projection`](https://en.wikipedia.org/wiki/3D_projection#Orthographic_projection).
#[derive(Clone, Debug, PartialEq)]
pub struct Orthographic {
    pub center: mint::Point2<f32>,
    /// Vertical extent from the center point. The height is double the extent.
    /// The width is derived from the height based on the current aspect ratio.
    pub extent_y: f32,
    pub near: f32,
    pub far: f32,
}

impl Projection for Orthographic {
    fn get_matrix(&self, aspect: f32) -> mint::ColumnMatrix4<f32> {
        let extent_x = aspect * self.extent_y;
        let m: [[f32; 4]; 4];
        m = cgmath_ortho(self.center.x - extent_x,
                         self.center.x + extent_x,
                         self.center.y - self.extent_y,
                         self.center.y + self.extent_y,
                         self.near, self.far
                         ).into();
        m.into()
    }
}

/// Perspective projection parameters.
/// See [`Perspective projection`](https://en.wikipedia.org/wiki/3D_projection#Perspective_projection).
#[derive(Clone, Debug, PartialEq)]
pub struct Perspective {
    /// Vertical field of view in degrees.
    ///Note: the horizontal FOV is computed based on the aspect.
    pub fov_y: f32,
    pub near: f32,
    pub far: f32,
}

impl Projection for Perspective {
    fn get_matrix(&self, aspect: f32) -> mint::ColumnMatrix4<f32> {
        let m: [[f32; 4]; 4];
        m = cgmath_perspective(Deg(self.fov_y),
                               aspect, self.near, self.far
                               ).into();
        m.into()
    }
}

pub struct OrbitControls {
    object: Object,
    transform: Transform,
    target: Point3<f32>,
    mouse_base: Option<mint::Point2<f32>>,
    button: Button,
    speed: f32,
}

pub struct OrbitControlsBuilder {
    object: Object,
    position: [f32; 3],
    target: [f32; 3],
    button: Button,
    speed: f32,
}

impl OrbitControlsBuilder {
    pub fn speed(&mut self, speed: f32) -> &mut Self {
        self.speed = speed;
        self
    }

    pub fn button(&mut self, button: Button) -> &mut Self {
        self.button = button;
        self
    }

    pub fn build(&mut self) -> OrbitControls {
        let dir = (Point3::from(self.position) - Point3::from(self.target)).normalize();
        let up = Vector3::unit_z();
        let q = Quaternion::look_at(dir, up).invert();
        //TEMP
        let qv: [f32; 3] = q.v.into();
        let rot = mint::Quaternion {
            s: q.s,
            v: qv.into(),
        };
        let mut object = self.object.clone();
        object.set_transform(self.position, rot, 1.0);

        OrbitControls {
            object,
            transform: Decomposed {
                disp: self.position.into(),
                rot: q,
                scale: 1.0,
            },
            target: self.target.into(),
            mouse_base: None,
            button: self.button,
            speed: self.speed,
        }
    }
}

impl OrbitControls {
    pub fn new<P>(object: &Object, position: P, target: P) -> OrbitControlsBuilder
    where P: Into<[f32; 3]>,
    {
        OrbitControlsBuilder {
            object: object.clone(),
            position: position.into(),
            target: target.into(),
            button: MOUSE_LEFT,
            speed: 1.0,
        }
    }

    pub fn update(&mut self, input: &Input) {
        if !self.button.is_hit(input) {
            self.mouse_base = None;
            return
        }

        let cur = input.get_mouse_pos();
        if let Some(base) = self.mouse_base {
            let pre = Decomposed {
                disp: -self.target.to_vec(),
                .. Decomposed::one()
            };
            let q_ver = Quaternion::from_angle_y(Rad(self.speed * (base.x - cur.x)));
            let axis = self.transform.rot * Vector3::unit_x();
            let q_hor = Quaternion::from_axis_angle(axis, Rad(self.speed * (cur.y - base.y)));
            let post = Decomposed {
                scale: 1.0,
                rot: q_hor * q_ver,
                disp: self.target.to_vec(),
            };
            self.transform = post.concat(&pre.concat(&self.transform));
            //TEMP
            let pf: [f32; 3] = self.transform.disp.into();
            let qv: [f32; 3] = self.transform.rot.v.into();
            let rot = mint::Quaternion {
                s: self.transform.rot.s,
                v: qv.into(),
            };
            self.object.set_transform(pf, rot, 1.0);
        }
        self.mouse_base = Some(cur);
    }
}
<commit_msg>Added zoom to orbit camera<commit_after>#![allow(missing_docs)] //TODO

use std::ops;

use cgmath::{ortho as cgmath_ortho, perspective as cgmath_perspective,
             Deg, Rad, Decomposed, Point3, Vector3, Quaternion,
             EuclideanSpace, InnerSpace, Rotation, Rotation3,
             Transform as Transform_};
use mint;

use {Camera, NodePointer, Object, Transform};
use input::{MOUSE_LEFT, Input, Button};

impl<P> AsRef<NodePointer> for Camera<P> {
    fn as_ref(&self) -> &NodePointer {
        &self.object.node
    }
}

impl<P> ops::Deref for Camera<P> {
    type Target = Object;
    fn deref(&self) -> &Object {
        &self.object
    }
}
impl<P> ops::DerefMut for Camera<P> {
    fn deref_mut(&mut self) -> &mut Object {
        &mut self.object
    }
}

/// Generic trait for different graphics projections.
pub trait Projection {
    /// Represents projection as projection matrix.
    fn get_matrix(&self, aspect: f32) -> mint::ColumnMatrix4<f32>;
}

/// Orthographic projection parameters.
/// See [`Orthographic projection`](https://en.wikipedia.org/wiki/3D_projection#Orthographic_projection).
#[derive(Clone, Debug, PartialEq)]
pub struct Orthographic {
    pub center: mint::Point2<f32>,
    /// Vertical extent from the center point. The height is double the extent.
    /// The width is derived from the height based on the current aspect ratio.
    pub extent_y: f32,
    pub near: f32,
    pub far: f32,
}

impl Projection for Orthographic {
    fn get_matrix(&self, aspect: f32) -> mint::ColumnMatrix4<f32> {
        let extent_x = aspect * self.extent_y;
        let m: [[f32; 4]; 4];
        m = cgmath_ortho(self.center.x - extent_x,
                         self.center.x + extent_x,
                         self.center.y - self.extent_y,
                         self.center.y + self.extent_y,
                         self.near, self.far
                         ).into();
        m.into()
    }
}

/// Perspective projection parameters.
/// See [`Perspective projection`](https://en.wikipedia.org/wiki/3D_projection#Perspective_projection).
#[derive(Clone, Debug, PartialEq)]
pub struct Perspective {
    /// Vertical field of view in degrees.
    ///Note: the horizontal FOV is computed based on the aspect.
    pub fov_y: f32,
    pub near: f32,
    pub far: f32,
}

impl Projection for Perspective {
    fn get_matrix(&self, aspect: f32) -> mint::ColumnMatrix4<f32> {
        let m: [[f32; 4]; 4];
        m = cgmath_perspective(Deg(self.fov_y),
                               aspect, self.near, self.far
                               ).into();
        m.into()
    }
}

pub struct OrbitControls {
    object: Object,
    transform: Transform,
    target: Point3<f32>,
    mouse_base: Option<mint::Point2<f32>>,
    button: Button,
    speed: f32,
}

pub struct OrbitControlsBuilder {
    object: Object,
    position: [f32; 3],
    target: [f32; 3],
    button: Button,
    speed: f32,
}

impl OrbitControlsBuilder {
    pub fn speed(&mut self, speed: f32) -> &mut Self {
        self.speed = speed;
        self
    }

    pub fn button(&mut self, button: Button) -> &mut Self {
        self.button = button;
        self
    }

    pub fn build(&mut self) -> OrbitControls {
        let dir = (Point3::from(self.position) - Point3::from(self.target)).normalize();
        let up = Vector3::unit_z();
        let q = Quaternion::look_at(dir, up).invert();
        //TEMP
        let qv: [f32; 3] = q.v.into();
        let rot = mint::Quaternion {
            s: q.s,
            v: qv.into(),
        };
        let mut object = self.object.clone();
        object.set_transform(self.position, rot, 1.0);

        OrbitControls {
            object,
            transform: Decomposed {
                disp: self.position.into(),
                rot: q,
                scale: 1.0,
            },
            target: self.target.into(),
            mouse_base: None,
            button: self.button,
            speed: self.speed,
        }
    }
}

impl OrbitControls {
    pub fn new<P>(object: &Object, position: P, target: P) -> OrbitControlsBuilder
    where P: Into<[f32; 3]>,
    {
        OrbitControlsBuilder {
            object: object.clone(),
            position: position.into(),
            target: target.into(),
            button: MOUSE_LEFT,
            speed: 1.0,
        }
    }

    pub fn update(&mut self, input: &Input) {
        if !self.button.is_hit(input) && !(input.get_mouse_wheel_movements().len()!=0) {
            self.mouse_base = None;
            return
        }

        let cur = input.get_mouse_pos();
        if self.mouse_base == None { self.mouse_base = Some(cur); } // Fake previous mouse input
                                                                    // if change only comes from mouse wheel
        if let Some(base) = self.mouse_base {
            let pre = Decomposed {
                disp: -self.target.to_vec(),
                .. Decomposed::one()
            };
            let q_ver = Quaternion::from_angle_y(Rad(self.speed * (base.x - cur.x)));
            let axis = self.transform.rot * Vector3::unit_x();
            let q_hor = Quaternion::from_axis_angle(axis, Rad(self.speed * (cur.y - base.y)));
            let post = Decomposed {
                scale: 1.0 + input.get_mouse_wheel_movements().iter().sum::<f32>()/1000.0,
                rot: q_hor * q_ver,
                disp: self.target.to_vec(),
            };
            self.transform = post.concat(&pre.concat(&self.transform));
            //TEMP
            let pf: [f32; 3] = self.transform.disp.into();
            let qv: [f32; 3] = self.transform.rot.v.into();
            let rot = mint::Quaternion {
                s: self.transform.rot.s,
                v: qv.into(),
            };
            self.object.set_transform(pf, rot, 1.0);
        }
        self.mouse_base = Some(cur);
    }
}
<|endoftext|>


<commit_before>use fuzzy::{matches, Score};

/// A Choice wraps a String and it's calculated Score
pub struct Choice(String, Score);

impl Choice {
    /// Creates a new Choice if the needle matches the haystack.
    ///
    /// # Examples
    ///
    /// ```
    /// use rff::choice::Choice;
    /// assert!(Choice::new("amo", String::from("app/models/order")).is_some());
    /// ```
    pub fn new(needle: &str, haystack: String) -> Option<Choice> {
        if matches(&needle, &haystack) {
            let score = Score::calculate(&needle, &haystack);
            Some(Choice(haystack, score))
        } else {
            None
        }
    }
}

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

    #[bench]
    fn create_choice(b: &mut Bencher) {
        b.iter(|| Choice::new("app/models", String::from("app/models/order")))
    }
}
<commit_msg>Implement PartialOrd for Choice<commit_after>use std::cmp::Ordering;
use fuzzy::{matches, Score};

/// A Choice wraps a String and it's calculated Score
pub struct Choice(String, Score);

impl Choice {
    /// Creates a new Choice if the needle matches the haystack.
    ///
    /// # Examples
    ///
    /// ```
    /// use rff::choice::Choice;
    /// assert!(Choice::new("amo", String::from("app/models/order")).is_some());
    /// ```
    pub fn new(needle: &str, haystack: String) -> Option<Choice> {
        if matches(&needle, &haystack) {
            let score = Score::calculate(&needle, &haystack);
            Some(Choice(haystack, score))
        } else {
            None
        }
    }
}

impl PartialEq for Choice {
    fn eq(&self, other: &Choice) -> bool {
        self.1.eq(&other.1)
    }
}

impl PartialOrd for Choice {
    fn partial_cmp(&self, other: &Choice) -> Option<Ordering> {
        self.1.partial_cmp(&other.1)
    }
}

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

    #[bench]
    fn create_choice(b: &mut Bencher) {
        b.iter(|| Choice::new("app/models", String::from("app/models/order")))
    }

    #[test]
    fn partial_cmp() {
        let a = Choice::new("amor", String::from("app/models/order")).unwrap();
        let b = Choice::new("amor", String::from("app/models/zrder")).unwrap();

        assert!(a > b);
    }
}
<|endoftext|>


<commit_before>use regex::Regex;

use super::mailbox::Mailbox;
use super::error::{Error, ParseError, Result};

pub fn parse_capability(lines: Vec<String>) -> Result<Vec<String>> {
    let capability_regex = Regex::new(r"^\* CAPABILITY (.*)\r\n").unwrap();

    //Check Ok
    match parse_response_ok(lines.clone()) {
        Ok(_) => (),
        Err(e) => return Err(e)
    };

    for line in lines.iter() {
        if capability_regex.is_match(line) {
            let cap = capability_regex.captures(line).unwrap();
            let capabilities_str = cap.at(1).unwrap();
            return Ok(capabilities_str.split(' ').map(|x| x.to_string()).collect());
        }
    }

    Err(Error::Parse(ParseError::Capability(lines)))
}

pub fn parse_response_ok(lines: Vec<String>) -> Result<()> {
    let ok_regex = Regex::new(r"^([a-zA-Z0-9]+) ([a-zA-Z0-9]+)(.*)").unwrap();
    let last_line = lines.last().unwrap();

    for cap in ok_regex.captures_iter(last_line) {
        let response_type = cap.at(2).unwrap_or("");
        if response_type == "OK" {
            return Ok(());
        }
    }

    Err(Error::Parse(ParseError::StatusResponse(lines.clone())))
}

pub fn parse_select_or_examine(lines: Vec<String>) -> Result<Mailbox> {
    let exists_regex = Regex::new(r"^\* (\d+) EXISTS\r\n").unwrap();

    let recent_regex = Regex::new(r"^\* (\d+) RECENT\r\n").unwrap();

    let flags_regex = Regex::new(r"^\* FLAGS (.+)\r\n").unwrap();

    let unseen_regex = Regex::new(r"^\* OK \[UNSEEN (\d+)\](.*)\r\n").unwrap();

    let uid_validity_regex = Regex::new(r"^\* OK \[UIDVALIDITY (\d+)\](.*)\r\n").unwrap();

    let uid_next_regex = Regex::new(r"^\* OK \[UIDNEXT (\d+)\](.*)\r\n").unwrap();

    let permanent_flags_regex = Regex::new(r"^\* OK \[PERMANENTFLAGS (.+)\](.*)\r\n").unwrap();

    //Check Ok
    match parse_response_ok(lines.clone()) {
        Ok(_) => (),
        Err(e) => return Err(e)
    };

    let mut mailbox = Mailbox::default();

    for line in lines.iter() {
        if exists_regex.is_match(line) {
            let cap = exists_regex.captures(line).unwrap();
            mailbox.exists = cap.at(1).unwrap().parse::<u32>().unwrap();
        } else if recent_regex.is_match(line) {
            let cap = recent_regex.captures(line).unwrap();
            mailbox.recent = cap.at(1).unwrap().parse::<u32>().unwrap();
        } else if flags_regex.is_match(line) {
            let cap = flags_regex.captures(line).unwrap();
            mailbox.flags = cap.at(1).unwrap().to_string();
        } else if unseen_regex.is_match(line) {
            let cap = unseen_regex.captures(line).unwrap();
            mailbox.unseen = Some(cap.at(1).unwrap().parse::<u32>().unwrap());
        } else if uid_validity_regex.is_match(line) {
            let cap = uid_validity_regex.captures(line).unwrap();
            mailbox.uid_validity = Some(cap.at(1).unwrap().parse::<u32>().unwrap());
        } else if uid_next_regex.is_match(line) {
            let cap = uid_next_regex.captures(line).unwrap();
            mailbox.uid_next = Some(cap.at(1).unwrap().parse::<u32>().unwrap());
        } else if permanent_flags_regex.is_match(line) {
            let cap = permanent_flags_regex.captures(line).unwrap();
            mailbox.permanent_flags = Some(cap.at(1).unwrap().to_string());
        }
    }

    Ok(mailbox)
}
<commit_msg>Add testing for capability parsing<commit_after>use regex::Regex;

use super::mailbox::Mailbox;
use super::error::{Error, ParseError, Result};

pub fn parse_capability(lines: Vec<String>) -> Result<Vec<String>> {
    let capability_regex = Regex::new(r"^\* CAPABILITY (.*)\r\n").unwrap();

    //Check Ok
    match parse_response_ok(lines.clone()) {
        Ok(_) => (),
        Err(e) => return Err(e)
    };

    for line in lines.iter() {
        if capability_regex.is_match(line) {
            let cap = capability_regex.captures(line).unwrap();
            let capabilities_str = cap.at(1).unwrap();
            return Ok(capabilities_str.split(' ').map(|x| x.to_string()).collect());
        }
    }

    Err(Error::Parse(ParseError::Capability(lines)))
}

pub fn parse_response_ok(lines: Vec<String>) -> Result<()> {
    let ok_regex = Regex::new(r"^([a-zA-Z0-9]+) ([a-zA-Z0-9]+)(.*)").unwrap();
    let last_line = lines.last().unwrap();

    for cap in ok_regex.captures_iter(last_line) {
        let response_type = cap.at(2).unwrap_or("");
        if response_type == "OK" {
            return Ok(());
        }
    }

    Err(Error::Parse(ParseError::StatusResponse(lines.clone())))
}

pub fn parse_select_or_examine(lines: Vec<String>) -> Result<Mailbox> {
    let exists_regex = Regex::new(r"^\* (\d+) EXISTS\r\n").unwrap();

    let recent_regex = Regex::new(r"^\* (\d+) RECENT\r\n").unwrap();

    let flags_regex = Regex::new(r"^\* FLAGS (.+)\r\n").unwrap();

    let unseen_regex = Regex::new(r"^\* OK \[UNSEEN (\d+)\](.*)\r\n").unwrap();

    let uid_validity_regex = Regex::new(r"^\* OK \[UIDVALIDITY (\d+)\](.*)\r\n").unwrap();

    let uid_next_regex = Regex::new(r"^\* OK \[UIDNEXT (\d+)\](.*)\r\n").unwrap();

    let permanent_flags_regex = Regex::new(r"^\* OK \[PERMANENTFLAGS (.+)\](.*)\r\n").unwrap();

    //Check Ok
    match parse_response_ok(lines.clone()) {
        Ok(_) => (),
        Err(e) => return Err(e)
    };

    let mut mailbox = Mailbox::default();

    for line in lines.iter() {
        if exists_regex.is_match(line) {
            let cap = exists_regex.captures(line).unwrap();
            mailbox.exists = cap.at(1).unwrap().parse::<u32>().unwrap();
        } else if recent_regex.is_match(line) {
            let cap = recent_regex.captures(line).unwrap();
            mailbox.recent = cap.at(1).unwrap().parse::<u32>().unwrap();
        } else if flags_regex.is_match(line) {
            let cap = flags_regex.captures(line).unwrap();
            mailbox.flags = cap.at(1).unwrap().to_string();
        } else if unseen_regex.is_match(line) {
            let cap = unseen_regex.captures(line).unwrap();
            mailbox.unseen = Some(cap.at(1).unwrap().parse::<u32>().unwrap());
        } else if uid_validity_regex.is_match(line) {
            let cap = uid_validity_regex.captures(line).unwrap();
            mailbox.uid_validity = Some(cap.at(1).unwrap().parse::<u32>().unwrap());
        } else if uid_next_regex.is_match(line) {
            let cap = uid_next_regex.captures(line).unwrap();
            mailbox.uid_next = Some(cap.at(1).unwrap().parse::<u32>().unwrap());
        } else if permanent_flags_regex.is_match(line) {
            let cap = permanent_flags_regex.captures(line).unwrap();
            mailbox.permanent_flags = Some(cap.at(1).unwrap().to_string());
        }
    }

    Ok(mailbox)
}

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

    #[test]
    fn parse_capability_test() {
        let expected_capabilities = vec![String::from("IMAP4rev1"), String::from("STARTTLS"), String::from("AUTH=GSSAPI"), String::from("LOGINDISABLED")];
        let lines = vec![String::from("* CAPABILITY IMAP4rev1 STARTTLS AUTH=GSSAPI LOGINDISABLED\r\n"), String::from("a1 OK CAPABILITY completed\r\n")];
        let capabilities = parse_capability(lines).unwrap();
        assert!(capabilities == expected_capabilities, "Unexpected capabilities parse response");
    }

    #[test]
    #[should_panic]
    fn parse_capability_invalid_test() {
        let lines = vec![String::from("* JUNK IMAP4rev1 STARTTLS AUTH=GSSAPI LOGINDISABLED\r\n"), String::from("a1 OK CAPABILITY completed\r\n")];
        parse_capability(lines).unwrap();
    }
}
<|endoftext|>


<commit_before>use hyper::client::Client;
use hyper::client::response::Response;
use hyper::error::Error;
use hyper::header::Headers;
use hyper::method::Method;

/// Trait that represents some methods to send a specific request
pub trait GetResponse {
    /// Given a specific URL, get the response from the target server
    fn get_http_response(&self, url: &str) -> Result<Response, Error>;

    /// Given a specific URL and an header, get the response from the target server
    fn get_http_response_using_headers(&self,
                                       url: &str,
                                       header: Headers)
                                       -> Result<Response, Error>;
}

impl GetResponse for Client {
    fn get_http_response(&self, url: &str) -> Result<Response, Error> {
        self.request(Method::Get, url).send()
    }

    fn get_http_response_using_headers(&self,
                                       url: &str,
                                       custom_header: Headers)
                                       -> Result<Response, Error> {
        self.request(Method::Get, url).headers(custom_header).send()
    }
}<commit_msg>Changed the body of get_http_response<commit_after>use hyper::client::Client;
use hyper::client::response::Response;
use hyper::error::Error;
use hyper::header::Headers;
use hyper::method::Method;

/// Trait that represents some methods to send a specific request
pub trait GetResponse {
    /// Given a specific URL, get the response from the target server
    fn get_http_response(&self, url: &str) -> Result<Response, Error>;

    /// Given a specific URL and an header, get the response from the target server
    fn get_http_response_using_headers(&self,
                                       url: &str,
                                       header: Headers)
                                       -> Result<Response, Error>;
}

impl GetResponse for Client {

    fn get_http_response(&self, url: &str) -> Result<Response, Error> {
        self.get_http_response_using_headers(url, Headers::new())
    }

    fn get_http_response_using_headers(&self,
                                       url: &str,
                                       custom_header: Headers)
                                       -> Result<Response, Error> {
        self.request(Method::Get, url).headers(custom_header).send()
    }
}<|endoftext|>