<commit_before>//! An abstraction for spawning futures
//!
//! [futures-rs](http://github.com/alexcrichton/futures-rs) provides a task
//! abstraction and the ability for custom executors to manage how future
//! execution is scheduled across them.
//!
//! `futures-spawn` provides an abstraction representing the act of spawning a
//! future. This enables writing code that is not hard coded to a specific
//! executor.

#![deny(warnings, missing_docs)]

extern crate futures;

use futures::{Future};

/// Value that can spawn a future
///
/// On spawn, the executor takes ownership of the future and becomes responsible
/// to call `Future::poll()` whenever a readiness notification is raised.
pub trait Spawn<T: Future<Item = (), Error = ()>> {

    /// Spawns a future to run on this `Spawn`.
    ///
    /// This function will return immediately, and schedule the future `f` to
    /// run on `self`. The details of scheduling and execution are left to the
    /// implementations of `Spawn`.
    fn spawn_detached(&self, f: T);

    /// Spawns a future to run on this `Spawn`, returning a future representing
    /// the produced value.
    ///
    ///
    /// This function will return immediately, and schedule the future `f` to
    /// run on `self`. The details of scheduling and execution are left to the
    /// implementations of `Spawn`. The returned future serves as a proxy to the
    /// computation that `F` is running.
    ///
    /// To simply run an arbitrary closure and extract the result, you can use
    /// the `future::lazy` combinator to defer work to executing on `&self`.
    ///
    /// Note that if the future `f` panics it will be caught by default and the
    /// returned future will propagate the panic. That is, panics will not reach
    /// `&self` and will be propagated to the returned future's `poll` method if
    /// queried.
    ///
    /// If the returned future is dropped then `f` will be canceled, if
    /// possible. That is, if the computation is in the middle of working, it
    /// will be interrupted when possible.
    #[cfg(feature = "use_std")]
    fn spawn<F>(&self, f: F) -> SpawnHandle<F::Item, F::Error>
        where F: Future,
              Self: Spawn<Spawned<F>>
    {
        with_std::spawn(self, f)
    }

    /// Spawns a closure on this `Spawn`
    ///
    /// This function is a convenience wrapper around the `spawn` function above
    /// for running a closure wrapped in `future::lazy`. It will spawn the
    /// function `f` provided onto the thread pool, and continue to run the
    /// future returned by `f` on the thread pool as well.
    #[cfg(feature = "use_std")]
    fn spawn_fn<F, R>(&self, f: F) -> SpawnHandle<R::Item, R::Error>
        where F: FnOnce() -> R,
              R: futures::IntoFuture,
              Self: Spawn<Spawned<futures::future::Lazy<F, R>>>,
    {
        use futures::future;
        with_std::spawn(self, future::lazy(f))
    }
}

#[cfg(feature = "use_std")]
pub use with_std::{NewThread, SpawnHandle, Spawned};

#[cfg(feature = "use_std")]
mod with_std {
    use {Spawn};
    use futures::{Future, Poll, Async};
    use futures::future::CatchUnwind;
    use futures::sync::oneshot;

    use std::{thread};
    use std::panic::{self, AssertUnwindSafe};
    use std::sync::Arc;
    use std::sync::atomic::AtomicBool;
    use std::sync::atomic::Ordering::SeqCst;

    /// The type of future returned from the `Spawn::spawn` function, which
    /// proxies the futures running on the thread pool.
    ///
    /// This future will resolve in the same way as the underlying future, and it
    /// will propagate panics.
    #[must_use]
    pub struct SpawnHandle<T, E> {
        inner: oneshot::Receiver<thread::Result<Result<T, E>>>,
        keep_running_flag: Arc<AtomicBool>,
    }

    /// Contains a future that was spawned
    pub struct Spawned<F: Future> {
        future: CatchUnwind<AssertUnwindSafe<F>>,
        tx: Option<oneshot::Sender<thread::Result<Result<F::Item, F::Error>>>>,
        keep_running_flag: Arc<AtomicBool>,
    }

    /// Spawn all futures on a new thread
    ///
    /// This is the most basic `Spawn` implementation. Each call to `spawn` results
    /// in a new thread dedicated to processing the given future to completion.
    pub struct NewThread;

    pub fn spawn<F, S: ?Sized>(s: &S, future: F) -> SpawnHandle<F::Item, F::Error>
        where F: Future,
              S: Spawn<Spawned<F>>
    {
        use futures::sync::oneshot;
        use std::panic::AssertUnwindSafe;
        use std::sync::Arc;
        use std::sync::atomic::AtomicBool;

        let (tx, rx) = oneshot::channel();
        let keep_running_flag = Arc::new(AtomicBool::new(false));

        // AssertUnwindSafe is used here becuase `Send + 'static` is basically
        // an alias for an implementation of the `UnwindSafe` trait but we can't
        // express that in the standard library right now.
        let sender = Spawned {
            future: AssertUnwindSafe(future).catch_unwind(),
            tx: Some(tx),
            keep_running_flag: keep_running_flag.clone(),
        };

        // Spawn the future
        s.spawn_detached(sender);

        SpawnHandle {
            inner: rx,
            keep_running_flag: keep_running_flag,
        }
    }

    impl<T, E> SpawnHandle<T, E> {
        /// Drop this future without canceling the underlying future.
        ///
        /// When `SpawnHandle` is dropped, the spawned future will be dropped as
        /// well. This function can be used when user wants to drop but keep
        /// executing the underlying future.
        pub fn detach(self) {
            self.keep_running_flag.store(true, SeqCst);
        }
    }

    impl<T, E> Future for SpawnHandle<T, E> {
        type Item = T;
        type Error = E;

        fn poll(&mut self) -> Poll<T, E> {
            match self.inner.poll().expect("shouldn't be canceled") {
                Async::Ready(Ok(Ok(e))) => Ok(e.into()),
                Async::Ready(Ok(Err(e))) => Err(e),
                Async::Ready(Err(e)) => panic::resume_unwind(e),
                Async::NotReady => Ok(Async::NotReady),
            }
        }
    }

    impl<F: Future> Future for Spawned<F> {
        type Item = ();
        type Error = ();

        fn poll(&mut self) -> Poll<(), ()> {
            if let Ok(Async::Ready(_)) = self.tx.as_mut().unwrap().poll_cancel() {
                if !self.keep_running_flag.load(SeqCst) {
                    // Cancelled, bail out
                    return Ok(().into())
                }
            }

            let res = match self.future.poll() {
                Ok(Async::Ready(e)) => Ok(e),
                Ok(Async::NotReady) => return Ok(Async::NotReady),
                Err(e) => Err(e),
            };

            self.tx.take().unwrap().complete(res);

            Ok(Async::Ready(()))
        }
    }

    impl<T: Future<Item = (), Error = ()> + Send + 'static> Spawn<T> for NewThread {
        fn spawn_detached(&self, future: T) {
            use std::thread;

            thread::spawn(move || {
                let _ = future.wait();
            });
        }
    }
}

#[cfg(feature = "tokio")]
mod tokio {
    extern crate tokio_core;

    use {Spawn};
    use futures::Future;
    use self::tokio_core::reactor::{Core, Handle, Remote};

    impl<T: Future<Item = (), Error = ()> + 'static> Spawn<T> for Handle {
        fn spawn_detached(&self, future: T) {
            Handle::spawn(self, future);
        }
    }

    impl<T: Future<Item = (), Error = ()> + 'static> Spawn<T> for Core {
        fn spawn_detached(&self, future: T) {
            self.handle().spawn_detached(future);
        }
    }

    impl<T: Future<Item = (), Error = ()> + Send + 'static> Spawn<T> for Remote {
        fn spawn_detached(&self, future: T) {
            Remote::spawn(self, move |_| future);
        }
    }
}
<commit_msg>Provide additional spawn helpers<commit_after>//! An abstraction for spawning futures
//!
//! [futures-rs](http://github.com/alexcrichton/futures-rs) provides a task
//! abstraction and the ability for custom executors to manage how future
//! execution is scheduled across them.
//!
//! `futures-spawn` provides an abstraction representing the act of spawning a
//! future. This enables writing code that is not hard coded to a specific
//! executor.

#![deny(warnings, missing_docs)]

extern crate futures;

use futures::{Future};

/// Value that can spawn a future
///
/// On spawn, the executor takes ownership of the future and becomes responsible
/// to call `Future::poll()` whenever a readiness notification is raised.
pub trait Spawn<T: Future<Item = (), Error = ()>> {

    /// Spawns a future to run on this `Spawn`.
    ///
    /// This function will return immediately, and schedule the future `f` to
    /// run on `self`. The details of scheduling and execution are left to the
    /// implementations of `Spawn`.
    fn spawn_detached(&self, f: T);
}

#[cfg(feature = "use_std")]
pub use with_std::{NewThread, SpawnHandle, Spawned, SpawnHelper};

#[cfg(feature = "use_std")]
mod with_std {
    use {Spawn};
    use futures::{Future, IntoFuture, Poll, Async};
    use futures::future::{self, CatchUnwind, Lazy};
    use futures::sync::oneshot;

    use std::{thread};
    use std::panic::{self, AssertUnwindSafe};
    use std::sync::Arc;
    use std::sync::atomic::AtomicBool;
    use std::sync::atomic::Ordering::SeqCst;

    /// The type of future returned from the `Spawn::spawn` function, which
    /// proxies the futures running on the thread pool.
    ///
    /// This future will resolve in the same way as the underlying future, and it
    /// will propagate panics.
    #[must_use]
    pub struct SpawnHandle<T, E> {
        inner: oneshot::Receiver<thread::Result<Result<T, E>>>,
        keep_running_flag: Arc<AtomicBool>,
    }

    /// Contains a future that was spawned
    pub struct Spawned<F: Future> {
        future: CatchUnwind<AssertUnwindSafe<F>>,
        tx: Option<oneshot::Sender<thread::Result<Result<F::Item, F::Error>>>>,
        keep_running_flag: Arc<AtomicBool>,
    }

    /// Spawn all futures on a new thread
    ///
    /// This is the most basic `Spawn` implementation. Each call to `spawn` results
    /// in a new thread dedicated to processing the given future to completion.
    pub struct NewThread;

    /// Additional strategies for spawning a future.
    ///
    /// These functions have to be on a separate trait vs. on the `Spawn` trait
    /// in order to make rustc happy.
    pub trait SpawnHelper {
        /// Spawns a future to run on this `Spawn`, returning a future representing
        /// the produced value.
        ///
        ///
        /// This function will return immediately, and schedule the future `f` to
        /// run on `self`. The details of scheduling and execution are left to the
        /// implementations of `Spawn`. The returned future serves as a proxy to the
        /// computation that `F` is running.
        ///
        /// To simply run an arbitrary closure and extract the result, you can use
        /// the `future::lazy` combinator to defer work to executing on `&self`.
        ///
        /// Note that if the future `f` panics it will be caught by default and the
        /// returned future will propagate the panic. That is, panics will not reach
        /// `&self` and will be propagated to the returned future's `poll` method if
        /// queried.
        ///
        /// If the returned future is dropped then `f` will be canceled, if
        /// possible. That is, if the computation is in the middle of working, it
        /// will be interrupted when possible.
        fn spawn<F>(&self, future: F) -> SpawnHandle<F::Item, F::Error>
            where F: Future,
                  Self: Spawn<Spawned<F>>
        {
            use futures::sync::oneshot;
            use std::panic::AssertUnwindSafe;
            use std::sync::Arc;
            use std::sync::atomic::AtomicBool;

            let (tx, rx) = oneshot::channel();
            let keep_running_flag = Arc::new(AtomicBool::new(false));

            // AssertUnwindSafe is used here becuase `Send + 'static` is basically
            // an alias for an implementation of the `UnwindSafe` trait but we can't
            // express that in the standard library right now.
            let sender = Spawned {
                future: AssertUnwindSafe(future).catch_unwind(),
                tx: Some(tx),
                keep_running_flag: keep_running_flag.clone(),
            };

            // Spawn the future
            self.spawn_detached(sender);

            SpawnHandle {
                inner: rx,
                keep_running_flag: keep_running_flag,
            }
        }

