<commit_before>//! A single-producer, multi-consumer channel that only retains the *last* sent
//! value.
//!
//! This channel is useful for watching for changes to a value from multiple
//! points in the code base, for example, changes to configuration values.
//!
//! # Usage
//!
//! [`channel`] returns a [`Sender`] / [`Receiver`] pair. These are the producer
//! and sender halves of the channel. The channel is created with an initial
//! value. The **latest** value stored in the channel is accessed with
//! [`Receiver::borrow()`]. Awaiting [`Receiver::changed()`] waits for a new
//! value to sent by the [`Sender`] half.
//!
//! # Examples
//!
//! ```
//! use tokio::sync::watch;
//!
//! # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
//!     let (tx, mut rx) = watch::channel("hello");
//!
//!     tokio::spawn(async move {
//!         while rx.changed().await.is_ok() {
//!             println!("received = {:?}", *rx.borrow());
//!         }
//!     });
//!
//!     tx.send("world")?;
//! # Ok(())
//! # }
//! ```
//!
//! # Closing
//!
//! [`Sender::closed`] allows the producer to detect when all [`Receiver`]
//! handles have been dropped. This indicates that there is no further interest
//! in the values being produced and work can be stopped.
//!
//! # Thread safety
//!
//! Both [`Sender`] and [`Receiver`] are thread safe. They can be moved to other
//! threads and can be used in a concurrent environment. Clones of [`Receiver`]
//! handles may be moved to separate threads and also used concurrently.
//!
//! [`Sender`]: crate::sync::watch::Sender
//! [`Receiver`]: crate::sync::watch::Receiver
//! [`Receiver::changed()`]: crate::sync::watch::Receiver::changed
//! [`Receiver::borrow()`]: crate::sync::watch::Receiver::borrow
//! [`channel`]: crate::sync::watch::channel
//! [`Sender::closed`]: crate::sync::watch::Sender::closed

use crate::sync::Notify;

use std::ops;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::{Relaxed, SeqCst};
use std::sync::{Arc, RwLock, RwLockReadGuard};

/// Receives values from the associated [`Sender`](struct@Sender).
///
/// Instances are created by the [`channel`](fn@channel) function.
#[derive(Debug)]
pub struct Receiver<T> {
    /// Pointer to the shared state
    shared: Arc<Shared<T>>,

    /// Last observed version
    version: usize,
}

/// Sends values to the associated [`Receiver`](struct@Receiver).
///
/// Instances are created by the [`channel`](fn@channel) function.
#[derive(Debug)]
pub struct Sender<T> {
    shared: Arc<Shared<T>>,
}

/// Returns a reference to the inner value
///
/// Outstanding borrows hold a read lock on the inner value. This means that
/// long lived borrows could cause the produce half to block. It is recommended
/// to keep the borrow as short lived as possible.
#[derive(Debug)]
pub struct Ref<'a, T> {
    inner: RwLockReadGuard<'a, T>,
}

#[derive(Debug)]
struct Shared<T> {
    /// The most recent value
    value: RwLock<T>,

    /// The current version
    ///
    /// The lowest bit represents a "closed" state. The rest of the bits
    /// represent the current version.
    version: AtomicUsize,

    /// Tracks the number of `Receiver` instances
    ref_count_rx: AtomicUsize,

    /// Notifies waiting receivers that the value changed.
    notify_rx: Notify,

    /// Notifies any task listening for `Receiver` dropped events
    notify_tx: Notify,
}

pub mod error {
    //! Watch error types

    use std::fmt;

    /// Error produced when sending a value fails.
    #[derive(Debug)]
    pub struct SendError<T> {
        pub(crate) inner: T,
    }

    // ===== impl SendError =====

    impl<T: fmt::Debug> fmt::Display for SendError<T> {
        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
            write!(fmt, "channel closed")
        }
    }

    impl<T: fmt::Debug> std::error::Error for SendError<T> {}

    /// Error produced when receiving a change notification.
    #[derive(Debug)]
    pub struct RecvError(pub(super) ());

    // ===== impl RecvError =====

    impl fmt::Display for RecvError {
        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
            write!(fmt, "channel closed")
        }
    }

    impl std::error::Error for RecvError {}
}

const CLOSED: usize = 1;

/// Creates a new watch channel, returning the "send" and "receive" handles.
///
/// All values sent by [`Sender`] will become visible to the [`Receiver`] handles.
/// Only the last value sent is made available to the [`Receiver`] half. All
/// intermediate values are dropped.
///
/// # Examples
///
/// ```
/// use tokio::sync::watch;
///
/// # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
///     let (tx, mut rx) = watch::channel("hello");
///
///     tokio::spawn(async move {
///         while rx.changed().await.is_ok() {
///             println!("received = {:?}", *rx.borrow());
///         }
///     });
///
///     tx.send("world")?;
/// # Ok(())
/// # }
/// ```
///
/// [`Sender`]: struct@Sender
/// [`Receiver`]: struct@Receiver
pub fn channel<T>(init: T) -> (Sender<T>, Receiver<T>) {
    let shared = Arc::new(Shared {
        value: RwLock::new(init),
        version: AtomicUsize::new(0),
        ref_count_rx: AtomicUsize::new(1),
        notify_rx: Notify::new(),
        notify_tx: Notify::new(),
    });

    let tx = Sender {
        shared: shared.clone(),
    };

    let rx = Receiver { shared, version: 0 };

    (tx, rx)
}

impl<T> Receiver<T> {
    /// Returns a reference to the most recently sent value
    ///
    /// Outstanding borrows hold a read lock. This means that long lived borrows
    /// could cause the send half to block. It is recommended to keep the borrow
    /// as short lived as possible.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::watch;
    ///
    /// let (_, rx) = watch::channel("hello");
    /// assert_eq!(*rx.borrow(), "hello");
    /// ```
    pub fn borrow(&self) -> Ref<'_, T> {
        let inner = self.shared.value.read().unwrap();
        Ref { inner }
    }

    /// Wait for a change notification
    ///
    /// Returns when a new value has been sent by the [`Sender`] since the last
    /// time `changed()` was called. When the `Sender` half is dropped, `Err` is
    /// returned.
    ///
    /// [`Sender`]: struct@Sender
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::watch;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let (tx, mut rx) = watch::channel("hello");
    ///
    ///     tokio::spawn(async move {
    ///         tx.send("goodbye").unwrap();
    ///     });
    ///
    ///     assert!(rx.changed().await.is_ok());
    ///     assert_eq!(*rx.borrow(), "goodbye");
    ///
    ///     // The `tx` handle has been dropped
    ///     assert!(rx.changed().await.is_err());
    /// }
    /// ```
    pub async fn changed(&mut self) -> Result<(), error::RecvError> {
        use std::future::Future;
        use std::pin::Pin;
        use std::task::Poll;

        // In order to avoid a race condition, we first request a notification,
        // **then** check the current value's version. If a new version exists,
        // the notification request is dropped. Requesting the notification
        // requires polling the future once.
        let notified = self.shared.notify_rx.notified();
        pin!(notified);

        // Polling the future once is guaranteed to return `Pending` as `watch`
        // only notifies using `notify_waiters`.
        crate::future::poll_fn(|cx| {
            let res = Pin::new(&mut notified).poll(cx);
            assert!(!res.is_ready());
            Poll::Ready(())
        })
        .await;

        if let Some(ret) = maybe_changed(&self.shared, &mut self.version) {
            return ret;
        }

        notified.await;

        maybe_changed(&self.shared, &mut self.version)
            .expect("[bug] failed to observe change after notificaton.")
    }
}

fn maybe_changed<T>(
    shared: &Shared<T>,
    version: &mut usize,
) -> Option<Result<(), error::RecvError>> {
    // Load the version from the state
    let state = shared.version.load(SeqCst);
    let new_version = state & !CLOSED;

    if *version != new_version {
        // Observe the new version and return
        *version = new_version;
        return Some(Ok(()));
    }

    if CLOSED == state & CLOSED {
        // All receivers have dropped.
        return Some(Err(error::RecvError(())));
    }

    None
}

impl<T> Clone for Receiver<T> {
    fn clone(&self) -> Self {
        let version = self.version;
        let shared = self.shared.clone();

        // No synchronization necessary as this is only used as a counter and
        // not memory access.
        shared.ref_count_rx.fetch_add(1, Relaxed);

        Receiver { version, shared }
    }
}

impl<T> Drop for Receiver<T> {
    fn drop(&mut self) {
        // No synchronization necessary as this is only used as a counter and
        // not memory access.
        if 1 == self.shared.ref_count_rx.fetch_sub(1, Relaxed) {
            // This is the last `Receiver` handle, tasks waiting on `Sender::closed()`
            self.shared.notify_tx.notify_waiters();
        }
    }
}

impl<T> Sender<T> {
    /// Sends a new value via the channel, notifying all receivers.
    pub fn send(&self, value: T) -> Result<(), error::SendError<T>> {
        // This is pretty much only useful as a hint anyway, so synchronization isn't critical.
        if 0 == self.shared.ref_count_rx.load(Relaxed) {
            return Err(error::SendError { inner: value });
        }

        *self.shared.value.write().unwrap() = value;

        // Update the version. 2 is used so that the CLOSED bit is not set.
        self.shared.version.fetch_add(2, SeqCst);

        // Notify all watchers
        self.shared.notify_rx.notify_waiters();

        Ok(())
    }

    /// Completes when all receivers have dropped.
    ///
    /// This allows the producer to get notified when interest in the produced
    /// values is canceled and immediately stop doing work.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::watch;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let (tx, rx) = watch::channel("hello");
    ///
    ///     tokio::spawn(async move {
    ///         // use `rx`
    ///         drop(rx);
    ///     });
    ///
    ///     // Waits for `rx` to drop
    ///     tx.closed().await;
    ///     println!("the `rx` handles dropped")
    /// }
    /// ```
    pub async fn closed(&self) {
        let notified = self.shared.notify_tx.notified();

        if self.shared.ref_count_rx.load(Relaxed) == 0 {
            return;
        }

        notified.await;
        debug_assert_eq!(0, self.shared.ref_count_rx.load(Relaxed));
    }
}

impl<T> Drop for Sender<T> {
    fn drop(&mut self) {
        self.shared.version.fetch_or(CLOSED, SeqCst);
        self.shared.notify_rx.notify_waiters();
    }
}

// ===== impl Ref =====