        /// Spawns a closure on this `Spawn`
        ///
        /// This function is a convenience wrapper around the `spawn` function above
        /// for running a closure wrapped in `future::lazy`. It will spawn the
        /// function `f` provided onto the thread pool, and continue to run the
        /// future returned by `f` on the thread pool as well.
        fn spawn_fn<F, R>(&self, f: F) -> SpawnHandle<R::Item, R::Error>
            where F: FnOnce() -> R,
                  R: IntoFuture,
                  Self: Spawn<Spawned<Lazy<F, R>>>,
        {
            self.spawn(future::lazy(f))
        }
    }

    impl<T> SpawnHelper for T {
    }

    impl<T, E> SpawnHandle<T, E> {
        /// Drop this future without canceling the underlying future.
        ///
        /// When `SpawnHandle` is dropped, the spawned future will be dropped as
        /// well. This function can be used when user wants to drop but keep
        /// executing the underlying future.
        pub fn detach(self) {
            self.keep_running_flag.store(true, SeqCst);
        }
    }

    impl<T, E> Future for SpawnHandle<T, E> {
        type Item = T;
        type Error = E;

        fn poll(&mut self) -> Poll<T, E> {
            match self.inner.poll().expect("shouldn't be canceled") {
                Async::Ready(Ok(Ok(e))) => Ok(e.into()),
                Async::Ready(Ok(Err(e))) => Err(e),
                Async::Ready(Err(e)) => panic::resume_unwind(e),
                Async::NotReady => Ok(Async::NotReady),
            }
        }
    }

    impl<F: Future> Future for Spawned<F> {
        type Item = ();
        type Error = ();

        fn poll(&mut self) -> Poll<(), ()> {
            if let Ok(Async::Ready(_)) = self.tx.as_mut().unwrap().poll_cancel() {
                if !self.keep_running_flag.load(SeqCst) {
                    // Cancelled, bail out
                    return Ok(().into())
                }
            }

            let res = match self.future.poll() {
                Ok(Async::Ready(e)) => Ok(e),
                Ok(Async::NotReady) => return Ok(Async::NotReady),
                Err(e) => Err(e),
            };

            self.tx.take().unwrap().complete(res);

            Ok(Async::Ready(()))
        }
    }

    impl<T: Future<Item = (), Error = ()> + Send + 'static> Spawn<T> for NewThread {
        fn spawn_detached(&self, future: T) {
            use std::thread;

            thread::spawn(move || {
                let _ = future.wait();
            });
        }
    }

    #[test]
    fn test_new_thread() {
        let new_thread = NewThread;
        let res = new_thread.spawn_fn(|| Ok::<u32, ()>(1));

        assert_eq!(1, res.wait().unwrap());
    }
}

#[cfg(feature = "tokio")]
mod tokio {
    extern crate tokio_core;

    use {Spawn};
    use futures::Future;
    use self::tokio_core::reactor::{Core, Handle, Remote};

    impl<T: Future<Item = (), Error = ()> + 'static> Spawn<T> for Handle {
        fn spawn_detached(&self, future: T) {
            Handle::spawn(self, future);
        }
    }

    impl<T: Future<Item = (), Error = ()> + 'static> Spawn<T> for Core {
        fn spawn_detached(&self, future: T) {
            self.handle().spawn_detached(future);
        }
    }

    impl<T: Future<Item = (), Error = ()> + Send + 'static> Spawn<T> for Remote {
        fn spawn_detached(&self, future: T) {
            Remote::spawn(self, move |_| future);
        }
    }
}
<|endoftext|>


<commit_before>/* Copyright 2016 The encode_unicode Developers
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
 * http://opensource.org/licenses/MIT>, at your option. This file may not be
 * copied, modified, or distributed except according to those terms.
 */

/*!
Miscellaneous UTF-8 and UTF-16 types and methods.

# Optional features:
* `#![no_std]`-mode: There are a few differences:
  * `Error` doesn't exist, but `description()` is made available as an inherent impl.
  * `Extend`/`FromIterator`-implementations for `String`/`Vec<u8>`/`Vec<u16>` are missing.
  * There is no `io`, so `Utf8Iterator` and `Utf8CharSplitter` doesn't implement `Read`.

  This feature is enabled by setting `default-features=false` in `Cargo.toml`:
  `encode_unicode = {version="0.3.4", default-features=false}`
* Integration with the [ascii](https://tomprogrammer.github.io/rust-ascii/ascii/index.html) crate:
  Convert `Utf8Char` and `Utf16Char` to and from
  [ascii::`AsciiChar`](https://tomprogrammer.github.io/rust-ascii/ascii/enum.AsciiChar.html).

# Minimum supported Rust version

The minimum supported Rust version for 1.0.\* releases is 1.33.0.
Later 1.y.0 releases might require newer Rust versions, but the three most
recent stable releases at the time of publishing will always be supported.
For example this means that if the current stable Rust version is 1.44 when
encode_unicode 1.1.0 is released, then encode_unicode 1.1.\* will
not require a newer Rust version than 1.42.

[crates.io page](https://crates.io/crates/encode_unicode)
[github repository](https://github.com/tormol/encode_unicode)

*/

#![cfg_attr(not(feature="std"), no_std)]

#![warn(missing_docs)]
#![cfg_attr(feature="cargo-clippy", allow(
    inconsistent_digit_grouping,
    large_digit_groups,// I sometimes group into UTF-8 control part and codepoint part
    derive_hash_xor_eq,// tested
    len_without_is_empty,// tha character types are never empty
    needless_return,// `foo.bar();\n foo` looks unfinished
    redundant_closure,// looks weird just passing the name of an enum variant
    redundant_closure_call,// not redundant in macros
    cast_lossless,// the sizes are part of the struct name and so won't change
    many_single_char_names,// the variables are in different scopes
    needless_range_loop,// the suggested iterator chains are less intuitive
    trivially_copy_pass_by_ref,// compatibility with char methods originally from AsciiExt
    identity_op,// applying a set of opereations with varying arguments to many elements looks nice
))]
#![cfg_attr(feature="cargo-clippy", warn(doc_markdown, filter_map))]
// opt-in lints that might be interesting to recheck once in a while:
//#![cfg_attr(feature="cargo-clippy", warn(result_unwrap_used, option_unwrap_used))]

mod errors;
mod traits;
mod utf8_char;
mod utf8_iterators;
mod utf16_char;
mod utf16_iterators;
mod decoding_iterators;

pub use traits::{CharExt, U8UtfExt, U16UtfExt, StrExt, IterExt, SliceExt};
pub use utf8_char::Utf8Char;
pub use utf16_char::Utf16Char;
pub use utf8_iterators::{Utf8Iterator, iter_bytes};
pub use utf16_iterators::{Utf16Iterator, iter_units};

pub mod error {// keeping the public interface in one file
    //! Errors returned by various conversion methods in this crate.
    pub use errors::{FromStrError, EmptyStrError};
    pub use errors::{InvalidCodepoint, InvalidUtf8};
    pub use errors::{InvalidUtf8FirstByte,InvalidUtf16FirstUnit};
    pub use errors::{InvalidUtf8Slice,InvalidUtf16Slice};
    pub use errors::{InvalidUtf8Array,InvalidUtf16Array,InvalidUtf16Tuple};
    pub use errors::Utf16PairError;
}

pub mod iterator {
    //! Iterator types that you should rarely need to name
    pub use utf8_iterators::{Utf8Iterator, Utf8CharSplitter, Utf8Chars, Utf8CharIndices};
    pub use utf16_iterators::{Utf16Iterator, Utf16CharSplitter, Utf16Chars, Utf16CharIndices};
    pub use decoding_iterators::{Utf8CharMerger, Utf8CharDecoder};
    pub use decoding_iterators::{Utf16CharMerger, Utf16CharDecoder};
}
<commit_msg>Switch to Rust 1.30's tool attributes for clippy lints<commit_after>/* Copyright 2016 The encode_unicode Developers
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
 * http://opensource.org/licenses/MIT>, at your option. This file may not be
 * copied, modified, or distributed except according to those terms.
 */

/*!
Miscellaneous UTF-8 and UTF-16 types and methods.

# Optional features:
* `#![no_std]`-mode: There are a few differences:
  * `Error` doesn't exist, but `description()` is made available as an inherent impl.
  * `Extend`/`FromIterator`-implementations for `String`/`Vec<u8>`/`Vec<u16>` are missing.
  * There is no `io`, so `Utf8Iterator` and `Utf8CharSplitter` doesn't implement `Read`.

  This feature is enabled by setting `default-features=false` in `Cargo.toml`:
  `encode_unicode = {version="0.3.4", default-features=false}`
* Integration with the [ascii](https://tomprogrammer.github.io/rust-ascii/ascii/index.html) crate:
  Convert `Utf8Char` and `Utf16Char` to and from
  [ascii::`AsciiChar`](https://tomprogrammer.github.io/rust-ascii/ascii/enum.AsciiChar.html).

# Minimum supported Rust version

The minimum supported Rust version for 1.0.\* releases is 1.33.0.
Later 1.y.0 releases might require newer Rust versions, but the three most
recent stable releases at the time of publishing will always be supported.
For example this means that if the current stable Rust version is 1.44 when
encode_unicode 1.1.0 is released, then encode_unicode 1.1.\* will
not require a newer Rust version than 1.42.

[crates.io page](https://crates.io/crates/encode_unicode)
[github repository](https://github.com/tormol/encode_unicode)

*/

#![cfg_attr(not(feature="std"), no_std)]

#![warn(missing_docs)]
#![allow(
    clippy::inconsistent_digit_grouping,
    clippy::large_digit_groups,// I sometimes group into UTF-8 control part and codepoint part
    clippy::derive_hash_xor_eq,// tested
    clippy::len_without_is_empty,// tha character types are never empty
    clippy::needless_return,// `foo.bar();\n foo` looks unfinished
    clippy::redundant_closure,// looks weird just passing the name of an enum variant
    clippy::redundant_closure_call,// not redundant in macros
    clippy::cast_lossless,// the sizes are part of the struct name and so won't change
    clippy::many_single_char_names,// the variables are in different scopes
    clippy::needless_range_loop,// the suggested iterator chains are less intuitive
    clippy::trivially_copy_pass_by_ref,// compatibility with char methods originally from AsciiExt
    clippy::identity_op,// applying a set of opereations with varying arguments to many elements looks nice
)]
#![warn(clippy::doc_markdown, clippy::filter_map)]
// opt-in lints that might be interesting to recheck once in a while:
//#![warn(clippy::result_unwrap_used, clippy::option_unwrap_used))]

mod errors;
mod traits;
mod utf8_char;
mod utf8_iterators;
mod utf16_char;
mod utf16_iterators;
mod decoding_iterators;

pub use traits::{CharExt, U8UtfExt, U16UtfExt, StrExt, IterExt, SliceExt};
pub use utf8_char::Utf8Char;
pub use utf16_char::Utf16Char;
pub use utf8_iterators::{Utf8Iterator, iter_bytes};
pub use utf16_iterators::{Utf16Iterator, iter_units};

pub mod error {// keeping the public interface in one file
    //! Errors returned by various conversion methods in this crate.
    pub use errors::{FromStrError, EmptyStrError};
    pub use errors::{InvalidCodepoint, InvalidUtf8};
    pub use errors::{InvalidUtf8FirstByte,InvalidUtf16FirstUnit};
    pub use errors::{InvalidUtf8Slice,InvalidUtf16Slice};
    pub use errors::{InvalidUtf8Array,InvalidUtf16Array,InvalidUtf16Tuple};
    pub use errors::Utf16PairError;
}

pub mod iterator {
    //! Iterator types that you should rarely need to name
    pub use utf8_iterators::{Utf8Iterator, Utf8CharSplitter, Utf8Chars, Utf8CharIndices};
    pub use utf16_iterators::{Utf16Iterator, Utf16CharSplitter, Utf16Chars, Utf16CharIndices};
    pub use decoding_iterators::{Utf8CharMerger, Utf8CharDecoder};
    pub use decoding_iterators::{Utf16CharMerger, Utf16CharDecoder};
}
<|endoftext|>


<commit_before>extern crate libc;

use std::net::{SocketAddrV4, SocketAddrV6};
use std::ffi::CString;
use libc::*;

const IW_AUTH_WPA_VERSION_DISABLED: u8 = 0x00000001;
const IW_AUTH_WPA_VERSION_WPA: u8 = 0x00000002;
const IW_AUTH_WPA_VERSION_WPA2: u8 = 0x00000004;
const IW_MAX_BITRATES: usize = 32;
const IW_MAX_ENCODING_SIZES: usize = 8;
const IW_MAX_FREQUENCIES: usize = 32;
const IW_MAX_TXPOWER: usize = 8;

pub enum WirelessMode {
    Auto, /* Let the driver decide */
    AdHoc, /* Single cell network */
    Infra, /* Multi cell network, roaming, ... */
    Master, /* Synchronisation master or Access Point */
    Repeat, /* Wireless Repeater (forwarder) */
    Second, /* Secondary master/repeater (backup) */
    Monitor, /* Passive monitor (listen only) */
}

pub struct IwQuality {
    quality: u8,
    level: u8,
    noise: u8,
}

pub struct IwStats {
    status: uint16_t,
    quality: IwQuality,
}

pub struct WirelessKey<'a> {
    key: &'a [u8],
    size: u32,
    flags: i32,
}

pub struct WirelessNetwork<'a> {
    ap_addr4: Option<SocketAddrV4>,
    ap_addr6: Option<SocketAddrV6>,
    stats: Option<IwStats>,
    maxbitrate: Option<i32>,
    name: String,
    freq: Option<f64>,
    key: Option<WirelessKey<'a>>,
    essid: Option<String>,
    mode: Option<WirelessMode>,
}

#[repr(C)]
struct priv_iw_quality {
    qual: uint8_t,
    level: uint8_t,
    noise: uint8_t,
    updated: uint8_t,
}

#[repr(C)]
struct priv_iw_freq {
    m: int32_t,
    e: int16_t,
    i: uint8_t,
    flags: uint8_t,
}

#[repr(C)]
struct iw_range {
    /* Informative stuff (to choose between different interface) */
    throughput: uint32_t, /* To give an idea... */
    /* In theory this value should be the maximum benchmarked
     * TCP/IP throughput, because with most of these devices the
     * bit rate is meaningless (overhead an co) to estimate how
     * fast the connection will go and pick the fastest one.
     * I suggest people to play with Netperf or any benchmark...
     */

    /* NWID (or domain id) */
    min_nwid: uint32_t, /* Minimal NWID we are able to set */
    max_nwid: uint32_t, /* Maximal NWID we are able to set */

    /* Old Frequency (backward compat - moved lower ) */
    old_num_channels: uint16_t,
    old_num_frequency: uint8_t,

    /* Wireless event capability bitmasks */
    event_capa: [uint32_t; 6],

    /* signal level threshold range */
    sensitivity: int32_t,

    /* Quality of link & SNR stuff */
    /* Quality range (link, level, noise)
     * If the quality is absolute, it will be in the range [0 , max_qual],
     * if the quality is dBm, it will be in the range [max_qual , 0].
     * Don't forget that we use 8 bit arithmetics... */
    max_qual: priv_iw_quality, /* Quality of the link */
    /* This should contain the average/typical values of the quality
     * indicator. This should be the threshold between a "good" and
     * a "bad" link (example : monitor going from green to orange).
     * Currently, user space apps like quality monitors don't have any
     * way to calibrate the measurement. With this, they can split
     * the range between 0 and max_qual in different quality level
     * (using a geometric subdivision centered on the average).
     * I expect that people doing the user space apps will feedback
     * us on which value we need to put in each driver... */
    avg_qual: priv_iw_quality, /* Quality of the link */

    /* Rates */
    num_bitrates: uint8_t, /* Number of entries in the list */
    bitrate: [int32_t; IW_MAX_BITRATES], /* list, in bps */

    /* RTS threshold */
    min_rts: int32_t, /* Minimal RTS threshold */
    max_rts: int32_t, /* Maximal RTS threshold */

    /* Frag threshold */
    min_frag: int32_t, /* Minimal frag threshold */
    max_frag: int32_t, /* Maximal frag threshold */

    /* Power Management duration & timeout */
    min_pmp: int32_t, /* Minimal PM period */
    max_pmp: int32_t, /* Maximal PM period */
    min_pmt: int32_t, /* Minimal PM timeout */
    max_pmt: int32_t, /* Maximal PM timeout */
    pmp_flags: uint16_t, /* How to decode max/min PM period */
    pmt_flags: uint16_t, /* How to decode max/min PM timeout */
    pm_capa: uint16_t, /* What PM options are supported */

    /* Encoder stuff */
    encoding_size: [uint16_t; IW_MAX_ENCODING_SIZES], /* Different token sizes */
    num_encoding_sizes: uint8_t, /* Number of entry in the list */
    max_encoding_tokens: uint8_t, /* Max number of tokens */
    /* For drivers that need a "login/passwd" form */
    encoding_login_index: uint8_t, /* token index for login token */

    /* Transmit power */
    txpower_capa: uint16_t, /* What options are supported */
    num_txpower: uint8_t, /* Number of entries in the list */
    txpower: [int32_t; IW_MAX_TXPOWER], /* list, in bps */

    /* Wireless Extension version info */
    we_version_compiled: uint8_t, /* Must be WIRELESS_EXT */
    we_version_source: uint8_t, /* Last update of source */

    /* Retry limits and lifetime */
    retry_capa: uint16_t, /* What retry options are supported */
    retry_flags: uint16_t, /* How to decode max/min retry limit */
    r_time_flags: uint16_t, /* How to decode max/min retry life */
    min_retry: int32_t, /* Minimal number of retries */
    max_retry: int32_t, /* Maximal number of retries */
    min_r_time: int32_t, /* Minimal retry lifetime */
    max_r_time: int32_t, /* Maximal retry lifetime */

    /* Frequency */
    num_channels: uint16_t, /* Number of channels [0, num - 1] */
    num_frequency: uint8_t, /* Number of entry in the list */
    freq: [priv_iw_freq; IW_MAX_FREQUENCIES], /* list */
    /* Note : this frequency list doesn't need to fit channel numbers,
     * because each entry contain its channel index */
    enc_capa: uint32_t, /* IW_ENC_CAPA_* bit field */

    /* More power management stuff */
    min_pms: int32_t, /* Minimal PM saving */
    max_pms: int32_t, /* Maximal PM saving */
    pms_flags: int16_t, /* How to decode max/min PM saving */

    /* All available modulations for driver (hw may support less) */
    modul_capa: uint32_t, /* IW_MODUL_* bit field */

    /* More bitrate stuff */
    bitrate_capa: uint32_t, /* Types of bitrates supported */
}

#[link(name="iwlib")]
extern {
    fn iw_socket_open() -> c_int;
    fn iw_get_range_info(socket: c_int,
                         interface: CString,
                         range: &iw_range) -> c_int;
    fn iw_scan(socket: c_int,
               interface: CString,
               version: c_int,
               head: &wireless_scan_head) -> c_int;
}

pub struct WifiScan<'a> {
    networks: Vec<WirelessNetwork<'a>>,
}

impl<'a> WifiScan<'a> {
    pub fn scan(interface: String) -> Result<WifiScan<'a>, WifiScanError> {
        // Scan things here
        unsafe { // TODO: Slim down unsafe blocks.
            // First get an iw socket.
            let sock = iw_socket_open();
            let interface_name = CString::new(interface).unwrap(); // TODO: Make the interface name configurable.
            let range: iw_range;
            let head: wireless_scan_head;
            if iw_get_range_info(sock, interface_name, &range) < 0 {
                // We have to make this call in order to get the version of the library on the computer
                Err("Got an error from the iw library")
            }
            if iw_scan(sock, interface_name, range.we_version_compiled, &head) <0 {
                // This is the actual scan call that fills in the `head` struct with information about the visible networks.
                Err("Got an error from the iw library")
            }
            let result = head.result;
            let mut list = Vec::new();
            while result != ptr::null {
                // The scan results are a linked list of structs with a bunch of information about each network
                // The type of encryption is encoded in a bitflag called `key_flags` which we check by doing
                // a bitwise and against the known bitflags.
                let answer = if result.b.key_flags & IW_AUTH_WPA_VERSION_DISABLED > 0 {
                    "None".to_string()
                } else if result.b.key_flags & IW_AUTH_WPA_VERSION_WPA > 0 {
                    "WPA".to_string()
                } else if result.b.key_flags & IW_AUTH_WPA_VERSION_WPA2 > 0 {
                    "WPA2".to_string()
                } ;
                list.push(WirelessNetwork {
                    SSID: result.b.essid.to_string(),
                    encryption: answer, // TODO Figure out how to get encryption type from `result`
                    strength: result.stats
                });
                result = result.next;
            }
        }
        Ok( WifiScan { networks: list });
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<commit_msg>Create default empty structs to be passed to iw<commit_after>extern crate libc;

use std::net::{SocketAddrV4, SocketAddrV6};
use std::ffi::CString;
use libc::*;

const IW_AUTH_WPA_VERSION_DISABLED: u8 = 0x00000001;
const IW_AUTH_WPA_VERSION_WPA: u8 = 0x00000002;
const IW_AUTH_WPA_VERSION_WPA2: u8 = 0x00000004;
const IW_MAX_BITRATES: usize = 32;
const IW_MAX_ENCODING_SIZES: usize = 8;
const IW_MAX_FREQUENCIES: usize = 32;
const IW_MAX_TXPOWER: usize = 8;

pub enum WirelessMode {
    Auto, /* Let the driver decide */
    AdHoc, /* Single cell network */
    Infra, /* Multi cell network, roaming, ... */
    Master, /* Synchronisation master or Access Point */
    Repeat, /* Wireless Repeater (forwarder) */
    Second, /* Secondary master/repeater (backup) */
    Monitor, /* Passive monitor (listen only) */
}

pub struct IwQuality {
    quality: u8,
    level: u8,
    noise: u8,
}

pub struct IwStats {
    status: uint16_t,
    quality: IwQuality,
}

pub struct WirelessKey<'a> {
    key: &'a [u8],
    size: u32,
    flags: i32,
}

pub struct WirelessNetwork<'a> {
    ap_addr4: Option<SocketAddrV4>,
    ap_addr6: Option<SocketAddrV6>,
    stats: Option<IwStats>,
    maxbitrate: Option<i32>,
    name: String,
    freq: Option<f64>,
    key: Option<WirelessKey<'a>>,
    essid: Option<String>,
    mode: Option<WirelessMode>,
}