impl<T> ops::Deref for Ref<'_, T> {
    type Target = T;

    fn deref(&self) -> &T {
        self.inner.deref()
    }
}
<commit_msg>sync: add is_closed method to watch sender (#2991)<commit_after>//! A single-producer, multi-consumer channel that only retains the *last* sent
//! value.
//!
//! This channel is useful for watching for changes to a value from multiple
//! points in the code base, for example, changes to configuration values.
//!
//! # Usage
//!
//! [`channel`] returns a [`Sender`] / [`Receiver`] pair. These are the producer
//! and sender halves of the channel. The channel is created with an initial
//! value. The **latest** value stored in the channel is accessed with
//! [`Receiver::borrow()`]. Awaiting [`Receiver::changed()`] waits for a new
//! value to sent by the [`Sender`] half.
//!
//! # Examples
//!
//! ```
//! use tokio::sync::watch;
//!
//! # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
//!     let (tx, mut rx) = watch::channel("hello");
//!
//!     tokio::spawn(async move {
//!         while rx.changed().await.is_ok() {
//!             println!("received = {:?}", *rx.borrow());
//!         }
//!     });
//!
//!     tx.send("world")?;
//! # Ok(())
//! # }
//! ```
//!
//! # Closing
//!
//! [`Sender::is_closed`] and [`Sender::closed`] allow the producer to detect
//! when all [`Receiver`] handles have been dropped. This indicates that there
//! is no further interest in the values being produced and work can be stopped.
//!
//! # Thread safety
//!
//! Both [`Sender`] and [`Receiver`] are thread safe. They can be moved to other
//! threads and can be used in a concurrent environment. Clones of [`Receiver`]
//! handles may be moved to separate threads and also used concurrently.
//!
//! [`Sender`]: crate::sync::watch::Sender
//! [`Receiver`]: crate::sync::watch::Receiver
//! [`Receiver::changed()`]: crate::sync::watch::Receiver::changed
//! [`Receiver::borrow()`]: crate::sync::watch::Receiver::borrow
//! [`channel`]: crate::sync::watch::channel
//! [`Sender::is_closed`]: crate::sync::watch::Sender::is_closed
//! [`Sender::closed`]: crate::sync::watch::Sender::closed

use crate::sync::Notify;

use std::ops;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::{Relaxed, SeqCst};
use std::sync::{Arc, RwLock, RwLockReadGuard};

/// Receives values from the associated [`Sender`](struct@Sender).
///
/// Instances are created by the [`channel`](fn@channel) function.
#[derive(Debug)]
pub struct Receiver<T> {
    /// Pointer to the shared state
    shared: Arc<Shared<T>>,

    /// Last observed version
    version: usize,
}

/// Sends values to the associated [`Receiver`](struct@Receiver).
///
/// Instances are created by the [`channel`](fn@channel) function.
#[derive(Debug)]
pub struct Sender<T> {
    shared: Arc<Shared<T>>,
}

/// Returns a reference to the inner value
///
/// Outstanding borrows hold a read lock on the inner value. This means that
/// long lived borrows could cause the produce half to block. It is recommended
/// to keep the borrow as short lived as possible.
#[derive(Debug)]
pub struct Ref<'a, T> {
    inner: RwLockReadGuard<'a, T>,
}

#[derive(Debug)]
struct Shared<T> {
    /// The most recent value
    value: RwLock<T>,

    /// The current version
    ///
    /// The lowest bit represents a "closed" state. The rest of the bits
    /// represent the current version.
    version: AtomicUsize,

    /// Tracks the number of `Receiver` instances
    ref_count_rx: AtomicUsize,

    /// Notifies waiting receivers that the value changed.
    notify_rx: Notify,

    /// Notifies any task listening for `Receiver` dropped events
    notify_tx: Notify,
}

pub mod error {
    //! Watch error types

    use std::fmt;

    /// Error produced when sending a value fails.
    #[derive(Debug)]
    pub struct SendError<T> {
        pub(crate) inner: T,
    }

    // ===== impl SendError =====

    impl<T: fmt::Debug> fmt::Display for SendError<T> {
        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
            write!(fmt, "channel closed")
        }
    }

    impl<T: fmt::Debug> std::error::Error for SendError<T> {}

    /// Error produced when receiving a change notification.
    #[derive(Debug)]
    pub struct RecvError(pub(super) ());

    // ===== impl RecvError =====

    impl fmt::Display for RecvError {
        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
            write!(fmt, "channel closed")
        }
    }

    impl std::error::Error for RecvError {}
}

const CLOSED: usize = 1;

/// Creates a new watch channel, returning the "send" and "receive" handles.
///
/// All values sent by [`Sender`] will become visible to the [`Receiver`] handles.
/// Only the last value sent is made available to the [`Receiver`] half. All
/// intermediate values are dropped.
///
/// # Examples
///
/// ```
/// use tokio::sync::watch;
///
/// # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
///     let (tx, mut rx) = watch::channel("hello");
///
///     tokio::spawn(async move {
///         while rx.changed().await.is_ok() {
///             println!("received = {:?}", *rx.borrow());
///         }
///     });
///
///     tx.send("world")?;
/// # Ok(())
/// # }
/// ```
///
/// [`Sender`]: struct@Sender
/// [`Receiver`]: struct@Receiver
pub fn channel<T>(init: T) -> (Sender<T>, Receiver<T>) {
    let shared = Arc::new(Shared {
        value: RwLock::new(init),
        version: AtomicUsize::new(0),
        ref_count_rx: AtomicUsize::new(1),
        notify_rx: Notify::new(),
        notify_tx: Notify::new(),
    });

    let tx = Sender {
        shared: shared.clone(),
    };

    let rx = Receiver { shared, version: 0 };

    (tx, rx)
}

impl<T> Receiver<T> {
    /// Returns a reference to the most recently sent value
    ///
    /// Outstanding borrows hold a read lock. This means that long lived borrows
    /// could cause the send half to block. It is recommended to keep the borrow
    /// as short lived as possible.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::watch;
    ///
    /// let (_, rx) = watch::channel("hello");
    /// assert_eq!(*rx.borrow(), "hello");
    /// ```
    pub fn borrow(&self) -> Ref<'_, T> {
        let inner = self.shared.value.read().unwrap();
        Ref { inner }
    }

    /// Wait for a change notification
    ///
    /// Returns when a new value has been sent by the [`Sender`] since the last
    /// time `changed()` was called. When the `Sender` half is dropped, `Err` is
    /// returned.
    ///
    /// [`Sender`]: struct@Sender
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::watch;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let (tx, mut rx) = watch::channel("hello");
    ///
    ///     tokio::spawn(async move {
    ///         tx.send("goodbye").unwrap();
    ///     });
    ///
    ///     assert!(rx.changed().await.is_ok());
    ///     assert_eq!(*rx.borrow(), "goodbye");
    ///
    ///     // The `tx` handle has been dropped
    ///     assert!(rx.changed().await.is_err());
    /// }
    /// ```
    pub async fn changed(&mut self) -> Result<(), error::RecvError> {
        use std::future::Future;
        use std::pin::Pin;
        use std::task::Poll;

        // In order to avoid a race condition, we first request a notification,
        // **then** check the current value's version. If a new version exists,
        // the notification request is dropped. Requesting the notification
        // requires polling the future once.
        let notified = self.shared.notify_rx.notified();
        pin!(notified);

        // Polling the future once is guaranteed to return `Pending` as `watch`
        // only notifies using `notify_waiters`.
        crate::future::poll_fn(|cx| {
            let res = Pin::new(&mut notified).poll(cx);
            assert!(!res.is_ready());
            Poll::Ready(())
        })
        .await;

        if let Some(ret) = maybe_changed(&self.shared, &mut self.version) {
            return ret;
        }

        notified.await;

        maybe_changed(&self.shared, &mut self.version)
            .expect("[bug] failed to observe change after notificaton.")
    }
}

fn maybe_changed<T>(
    shared: &Shared<T>,
    version: &mut usize,
) -> Option<Result<(), error::RecvError>> {
    // Load the version from the state
    let state = shared.version.load(SeqCst);
    let new_version = state & !CLOSED;

    if *version != new_version {
        // Observe the new version and return
        *version = new_version;
        return Some(Ok(()));
    }

    if CLOSED == state & CLOSED {
        // All receivers have dropped.
        return Some(Err(error::RecvError(())));
    }

    None
}

impl<T> Clone for Receiver<T> {
    fn clone(&self) -> Self {
        let version = self.version;
        let shared = self.shared.clone();

        // No synchronization necessary as this is only used as a counter and
        // not memory access.
        shared.ref_count_rx.fetch_add(1, Relaxed);

        Receiver { version, shared }
    }
}

impl<T> Drop for Receiver<T> {
    fn drop(&mut self) {
        // No synchronization necessary as this is only used as a counter and
        // not memory access.
        if 1 == self.shared.ref_count_rx.fetch_sub(1, Relaxed) {
            // This is the last `Receiver` handle, tasks waiting on `Sender::closed()`
            self.shared.notify_tx.notify_waiters();
        }
    }
}

impl<T> Sender<T> {
    /// Sends a new value via the channel, notifying all receivers.
    pub fn send(&self, value: T) -> Result<(), error::SendError<T>> {
        // This is pretty much only useful as a hint anyway, so synchronization isn't critical.
        if 0 == self.shared.ref_count_rx.load(Relaxed) {
            return Err(error::SendError { inner: value });
        }

        *self.shared.value.write().unwrap() = value;

        // Update the version. 2 is used so that the CLOSED bit is not set.
        self.shared.version.fetch_add(2, SeqCst);

        // Notify all watchers
        self.shared.notify_rx.notify_waiters();

        Ok(())
    }

    /// Checks if the channel has been closed. This happens when all receivers
    /// have dropped.
    ///
    /// # Examples
    ///
    /// ```
    /// let (tx, rx) = tokio::sync::watch::channel(());
    /// assert!(!tx.is_closed());
    ///
    /// drop(rx);
    /// assert!(tx.is_closed());
    /// ```
    pub fn is_closed(&self) -> bool {
        self.shared.ref_count_rx.load(Relaxed) == 0
    }

    /// Completes when all receivers have dropped.
    ///
    /// This allows the producer to get notified when interest in the produced
    /// values is canceled and immediately stop doing work.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::watch;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let (tx, rx) = watch::channel("hello");
    ///
    ///     tokio::spawn(async move {
    ///         // use `rx`
    ///         drop(rx);
    ///     });
    ///
    ///     // Waits for `rx` to drop
    ///     tx.closed().await;
    ///     println!("the `rx` handles dropped")
    /// }
    /// ```
    pub async fn closed(&self) {
        let notified = self.shared.notify_tx.notified();

        if self.shared.ref_count_rx.load(Relaxed) == 0 {
            return;
        }

        notified.await;
        debug_assert_eq!(0, self.shared.ref_count_rx.load(Relaxed));
    }
}

impl<T> Drop for Sender<T> {
    fn drop(&mut self) {
        self.shared.version.fetch_or(CLOSED, SeqCst);
        self.shared.notify_rx.notify_waiters();
    }
}

// ===== impl Ref =====

impl<T> ops::Deref for Ref<'_, T> {
    type Target = T;

    fn deref(&self) -> &T {
        self.inner.deref()
    }
}
<|endoftext|>


<commit_before>use racer::Match;
use racer::{do_local_search,first_match,to_refs};
use racer::ast;
use racer::codeiter;
use racer::scopes;
use racer;

use std::io::File;
use std::io::BufferedReader;
use std::str;
use std::strbuf::StrBuf;

fn find_start_of_function_body(src: &str) -> uint {
    // TODO: this should ignore anything inside parens so as to skip the arg list
    return src.find_str("{").unwrap();
}

fn get_type_of_fnarg(m: &Match, fpath: &Path, msrc: &str) -> Option<Match> {
    debug!("PHIL get type of fn arg {:?}",m);
    let point = scopes::find_stmt_start(msrc, m.point).unwrap();
    for (start,end) in codeiter::iter_stmts(msrc.slice_from(point)) {
        let blob = msrc.slice(point+start,point+end);

        // wrap in "impl blah { }" so that methods get parsed correctly too
        let mut s = StrBuf::new();
        s.push_str("impl blah {");
        let impl_header_len = s.len();
        s.push_str(blob.slice_to(find_start_of_function_body(blob)+1));
        s.push_str("}}");
        let fn_ = ast::parse_fn(s);
        let mut result = None;
        for (_/*name*/, pos, ty_) in fn_.args.move_iter() {
            let globalpos = pos - impl_header_len + start + point;
            if globalpos == m.point && ty_.len() != 0 {
                let v = to_refs(&ty_);
                let fqn = v.as_slice();
                result = first_match(|m| do_local_search(fqn,
                                                         fpath,
                                                         globalpos,
                                                         racer::ExactMatch, m));
            }
        }
        return result;
    }
    None
}

fn get_type_of_let_expr(m: &Match, fpath: &Path, msrc: &str) -> Option<Match> {
    // ASSUMPTION: this is being called on a let decl
    let mut result = None;

    let opoint = scopes::find_stmt_start(msrc, m.point);
    let point = opoint.unwrap();

    let src = msrc.slice_from(point);
    for (start,end) in codeiter::iter_stmts(src) {
        let blob = src.slice(start,end);

        ast::parse_let(StrBuf::from_str(blob)).map(|letres|{
            debug!("PHIL parse let result {}", &letres.init);
            // HACK, convert from &[~str] to &[&str]
            let v = to_refs(&letres.init);
            let fqn = v.as_slice();
            result = first_match(|m| do_local_search(fqn, fpath, point+start, racer::ExactMatch, m));
        });
        break;
    }

    debug!("PHIL let search result is {:?}",result);

    // if it's a struct then cool
    // if it's a function then we need to resolve the return type

    if result.is_none(){
        return result
    }

    let res = result.unwrap();
    match res.mtype {
        Struct => {
            return Some(res);
        }
        Function => {
            let path = get_return_type_of_function(&res);
            if path.len() == 0 {
                return None;
            }

            debug!("PHIL return type is {}", path);
            let v = to_refs(&path);
            let fqn = v.as_slice();
            return first_match(|m| do_local_search(fqn, &res.filepath, res.point, racer::ExactMatch, m));
        }
        _ => { return None }
    };
}

pub fn get_type_of_OLD(m: &Match, fpath: &Path, msrc: &str) -> Option<Match> {
    debug!("PHIL get_type_of OLD {:?}",m);
    debug!("PHIL get_type_of OLD {}",m.matchstr);

    match m.mtype {
        Let => get_type_of_let_expr(m, fpath, msrc),
        FnArg => get_type_of_fnarg(m, fpath, msrc),
        _ => { println!("Can't get type of {:?}",m.mtype); None }
    }
}

pub fn get_fields_of_struct(m: &Match) -> Vec<(StrBuf, uint)> {
    let filetxt = BufferedReader::new(File::open(&m.filepath)).read_to_end().unwrap();
    let src = str::from_utf8(filetxt.as_slice()).unwrap();

    let opoint = scopes::find_stmt_start(src, m.point);
    let structsrc = scopes::end_of_next_scope(src.slice_from(opoint.unwrap()));

    return ast::parse_struct_fields(StrBuf::from_str(structsrc));
}

pub fn get_return_type_of_function(fnmatch: &Match) -> Vec<~str> {
    let filetxt = BufferedReader::new(File::open(&fnmatch.filepath)).read_to_end().unwrap();
    let src = str::from_utf8(filetxt.as_slice()).unwrap();
    let point = scopes::find_stmt_start(src, fnmatch.point).unwrap();

    debug!("get_return_type_of_function |{}|",src.slice_from(point));

    let outputpath = src.slice_from(point).find_str("{").map(|n|{

        // TODO: surround this with 'impl { ... }' so that methods get parsed also
        let ss = src.slice(point, point+n+1);
        let mut decl = StrBuf::from_str(ss);
        decl = decl.append("}");
        debug!("PHIL: passing in {}",decl);
        return ast::parse_fn_output(decl);
    }).unwrap_or(Vec::new());

    return outputpath;
}
<commit_msg>Update resolve.rs<commit_after>use racer::Match;
use racer::{Struct, Function, Let, FnArg};
use racer::{do_local_search,first_match,to_refs};
use racer::ast;
use racer::codeiter;
use racer::scopes;
use racer;

use std::io::File;
use std::io::BufferedReader;
use std::str;
use std::strbuf::StrBuf;

fn find_start_of_function_body(src: &str) -> uint {
    // TODO: this should ignore anything inside parens so as to skip the arg list
    return src.find_str("{").unwrap();
}

fn get_type_of_fnarg(m: &Match, fpath: &Path, msrc: &str) -> Option<Match> {
    debug!("PHIL get type of fn arg {:?}",m);
    let point = scopes::find_stmt_start(msrc, m.point).unwrap();
    for (start,end) in codeiter::iter_stmts(msrc.slice_from(point)) {
        let blob = msrc.slice(point+start,point+end);

        // wrap in "impl blah { }" so that methods get parsed correctly too
        let mut s = StrBuf::new();
        s.push_str("impl blah {");
        let impl_header_len = s.len();
        s.push_str(blob.slice_to(find_start_of_function_body(blob)+1));
        s.push_str("}}");
        let fn_ = ast::parse_fn(s);
        let mut result = None;
        for (_/*name*/, pos, ty_) in fn_.args.move_iter() {
            let globalpos = pos - impl_header_len + start + point;
            if globalpos == m.point && ty_.len() != 0 {
                let v = to_refs(&ty_);
                let fqn = v.as_slice();
                result = first_match(|m| do_local_search(fqn,
                                                         fpath,
                                                         globalpos,
                                                         racer::ExactMatch, m));
            }
        }
        return result;
    }
    None
}

fn get_type_of_let_expr(m: &Match, fpath: &Path, msrc: &str) -> Option<Match> {
    // ASSUMPTION: this is being called on a let decl
    let mut result = None;

    let opoint = scopes::find_stmt_start(msrc, m.point);
    let point = opoint.unwrap();

    let src = msrc.slice_from(point);
    for (start,end) in codeiter::iter_stmts(src) {
        let blob = src.slice(start,end);

        ast::parse_let(StrBuf::from_str(blob)).map(|letres|{
            debug!("PHIL parse let result {}", &letres.init);
            // HACK, convert from &[~str] to &[&str]
            let v = to_refs(&letres.init);
            let fqn = v.as_slice();
            result = first_match(|m| do_local_search(fqn, fpath, point+start, racer::ExactMatch, m));
        });
        break;
    }

    debug!("PHIL let search result is {:?}",result);

    // if it's a struct then cool
    // if it's a function then we need to resolve the return type

    if result.is_none(){
        return result
    }

    let res = result.unwrap();
    match res.mtype {
        Struct => {
            return Some(res);
        }
        Function => {
            let path = get_return_type_of_function(&res);
            if path.len() == 0 {
                return None;
            }

            debug!("PHIL return type is {}", path);
            let v = to_refs(&path);
            let fqn = v.as_slice();
            return first_match(|m| do_local_search(fqn, &res.filepath, res.point, racer::ExactMatch, m));
        }
        _ => { return None }
    };
}

pub fn get_type_of_OLD(m: &Match, fpath: &Path, msrc: &str) -> Option<Match> {
    debug!("PHIL get_type_of OLD {:?}",m);
    debug!("PHIL get_type_of OLD {}",m.matchstr);

    match m.mtype {
        Let => get_type_of_let_expr(m, fpath, msrc),
        FnArg => get_type_of_fnarg(m, fpath, msrc),
        _ => { println!("Can't get type of {:?}",m.mtype); None }
    }
}

pub fn get_fields_of_struct(m: &Match) -> Vec<(StrBuf, uint)> {
    let filetxt = BufferedReader::new(File::open(&m.filepath)).read_to_end().unwrap();
    let src = str::from_utf8(filetxt.as_slice()).unwrap();

    let opoint = scopes::find_stmt_start(src, m.point);
    let structsrc = scopes::end_of_next_scope(src.slice_from(opoint.unwrap()));

    return ast::parse_struct_fields(StrBuf::from_str(structsrc));
}

pub fn get_return_type_of_function(fnmatch: &Match) -> Vec<~str> {
    let filetxt = BufferedReader::new(File::open(&fnmatch.filepath)).read_to_end().unwrap();
    let src = str::from_utf8(filetxt.as_slice()).unwrap();
    let point = scopes::find_stmt_start(src, fnmatch.point).unwrap();

    debug!("get_return_type_of_function |{}|",src.slice_from(point));

    let outputpath = src.slice_from(point).find_str("{").map(|n|{

        // TODO: surround this with 'impl { ... }' so that methods get parsed also
        let ss = src.slice(point, point+n+1);
        let mut decl = StrBuf::from_str(ss);
        decl = decl.append("}");
        debug!("PHIL: passing in {}",decl);
        return ast::parse_fn_output(decl);
    }).unwrap_or(Vec::new());

    return outputpath;
}
<|endoftext|>


<commit_before>#[macro_use]
pub mod proto;

use std::collections::HashMap;
use std::sync::Arc;
use std::io;
use std::time::Duration;
use parking_lot::{Mutex, RwLock};
use std::thread;
use tcp;
use utils::time;
use utils::u8vec::*;
use futures::Future;
use bifrost_hasher::hash_str;
use DISABLE_SHORTCUT;

lazy_static! {
    pub static ref DEFAULT_CLIENT_POOL: ClientPool = ClientPool::new();
}

#[derive(Serialize, Deserialize, Debug)]
pub enum RPCRequestError {
    FunctionIdNotFound,
    ServiceIdNotFound,
    Other,
}

#[derive(Debug)]
pub enum RPCError {
    IOError(io::Error),
    RequestError(RPCRequestError),
}

pub trait RPCService: Sync + Send {
    fn dispatch(&self, data: Vec<u8>) -> Result<Vec<u8>, RPCRequestError>;
    fn register_shortcut_service(&self, service_ptr: usize, server_id: u64, service_id: u64);
}

pub struct Server {
    services: RwLock<HashMap<u64, Arc<RPCService>>>,
    pub address: String,
    pub server_id: u64
}

pub struct ClientPool {
    clients: Mutex<HashMap<String, Arc<RPCClient>>>
}

fn encode_res(res: Result<Vec<u8>, RPCRequestError>) -> Vec<u8> {
    match res {
        Ok(vec) => {
            [0u8; 1].iter().cloned().chain(vec.into_iter()).collect()
        },
        Err(e) => {
            let err_id = match e {
                RPCRequestError::FunctionIdNotFound => 1u8,
                RPCRequestError::ServiceIdNotFound => 2u8,
                _ => 255u8
            };
            vec!(err_id)
        }
    }
}

fn decode_res(res: io::Result<Vec<u8>>) -> Result<Vec<u8>, RPCError> {
    match res {
        Ok(res) => {
            if res[0] == 0u8 {
                Ok(res.into_iter().skip(1).collect())
            } else {
                match res[0] {
                    1u8 => Err(RPCError::RequestError(RPCRequestError::FunctionIdNotFound)),
                    2u8 => Err(RPCError::RequestError(RPCRequestError::ServiceIdNotFound)),
                    _ => Err(RPCError::RequestError(RPCRequestError::Other)),
                }
            }
        },
        Err(e) => Err(RPCError::IOError(e))
    }
}

impl Server {
    pub fn new(address: &String) -> Arc<Server> {
        Arc::new(Server {
            services: RwLock::new(HashMap::new()),
            address: address.clone(),
            server_id: hash_str(address)
        })
    }
    pub fn listen(server: &Arc<Server>) {
        let address = &server.address;
        let server = server.clone();
        tcp::server::Server::new(address, Box::new(move |data| {
            let (svr_id, data) = extract_u64_head(data);
            let svr_map = server.services.read();
            let service = svr_map.get(&svr_id);
            let res = match service {
                Some(service) => {
                    encode_res(service.dispatch(data))
                },
                None => encode_res(Err(RPCRequestError::ServiceIdNotFound) as Result<Vec<u8>, RPCRequestError>)
            };
            //println!("SVR RPC: {} - {}ms", svr_id, time::get_time() - t);
            res
        }));
    }
    pub fn listen_and_resume(server: &Arc<Server>) {
        let server = server.clone();
        thread::spawn(move|| {
            let server = server;
            Server::listen(&server);
        });
    }
    pub fn register_service<T>(&self, service_id: u64,  service: &Arc<T>)
    where T: RPCService + Sized + 'static{
        let service = service.clone();
        if !DISABLE_SHORTCUT {
            println!("SERVICE SHORTCUT DISABLED");
            let service_ptr = Arc::into_raw(service.clone()) as usize;
            service.register_shortcut_service(service_ptr, self.server_id, service_id);
        }
        self.services.write().insert(service_id, service);
    }
    pub fn remove_service(&self, service_id: u64) {
        self.services.write().remove(&service_id);
    }
    pub fn address(&self) -> &String {
        &self.address
    }
}