#[repr(C)]
struct priv_iw_quality {
    qual: uint8_t,
    level: uint8_t,
    noise: uint8_t,
    updated: uint8_t,
}

impl Default for priv_iw_quality {
    fn default() -> priv_iw_quality {
        priv_iw_quality {
            qual: 0,
            level: 0,
            noise: 0,
            updated: 0
        }
    }
}

#[repr(C)]
struct priv_iw_freq {
    m: int32_t,
    e: int16_t,
    i: uint8_t,
    flags: uint8_t,
}

impl Default for priv_iw_freq {
    fn default() -> priv_iw_freq {
        priv_iw_freq {
            m: 0,
            e: 0,
            i: 0,
            flags: 0
        }
    }
}

#[repr(C)]
struct iw_range {
    /* Informative stuff (to choose between different interface) */
    throughput: uint32_t, /* To give an idea... */
    /* In theory this value should be the maximum benchmarked
     * TCP/IP throughput, because with most of these devices the
     * bit rate is meaningless (overhead an co) to estimate how
     * fast the connection will go and pick the fastest one.
     * I suggest people to play with Netperf or any benchmark...
     */

    /* NWID (or domain id) */
    min_nwid: uint32_t, /* Minimal NWID we are able to set */
    max_nwid: uint32_t, /* Maximal NWID we are able to set */

    /* Old Frequency (backward compat - moved lower ) */
    old_num_channels: uint16_t,
    old_num_frequency: uint8_t,

    /* Wireless event capability bitmasks */
    event_capa: [uint32_t; 6],

    /* signal level threshold range */
    sensitivity: int32_t,

    /* Quality of link & SNR stuff */
    /* Quality range (link, level, noise)
     * If the quality is absolute, it will be in the range [0 , max_qual],
     * if the quality is dBm, it will be in the range [max_qual , 0].
     * Don't forget that we use 8 bit arithmetics... */
    max_qual: priv_iw_quality, /* Quality of the link */
    /* This should contain the average/typical values of the quality
     * indicator. This should be the threshold between a "good" and
     * a "bad" link (example : monitor going from green to orange).
     * Currently, user space apps like quality monitors don't have any
     * way to calibrate the measurement. With this, they can split
     * the range between 0 and max_qual in different quality level
     * (using a geometric subdivision centered on the average).
     * I expect that people doing the user space apps will feedback
     * us on which value we need to put in each driver... */
    avg_qual: priv_iw_quality, /* Quality of the link */

    /* Rates */
    num_bitrates: uint8_t, /* Number of entries in the list */
    bitrate: [int32_t; IW_MAX_BITRATES], /* list, in bps */

    /* RTS threshold */
    min_rts: int32_t, /* Minimal RTS threshold */
    max_rts: int32_t, /* Maximal RTS threshold */

    /* Frag threshold */
    min_frag: int32_t, /* Minimal frag threshold */
    max_frag: int32_t, /* Maximal frag threshold */

    /* Power Management duration & timeout */
    min_pmp: int32_t, /* Minimal PM period */
    max_pmp: int32_t, /* Maximal PM period */
    min_pmt: int32_t, /* Minimal PM timeout */
    max_pmt: int32_t, /* Maximal PM timeout */
    pmp_flags: uint16_t, /* How to decode max/min PM period */
    pmt_flags: uint16_t, /* How to decode max/min PM timeout */
    pm_capa: uint16_t, /* What PM options are supported */

    /* Encoder stuff */
    encoding_size: [uint16_t; IW_MAX_ENCODING_SIZES], /* Different token sizes */
    num_encoding_sizes: uint8_t, /* Number of entry in the list */
    max_encoding_tokens: uint8_t, /* Max number of tokens */
    /* For drivers that need a "login/passwd" form */
    encoding_login_index: uint8_t, /* token index for login token */

    /* Transmit power */
    txpower_capa: uint16_t, /* What options are supported */
    num_txpower: uint8_t, /* Number of entries in the list */
    txpower: [int32_t; IW_MAX_TXPOWER], /* list, in bps */

    /* Wireless Extension version info */
    we_version_compiled: uint8_t, /* Must be WIRELESS_EXT */
    we_version_source: uint8_t, /* Last update of source */

    /* Retry limits and lifetime */
    retry_capa: uint16_t, /* What retry options are supported */
    retry_flags: uint16_t, /* How to decode max/min retry limit */
    r_time_flags: uint16_t, /* How to decode max/min retry life */
    min_retry: int32_t, /* Minimal number of retries */
    max_retry: int32_t, /* Maximal number of retries */
    min_r_time: int32_t, /* Minimal retry lifetime */
    max_r_time: int32_t, /* Maximal retry lifetime */

    /* Frequency */
    num_channels: uint16_t, /* Number of channels [0, num - 1] */
    num_frequency: uint8_t, /* Number of entry in the list */
    freq: [priv_iw_freq; IW_MAX_FREQUENCIES], /* list */
    /* Note : this frequency list doesn't need to fit channel numbers,
     * because each entry contain its channel index */
    enc_capa: uint32_t, /* IW_ENC_CAPA_* bit field */

    /* More power management stuff */
    min_pms: int32_t, /* Minimal PM saving */
    max_pms: int32_t, /* Maximal PM saving */
    pms_flags: int16_t, /* How to decode max/min PM saving */

    /* All available modulations for driver (hw may support less) */
    modul_capa: uint32_t, /* IW_MODUL_* bit field */

    /* More bitrate stuff */
    bitrate_capa: uint32_t, /* Types of bitrates supported */
}

impl Default for iw_range {
    fn default() -> iw_range {
        iw_range {
            min_nwid: 0,
            max_nwid: 0,
            old_num_channels: 0,
            old_num_frequency: 0,
            event_capa: [0; ..6u],
            sensitivity: 0,
            max_qual: priv_iw_quality, /* Quality of the link */
            avg_qual: priv_iw_quality, /* Quality of the link */
            num_bitrates: 0, /* Number of entries in the list */
            bitrate: [0; ..IW_MAX_BITRATES], /* list, in bps */
            min_rts: 0, /* Minimal RTS threshold */
            max_rts: 0, /* Maximal RTS threshold */
            min_frag: 0, /* Minimal frag threshold */
            max_frag: 0, /* Maximal frag threshold */
            min_pmp: 0, /* Minimal PM period */
            max_pmp: 0, /* Maximal PM period */
            min_pmt: 0, /* Minimal PM timeout */
            max_pmt: 0, /* Maximal PM timeout */
            pmp_flags: 0, /* How to decode max/min PM period */
            pmt_flags: 0, /* How to decode max/min PM timeout */
            pm_capa: 0, /* What PM options are supported */
            encoding_size: [0; ..IW_MAX_ENCODING_SIZES], /* Different token sizes */
            num_encoding_sizes: 0, /* Number of entry in the list */
            max_encoding_tokens: 0, /* Max number of tokens */
            encoding_login_index: 0, /* token index for login token */
            txpower_capa: 0, /* What options are supported */
            num_txpower: 0, /* Number of entries in the list */
            txpower: [0; ..IW_MAX_TXPOWER], /* list, in bps */
            we_version_compiled: 0, /* Must be WIRELESS_EXT */
            we_version_source: 0, /* Last update of source */
            retry_capa: 0, /* What retry options are supported */
            retry_flags: 0, /* How to decode max/min retry limit */
            r_time_flags: 0, /* How to decode max/min retry life */
            min_retry: 0, /* Minimal number of retries */
            max_retry: 0, /* Maximal number of retries */
            min_r_time: 0, /* Minimal retry lifetime */
            max_r_time: 0, /* Maximal retry lifetime */
            num_channels: 0, /* Number of channels [0, num - 1] */
            num_frequency: 0, /* Number of entry in the list */
            freq: [priv_iw_freq; ..IW_MAX_FREQUENCIES], /* list */
            enc_capa: 0, /* IW_ENC_CAPA_* bit field */
            min_pms: 0, /* Minimal PM saving */
            max_pms: 0, /* Maximal PM saving */
            pms_flags: 0, /* How to decode max/min PM saving */
            modul_capa: 0, /* IW_MODUL_* bit field */
            bitrate_capa: 0, /* Types of bitrates supported */
        }
    }
}

#[link(name="iwlib")]
extern {
    fn iw_socket_open() -> c_int;
    fn iw_get_range_info(socket: c_int,
                         interface: CString,
                         range: &iw_range) -> c_int;
    fn iw_scan(socket: c_int,
               interface: CString,
               version: c_int,
               head: &wireless_scan_head) -> c_int;
}

pub struct WifiScan<'a> {
    networks: Vec<WirelessNetwork<'a>>,
}

impl<'a> WifiScan<'a> {
    pub fn scan(interface: String) -> Result<WifiScan<'a>, WifiScanError> {
        // Scan things here
        unsafe { // TODO: Slim down unsafe blocks.
            // First get an iw socket.
            let sock = iw_socket_open();
            let interface_name = CString::new(interface).unwrap(); // TODO: Make the interface name configurable.
            let range: iw_range;
            let head: wireless_scan_head;
            if iw_get_range_info(sock, interface_name, &range) < 0 {
                // We have to make this call in order to get the version of the library on the computer
                Err("Got an error from the iw library")
            }
            if iw_scan(sock, interface_name, range.we_version_compiled, &head) <0 {
                // This is the actual scan call that fills in the `head` struct with information about the visible networks.
                Err("Got an error from the iw library")
            }
            let result = head.result;
            let mut list = Vec::new();
            while result != ptr::null {
                // The scan results are a linked list of structs with a bunch of information about each network
                // The type of encryption is encoded in a bitflag called `key_flags` which we check by doing
                // a bitwise and against the known bitflags.
                let answer = if result.b.key_flags & IW_AUTH_WPA_VERSION_DISABLED > 0 {
                    "None".to_string()
                } else if result.b.key_flags & IW_AUTH_WPA_VERSION_WPA > 0 {
                    "WPA".to_string()
                } else if result.b.key_flags & IW_AUTH_WPA_VERSION_WPA2 > 0 {
                    "WPA2".to_string()
                } ;
                list.push(WirelessNetwork {
                    SSID: result.b.essid.to_string(),
                    encryption: answer, // TODO Figure out how to get encryption type from `result`
                    strength: result.stats
                });
                result = result.next;
            }
        }
        Ok( WifiScan { networks: list });
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<|endoftext|>


<commit_before>extern crate base64;
extern crate hyper;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

pub mod logging;
pub mod http;
pub mod ctapi;

#[no_mangle]
#[allow(non_snake_case, unused_must_use)]
pub extern "system" fn CT_init(ctn: u16, pn: u16) -> i8 {
    ctapi::init::init(ctn, pn)
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn CT_data(ctn: u16,
                               dad: *mut u8,
                               sad: *mut u8,
                               lenc: usize,
                               command: *const u8,
                               lenr: *mut usize,
                               response: *mut u8)
                               -> i8 {
    ctapi::data::data(ctn, dad, sad, lenc, command, lenr, response)
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn CT_close(ctn: u16) -> i8 {
    ctapi::close::close(ctn)
}
<commit_msg>adjust mod order<commit_after>extern crate base64;
extern crate hyper;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

pub mod ctapi;
pub mod http;
pub mod logging;

#[no_mangle]
#[allow(non_snake_case, unused_must_use)]
pub extern "system" fn CT_init(ctn: u16, pn: u16) -> i8 {
    ctapi::init::init(ctn, pn)
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn CT_data(ctn: u16,
                               dad: *mut u8,
                               sad: *mut u8,
                               lenc: usize,
                               command: *const u8,
                               lenr: *mut usize,
                               response: *mut u8)
                               -> i8 {
    ctapi::data::data(ctn, dad, sad, lenc, command, lenr, response)
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn CT_close(ctn: u16) -> i8 {
    ctapi::close::close(ctn)
}
<|endoftext|>


<commit_before>//! Holmes
//!
//! Holmes is a Datalog inspired system for binding codependent analyses
//! together.
// TODO extend crate docs with example and tutorial on how to write a Holmes
// program.
#![warn(missing_docs)]
extern crate postgres;
extern crate postgres_array;
extern crate rustc_serialize;

pub mod pg;
pub mod fact_db;
pub mod mem_db;
pub mod engine;
pub mod edsl;

use pg::dyn::{Value, Type};
use engine::types::*;
use fact_db::FactDB;
use mem_db::MemDB;

/// Defines the database connection parameters
#[derive (Clone)]
pub enum DB {
  /// A postgres database, via a connection string
  Postgres(String),
  /// A memory backed database, *VERY INEFFICIENT*
  Memory
}

/// Ways that a `Holmes` operation might go wrong
// TODO: refactor based on cause() to have more semantic error types
pub enum Error {
  /// No database was specified
  NoDB,
  /// There was an error connecting to the database
  PgConnect(::postgres::error::ConnectError),
  /// There was a database error when setting up the database
  Pg(::postgres::error::Error),
  /// There was an error in the Holmes fact database layer
  Db(Box<::std::error::Error>),
  /// General IO Error
  IO(::std::io::Error),
  /// Parsing the connection string failed
  PgConnectStr(Box<::std::error::Error + Send + Sync>),
  /// There was an error in the Holmes engine layer
  Engine(engine::Error)
}

use engine::Engine;
use pg::PgDB;

/// `Result` is a shorthand type for the standard `Result` specialized to our
/// `Error type.
pub type Result<T> = ::std::result::Result<T, Error>;

use std::fmt::{Debug, Display, Formatter};

impl Display for Error {
  fn fmt(&self, fmt : &mut Formatter)
        -> ::std::result::Result<(),::std::fmt::Error> {
    use self::Error::*;
    match *self {
      NoDB             => fmt.write_str("No database specified"),
      PgConnect(ref e) => fmt.write_fmt(format_args!("Connection failed: {}", e)),
      Pg(ref e)     => fmt.write_fmt(format_args!("Postgres error: {}", e)),
      Db(ref e)   => fmt.write_fmt(format_args!("Deductive DB error: {}", e)),
      PgConnectStr(ref e) => fmt.write_fmt(format_args!("Connection string failed to parse: {}", e)),
      IO(ref e) => fmt.write_fmt(format_args!("IO failed: {}", e)),
      Engine(ref e) => fmt.write_fmt(format_args!("Engine Error: {}", e))
    }
  }
}

impl Debug for Error  {
  fn fmt(&self, fmt : &mut Formatter)
        -> ::std::result::Result<(),::std::fmt::Error> {
    Display::fmt(self, fmt)
  }
}

impl ::std::error::Error for Error {
  fn description(&self) -> &str {
    use self::Error::*;
    match self {
      &NoDB              => "No database specified",
      &PgConnect(ref e)  => e.description(),
      &Pg(ref e)         => e.description(),
      &Db(ref e)         => e.description(),
      &IO(ref e)         => e.description(),
      &Engine(ref e)     => e.description(),
      &PgConnectStr(_)   => "Connection string failed to parse"
    }
  }
}

impl From<::postgres::error::ConnectError> for Error {
  fn from(ce : ::postgres::error::ConnectError) -> Error {Error::PgConnect(ce)}
}

impl From<::postgres::error::Error> for Error {
  fn from(e : ::postgres::error::Error) -> Error {Error::Pg(e)}
}

impl From<Box<::std::error::Error>> for Error {
  fn from(e : Box<::std::error::Error>) -> Error {Error::Db(e)}
}

impl From<engine::Error> for Error {
  fn from(e : engine::Error) -> Error {Error::Engine(e)}
}

impl From<::std::io::Error> for Error {
  fn from(e : ::std::io::Error) -> Error {Error::IO(e)}
}

impl<'a> DB {
  /// Destroy the fact database entirely
  ///
  /// * Kicks everyone off the database
  /// * Drops the database
  fn destroy(&self) -> Result<()> {
    match self {
      &DB::Postgres(ref str) => {
        use postgres::{Connection, SslMode, IntoConnectParams};
        let mut params = try!(str.into_connect_params()
                                 .map_err(Error::PgConnectStr));
        let old_db = try!(params.database.ok_or(Error::NoDB));
        params.database = Some("postgres".to_owned());
        let conn = try!(Connection::connect(params, SslMode::None));
        let disco_query = format!("SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '{}' AND pid <> pg_backend_pid()", &old_db);
        try!(conn.execute(&disco_query, &[]));
        let drop_query = format!("DROP DATABASE {}", &old_db);
        try!(conn.execute(&drop_query, &[]));
      }
      &DB::Memory => ()
    }
    Ok(())
  }
  /// Creates a fresh fact database
  fn create(&self) -> Result<Box<FactDB>> {
    match self {
      &DB::Postgres(ref str) => {
        use postgres::{Connection, SslMode, IntoConnectParams};
        let mut params = try!(str.into_connect_params()
                                 .map_err(Error::PgConnectStr));
        let old_db = try!(params.database.ok_or(Error::NoDB));
        params.database = Some("postgres".to_owned());
        let conn = try!(Connection::connect(params, SslMode::None));
        let create_query = format!("CREATE DATABASE {}", &old_db);
        //TODO accept success or db already exists, not other errors
        let _ = conn.execute(&create_query, &[]);
        Ok(Box::new(try!(PgDB::new(str))))
      }
      &DB::Memory => Ok(Box::new(MemDB::new()))
    }
  }
}

/// Encapsulates the user-level interface to a holmes database
pub struct Holmes {
  db : DB,
  engine : Engine
}

impl Holmes {
  /// Create a new holmes instance from a db specification
  pub fn new(db : DB) -> Result<Holmes> {
    Ok(Holmes {
      engine : Engine::new(try!(db.create())),
      db : db
    })
  }

  /// Tear down and destroy the database.
  /// THIS DELETES YOUR DATA
  pub fn destroy(self) -> Result<()> {
    let db = self.db.clone();
    drop(self);
    db.destroy()
  }

  /// Register a new predicate with the database. This should be done before
  /// adding facts to that predicate or rules that refer to it.
  /// Do not attempt to register two predicates with the same name.
  pub fn add_predicate(&mut self, pred : &engine::types::Predicate)
                      -> Result<()> {
    self.engine.new_predicate(pred).map_err(|e| {Error::Engine(e)})
  }

  /// Add a new fact to the database. The predicate must be registered first.
  /// Duplicate facts are ignored.
  pub fn add_fact(&mut self, fact : &engine::types::Fact)
                      -> Result<()> {
    self.engine.new_fact(fact).map_err(|e| {Error::Engine(e)})
  }

  /// Query the database with the right hand side of a datalog rule, returning
  /// all legal assignments to the variables to make it true
  pub fn query(&mut self, query : &Vec<engine::types::Clause>) -> Result<Vec<Vec<Value>>> {
    self.engine.derive(query).map_err(|e| {Error::Engine(e)})
  }

  /// Get a dynamic type registered with Holmes by name. If it is present, it
  /// returns `Some(Type)`, otherwise it returns `None`. The type database is
  /// prepopulated with a few defaults, but otherwise this will only work if
  /// you registered the type via `add_type`.
  pub fn get_type(&self, name : &str) -> Option<Type> {
    self.engine.get_type(name)
  }

  /// Registers a new type with Holmes. It must be a named type, e.g.
  /// `type.name()` would return the `Some` branch.
  /// Types should be registered exactly once
  pub fn add_type(&mut self, type_ : Type) -> Result<()> {
    self.engine.add_type(type_).map_err(|e| {Error::Engine(e)})
  }

  /// Adds a new inference rule to the Holmes program
  pub fn add_rule(&mut self, rule : &engine::types::Rule) -> Result<()> {
    self.engine.new_rule(rule).map_err(|e| {Error::Engine(e)})
  }

  /// Registers a dynamically typed function for use in Holmes where clauses
  pub fn reg_func(&mut self,
                  name : String,
                  input_type  : Type,
                  output_type : Type,
                  func : Box<Fn(Value) -> Value>) -> Result<()> {
    self.engine.reg_func(name, engine::types::Func {
      input_type  : input_type,
      output_type : output_type,
      run : func
    });
    Ok(())
  }
}
<commit_msg>Add docs for basic datalog to the crate<commit_after>//! Holmes
//!
//! Holmes is a Datalog inspired system for binding codependent analyses
//! together.
//!
//! # Tutorial
//!
//! ## Basic Datalog
//! If you are already familiar with logic languages, this section will likely
//! be straightforwards for you, but it may still be useful to provide an
//! overview of basic functions and syntax.
//!
//! Datalog is a forward-chaining logic language. This means that a program
//! written in Datalog consists of a set of rules which "fire" whenever their
//! requirements are met which operate on a database of facts.
//!
//! A predicate represents a property on a list of typed values. For example,
//! to express the distance between two cities in miles, we might write
//!
//! ```
//! # #[macro_use]
//! # extern crate holmes;
//! # use holmes::{Holmes, Result};
//! # use holmes::DB::Memory;
//! # fn f () -> Result<()> {
//! # let mut holmes = try!(Holmes::new(Memory));
//! # let b = &mut holmes;
//! # holmes_exec!(b, {
//! predicate!(distance(string, string, uint64))
//! # });
//! # Ok(())
//! # }
//! # fn main () {f().unwrap()}
//! ```
//!
//! N.B. while this code is being built via doctests, there are a few lines of
//! support code above and below being hidden for clarity. See the complete
//! example at the end of the section for a template.
//!
//! Facts are formed by the application of predicates to values. Continuing
//! with the example from before, we can add a fact to the database for the
//! predicate we defined
//!
//! ```
//! # #[macro_use]
//! # extern crate holmes;
//! # use holmes::{Holmes, Result};
//! # use holmes::DB::Memory;
//! # fn f () -> Result<()> {
//! # let mut holmes = try!(Holmes::new(Memory));
//! # let b = &mut holmes;
//! # holmes_exec!(b, {
//! predicate!(distance(string, string, uint64));
//! fact!(distance("New York", "Albuquerque", 1810))
//! # });
//! # Ok(())
//! # }
//! # fn main () {f().unwrap()}
//! ```
//!
//! Rules are formed from a body clause and a head clause.
//! When the rule body matches, variable assignments from the match are
//! substituted into the head clause, which is then added to the database.
//! Here, we might want to add the symmetry property to our previous example,
//! e.g. "If the distance from A to B is N, then the distance from B to A is
//! also N".
//!
//! ```
//! # #[macro_use]
//! # extern crate holmes;
//! # use holmes::{Holmes, Result};
//! # use holmes::DB::Memory;
//! # fn f () -> Result<()> {
//! # let mut holmes = try!(Holmes::new(Memory));
//! # let b = &mut holmes;
//! # holmes_exec!(b, {
//! predicate!(distance(string, string, uint64));
//! fact!(distance("New York", "Albuquerque", 1810));
//! rule!(distance(B, A, N) <= distance(A, B, N))
//! # });
//! # Ok(())
//! # }
//! # fn main () {f().unwrap()}
//! ```
//!
//! Now that the database has more facts in it than we started with, it makes
//! sense to be able to query the database and see what is inside.
//!
//! ```
//! # #[macro_use]
//! # extern crate holmes;
//! # use holmes::{Holmes, Result};
//! # use holmes::DB::Memory;
//! # use holmes::pg::dyn::values::ToValue;
//! # fn f () -> Result<()> {
//! # let mut holmes_own = try!(Holmes::new(Memory));
//! # let holmes = &mut holmes_own;
//! holmes_exec!(holmes, {
//!   predicate!(distance(string, string, uint64));
//!   fact!(distance("New York", "Albuquerque", 1810));
//!   rule!(distance(B, A, N) <= distance(A, B, N))
//! });
//! let mut res = try!(query!(holmes, distance(A, [_], [_])));
//! # res.sort_by(|x, y| x.partial_cmp(y).unwrap_or(
//! #   ::std::cmp::Ordering::Greater));
//! assert_eq!(res,
//!            vec![vec!["Albuquerque".to_value()],
//!                 vec!["New York".to_value()]]);
//! # Ok(())
//! # }
//! # fn main () {f().unwrap()}
//! ```
//!
//! Let's go one step further, and use a rule to check connectivity between
//! cities, based on the facts in the database. We want to express "If A
//! connects to B, and B connects to C, then A connects to C".
//!
//! ```
//! # #[macro_use]
//! # extern crate holmes;
//! # use holmes::{Holmes, Result};
//! # use holmes::DB::Memory;
//! # use holmes::pg::dyn::values::ToValue;
//! # fn f () -> Result<()> {
//! # let mut holmes_own = try!(Holmes::new(Memory));
//! # let holmes = &mut holmes_own;
//! holmes_exec!(holmes, {
//!   predicate!(distance(string, string, uint64));
//!   fact!(distance("New York", "Albuquerque", 1810));
//!   fact!(distance("New York", "Las Vegas", 2225));
//!   fact!(distance("Las Vegas", "Palo Alto", 542));
//!   fact!(distance("Rome", "Florence", 173));
//!   rule!(distance(B, A, N) <= distance(A, B, N));
//!   predicate!(connected(string, string));
//!   rule!(connected(A, B) <= distance(A, B, [_]));
//!   rule!(connected(A, C) <= connected(A, B) & connected(B, C))
//! });
//! assert_eq!(try!(query!(holmes, connected(("Rome"), ("Las Vegas")))).len(),
//!            0);
//! let mut res = try!(query!(holmes, connected(("Palo Alto"), x)));
//! # res.sort_by(|x, y| x.partial_cmp(y).unwrap_or(
//! #   ::std::cmp::Ordering::Greater));
//! assert_eq!(res,
//!            vec![vec!["Albuquerque".to_value()],
//!                 vec!["Las Vegas".to_value()],
//!                 vec!["New York".to_value()],
//!                 vec!["Palo Alto".to_value()]]);
//! # Ok(())
//! # }
//! # fn main () {f().unwrap()}
//! ```
//!
//! Finally, just for reference (so you can actually write your own program
//! using this) here's the unredacted version of that last example:
//!
//! ```
//! #[macro_use]
//! extern crate holmes;
//! use holmes::{Holmes, Result};
//! use holmes::DB::Memory;
//! use holmes::pg::dyn::values::ToValue;
//! fn f () -> Result<()> {
//!   // I'm using `Memory` in the examples, but you probably don't want to use
//!   // it in your own code. Check out `Holmes::DB`'s wings to see what your
//!   // options are. `Memory` is super slow for the moment, and I don't forsee
//!   // taking time to optimize it.
//!   let mut holmes_own = try!(Holmes::new(Memory));
//!   // For the moment, the `holmes_exec` macro needs a &mut ident. I'll
//!   // try to make this more flexible in the future.
//!   let holmes = &mut holmes_own;
//!   holmes_exec!(holmes, {
//!     predicate!(distance(string, string, uint64));
//!     fact!(distance("New York", "Albuquerque", 1810));
//!     fact!(distance("New York", "Las Vegas", 2225));
//!     fact!(distance("Las Vegas", "Palo Alto", 542));
//!     fact!(distance("Rome", "Florence", 173));
//!     rule!(distance(B, A, N) <= distance(A, B, N));
//!     predicate!(connected(string, string));
//!     rule!(connected(A, B) <= distance(A, B, [_]));
//!     rule!(connected(A, C) <= connected(A, B) & connected(B, C))
//!   });
//!   assert_eq!(try!(query!(holmes, connected(("Rome"), ("Las Vegas")))).len(),
//!              0);
//!   let mut res = try!(query!(holmes, connected(("Palo Alto"), x)));
//!   // Order is not gauranteed when it comes back from the query, so I
//!   // sort it in the example to get the doctest to pass. `Value` only has
//!   // `PartialOrd` implemented for it, since there isn't a clean comparison
//!   // between `Value`s of different types, so I just default to `Greater`.
//!   res.sort_by(|x, y| x.partial_cmp(y).unwrap_or(
//!     ::std::cmp::Ordering::Greater));
//!   assert_eq!(res,
//!              vec![vec!["Albuquerque".to_value()],
//!                   vec!["Las Vegas".to_value()],
//!                   vec!["New York".to_value()],
//!                   vec!["Palo Alto".to_value()]]);
//!   Ok(())
//! }
//! fn main () {f().unwrap()}
//! ```
//!
// TODO extend crate docs with example and tutorial on how to use functions
#![warn(missing_docs)]
extern crate postgres;
extern crate postgres_array;
extern crate rustc_serialize;

pub mod pg;
pub mod fact_db;
pub mod mem_db;
pub mod engine;
pub mod edsl;

use pg::dyn::{Value, Type};
use engine::types::*;
use fact_db::FactDB;
use mem_db::MemDB;

/// Defines the database connection parameters
#[derive (Clone)]
pub enum DB {
  /// A postgres database, via a connection string
  Postgres(String),
  /// A memory backed database, *VERY INEFFICIENT*
  Memory
}

/// Ways that a `Holmes` operation might go wrong
// TODO: refactor based on cause() to have more semantic error types
pub enum Error {
  /// No database was specified
  NoDB,
  /// There was an error connecting to the database
  PgConnect(::postgres::error::ConnectError),
  /// There was a database error when setting up the database
  Pg(::postgres::error::Error),
  /// There was an error in the Holmes fact database layer
  Db(Box<::std::error::Error>),
  /// General IO Error
  IO(::std::io::Error),
  /// Parsing the connection string failed
  PgConnectStr(Box<::std::error::Error + Send + Sync>),
  /// There was an error in the Holmes engine layer
  Engine(engine::Error)
}

use engine::Engine;
use pg::PgDB;

/// `Result` is a shorthand type for the standard `Result` specialized to our
/// `Error type.
pub type Result<T> = ::std::result::Result<T, Error>;

use std::fmt::{Debug, Display, Formatter};

impl Display for Error {
  fn fmt(&self, fmt : &mut Formatter)
        -> ::std::result::Result<(),::std::fmt::Error> {
    use self::Error::*;
    match *self {
      NoDB             => fmt.write_str("No database specified"),
      PgConnect(ref e) => fmt.write_fmt(format_args!("Connection failed: {}", e)),
      Pg(ref e)     => fmt.write_fmt(format_args!("Postgres error: {}", e)),
      Db(ref e)   => fmt.write_fmt(format_args!("Deductive DB error: {}", e)),
      PgConnectStr(ref e) => fmt.write_fmt(format_args!("Connection string failed to parse: {}", e)),
      IO(ref e) => fmt.write_fmt(format_args!("IO failed: {}", e)),
      Engine(ref e) => fmt.write_fmt(format_args!("Engine Error: {}", e))
    }
  }
}

impl Debug for Error  {
  fn fmt(&self, fmt : &mut Formatter)
        -> ::std::result::Result<(),::std::fmt::Error> {
    Display::fmt(self, fmt)
  }
}

impl ::std::error::Error for Error {
  fn description(&self) -> &str {
    use self::Error::*;
    match self {
      &NoDB              => "No database specified",
      &PgConnect(ref e)  => e.description(),
      &Pg(ref e)         => e.description(),
      &Db(ref e)         => e.description(),
      &IO(ref e)         => e.description(),
      &Engine(ref e)     => e.description(),
      &PgConnectStr(_)   => "Connection string failed to parse"
    }
  }
}

impl From<::postgres::error::ConnectError> for Error {
  fn from(ce : ::postgres::error::ConnectError) -> Error {Error::PgConnect(ce)}
}

impl From<::postgres::error::Error> for Error {
  fn from(e : ::postgres::error::Error) -> Error {Error::Pg(e)}
}

impl From<Box<::std::error::Error>> for Error {
  fn from(e : Box<::std::error::Error>) -> Error {Error::Db(e)}
}

impl From<engine::Error> for Error {
  fn from(e : engine::Error) -> Error {Error::Engine(e)}
}

impl From<::std::io::Error> for Error {
  fn from(e : ::std::io::Error) -> Error {Error::IO(e)}
}

impl<'a> DB {
  /// Destroy the fact database entirely
  ///
  /// * Kicks everyone off the database
  /// * Drops the database
  fn destroy(&self) -> Result<()> {
    match self {
      &DB::Postgres(ref str) => {
        use postgres::{Connection, SslMode, IntoConnectParams};
        let mut params = try!(str.into_connect_params()
                                 .map_err(Error::PgConnectStr));
        let old_db = try!(params.database.ok_or(Error::NoDB));
        params.database = Some("postgres".to_owned());
        let conn = try!(Connection::connect(params, SslMode::None));
        let disco_query = format!("SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '{}' AND pid <> pg_backend_pid()", &old_db);
        try!(conn.execute(&disco_query, &[]));
        let drop_query = format!("DROP DATABASE {}", &old_db);
        try!(conn.execute(&drop_query, &[]));
      }
      &DB::Memory => ()
    }
    Ok(())
  }
  /// Creates a fresh fact database
  fn create(&self) -> Result<Box<FactDB>> {
    match self {
      &DB::Postgres(ref str) => {
        use postgres::{Connection, SslMode, IntoConnectParams};
        let mut params = try!(str.into_connect_params()
                                 .map_err(Error::PgConnectStr));
        let old_db = try!(params.database.ok_or(Error::NoDB));
        params.database = Some("postgres".to_owned());
        let conn = try!(Connection::connect(params, SslMode::None));
        let create_query = format!("CREATE DATABASE {}", &old_db);
        //TODO accept success or db already exists, not other errors
        let _ = conn.execute(&create_query, &[]);
        Ok(Box::new(try!(PgDB::new(str))))
      }
      &DB::Memory => Ok(Box::new(MemDB::new()))
    }
  }
}

/// Encapsulates the user-level interface to a holmes database
pub struct Holmes {
  db : DB,
  engine : Engine
}

impl Holmes {
  /// Create a new holmes instance from a db specification
  pub fn new(db : DB) -> Result<Holmes> {
    Ok(Holmes {
      engine : Engine::new(try!(db.create())),
      db : db
    })
  }

  /// Tear down and destroy the database.
  /// THIS DELETES YOUR DATA
  pub fn destroy(self) -> Result<()> {
    let db = self.db.clone();
    drop(self);
    db.destroy()
  }

  /// Register a new predicate with the database. This should be done before
  /// adding facts to that predicate or rules that refer to it.
  /// Do not attempt to register two predicates with the same name.
  pub fn add_predicate(&mut self, pred : &engine::types::Predicate)
                      -> Result<()> {
    self.engine.new_predicate(pred).map_err(|e| {Error::Engine(e)})
  }

  /// Add a new fact to the database. The predicate must be registered first.
  /// Duplicate facts are ignored.
  pub fn add_fact(&mut self, fact : &engine::types::Fact)
                      -> Result<()> {
    self.engine.new_fact(fact).map_err(|e| {Error::Engine(e)})
  }

  /// Query the database with the right hand side of a datalog rule, returning
  /// all legal assignments to the variables to make it true
  pub fn query(&mut self, query : &Vec<engine::types::Clause>) -> Result<Vec<Vec<Value>>> {
    self.engine.derive(query).map_err(|e| {Error::Engine(e)})
  }

  /// Get a dynamic type registered with Holmes by name. If it is present, it
  /// returns `Some(Type)`, otherwise it returns `None`. The type database is
  /// prepopulated with a few defaults, but otherwise this will only work if
  /// you registered the type via `add_type`.
  pub fn get_type(&self, name : &str) -> Option<Type> {
    self.engine.get_type(name)
  }

  /// Registers a new type with Holmes. It must be a named type, e.g.
  /// `type.name()` would return the `Some` branch.
  /// Types should be registered exactly once
  pub fn add_type(&mut self, type_ : Type) -> Result<()> {
    self.engine.add_type(type_).map_err(|e| {Error::Engine(e)})
  }

  /// Adds a new inference rule to the Holmes program
  pub fn add_rule(&mut self, rule : &engine::types::Rule) -> Result<()> {
    self.engine.new_rule(rule).map_err(|e| {Error::Engine(e)})
  }

  /// Registers a dynamically typed function for use in Holmes where clauses
  pub fn reg_func(&mut self,
                  name : String,
                  input_type  : Type,
                  output_type : Type,
                  func : Box<Fn(Value) -> Value>) -> Result<()> {
    self.engine.reg_func(name, engine::types::Func {
      input_type  : input_type,
      output_type : output_type,
      run : func
    });
    Ok(())
  }
}
<|endoftext|>


<commit_before>//! which
//!
//! A Rust equivalent of Unix command "which".
//! # Exmaple:
//!
//! To find wihch rustc exectable binary is using.
//!
//! ``` norun
//! use which::which;
//!
//! let result = which::which("rustc").unwrap();
//! assert_eq!(result, PathBuf::from("/usr/bin/rustc"));
//!
//! ```

use std::path::PathBuf;
use std::{env, fs};

fn is_exist(bin_path: &PathBuf) -> bool {

    match fs::metadata(bin_path).map(|metadata|{
        metadata.is_file()
    }) {
        Ok(true) => true,
        _ => false
    }
}

/// Find a exectable binary's path by name.
///
/// # Example
///
/// ``` norun
/// use which::which;
/// use std::path::PathBuf;
///
/// let result = which::which("rustc").unwrap();
/// assert_eq!(result, PathBuf::from("/usr/bin/rustc"));
///
/// ```
pub fn which(binary_name: &'static str)
             -> Result<PathBuf, &'static str> {

    let path_buf = env::var_os("PATH").and_then(
        |paths| -> Option<PathBuf> {
            for path in env::split_paths(&paths) {
                let bin_path = path.join(binary_name);
                if is_exist(&bin_path) {
                    return Some(bin_path);
                }
            }
            return None;

        });

    match path_buf {
        Some(path) => Ok(path),
        None => Err("Can not find binary path")
    }

}

#[test]
fn it_works() {
    use std::process::Command;
    let result = which("rustc");
    assert!(result.is_ok());

    let which_result = Command::new("which")
        .arg("rustc")
        .output();

    assert_eq!(String::from(result.unwrap().to_str().unwrap()),
        String::from_utf8(which_result.unwrap().stdout).unwrap().trim());
}

#[test]
fn dont_works() {
    let result = which("cargo-no-exist");
    assert_eq!(result, Err("Can not find binary path"))
}
<commit_msg>Change binary_name parameter to AsRef<OsStr><commit_after>//! which
//!
//! A Rust equivalent of Unix command "which".
//! # Exmaple:
//!
//! To find wihch rustc exectable binary is using.
//!
//! ``` norun
//! use which::which;
//!
//! let result = which::which("rustc").unwrap();
//! assert_eq!(result, PathBuf::from("/usr/bin/rustc"));
//!
//! ```

use std::path::PathBuf;
use std::{env, fs};
use std::ffi::OsStr;

fn is_exist(bin_path: &PathBuf) -> bool {

    match fs::metadata(bin_path).map(|metadata|{
        metadata.is_file()
    }) {
        Ok(true) => true,
        _ => false
    }
}

/// Find a exectable binary's path by name.
///
/// # Example
///
/// ``` norun
/// use which::which;
/// use std::path::PathBuf;
///
/// let result = which::which("rustc").unwrap();
/// assert_eq!(result, PathBuf::from("/usr/bin/rustc"));
///
/// ```
pub fn which<T: AsRef<OsStr>>(binary_name: T)
             -> Result<PathBuf, &'static str> {

    let path_buf = env::var_os("PATH").and_then(
        |paths| -> Option<PathBuf> {
            for path in env::split_paths(&paths) {
                let bin_path = path.join(binary_name.as_ref());
                if is_exist(&bin_path) {
                    return Some(bin_path);
                }
            }
            return None;

        });

    match path_buf {
        Some(path) => Ok(path),
        None => Err("Can not find binary path")
    }

}

#[test]
fn it_works() {
    use std::process::Command;
    let result = which("rustc");
    assert!(result.is_ok());

    let which_result = Command::new("which")
        .arg("rustc")
        .output();

    assert_eq!(String::from(result.unwrap().to_str().unwrap()),
        String::from_utf8(which_result.unwrap().stdout).unwrap().trim());
}

#[test]
fn dont_works() {
    let result = which("cargo-no-exist");
    assert_eq!(result, Err("Can not find binary path"))
}
<|endoftext|>


<commit_before>//! **A undo-redo library.**
//!
//! It is an implementation of the action pattern, where all modifications are done
//! by creating objects of actions that applies the modifications. All actions knows
//! how to undo the changes it applies, and by using the provided data structures
//! it is easy to apply, undo, and redo changes made to a target.
//!
//! # Features
//!
//! * [Action](trait.Action.html) provides the base functionality for all actions.
//! * [Record](record/struct.Record.html) provides basic undo-redo functionality.
//! * [Timeline](timeline/struct.Timeline.html) provides basic undo-redo functionality using a fixed size.
//! * [History](history/struct.History.html) provides non-linear undo-redo functionality that allows you to jump between different branches.
//! * Queues wraps a record or history and extends them with queue functionality.
//! * Checkpoints wraps a record or history and extends them with checkpoint functionality.
//! * Actions can be merged into a single action by implementing the
//!   [merge](trait.Action.html#method.merge) method on the action.
//!   This allows smaller actions to be used to build more complex operations, or smaller incremental changes to be
//!   merged into larger changes that can be undone and redone in a single step.
//! * The target can be marked as being saved to disk and the data-structures can track the saved state and notify
//!   when it changes.
//! * The amount of changes being tracked can be configured by the user so only the `N` most recent changes are stored.
//! * Configurable display formatting using the display structure.
//! * The library can be used as `no_std`.
//!
//! # Cargo Feature Flags
//!
//! * `alloc`: Enables the use of the alloc crate, enabled by default.
//! * `arrayvec`: Required for the timeline module, enabled by default.
//! * `chrono`: Enables time stamps and time travel.
//! * `serde`: Enables serialization and deserialization.
//! * `colored`: Enables colored output when visualizing the display structures.
//!
//! # Examples
//!
//! ```rust
//! use undo::{Action, History};
//!
//! struct Add(char);
//!
//! impl Action for Add {
//!     type Target = String;
//!     type Output = ();
//!     type Error = &'static str;
//!
//!     fn apply(&mut self, s: &mut String) -> undo::Result<Add> {
//!         s.push(self.0);
//!         Ok(())
//!     }
//!
//!     fn undo(&mut self, s: &mut String) -> undo::Result<Add> {
//!         self.0 = s.pop().ok_or("s is empty")?;
//!         Ok(())
//!     }
//! }
//!
//! fn main() {
//!     let mut target = String::new();
//!     let mut history = History::new();
//!     history.apply(&mut target, Add('a')).unwrap();
//!     history.apply(&mut target, Add('b')).unwrap();
//!     history.apply(&mut target, Add('c')).unwrap();
//!     assert_eq!(target, "abc");
//!     history.undo(&mut target).unwrap().unwrap();
//!     history.undo(&mut target).unwrap().unwrap();
//!     history.undo(&mut target).unwrap().unwrap();
//!     assert_eq!(target, "");
//!     history.redo(&mut target).unwrap().unwrap();
//!     history.redo(&mut target).unwrap().unwrap();
//!     history.redo(&mut target).unwrap().unwrap();
//!     assert_eq!(target, "abc");
//! }
//! ```

#![no_std]
#![doc(html_root_url = "https://docs.rs/undo")]
#![deny(missing_docs)]
#![forbid(unsafe_code)]
#![cfg_attr(not(feature = "alloc"), allow(dead_code))]

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "alloc")]
mod format;
#[cfg(feature = "alloc")]
pub mod history;
#[cfg(feature = "alloc")]
pub mod record;
#[cfg(feature = "arrayvec")]
pub mod timeline;