pub struct RPCClient {
    client: Mutex<tcp::client::Client>,
    pub server_id: u64,
    pub address: String
}

impl RPCClient {
    pub fn send(&self, svr_id: u64, data: Vec<u8>) -> Result<Vec<u8>, RPCError> {
        decode_res(self.client.lock().send(prepend_u64(svr_id, data)))
    }
    pub fn send_async(&self, svr_id: u64, data: Vec<u8>) -> Box<Future<Item = Vec<u8>, Error = RPCError>> {
        Box::new(self.client.lock()
            .send_async(prepend_u64(svr_id, data))
            .then(move |res| decode_res(res)))
    }
    pub fn new(addr: &String) -> io::Result<Arc<RPCClient>> {
        let client = tcp::client::Client::connect(addr)?;
        Ok(Arc::new(RPCClient {
            server_id: client.server_id,
            client: Mutex::new(client),
            address: addr.clone()
        }))
    }
    pub fn with_timeout(addr: &String, timeout: Duration) -> io::Result<Arc<RPCClient>> {
        let client = tcp::client::Client::connect_with_timeout(addr, timeout)?;
        Ok(Arc::new(RPCClient {
            server_id: client.server_id,
            client: Mutex::new(client),
            address: addr.clone()
        }))
    }
}

impl ClientPool {
    pub fn new() -> ClientPool {
        ClientPool {
            clients: Mutex::new(HashMap::new())
        }
    }

    pub fn get(&self, addr: &String) -> io::Result<Arc<RPCClient>> {
        let mut clients = self.clients.lock();
        if clients.contains_key(addr) {
            Ok(clients.get(addr).unwrap().clone())
        } else {
            let client = RPCClient::new(addr);
            if let Ok(client) = client {
                clients.insert(addr.clone(), client.clone());
                Ok(client)
            } else {
                Err(client.err().unwrap())
            }
        }
    }
}<commit_msg>wrong info<commit_after>#[macro_use]
pub mod proto;

use std::collections::HashMap;
use std::sync::Arc;
use std::io;
use std::time::Duration;
use parking_lot::{Mutex, RwLock};
use std::thread;
use tcp;
use utils::time;
use utils::u8vec::*;
use futures::Future;
use bifrost_hasher::hash_str;
use DISABLE_SHORTCUT;

lazy_static! {
    pub static ref DEFAULT_CLIENT_POOL: ClientPool = ClientPool::new();
}

#[derive(Serialize, Deserialize, Debug)]
pub enum RPCRequestError {
    FunctionIdNotFound,
    ServiceIdNotFound,
    Other,
}

#[derive(Debug)]
pub enum RPCError {
    IOError(io::Error),
    RequestError(RPCRequestError),
}

pub trait RPCService: Sync + Send {
    fn dispatch(&self, data: Vec<u8>) -> Result<Vec<u8>, RPCRequestError>;
    fn register_shortcut_service(&self, service_ptr: usize, server_id: u64, service_id: u64);
}

pub struct Server {
    services: RwLock<HashMap<u64, Arc<RPCService>>>,
    pub address: String,
    pub server_id: u64
}

pub struct ClientPool {
    clients: Mutex<HashMap<String, Arc<RPCClient>>>
}

fn encode_res(res: Result<Vec<u8>, RPCRequestError>) -> Vec<u8> {
    match res {
        Ok(vec) => {
            [0u8; 1].iter().cloned().chain(vec.into_iter()).collect()
        },
        Err(e) => {
            let err_id = match e {
                RPCRequestError::FunctionIdNotFound => 1u8,
                RPCRequestError::ServiceIdNotFound => 2u8,
                _ => 255u8
            };
            vec!(err_id)
        }
    }
}

fn decode_res(res: io::Result<Vec<u8>>) -> Result<Vec<u8>, RPCError> {
    match res {
        Ok(res) => {
            if res[0] == 0u8 {
                Ok(res.into_iter().skip(1).collect())
            } else {
                match res[0] {
                    1u8 => Err(RPCError::RequestError(RPCRequestError::FunctionIdNotFound)),
                    2u8 => Err(RPCError::RequestError(RPCRequestError::ServiceIdNotFound)),
                    _ => Err(RPCError::RequestError(RPCRequestError::Other)),
                }
            }
        },
        Err(e) => Err(RPCError::IOError(e))
    }
}

impl Server {
    pub fn new(address: &String) -> Arc<Server> {
        Arc::new(Server {
            services: RwLock::new(HashMap::new()),
            address: address.clone(),
            server_id: hash_str(address)
        })
    }
    pub fn listen(server: &Arc<Server>) {
        let address = &server.address;
        let server = server.clone();
        tcp::server::Server::new(address, Box::new(move |data| {
            let (svr_id, data) = extract_u64_head(data);
            let svr_map = server.services.read();
            let service = svr_map.get(&svr_id);
            let res = match service {
                Some(service) => {
                    encode_res(service.dispatch(data))
                },
                None => encode_res(Err(RPCRequestError::ServiceIdNotFound) as Result<Vec<u8>, RPCRequestError>)
            };
            //println!("SVR RPC: {} - {}ms", svr_id, time::get_time() - t);
            res
        }));
    }
    pub fn listen_and_resume(server: &Arc<Server>) {
        let server = server.clone();
        thread::spawn(move|| {
            let server = server;
            Server::listen(&server);
        });
    }
    pub fn register_service<T>(&self, service_id: u64,  service: &Arc<T>)
    where T: RPCService + Sized + 'static{
        let service = service.clone();
        if !DISABLE_SHORTCUT {
            let service_ptr = Arc::into_raw(service.clone()) as usize;
            service.register_shortcut_service(service_ptr, self.server_id, service_id);
        } else {
            println!("SERVICE SHORTCUT DISABLED");
        }
        self.services.write().insert(service_id, service);
    }
    pub fn remove_service(&self, service_id: u64) {
        self.services.write().remove(&service_id);
    }
    pub fn address(&self) -> &String {
        &self.address
    }
}

pub struct RPCClient {
    client: Mutex<tcp::client::Client>,
    pub server_id: u64,
    pub address: String
}

impl RPCClient {
    pub fn send(&self, svr_id: u64, data: Vec<u8>) -> Result<Vec<u8>, RPCError> {
        decode_res(self.client.lock().send(prepend_u64(svr_id, data)))
    }
    pub fn send_async(&self, svr_id: u64, data: Vec<u8>) -> Box<Future<Item = Vec<u8>, Error = RPCError>> {
        Box::new(self.client.lock()
            .send_async(prepend_u64(svr_id, data))
            .then(move |res| decode_res(res)))
    }
    pub fn new(addr: &String) -> io::Result<Arc<RPCClient>> {
        let client = tcp::client::Client::connect(addr)?;
        Ok(Arc::new(RPCClient {
            server_id: client.server_id,
            client: Mutex::new(client),
            address: addr.clone()
        }))
    }
    pub fn with_timeout(addr: &String, timeout: Duration) -> io::Result<Arc<RPCClient>> {
        let client = tcp::client::Client::connect_with_timeout(addr, timeout)?;
        Ok(Arc::new(RPCClient {
            server_id: client.server_id,
            client: Mutex::new(client),
            address: addr.clone()
        }))
    }
}

impl ClientPool {
    pub fn new() -> ClientPool {
        ClientPool {
            clients: Mutex::new(HashMap::new())
        }
    }

    pub fn get(&self, addr: &String) -> io::Result<Arc<RPCClient>> {
        let mut clients = self.clients.lock();
        if clients.contains_key(addr) {
            Ok(clients.get(addr).unwrap().clone())
        } else {
            let client = RPCClient::new(addr);
            if let Ok(client) = client {
                clients.insert(addr.clone(), client.clone());
                Ok(client)
            } else {
                Err(client.err().unwrap())
            }
        }
    }
}<|endoftext|>


<commit_before>use iron::prelude::*;
use iron::status;

use std::io;
use std::string::*;
use std::path::{PathBuf, Path};
use std::env;
use std::fs;
use rustc_serialize::{Encodable, Encoder};
use std::process::Output;

use mopa::Any;

use handlers::powershell::PowerShellScript;
use handlers::python::PythonScript;
use handlers::sh::ShellScript;
use handlers::binary::BinaryScript;
use constants;

pub trait Script : Send + Sync + Any {
    fn get_name(&self) -> &str;
    fn get_relative_path(&self) -> &str;
    fn get_extension(&self) -> &str;
    fn get_full_path(&self) -> io::Result<PathBuf>;
    fn run(&self) -> IronResult<Response>;
}
mopafy!(Script);

// -- New script types must be added here for proper serialization
// Implements encoding for Script trait objects
impl Encodable for Box<Script> {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        if let Some(script) = self.downcast_ref::<PowerShellScript>() {
            script.encode(s)
        } else if let Some(script) = self.downcast_ref::<PythonScript>() {
            script.encode(s)
        } else if let Some(script) = self.downcast_ref::<ShellScript>() {
            script.encode(s)
        } else {
            panic!("Unknown concrete script type.")
        }
    }
}

// -- New script types must be added here so they can be constructed
pub fn construct_script(name: String, path: String, extension: String) -> Option<Box<Script>> {
    let script_kind = get_type_kind_for_ext(&extension);
    match script_kind {
        ScriptKind::PowerShell => Some(Box::new(PowerShellScript::new(name, path, extension))),
        ScriptKind::Python => Some(Box::new(PythonScript::new(name, path, extension))),
        ScriptKind::Shell => Some(Box::new(ShellScript::new(name, path, extension))),
        ScriptKind::Binary => Some(Box::new(BinaryScript::new(name, path))),
        ScriptKind::Unknown => None,
    }
}

pub fn construct_script_binary(name: String, rel_path: String, full_path: &Path) -> Option<Box<Script>> {
    match check_is_executable(full_path) {
        true => Some(Box::new(BinaryScript::new(name, rel_path))),
        false => None,
    }
}

//todo: implement, and rename the _ to "path"
fn check_is_executable(_: &Path) -> bool {
    //todo: we only do this on Unix systems. Check file permissions, and see if we can execute it.
    return false;
}

// -- New script types must be added here so they can be identified
#[derive(RustcEncodable, Debug)]
pub enum ScriptKind {
    PowerShell,
    Python,
    Shell,
    Binary,
    Unknown,
}

// -- New script types must be added here so we can associate an extension with a ScriptKind
pub fn get_type_kind_for_ext(string: &str) -> ScriptKind {
    match string {
        "ps1" => ScriptKind::PowerShell,
        "py" => ScriptKind::Python,
        "sh" => ScriptKind::Shell,
        "" => ScriptKind::Unknown,
        _ => ScriptKind::Unknown,
    }
}

pub fn generic_get_full_path<T: Script>(script: &T) -> io::Result<PathBuf> {
    let current_exe = try!(env::current_exe());
    match current_exe.parent() {
        Some(parent_dir) => {
            let script_path = parent_dir.join("scripts")
                                        .join(format!("{}{}",
                                                      script.get_name(),
                                                      script.get_extension()));
            // check in scripts dir
            if fs::metadata(&script_path).is_ok() {
                Ok(script_path)
            } else {
                // check in subdir
                let script_path = parent_dir.join("scripts")
                                            .join(constants::IMMEDIATE_RET_PATH)
                                            .join(format!("{}{}",
                                                          script.get_name(),
                                                          script.get_extension()));
                if fs::metadata(&script_path).is_ok() {
                    Ok(script_path)
                } else {
                    Err(io::Error::new(io::ErrorKind::NotFound, "Unable to generate script path."))
                }
            }
        }
        None => Err(io::Error::new(io::ErrorKind::NotFound, "Unable to generate script path.")),
    }
}