use crate::format::Format;
#[cfg(feature = "chrono")]
use chrono::{DateTime, Utc};
use core::fmt;
#[cfg(feature = "serde")]
use serde_crate::{Deserialize, Serialize};

#[cfg(feature = "arrayvec")]
pub use self::timeline::Timeline;
#[cfg(feature = "alloc")]
pub use self::{history::History, record::Record};

/// A specialized Result type for undo-redo operations.
pub type Result<A> = core::result::Result<<A as Action>::Output, <A as Action>::Error>;

/// Base functionality for all actions.
pub trait Action {
    /// The target type.
    type Target;
    /// The output type.
    type Output;
    /// The error type.
    type Error;

    /// Applies the action on the target and returns `Ok` if everything went fine,
    /// and `Err` if something went wrong.
    fn apply(&mut self, target: &mut Self::Target) -> Result<Self>;

    /// Restores the state of the target as it was before the action was applied
    /// and returns `Ok` if everything went fine, and `Err` if something went wrong.
    fn undo(&mut self, target: &mut Self::Target) -> Result<Self>;

    /// Reapplies the action on the target and return `Ok` if everything went fine,
    /// and `Err` if something went wrong.
    ///
    /// The default implementation uses the [`apply`](trait.Action.html#tymethod.apply) implementation.
    fn redo(&mut self, target: &mut Self::Target) -> Result<Self> {
        self.apply(target)
    }