pub fn generic_run(output: io::Result<Output>) -> IronResult<Response> {
    match output {
        Ok(output) => {
            match output.status.success() {
                true => {
                    let script_output = String::from_utf8_lossy(&output.stdout).into_owned();
                    println!("Script success. Output:\n{}", script_output);
                    Ok(Response::with((status::Ok, script_output)))
                }
                false => {
                    println!("{}", String::from_utf8_lossy(&output.stderr).into_owned());
                    generic_error_handler()
                }
            }
        }
        Err(_) => {
            println!("No output from PowerShell script.");
            generic_error_handler()
        }
    }
}

pub fn generic_error_handler() -> IronResult<Response> {
    Ok(Response::with(status::InternalServerError))
}
<commit_msg>clarify use of mopa's Any<commit_after>use iron::prelude::*;
use iron::status;

use std::io;
use std::string::*;
use std::path::{PathBuf, Path};
use std::env;
use std::fs;
use rustc_serialize::{Encodable, Encoder};
use std::process::Output;

use mopa;

use handlers::powershell::PowerShellScript;
use handlers::python::PythonScript;
use handlers::sh::ShellScript;
use handlers::binary::BinaryScript;
use constants;

pub trait Script : Send + Sync + mopa::Any {
    fn get_name(&self) -> &str;
    fn get_relative_path(&self) -> &str;
    fn get_extension(&self) -> &str;
    fn get_full_path(&self) -> io::Result<PathBuf>;
    fn run(&self) -> IronResult<Response>;
}
mopafy!(Script);

// -- New script types must be added here for proper serialization
// Implements encoding for Script trait objects
impl Encodable for Box<Script> {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        if let Some(script) = self.downcast_ref::<PowerShellScript>() {
            script.encode(s)
        } else if let Some(script) = self.downcast_ref::<PythonScript>() {
            script.encode(s)
        } else if let Some(script) = self.downcast_ref::<ShellScript>() {
            script.encode(s)
        } else {
            panic!("Unknown concrete script type.")
        }
    }
}

// -- New script types must be added here so they can be constructed
pub fn construct_script(name: String, path: String, extension: String) -> Option<Box<Script>> {
    let script_kind = get_type_kind_for_ext(&extension);
    match script_kind {
        ScriptKind::PowerShell => Some(Box::new(PowerShellScript::new(name, path, extension))),
        ScriptKind::Python => Some(Box::new(PythonScript::new(name, path, extension))),
        ScriptKind::Shell => Some(Box::new(ShellScript::new(name, path, extension))),
        ScriptKind::Binary => Some(Box::new(BinaryScript::new(name, path))),
        ScriptKind::Unknown => None,
    }
}

pub fn construct_script_binary(name: String, rel_path: String, full_path: &Path) -> Option<Box<Script>> {
    match check_is_executable(full_path) {
        true => Some(Box::new(BinaryScript::new(name, rel_path))),
        false => None,
    }
}

//todo: implement, and rename the _ to "path"
fn check_is_executable(_: &Path) -> bool {
    //todo: we only do this on Unix systems. Check file permissions, and see if we can execute it.
    return false;
}

// -- New script types must be added here so they can be identified
#[derive(RustcEncodable, Debug)]
pub enum ScriptKind {
    PowerShell,
    Python,
    Shell,
    Binary,
    Unknown,
}

// -- New script types must be added here so we can associate an extension with a ScriptKind
pub fn get_type_kind_for_ext(string: &str) -> ScriptKind {
    match string {
        "ps1" => ScriptKind::PowerShell,
        "py" => ScriptKind::Python,
        "sh" => ScriptKind::Shell,
        "" => ScriptKind::Unknown,
        _ => ScriptKind::Unknown,
    }
}

pub fn generic_get_full_path<T: Script>(script: &T) -> io::Result<PathBuf> {
    let current_exe = try!(env::current_exe());
    match current_exe.parent() {
        Some(parent_dir) => {
            let script_path = parent_dir.join("scripts")
                                        .join(format!("{}{}",
                                                      script.get_name(),
                                                      script.get_extension()));
            // check in scripts dir
            if fs::metadata(&script_path).is_ok() {
                Ok(script_path)
            } else {
                // check in subdir
                let script_path = parent_dir.join("scripts")
                                            .join(constants::IMMEDIATE_RET_PATH)
                                            .join(format!("{}{}",
                                                          script.get_name(),
                                                          script.get_extension()));
                if fs::metadata(&script_path).is_ok() {
                    Ok(script_path)
                } else {
                    Err(io::Error::new(io::ErrorKind::NotFound, "Unable to generate script path."))
                }
            }
        }
        None => Err(io::Error::new(io::ErrorKind::NotFound, "Unable to generate script path.")),
    }
}

pub fn generic_run(output: io::Result<Output>) -> IronResult<Response> {
    match output {
        Ok(output) => {
            match output.status.success() {
                true => {
                    let script_output = String::from_utf8_lossy(&output.stdout).into_owned();
                    println!("Script success. Output:\n{}", script_output);
                    Ok(Response::with((status::Ok, script_output)))
                }
                false => {
                    println!("{}", String::from_utf8_lossy(&output.stderr).into_owned());
                    generic_error_handler()
                }
            }
        }
        Err(_) => {
            println!("No output from PowerShell script.");
            generic_error_handler()
        }
    }
}

pub fn generic_error_handler() -> IronResult<Response> {
    Ok(Response::with(status::InternalServerError))
}
<|endoftext|>


<commit_before>use core::{Distribution, DefaultDistribution, IntoDistribution};

use std::ops::{RangeFull};
use std::marker;
use std::mem;

use rand::Rng;
use num::PrimInt;

pub struct Uniform<T> (marker::PhantomData<fn() -> T>);

trait DowncastPrimitiveInteger: PrimInt {
    fn from_u32(u: u32) -> Self;
    fn from_u64(u: u64) -> Self;
}

impl <T> Uniform<T> {
    #[inline]
    pub fn new() -> Uniform<T> {
        Uniform(marker::PhantomData)
    }
}

impl <T: DowncastPrimitiveInteger> IntoDistribution<T> for RangeFull
{
    type Distribution = Uniform<T>;

    #[inline]
    fn into_distribution(self) -> Uniform<T> {
        Uniform::new()
    }
}

impl <T: DowncastPrimitiveInteger> Distribution for Uniform<T>
{
    type Output = T;

    #[inline]
    fn sample<R: Rng>(&self, rng: &mut R) -> T {
        if mem::size_of::<T>() <= 4 {
            T::from_u32(rng.next_u32())
        } else {
            T::from_u64(rng.next_u64())
        }
    }
}

macro_rules! integer_impls {
    ($($ty:ty),*) => {
        $(
            impl DowncastPrimitiveInteger for $ty {
                #[inline]
                fn from_u32(u: u32) -> $ty {
                    u as $ty
                }

                #[inline]
                fn from_u64(u: u64) -> $ty {
                    u as $ty
                }
            }
        )*
    }
}

integer_impls! {
    i8, i16, i32, i64, isize,
    u8, u16, u32, u64, usize
}

impl Distribution for Uniform<bool> {
    type Output = bool;

    #[inline]
    fn sample<R: Rng>(&self, rng: &mut R) -> bool {
        Uniform::<u8>::new().sample(rng) & 1 == 1
    }
}

macro_rules! default_distribution_is_uniform {
    ($($ty:ty),* ) => {
        $(
            impl DefaultDistribution for $ty {
                type Distribution = Uniform<Self>;

                #[inline]
                fn default_distribution() -> Uniform<Self> {
                    Uniform::new()
                }
            }
        )*
    }
}

default_distribution_is_uniform! { isize, i8, i16, i32, i64,
                                   usize, u8, u16, u32, u64,
                                   bool }

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

    use core::{Distribution, IntoDistribution};

    use rand::{self, thread_rng, Rng};
    use std::ops::{RangeFull};

    #[test]
    fn test_generate_u8() {
        let mut rng: rand::XorShiftRng = rand::thread_rng().gen();

        fn foo<D: IntoDistribution<T>, T, R: Rng>(d: D, rng: &mut R) -> T {
            d.into_distribution().sample(rng)
        }

        let _: u8 = foo(RangeFull, &mut rng);
    }

    #[test]
    fn test_generate_u8_with_type_annotation() {
        let mut rng: rand::XorShiftRng = rand::thread_rng().gen();

        let d = IntoDistribution::<u8>::into_distribution(RangeFull);
        let _: u8 = d.sample(&mut rng);
    }

    #[test]
    fn test_range_full_into_distribution() {
        let mut rng: rand::XorShiftRng = rand::thread_rng().gen();

        let d: Uniform<u8> = (..).into_distribution();
        let _: u8 = d.sample(&mut rng);
    }
}
<commit_msg>Simplifying tests.<commit_after>use core::{Distribution, DefaultDistribution, IntoDistribution};

use std::ops::{RangeFull};
use std::marker;
use std::mem;

use rand::Rng;
use num::PrimInt;

pub struct Uniform<T> (marker::PhantomData<fn() -> T>);

trait DowncastPrimitiveInteger: PrimInt {
    fn from_u32(u: u32) -> Self;
    fn from_u64(u: u64) -> Self;
}

impl <T> Uniform<T> {
    #[inline]
    pub fn new() -> Uniform<T> {
        Uniform(marker::PhantomData)
    }
}

impl <T: DowncastPrimitiveInteger> IntoDistribution<T> for RangeFull
{
    type Distribution = Uniform<T>;

    #[inline]
    fn into_distribution(self) -> Uniform<T> {
        Uniform::new()
    }
}

impl <T: DowncastPrimitiveInteger> Distribution for Uniform<T>
{
    type Output = T;

    #[inline]
    fn sample<R: Rng>(&self, rng: &mut R) -> T {
        if mem::size_of::<T>() <= 4 {
            T::from_u32(rng.next_u32())
        } else {
            T::from_u64(rng.next_u64())
        }
    }
}

macro_rules! integer_impls {
    ($($ty:ty),*) => {
        $(
            impl DowncastPrimitiveInteger for $ty {
                #[inline]
                fn from_u32(u: u32) -> $ty {
                    u as $ty
                }

                #[inline]
                fn from_u64(u: u64) -> $ty {
                    u as $ty
                }
            }
        )*
    }
}

integer_impls! {
    i8, i16, i32, i64, isize,
    u8, u16, u32, u64, usize
}

impl Distribution for Uniform<bool> {
    type Output = bool;

    #[inline]
    fn sample<R: Rng>(&self, rng: &mut R) -> bool {
        Uniform::<u8>::new().sample(rng) & 1 == 1
    }
}

macro_rules! default_distribution_is_uniform {
    ($($ty:ty),* ) => {
        $(
            impl DefaultDistribution for $ty {
                type Distribution = Uniform<Self>;

                #[inline]
                fn default_distribution() -> Uniform<Self> {
                    Uniform::new()
                }
            }
        )*
    }
}

default_distribution_is_uniform! { isize, i8, i16, i32, i64,
                                   usize, u8, u16, u32, u64,
                                   bool }

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

    use core::{Distribution, IntoDistribution};

    use rand::{self, thread_rng, Rng};
    use std::ops::{RangeFull};

    fn create_rng() -> rand::XorShiftRng {
        rand::thread_rng().gen()
    }

    #[test]
    fn test_generate_u8() {
        let mut rng = create_rng();

        fn foo<D: IntoDistribution<T>, T, R: Rng>(d: D, rng: &mut R) -> T {
            d.into_distribution().sample(rng)
        }

        let _: u8 = foo(RangeFull, &mut rng);
    }

    #[test]
    fn test_generate_u8_with_type_annotation() {
        let mut rng = create_rng();

        let d = IntoDistribution::<u8>::into_distribution(RangeFull);
        let _: u8 = d.sample(&mut rng);
    }

    #[test]
    fn test_range_full_into_distribution() {
        let mut rng = create_rng();

        let d: Uniform<u8> = (..).into_distribution();
        let _: u8 = d.sample(&mut rng);
    }
}
<|endoftext|>