    /// Used for manual merging of actions.
    fn merge(&mut self, _: &mut Self) -> Merged
    where
        Self: Sized,
    {
        Merged::No
    }
}

impl<A, D> Action for D
where
    A: Action + ?Sized,
    D: core::ops::DerefMut<Target = A>
{
    type Target = A::Target;
    type Output = A::Output;
    type Error = A::Error;

    fn apply(&mut self, target: &mut Self::Target) -> Result<Self> {
        self.deref_mut().apply(target)
    }

    fn undo(&mut self, target: &mut Self::Target) -> Result<Self> {
        self.deref_mut().undo(target)
    }
}

/// Says if the action have been merged with another action.
#[cfg_attr(
    feature = "serde",
    derive(Serialize, Deserialize),
    serde(crate = "serde_crate")
)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum Merged {
    /// The actions have been merged.
    Yes,
    /// The actions have not been merged.
    No,
    /// The two actions cancels each other out.
    Annul,
}

/// A position in a history tree.
#[cfg_attr(
    feature = "serde",
    derive(Serialize, Deserialize),
    serde(crate = "serde_crate")
)]
#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
struct At {
    branch: usize,
    current: usize,
}

impl At {
    const ROOT: At = At::new(0, 0);

    const fn new(branch: usize, current: usize) -> At {
        At { branch, current }
    }
}

/// The signal used for communicating state changes.
///
/// For example, if the record can no longer redo any actions, it sends a `Redo(false)`
/// signal to tell the user.
#[cfg_attr(
    feature = "serde",
    derive(Serialize, Deserialize),
    serde(crate = "serde_crate")
)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum Signal {
    /// Says if the structures can undo.
    Undo(bool),
    /// Says if the structures can redo.
    Redo(bool),
    /// Says if the target is in a saved state.
    Saved(bool),
}

#[cfg_attr(
    feature = "serde",
    derive(Serialize, Deserialize),
    serde(crate = "serde_crate")
)]
#[derive(Clone)]
struct Slot<F> {
    #[cfg_attr(feature = "serde", serde(default = "Option::default", skip))]
    f: Option<F>,
}

impl<F: FnMut(Signal)> Slot<F> {
    fn emit(&mut self, signal: Signal) {
        if let Some(ref mut f) = self.f {
            f(signal);
        }
    }

    fn emit_if(&mut self, cond: bool, signal: Signal) {
        if cond {
            self.emit(signal);
        }
    }
}

impl<F> From<F> for Slot<F> {
    fn from(f: F) -> Slot<F> {
        Slot { f: Some(f) }
    }
}

impl<F> Default for Slot<F> {
    fn default() -> Self {
        Slot { f: None }
    }
}

impl<F> fmt::Debug for Slot<F> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.f {
            Some(_) => f.pad("Slot { .. }"),
            None => f.pad("Empty"),
        }
    }
}

#[cfg_attr(
    feature = "serde",
    derive(Serialize, Deserialize),
    serde(crate = "serde_crate")
)]
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
struct Entry<A> {
    action: A,
    #[cfg(feature = "chrono")]
    timestamp: DateTime<Utc>,
}

impl<A> From<A> for Entry<A> {
    fn from(action: A) -> Self {
        Entry {
            action,
            #[cfg(feature = "chrono")]
            timestamp: Utc::now(),
        }
    }
}

impl<A: Action> Action for Entry<A> {
    type Target = A::Target;
    type Output = A::Output;
    type Error = A::Error;

    fn apply(&mut self, target: &mut Self::Target) -> Result<Self> {
        self.action.apply(target)
    }

    fn undo(&mut self, target: &mut Self::Target) -> Result<Self> {
        self.action.undo(target)
    }

    fn redo(&mut self, target: &mut Self::Target) -> Result<Self> {
        self.action.redo(target)
    }

    fn merge(&mut self, entry: &mut Self) -> Merged {
        self.action.merge(&mut entry.action)
    }
}

impl<A: fmt::Display> fmt::Display for Entry<A> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        (&self.action as &dyn fmt::Display).fmt(f)
    }
}
<commit_msg>fix: add missing `redo` implementation<commit_after>//! **A undo-redo library.**
//!
//! It is an implementation of the action pattern, where all modifications are done
//! by creating objects of actions that applies the modifications. All actions knows
//! how to undo the changes it applies, and by using the provided data structures
//! it is easy to apply, undo, and redo changes made to a target.
//!
//! # Features
//!
//! * [Action](trait.Action.html) provides the base functionality for all actions.
//! * [Record](record/struct.Record.html) provides basic undo-redo functionality.
//! * [Timeline](timeline/struct.Timeline.html) provides basic undo-redo functionality using a fixed size.
//! * [History](history/struct.History.html) provides non-linear undo-redo functionality that allows you to jump between different branches.
//! * Queues wraps a record or history and extends them with queue functionality.
//! * Checkpoints wraps a record or history and extends them with checkpoint functionality.
//! * Actions can be merged into a single action by implementing the
//!   [merge](trait.Action.html#method.merge) method on the action.
//!   This allows smaller actions to be used to build more complex operations, or smaller incremental changes to be
//!   merged into larger changes that can be undone and redone in a single step.
//! * The target can be marked as being saved to disk and the data-structures can track the saved state and notify
//!   when it changes.
//! * The amount of changes being tracked can be configured by the user so only the `N` most recent changes are stored.
//! * Configurable display formatting using the display structure.
//! * The library can be used as `no_std`.
//!
//! # Cargo Feature Flags
//!
//! * `alloc`: Enables the use of the alloc crate, enabled by default.
//! * `arrayvec`: Required for the timeline module, enabled by default.
//! * `chrono`: Enables time stamps and time travel.
//! * `serde`: Enables serialization and deserialization.
//! * `colored`: Enables colored output when visualizing the display structures.
//!
//! # Examples
//!
//! ```rust
//! use undo::{Action, History};
//!
//! struct Add(char);
//!
//! impl Action for Add {
//!     type Target = String;
//!     type Output = ();
//!     type Error = &'static str;
//!
//!     fn apply(&mut self, s: &mut String) -> undo::Result<Add> {
//!         s.push(self.0);
//!         Ok(())
//!     }
//!
//!     fn undo(&mut self, s: &mut String) -> undo::Result<Add> {
//!         self.0 = s.pop().ok_or("s is empty")?;
//!         Ok(())
//!     }
//! }
//!
//! fn main() {
//!     let mut target = String::new();
//!     let mut history = History::new();
//!     history.apply(&mut target, Add('a')).unwrap();
//!     history.apply(&mut target, Add('b')).unwrap();
//!     history.apply(&mut target, Add('c')).unwrap();
//!     assert_eq!(target, "abc");
//!     history.undo(&mut target).unwrap().unwrap();
//!     history.undo(&mut target).unwrap().unwrap();
//!     history.undo(&mut target).unwrap().unwrap();
//!     assert_eq!(target, "");
//!     history.redo(&mut target).unwrap().unwrap();
//!     history.redo(&mut target).unwrap().unwrap();
//!     history.redo(&mut target).unwrap().unwrap();
//!     assert_eq!(target, "abc");
//! }
//! ```

#![no_std]
#![doc(html_root_url = "https://docs.rs/undo")]
#![deny(missing_docs)]
#![forbid(unsafe_code)]
#![cfg_attr(not(feature = "alloc"), allow(dead_code))]

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "alloc")]
mod format;
#[cfg(feature = "alloc")]
pub mod history;
#[cfg(feature = "alloc")]
pub mod record;
#[cfg(feature = "arrayvec")]
pub mod timeline;

use crate::format::Format;
#[cfg(feature = "chrono")]
use chrono::{DateTime, Utc};
use core::fmt;
#[cfg(feature = "serde")]
use serde_crate::{Deserialize, Serialize};

#[cfg(feature = "arrayvec")]
pub use self::timeline::Timeline;
#[cfg(feature = "alloc")]
pub use self::{history::History, record::Record};

/// A specialized Result type for undo-redo operations.
pub type Result<A> = core::result::Result<<A as Action>::Output, <A as Action>::Error>;

/// Base functionality for all actions.
pub trait Action {
    /// The target type.
    type Target;
    /// The output type.
    type Output;
    /// The error type.
    type Error;

    /// Applies the action on the target and returns `Ok` if everything went fine,
    /// and `Err` if something went wrong.
    fn apply(&mut self, target: &mut Self::Target) -> Result<Self>;

    /// Restores the state of the target as it was before the action was applied
    /// and returns `Ok` if everything went fine, and `Err` if something went wrong.
    fn undo(&mut self, target: &mut Self::Target) -> Result<Self>;

    /// Reapplies the action on the target and return `Ok` if everything went fine,
    /// and `Err` if something went wrong.
    ///
    /// The default implementation uses the [`apply`](trait.Action.html#tymethod.apply) implementation.
    fn redo(&mut self, target: &mut Self::Target) -> Result<Self> {
        self.apply(target)
    }

    /// Used for manual merging of actions.
    fn merge(&mut self, _: &mut Self) -> Merged
    where
        Self: Sized,
    {
        Merged::No
    }
}

impl<A, D> Action for D
where
    A: Action + ?Sized,
    D: core::ops::DerefMut<Target = A>
{
    type Target = A::Target;
    type Output = A::Output;
    type Error = A::Error;

    fn apply(&mut self, target: &mut Self::Target) -> Result<Self> {
        self.deref_mut().apply(target)
    }

    fn undo(&mut self, target: &mut Self::Target) -> Result<Self> {
        self.deref_mut().undo(target)
    }

    fn redo(&mut self, target: &mut Self::Target) -> Result<Self> {
        self.deref_mut().redo(target)
    }
}

/// Says if the action have been merged with another action.
#[cfg_attr(
    feature = "serde",
    derive(Serialize, Deserialize),
    serde(crate = "serde_crate")
)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum Merged {
    /// The actions have been merged.
    Yes,
    /// The actions have not been merged.
    No,
    /// The two actions cancels each other out.
    Annul,
}

/// A position in a history tree.
#[cfg_attr(
    feature = "serde",
    derive(Serialize, Deserialize),
    serde(crate = "serde_crate")
)]
#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
struct At {
    branch: usize,
    current: usize,
}

impl At {
    const ROOT: At = At::new(0, 0);

    const fn new(branch: usize, current: usize) -> At {
        At { branch, current }
    }
}

/// The signal used for communicating state changes.
///
/// For example, if the record can no longer redo any actions, it sends a `Redo(false)`
/// signal to tell the user.
#[cfg_attr(
    feature = "serde",
    derive(Serialize, Deserialize),
    serde(crate = "serde_crate")
)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum Signal {
    /// Says if the structures can undo.
    Undo(bool),
    /// Says if the structures can redo.
    Redo(bool),
    /// Says if the target is in a saved state.
    Saved(bool),
}

#[cfg_attr(
    feature = "serde",
    derive(Serialize, Deserialize),
    serde(crate = "serde_crate")
)]
#[derive(Clone)]
struct Slot<F> {
    #[cfg_attr(feature = "serde", serde(default = "Option::default", skip))]
    f: Option<F>,
}

impl<F: FnMut(Signal)> Slot<F> {
    fn emit(&mut self, signal: Signal) {
        if let Some(ref mut f) = self.f {
            f(signal);
        }
    }

    fn emit_if(&mut self, cond: bool, signal: Signal) {
        if cond {
            self.emit(signal);
        }
    }
}

impl<F> From<F> for Slot<F> {
    fn from(f: F) -> Slot<F> {
        Slot { f: Some(f) }
    }
}

impl<F> Default for Slot<F> {
    fn default() -> Self {
        Slot { f: None }
    }
}

impl<F> fmt::Debug for Slot<F> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.f {
            Some(_) => f.pad("Slot { .. }"),
            None => f.pad("Empty"),
        }
    }
}

#[cfg_attr(
    feature = "serde",
    derive(Serialize, Deserialize),
    serde(crate = "serde_crate")
)]
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
struct Entry<A> {
    action: A,
    #[cfg(feature = "chrono")]
    timestamp: DateTime<Utc>,
}

impl<A> From<A> for Entry<A> {
    fn from(action: A) -> Self {
        Entry {
            action,
            #[cfg(feature = "chrono")]
            timestamp: Utc::now(),
        }
    }
}

impl<A: Action> Action for Entry<A> {
    type Target = A::Target;
    type Output = A::Output;
    type Error = A::Error;

    fn apply(&mut self, target: &mut Self::Target) -> Result<Self> {
        self.action.apply(target)
    }

    fn undo(&mut self, target: &mut Self::Target) -> Result<Self> {
        self.action.undo(target)
    }

    fn redo(&mut self, target: &mut Self::Target) -> Result<Self> {
        self.action.redo(target)
    }

    fn merge(&mut self, entry: &mut Self) -> Merged {
        self.action.merge(&mut entry.action)
    }
}

impl<A: fmt::Display> fmt::Display for Entry<A> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        (&self.action as &dyn fmt::Display).fmt(f)
    }
}
<|endoftext|>