<commit_before>/// All pressable keys.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum KeyCode {
	A,
	B,
	C,
	D,
	E,
	F,
	G,
	H,
	I,
	J,
	K,
	L,
	M,
	N,
	O,
	P,
	Q,
	R,
	S,
	T,
	U,
	V,
	W,
	X,
	Y,
	Z,
	/// Top-row `1/!` key.
	Row1,
	/// Top-row `2/@` key.
	Row2,
	/// Top-row `3/#` key.
	Row3,
	/// Top-row `4/$` key.
	Row4,
	/// Top-row `5/%` key.
	Row5,
	/// Top-row `6/^` key.
	Row6,
	/// Top-row `7/&` key.
	Row7,
	/// Top-row `8/*` key.
	Row8,
	/// Top-row `9/(` key.
	Row9,
	/// Top-row `0/)` key.
	Row0,
	/// Top-row `/~ key.
	Grave,
	/// Top-row `-/_` key.
	Minus,
	/// Top-row `=/+` key.
	Equals,
	/// Second-row `[/{` key.
	LeftBracket,
	/// Second-row `]/}` key.
	RightBracket,
	/// Second-row `\/|` key.
	Backslash,
	/// Third-row `;/:` key.
	Semicolon,
	/// Third-row `'/"` key.
	Apostrophe,
	/// Fourth-row `,/<` key.
	Comma,
	/// Fourth-row `./>` key.
	Period,
	/// Fourth-row `//?` key.
	Slash,
	F1,
	F2,
	F3,
	F4,
	F5,
	F6,
	F7,
	F8,
	F9,
	F10,
	F11,
	F12,
	Enter,
	Escape,
	Backspace,
	Tab,
	Space,
	Pause,
	Insert,
	Home,
	PageUp,
	Delete,
	End,
	PageDown,
	Right,
	Left,
	Down,
	Up,
	/// Numpad `/` key.
	NumDivide,
	/// Numpad `*` key.
	NumMultiply,
	/// Numpad `-` key.
	NumMinus,
	/// Numpad `+` key.
	NumPlus,
	/// Numpad ⏎ key.
	NumEnter,
	/// Numpad `Del/.` key (output locale-dependent).
	NumPeriod,
	/// Numpad `1/End` key.
	Num1,
	/// Numpad 2/↓ key.
	Num2,
	/// Numpad `3/PageDown` key.
	Num3,
	/// Numpad 4/← key.
	Num4,
	/// Numpad `5` key.
	Num5,
	/// Numpad 6/→ key.
	Num6,
	/// Numpad `7/Home` key.
	Num7,
	/// Numpad 8/↑ key.
	Num8,
	/// Numpad `9/PageUp` key.
	Num9,
	/// Numpad `0/Insert` key.
	Num0,
	/// Left mouse button.
	MouseLeft,
	/// Right mouse button.
	MouseRight,
	/// Middle mouse button a.k.a. pressed scroll wheel.
	MouseMiddle,
	MouseFourth,
	MouseFifth,
}

/// A single input event.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Event {
	/// Terminal window closed.
	Close,
	/// Terminal window resized. Needs to have `window.resizeable = true` to occur.
	///
	/// Note, that, as of [`40e6253`](https://bitbucket.org/cfyzium/bearlibterminal/commits/40e625311f0cccc43b94633add4dec0d6b77c2b7),
	/// the terminal window is cleared when resized.
	Resize{
		/// Width the terminal was resized to.
		width: i32,
		/// Heigth the terminal was resized to.
		height: i32,
	},
	/// Mouse moved.
	///
	/// If [`precise-mouse`](config/struct.Input.html#structfield.precise_mouse) is off, generated each time mouse moves from cell to cell, otherwise,
	/// when it moves from pixel to pixel.
	MouseMove{
		/// `0`-based cell index from the left to which the mouse cursor moved.
		x: i32,
		/// `0`-based cell index from the top to which the mouse cursor moved.
		y: i32
	},
	/// Mouse wheel moved.
	MouseScroll{
		/// Amount of steps the wheel rotated.
		///
		/// Positive when scrolled "down"/"backwards".
		///
		/// Negative when scrolled "up"/"forwards"/"away".
		delta: i32
	},
	/// A keyboard or mouse button pressed (might repeat, if set in OS).
	KeyPressed{
		/// The key pressed.
		key: KeyCode,
		/// Whether the Control key is pressed.
		ctrl: bool,
		/// Whether the Shift key is pressed.
		shift: bool
	},
	/// A keyboard or mouse button released.
	KeyReleased{
		/// The key released.
		key: KeyCode,
		/// Whether the Control key is pressed.
		ctrl: bool,
		/// Whether the Shift key is pressed.
		shift: bool
	},
	/// The Shift key pressed (might repeat, if set in OS).
	ShiftPressed,
	/// The Shift key released.
	ShiftReleased,
	/// The Shift key pressed (might repeat, if set in OS).
	ControlPressed,
	/// The Control key released.
	ControlReleased,
}
<commit_msg>More dscriptions for KeyCodes<commit_after>/// All pressable keys.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum KeyCode {
	A,
	B,
	C,
	D,
	E,
	F,
	G,
	H,
	I,
	J,
	K,
	L,
	M,
	N,
	O,
	P,
	Q,
	R,
	S,
	T,
	U,
	V,
	W,
	X,
	Y,
	Z,
	/// Top-row `1/!` key.
	Row1,
	/// Top-row `2/@` key.
	Row2,
	/// Top-row `3/#` key.
	Row3,
	/// Top-row `4/$` key.
	Row4,
	/// Top-row `5/%` key.
	Row5,
	/// Top-row `6/^` key.
	Row6,
	/// Top-row `7/&` key.
	Row7,
	/// Top-row `8/*` key.
	Row8,
	/// Top-row `9/(` key.
	Row9,
	/// Top-row `0/)` key.
	Row0,
	/// Top-row `/~ key.
	Grave,
	/// Top-row `-/_` key.
	Minus,
	/// Top-row `=/+` key.
	Equals,
	/// Second-row `[/{` key.
	LeftBracket,
	/// Second-row `]/}` key.
	RightBracket,
	/// Second-row `\/|` key.
	Backslash,
	/// Third-row `;/:` key.
	Semicolon,
	/// Third-row `'/"` key.
	Apostrophe,
	/// Fourth-row `,/<` key.
	Comma,
	/// Fourth-row `./>` key.
	Period,
	/// Fourth-row `//?` key.
	Slash,
	F1,
	F2,
	F3,
	F4,
	F5,
	F6,
	F7,
	F8,
	F9,
	F10,
	F11,
	F12,
	Enter,
	Escape,
	Backspace,
	Tab,
	Space,
	Pause,
	Insert,
	Home,
	PageUp,
	Delete,
	End,
	PageDown,
	/// Right arrow key.
	Right,
	/// Left arrow key.
	Left,
	/// Down arrow key.
	Down,
	/// Up arrow key.
	Up,
	/// Numpad `/` key.
	NumDivide,
	/// Numpad `*` key.
	NumMultiply,
	/// Numpad `-` key.
	NumMinus,
	/// Numpad `+` key.
	NumPlus,
	/// Numpad ⏎ key.
	NumEnter,
	/// Numpad `Del/.` key (output locale-dependent).
	NumPeriod,
	/// Numpad `1/End` key.
	Num1,
	/// Numpad 2/↓ key.
	Num2,
	/// Numpad `3/PageDown` key.
	Num3,
	/// Numpad 4/← key.
	Num4,
	/// Numpad `5` key.
	Num5,
	/// Numpad 6/→ key.
	Num6,
	/// Numpad `7/Home` key.
	Num7,
	/// Numpad 8/↑ key.
	Num8,
	/// Numpad `9/PageUp` key.
	Num9,
	/// Numpad `0/Insert` key.
	Num0,
	/// Left mouse button.
	MouseLeft,
	/// Right mouse button.
	MouseRight,
	/// Middle mouse button a.k.a. pressed scroll wheel.
	MouseMiddle,
	MouseFourth,
	MouseFifth,
}

/// A single input event.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Event {
	/// Terminal window closed.
	Close,
	/// Terminal window resized. Needs to have `window.resizeable = true` to occur.
	///
	/// Note, that, as of [`40e6253`](https://bitbucket.org/cfyzium/bearlibterminal/commits/40e625311f0cccc43b94633add4dec0d6b77c2b7),
	/// the terminal window is cleared when resized.
	Resize{
		/// Width the terminal was resized to.
		width: i32,
		/// Heigth the terminal was resized to.
		height: i32,
	},
	/// Mouse moved.
	///
	/// If [`precise-mouse`](config/struct.Input.html#structfield.precise_mouse) is off, generated each time mouse moves from cell to cell, otherwise,
	/// when it moves from pixel to pixel.
	MouseMove{
		/// `0`-based cell index from the left to which the mouse cursor moved.
		x: i32,
		/// `0`-based cell index from the top to which the mouse cursor moved.
		y: i32
	},
	/// Mouse wheel moved.
	MouseScroll{
		/// Amount of steps the wheel rotated.
		///
		/// Positive when scrolled "down"/"backwards".
		///
		/// Negative when scrolled "up"/"forwards"/"away".
		delta: i32
	},
	/// A keyboard or mouse button pressed (might repeat, if set in OS).
	KeyPressed{
		/// The key pressed.
		key: KeyCode,
		/// Whether the Control key is pressed.
		ctrl: bool,
		/// Whether the Shift key is pressed.
		shift: bool
	},
	/// A keyboard or mouse button released.
	KeyReleased{
		/// The key released.
		key: KeyCode,
		/// Whether the Control key is pressed.
		ctrl: bool,
		/// Whether the Shift key is pressed.
		shift: bool
	},
	/// The Shift key pressed (might repeat, if set in OS).
	ShiftPressed,
	/// The Shift key released.
	ShiftReleased,
	/// The Shift key pressed (might repeat, if set in OS).
	ControlPressed,
	/// The Control key released.
	ControlReleased,
}
<|endoftext|>


<commit_before>use super::schema::*;
use diesel::*;

#[test]
fn simple_distinct() {
    use schema::users::dsl::*;

    let connection = connection();
    connection
        .execute("INSERT INTO users (name) VALUES ('Sean'), ('Sean'), ('Tess')")
        .unwrap();

    let source = users.select(name).distinct().order(name);
    let expected_data = vec!["Sean".to_string(), "Tess".to_string()];
    let data: Vec<String> = source.load(&connection).unwrap();

    assert_eq!(expected_data, data);
}

#[cfg(feature = "postgres")]
#[test]
fn distinct_on() {
    use schema::users::dsl::*;

    let connection = connection();
    connection
        .execute(
            "INSERT INTO users (name, hair_color) VALUES ('Sean', 'black'), ('Sean', NULL), ('Tess', NULL), ('Tess', NULL)",
        )
        .unwrap();

    let source = users.select((name, hair_color)).order(name).distinct_on(name);
    let expected_data = vec![
        ("Sean".to_string(), Some("black".to_string())),
        ("Tess".to_string(), None),
    ];
    let data: Vec<_> = source.load(&connection).unwrap();

    assert_eq!(expected_data, data);
}
<commit_msg>Fix formatting for distinct integration tests<commit_after>use super::schema::*;
use diesel::*;

#[test]
fn simple_distinct() {
    use schema::users::dsl::*;

    let connection = connection();
    connection
        .execute("INSERT INTO users (name) VALUES ('Sean'), ('Sean'), ('Tess')")
        .unwrap();

    let source = users.select(name).distinct().order(name);
    let expected_data = vec!["Sean".to_string(), "Tess".to_string()];
    let data: Vec<String> = source.load(&connection).unwrap();

    assert_eq!(expected_data, data);
}

#[cfg(feature = "postgres")]
#[test]
fn distinct_on() {
    use schema::users::dsl::*;

    let connection = connection();
    connection
        .execute(
            "INSERT INTO users (name, hair_color) VALUES ('Sean', 'black'), ('Sean', NULL), ('Tess', NULL), ('Tess', NULL)",
        )
        .unwrap();

    let source = users
        .select((name, hair_color))
        .order(name)
        .distinct_on(name);
    let expected_data = vec![
        ("Sean".to_string(), Some("black".to_string())),
        ("Tess".to_string(), None),
    ];
    let data: Vec<_> = source.load(&connection).unwrap();

    assert_eq!(expected_data, data);
}
<|endoftext|>


<commit_before>//! AWS API requests.
//!
//! Wraps the `hyper` library to send PUT, POST, DELETE and GET requests.

//extern crate lazy_static;

use std::env;
use std::io::Read;
use std::io::Error as IoError;
use std::error::Error;
use std::fmt;
use std::collections::HashMap;

use hyper::Client;
use hyper::Error as HyperError;
use hyper::header::{Headers, UserAgent};
use hyper::status::StatusCode;
use hyper::method::Method;
use hyper::client::RedirectPolicy;
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;

use log::LogLevel::Debug;

use signature::SignedRequest;

// Pulls in the statically generated rustc version.
include!(concat!(env!("OUT_DIR"), "/user_agent_vars.rs"));

// Use a lazy static to cache the default User-Agent header
// because it never changes once it's been computed.
lazy_static! {
    static ref DEFAULT_USER_AGENT: Vec<Vec<u8>> = vec![format!("rusoto/{} rust/{} {}",
            env!("CARGO_PKG_VERSION"), RUST_VERSION, env::consts::OS).as_bytes().to_vec()];
}

pub struct HttpResponse {
    pub status: StatusCode,
    pub body: Box<Read>,
    pub headers: HashMap<String, String>,
}

#[derive(Debug, PartialEq)]
pub struct HttpDispatchError {
    message: String,
}

impl Error for HttpDispatchError {
    fn description(&self) -> &str {
        &self.message
    }
}

impl fmt::Display for HttpDispatchError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.message)
    }
}

impl From<HyperError> for HttpDispatchError {
    fn from(err: HyperError) -> HttpDispatchError {
        HttpDispatchError { message: err.description().to_string() }
    }
}

impl From<IoError> for HttpDispatchError {
    fn from(err: IoError) -> HttpDispatchError {
        HttpDispatchError { message: err.description().to_string() }
    }
}

pub trait DispatchSignedRequest {
    fn dispatch(&self, request: &SignedRequest) -> Result<HttpResponse, HttpDispatchError>;
}

impl DispatchSignedRequest for Client {
    fn dispatch(&self, request: &SignedRequest) -> Result<HttpResponse, HttpDispatchError> {
        let hyper_method = match request.method().as_ref() {
            "POST" => Method::Post,
            "PUT" => Method::Put,
            "DELETE" => Method::Delete,
            "GET" => Method::Get,
            "HEAD" => Method::Head,
            v => return Err(HttpDispatchError { message: format!("Unsupported HTTP verb {}", v) }),
        };

        // translate the headers map to a format Hyper likes
        let mut hyper_headers = Headers::new();
        for h in request.headers().iter() {
            hyper_headers.set_raw(h.0.to_owned(), h.1.to_owned());
        }

        // Add a default user-agent header if one is not already present.
        if !hyper_headers.has::<UserAgent>() {
            hyper_headers.set_raw("user-agent".to_owned(), DEFAULT_USER_AGENT.clone());
        }

        let mut final_uri = format!("{}://{}{}", request.scheme(), request.hostname(), request.canonical_path());
        if !request.canonical_query_string().is_empty() {
            final_uri = final_uri + &format!("?{}", request.canonical_query_string());
        }

        if log_enabled!(Debug) {
            let payload = match request.payload {
                Some(ref payload_bytes) => {
                    String::from_utf8(payload_bytes.to_owned())
                        .unwrap_or_else(|_| String::from("<non-UTF-8 data>"))
                }
                _ => "".to_owned(),
            };

            debug!("Full request: \n method: {}\n final_uri: {}\n payload: {}\nHeaders:\n",
                   hyper_method,
                   final_uri,
                   payload);
            for h in hyper_headers.iter() {
                debug!("{}:{}", h.name(), h.value_string());
            }
        }
        let hyper_response = match request.payload {
            None => {
                try!(self.request(hyper_method, &final_uri).headers(hyper_headers).body("").send())
            }
            Some(ref payload_contents) => {
                try!(self.request(hyper_method, &final_uri)
                    .headers(hyper_headers)
                    .body(payload_contents.as_slice())
                    .send())
            }
        };

        let mut headers: HashMap<String, String> = HashMap::new();

        for header in hyper_response.headers.iter() {
            headers.insert(header.name().to_string(), header.value_string());
        }

        Ok(HttpResponse {
            status: hyper_response.status,
            body: Box::new(hyper_response),
            headers: headers,
        })

    }
}

#[derive(Debug, PartialEq)]
pub struct TlsError {
    message: String,
}

impl Error for TlsError {
    fn description(&self) -> &str {
        &self.message
    }
}

impl fmt::Display for TlsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.message)
    }
}

/// Helper method for creating an http client with tls.
/// Makes a `hyper` client with `NativeTls` for HTTPS support.
pub fn default_tls_client() -> Result<Client, TlsError> {
    let ssl = match NativeTlsClient::new() {
        Ok(ssl) => ssl,
        Err(tls_error) => {
            return Err(TlsError {
                message: format!("Couldn't create NativeTlsClient: {}", tls_error),
            })
        }
    };
    let connector = HttpsConnector::new(ssl);
    let mut client = Client::with_connector(connector);
    client.set_redirect_policy(RedirectPolicy::FollowNone);
    Ok(client)
}

#[cfg(test)]
mod tests {
    use Region;
    use signature::SignedRequest;

    #[test]
    fn custom_region_http() {
        let a_region = Region::Custom("http://localhost".to_owned());
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("localhost", request.hostname());
    }

    #[test]
    fn custom_region_https() {
        let a_region = Region::Custom("https://localhost".to_owned());
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("localhost", request.hostname());
    }

    #[test]
    fn custom_region_with_port() {
        let a_region = Region::Custom("https://localhost:8000".to_owned());
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("localhost:8000", request.hostname());
    }
}
<commit_msg>make rusoto core use http pools in default client<commit_after>//! AWS API requests.
//!
//! Wraps the `hyper` library to send PUT, POST, DELETE and GET requests.

//extern crate lazy_static;

use std::env;
use std::io::Read;
use std::io::Error as IoError;
use std::error::Error;
use std::fmt;
use std::collections::HashMap;

use hyper::Client;
use hyper::Error as HyperError;
use hyper::header::{Headers, UserAgent};
use hyper::status::StatusCode;
use hyper::method::Method;
use hyper::client::RedirectPolicy;
use hyper::net::HttpsConnector;
use hyper::client::pool::Pool;
use hyper_native_tls::NativeTlsClient;

use log::LogLevel::Debug;

use signature::SignedRequest;

// Pulls in the statically generated rustc version.
include!(concat!(env!("OUT_DIR"), "/user_agent_vars.rs"));

// Use a lazy static to cache the default User-Agent header
// because it never changes once it's been computed.
lazy_static! {
    static ref DEFAULT_USER_AGENT: Vec<Vec<u8>> = vec![format!("rusoto/{} rust/{} {}",
            env!("CARGO_PKG_VERSION"), RUST_VERSION, env::consts::OS).as_bytes().to_vec()];
}

pub struct HttpResponse {
    pub status: StatusCode,
    pub body: Box<Read>,
    pub headers: HashMap<String, String>,
}

#[derive(Debug, PartialEq)]
pub struct HttpDispatchError {
    message: String,
}

impl Error for HttpDispatchError {
    fn description(&self) -> &str {
        &self.message
    }
}

impl fmt::Display for HttpDispatchError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.message)
    }
}

impl From<HyperError> for HttpDispatchError {
    fn from(err: HyperError) -> HttpDispatchError {
        HttpDispatchError { message: err.description().to_string() }
    }
}

impl From<IoError> for HttpDispatchError {
    fn from(err: IoError) -> HttpDispatchError {
        HttpDispatchError { message: err.description().to_string() }
    }
}

pub trait DispatchSignedRequest {
    fn dispatch(&self, request: &SignedRequest) -> Result<HttpResponse, HttpDispatchError>;
}

impl DispatchSignedRequest for Client {
    fn dispatch(&self, request: &SignedRequest) -> Result<HttpResponse, HttpDispatchError> {
        let hyper_method = match request.method().as_ref() {
            "POST" => Method::Post,
            "PUT" => Method::Put,
            "DELETE" => Method::Delete,
            "GET" => Method::Get,
            "HEAD" => Method::Head,
            v => return Err(HttpDispatchError { message: format!("Unsupported HTTP verb {}", v) }),
        };

        // translate the headers map to a format Hyper likes
        let mut hyper_headers = Headers::new();
        for h in request.headers().iter() {
            hyper_headers.set_raw(h.0.to_owned(), h.1.to_owned());
        }

        // Add a default user-agent header if one is not already present.
        if !hyper_headers.has::<UserAgent>() {
            hyper_headers.set_raw("user-agent".to_owned(), DEFAULT_USER_AGENT.clone());
        }

        let mut final_uri = format!("{}://{}{}", request.scheme(), request.hostname(), request.canonical_path());
        if !request.canonical_query_string().is_empty() {
            final_uri = final_uri + &format!("?{}", request.canonical_query_string());
        }

        if log_enabled!(Debug) {
            let payload = match request.payload {
                Some(ref payload_bytes) => {
                    String::from_utf8(payload_bytes.to_owned())
                        .unwrap_or_else(|_| String::from("<non-UTF-8 data>"))
                }
                _ => "".to_owned(),
            };

            debug!("Full request: \n method: {}\n final_uri: {}\n payload: {}\nHeaders:\n",
                   hyper_method,
                   final_uri,
                   payload);
            for h in hyper_headers.iter() {
                debug!("{}:{}", h.name(), h.value_string());
            }
        }
        let hyper_response = match request.payload {
            None => {
                try!(self.request(hyper_method, &final_uri).headers(hyper_headers).body("").send())
            }
            Some(ref payload_contents) => {
                try!(self.request(hyper_method, &final_uri)
                    .headers(hyper_headers)
                    .body(payload_contents.as_slice())
                    .send())
            }
        };

        let mut headers: HashMap<String, String> = HashMap::new();

        for header in hyper_response.headers.iter() {
            headers.insert(header.name().to_string(), header.value_string());
        }

        Ok(HttpResponse {
            status: hyper_response.status,
            body: Box::new(hyper_response),
            headers: headers,
        })

    }
}

#[derive(Debug, PartialEq)]
pub struct TlsError {
    message: String,
}

impl Error for TlsError {
    fn description(&self) -> &str {
        &self.message
    }
}

impl fmt::Display for TlsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.message)
    }
}

/// Helper method for creating an http client with tls.
/// Makes a `hyper` client with `NativeTls` for HTTPS support.
pub fn default_tls_client() -> Result<Client, TlsError> {
    let ssl = match NativeTlsClient::new() {
        Ok(ssl) => ssl,
        Err(tls_error) => {
            return Err(TlsError {
                message: format!("Couldn't create NativeTlsClient: {}", tls_error),
            })
        }
    };
    let connector = HttpsConnector::new(ssl);
    let mut client = Client::with_connector(Pool::with_connector(Default::default(), connector));
    client.set_redirect_policy(RedirectPolicy::FollowNone);
    Ok(client)
}

#[cfg(test)]
mod tests {
    use Region;
    use signature::SignedRequest;

    #[test]
    fn custom_region_http() {
        let a_region = Region::Custom("http://localhost".to_owned());
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("localhost", request.hostname());
    }

    #[test]
    fn custom_region_https() {
        let a_region = Region::Custom("https://localhost".to_owned());
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("localhost", request.hostname());
    }

    #[test]
    fn custom_region_with_port() {
        let a_region = Region::Custom("https://localhost:8000".to_owned());
        let request = SignedRequest::new("POST", "sqs", &a_region, "/");
        assert_eq!("localhost:8000", request.hostname());
    }
}
<|endoftext|>


<commit_before>//! The macros in this module can implement the serialisation traits for a
//! simple ASN.1 type definition/assignment, respresnted by a Rust newtype
//! (anonymous struct with a single field).
//!
//! You can either define both asn1_info! and asn1_newtype!, or all three
//! of asn1_info!, asn1_newtype_serialize! and asn1_newtype_deserialize!.
//!
//! IE:
//!
//! ```text
//! TYPE1 ::= SEQUENCE {
//!   a PrintableString
//! }
//!
//! TYPE1 ::= TYPE2
//! ```
//!
//! ```
//! #[macro_use] extern crate asn1_cereal; fn main() {
//!   struct Type1 {
//!     a: String
//!   }
//!
//!   asn1_sequence_info!(Type1, "TYPE1");
//!   asn1_sequence_serialize!(Type1, a);
//!   asn1_sequence_deserialize!(Type1, a);
//!
//!   struct Type2 (Type1);
//!   asn1_info!(Type2, 0x3, 0x1, true, "TYPE2");
//!   asn1_newtype!(Type2);
//!
//!   // OR
//!
//!   struct Type3 (Type1);
//!   asn1_info!(Type3, 0x3, 0x1, true, "TYPE2");
//!   asn1_newtype_serialize!(Type3);
//!   asn1_newtype_deserialize!(Type3);
//! }
//! ```

#[macro_export]
/// This macro is a compact way of defining both of the
/// Asn1 serialization traits - Asn1Serialize and Asn1Deserialize
/// - for a rust newtype, that represents an ASN.1 type definition.
macro_rules! asn1_newtype {
  ($rs_type:ident) => (
    asn1_newtype_serialize!($rs_type);
    asn1_newtype_deserialize!($rs_type);
  )
}

#[macro_export]
/// This macro defines the Asn1Serialize trait for a rust newtype.
macro_rules! asn1_newtype_serialize {
  ($rs_type:ident) => (
    impl $crate::serial::Asn1Serialize for $rs_type {
      fn serialize_enc<E: $crate::enc::Asn1EncRules, W: std::io::Write>
          (&self, e: E, writer: &mut W) -> Result<(), $crate::err::EncodeError> {
        // If encoding uses implicit tag, skip our tag.
        if E::tag_rules() == $crate::enc::TagEnc::Implicit {
          return self.0.serialize_enc(e, writer);
        }

        let mut bytes: Vec<u8> = Vec::new();
        try!(self.serialize_bytes(e, &mut bytes));

        try!(<Self as $crate::serial::Asn1Info>::asn1_tag().write_tag(writer));
        try!($crate::tag::Len::write_len(
          Some(bytes.len() as $crate::tag::LenNum).into(),
          writer
        ));
        try!(writer.write_all(&bytes));

        Ok(())
      }

      fn serialize_bytes<E: $crate::enc::Asn1EncRules, W: std::io::Write>
          (&self, e: E, writer: &mut W) -> Result<(), $crate::err::EncodeError> {
        self.0.serialize_enc(e, writer)
      }
    }
  )
}

#[macro_export]
/// This macro defines the Asn1Serialize trait for a rust newtype.
macro_rules! asn1_newtype_deserialize {
  ($rs_type:ident) => (
    impl $crate::serial::Asn1Deserialize for $rs_type {
      /// Reimplement this function to handle implicit tagging.
      fn deserialize_enc_tag<E: $crate::enc::Asn1EncRules, I: Iterator<Item=std::io::Result<u8>>>
          (e: E, reader: &mut I, tag: $crate::tag::Tag)
          -> Result<Self, $crate::err::DecodeError> {
        let my_tag = <Self as $crate::serial::Asn1Info>::asn1_tag();

        // If we're decoding using Implicit tagging rules, throw an error if this isn't an implicit tag.
        if E::tag_rules() == $crate::enc::TagEnc::Implicit && tag == my_tag {
          return Err($crate::err::DecodeError::ExplicitTag);
        }

        // If the tag doesn't match our tag, decode it as the inner type.
        if tag != my_tag {
          return Ok($rs_type(try!(
            $crate::serial::Asn1Deserialize::deserialize_enc_tag(e, reader, tag)
          )));
        }

        let len = try!($crate::tag::Len::read_len(reader));

        // If element is primitive, and length is indefinite, we can't decode it.
        if !tag.constructed && len == $crate::tag::Len::Indef {
          Err($crate::err::DecodeError::PrimIndef)
        } else {
          Self::deserialize_bytes(e, reader, len.as_num())
        }
      }
      fn deserialize_bytes<E: $crate::enc::Asn1EncRules, I: Iterator<Item=std::io::Result<u8>>>
          (e: E, reader: &mut I, _: Option<$crate::tag::LenNum>) -> Result<Self, $crate::err::DecodeError> {
        Ok($rs_type(try!($crate::serial::Asn1Deserialize::deserialize_enc(e, reader))))
      }
    }
  )
}
<commit_msg>Update newtype code<commit_after>//! The macros in this module can implement the serialisation traits for a
//! simple ASN.1 type definition/assignment, respresnted by a Rust newtype
//! (anonymous struct with a single field).
//!
//! You can either define both asn1_info! and asn1_newtype!, or all three
//! of asn1_info!, asn1_newtype_serialize! and asn1_newtype_deserialize!.
//!
//! IE:
//!
//! ```text
//! TYPE1 ::= SEQUENCE {
//!   a PrintableString
//! }
//!
//! TYPE1 ::= TYPE2
//! ```
//!
//! ```
//! #[macro_use] extern crate asn1_cereal; fn main() {
//!   struct Type1 {
//!     a: String
//!   }
//!
//!   asn1_sequence_info!(Type1, "TYPE1");
//!   asn1_sequence_serialize!(Type1, a);
//!   asn1_sequence_deserialize!(Type1, a);
//!
//!   struct Type2 (Type1);
//!   asn1_info!(Type2, 0x3, 0x1, true, "TYPE2");
//!   asn1_newtype!(Type2);
//!
//!   // OR
//!
//!   struct Type3 (Type1);
//!   asn1_info!(Type3, 0x3, 0x1, true, "TYPE3");
//!   asn1_newtype_serialize!(Type3);
//!   asn1_newtype_deserialize!(Type3);
//! }
//! ```

#[macro_export]
/// This macro is a compact way of defining both of the
/// Asn1 serialization traits - Asn1Serialize and Asn1Deserialize
/// - for a rust newtype, that represents an ASN.1 type definition.
macro_rules! asn1_newtype {
  ($rs_type:ident) => (
    asn1_newtype_serialize!($rs_type);
    asn1_newtype_deserialize!($rs_type);
  )
}

#[macro_export]
/// This macro defines the Asn1Serialize trait for a rust newtype.
macro_rules! asn1_newtype_serialize {
  ($rs_type:ident) => (
    impl $crate::serial::Asn1Serialize for $rs_type {
      fn serialize_enc<E: $crate::enc::Asn1EncRules, W: std::io::Write>
          (&self, e: E, writer: &mut W) -> Result<(), $crate::err::EncodeError> {
        // If encoding uses implicit tag, skip our tag.
        if E::tag_rules() == $crate::enc::TagEnc::Implicit {
          return self.0.serialize_enc(e, writer);
        }

        let tag = <Self as $crate::serial::Asn1Info>::asn1_tag();
        try!(tag.write_tag(writer));

        // If this is indefinite length and constructed, write the data directly.
        if E::len_rules() == $crate::enc::LenEnc::Indefinite &&
           tag.constructed {
          try!($crate::tag::Len::Indef.write_len(writer));
          try!(self.serialize_bytes(e, writer));
          try!($crate::tag::Len::write_indef_end(writer));
        // Otherwise write to a Vec first, so we can write the length.
        } else {
          let mut bytes: Vec<u8> = Vec::new();
          try!(self.serialize_bytes(e, &mut bytes));
          try!($crate::tag::Len::write_len(Some(bytes.len() as $crate::tag::LenNum).into(), writer));
          try!(writer.write_all(&bytes));
        }

        Ok(())
      }

      fn serialize_bytes<E: $crate::enc::Asn1EncRules, W: std::io::Write>
          (&self, e: E, writer: &mut W) -> Result<(), $crate::err::EncodeError> {
        self.0.serialize_enc(e, writer)
      }
    }
  )
}

#[macro_export]
/// This macro defines the Asn1Serialize trait for a rust newtype.
macro_rules! asn1_newtype_deserialize {
  ($rs_type:ident) => (
    impl $crate::serial::Asn1Deserialize for $rs_type {
      fn deserialize_enc_tag<E: $crate::enc::Asn1EncRules, I: Iterator<Item=std::io::Result<u8>>>
          (e: E, reader: &mut I, tag: $crate::tag::Tag)
          -> Result<Self, $crate::err::DecodeError> {
        let my_tag = <Self as $crate::serial::Asn1Info>::asn1_tag();

        // If we're decoding using Implicit tagging rules, throw an error if this isn't an implicit tag.
        if E::tag_rules() == $crate::enc::TagEnc::Implicit && tag == my_tag {
          return Err($crate::err::DecodeError::ExplicitTag);
        }

        // If the tag doesn't match our tag, decode it as the inner type.
        if tag != my_tag {
          return Ok($rs_type(try!(
            $crate::serial::Asn1Deserialize::deserialize_enc_tag(e, reader, tag)
          )));
        }

        // Read length fromm stream.
        let len = try!($crate::tag::Len::read_len(reader));

        // Handle any indefinite length error conditions.
        if len == $crate::tag::Len::Indef {
          // Return an error if the encoding rules only allow definite length
          // encoding.
          if E::len_rules() == $crate::enc::LenEnc::Definite {
            return Err($crate::err::DecodeError::IndefiniteLen);
          // If this element is primitve, the length isn't allowed to be indefinite length.
          } else if !tag.constructed {
           return Err($crate::err::DecodeError::PrimIndef)
          }
        }
        // Read the main data.
        let item: Self = try!(Self::deserialize_bytes(e, reader, len.as_num()));

        // If this is encoded with an indefinte length, try to read the end octets.
        if len == $crate::tag::Len::Indef {
          try!($crate::tag::Len::read_indef_end(reader));
        }

        Ok(item)
      }

      fn deserialize_bytes<E: $crate::enc::Asn1EncRules, I: Iterator<Item=std::io::Result<u8>>>
          (e: E, reader: &mut I, _: Option<$crate::tag::LenNum>) -> Result<Self, $crate::err::DecodeError> {
        Ok($rs_type(try!($crate::serial::Asn1Deserialize::deserialize_enc(e, reader))))
      }
    }
  )
}
<|endoftext|>