<commit_before>//! `sled` is a high-performance embedded database with
//! an API that is similar to a `BTreeMap<[u8], [u8]>`,
//! but with several additional capabilities for
//! assisting creators of stateful systems.
//!
//! It is fully thread-safe, and all operations are
//! atomic. Multiple `Tree`s are supported with the
//! [`Db::open_tree`](struct.Db.html#method.open_tree) method.
//!
//! ACID transactions involving reads and writes to
//! multiple items are supported with the
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! method. Transactions may also operate over
//! multiple `Tree`s (see
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! docs for more info).
//!
//! Users may also subscribe to updates on individual
//! `Tree`s by using the
//! [`Tree::watch_prefix`](struct.Tree.html#method.watch_prefix)
//! method, which returns a blocking `Iterator` over
//! updates to keys that begin with the provided
//! prefix. You may supply an empty prefix to subscribe
//! to everything.
//!
//! [Merge operators](https://github.com/spacejam/sled/wiki/merge-operators)
//! (aka read-modify-write operators) are supported. A
//! merge operator is a function that specifies
//! how new data can be merged into an existing value
//! without requiring both a read and a write.
//! Using the
//! [`Tree::merge`](struct.Tree.html#method.merge)
//! method, you may "push" data to a `Tree` value
//! and have the provided merge operator combine
//! it with the existing value, if there was one.
//! They are set on a per-`Tree` basis, and essentially
//! allow any sort of data structure to be built
//! using merges as an atomic high-level operation.
//!
//! `sled` is built by experienced database engineers
//! who think users should spend less time tuning and
//! working against high-friction APIs. Expect
//! significant ergonomic and performance improvements
//! over time. Most surprises are bugs, so please
//! [let us know](mailto:t@jujit.su?subject=sled%20sucks!!!) if something
//! is high friction.
//!
//! # Examples
//!
//! ```
//! use sled::Db;
//!
//! let t = Db::open("my_db").unwrap();
//!
//! // insert and get
//! t.insert(b"yo!", b"v1");
//! assert_eq!(&t.get(b"yo!").unwrap().unwrap(), b"v1");
//!
//! // Atomic compare-and-swap.
//! t.compare_and_swap(
//!     b"yo!",      // key
//!     Some(b"v1"), // old value, None for not present
//!     Some(b"v2"), // new value, None for delete
//! )
//! .unwrap();
//!
//! // Iterates over key-value pairs, starting at the given key.
//! let scan_key: &[u8] = b"a non-present key before yo!";
//! let mut iter = t.range(scan_key..);
//! assert_eq!(&iter.next().unwrap().unwrap().0, b"yo!");
//! assert_eq!(iter.next(), None);
//!
//! t.remove(b"yo!");
//! assert_eq!(t.get(b"yo!"), Ok(None));
//! ```
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/spacejam/sled/master/art/tree_face_anti-transphobia.png"
)]
#![cfg_attr(test, deny(warnings))]
#![deny(
    missing_docs,
    future_incompatible,
    nonstandard_style,
    rust_2018_idioms,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unused_qualifications
)]
#![deny(
    // clippy::else_if_without_else,
    // clippy::float_arithmetic,
    // clippy::indexing_slicing,
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
    clippy::cast_possible_wrap,
    clippy::cast_precision_loss,
    clippy::cast_sign_loss,
    clippy::checked_conversions,
    clippy::decimal_literal_representation,
    clippy::doc_markdown,
    clippy::empty_enum,
    clippy::expl_impl_clone_on_copy,
    clippy::explicit_into_iter_loop,
    clippy::explicit_iter_loop,
    clippy::explicit_iter_loop,
    clippy::fallible_impl_from,
    clippy::filter_map,
    clippy::filter_map_next,
    clippy::find_map,
    clippy::get_unwrap,
    clippy::if_not_else,
    clippy::inline_always,
    clippy::invalid_upcast_comparisons,
    clippy::items_after_statements,
    clippy::map_flatten,
    clippy::match_same_arms,
    clippy::maybe_infinite_iter,
    clippy::mem_forget,
    // clippy::missing_const_for_fn,
    // clippy::missing_docs_in_private_items,
    // clippy::module_name_repetitions,
    // clippy::multiple_crate_versions,
    clippy::multiple_inherent_impl,
    clippy::mut_mut,
    clippy::needless_borrow,
    clippy::needless_continue,
    clippy::needless_pass_by_value,
    clippy::non_ascii_literal,
    clippy::option_map_unwrap_or,
    clippy::option_map_unwrap_or_else,
    clippy::path_buf_push_overwrite,
    clippy::print_stdout,
    clippy::pub_enum_variant_names,
    clippy::redundant_closure_for_method_calls,
    clippy::replace_consts,
    clippy::result_map_unwrap_or_else,
    clippy::shadow_reuse,
    clippy::shadow_same,
    clippy::shadow_unrelated,
    clippy::single_match_else,
    clippy::string_add,
    clippy::string_add_assign,
    clippy::type_repetition_in_bounds,
    clippy::unicode_not_nfc,
    // clippy::unimplemented,
    clippy::unseparated_literal_suffix,
    clippy::used_underscore_binding,
    clippy::wildcard_dependencies,
    // clippy::wildcard_enum_match_arm,
    clippy::wrong_pub_self_convention,
)]

#[cfg(feature = "failpoints")]
use fail::fail_point;

macro_rules! maybe_fail {
    ($e:expr) => {
        #[cfg(feature = "failpoints")]
        fail_point!($e, |_| Err(Error::FailPoint));
    };
}

mod batch;
mod binary_search;
mod config;
mod context;
mod db;
mod dll;
mod frag;
mod histogram;
mod iter;
mod ivec;
mod lazy;
mod lru;
mod meta;
mod metrics;
mod node;
mod oneshot;
mod pagecache;
mod prefix;
mod result;
mod subscription;
mod sys_limits;
mod threadpool;
mod transaction;
mod tree;
mod vecset;

#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
mod flusher;

#[cfg(feature = "event_log")]
/// The event log helps debug concurrency issues.
pub mod event_log;

#[cfg(feature = "event_log")]
mod stack;

#[cfg(feature = "measure_allocs")]
mod measure_allocs;

#[cfg(feature = "measure_allocs")]
#[global_allocator]
static ALLOCATOR: measure_allocs::TrackingAllocator =
    measure_allocs::TrackingAllocator;

const DEFAULT_TREE_ID: &[u8] = b"__sled__default";

/// hidden re-export of items for testing purposes
#[doc(hidden)]
pub use {
    self::{
        config::RunningConfig,
        lazy::Lazy,
        pagecache::{
            constants::{
                MAX_SPACE_AMPLIFICATION, MINIMUM_ITEMS_PER_SEGMENT,
                MSG_HEADER_LEN, SEG_HEADER_LEN,
            },
            DiskPtr, Log, LogKind, LogOffset, LogRead, Lsn, PageCache, PageId,
            SegmentMode,
        },
    },
    crossbeam_epoch::{pin, Atomic, Guard, Owned, Shared},
};

pub use self::{
    batch::Batch,
    config::Config,
    db::Db,
    iter::Iter,
    ivec::IVec,
    result::{Error, Result},
    subscription::{Event, Subscriber},
    transaction::{
        abort, ConflictableTransactionError, ConflictableTransactionResult,
        TransactionError, TransactionResult, Transactional, TransactionalTree,
    },
    tree::{CompareAndSwapError, CompareAndSwapResult, Tree},
};

use {
    self::{
        binary_search::binary_search_lub,
        context::Context,
        histogram::Histogram,
        lru::Lru,
        meta::Meta,
        metrics::{clock, measure, Measure, M},
        node::{Data, Node},
        oneshot::{OneShot, OneShotFiller},
        result::CasResult,
        subscription::Subscriptions,
        tree::TreeInner,
        vecset::VecSet,
    },
    bincode::{deserialize, serialize},
    crossbeam_utils::{Backoff, CachePadded},
    log::{debug, error, trace, warn},
    pagecache::RecoveryGuard,
    parking_lot::{Condvar, Mutex, RwLock},
    serde::{Deserialize, Serialize},
    std::{
        collections::BTreeMap,
        convert::TryFrom,
        fmt::{self, Debug},
        io::{Read, Write},
        sync::{
            atomic::{
                AtomicI64 as AtomicLsn, AtomicU64, AtomicUsize,
                Ordering::{Acquire, Relaxed, Release, SeqCst},
            },
            Arc,
        },
    },
};

fn crc32(buf: &[u8]) -> u32 {
    let mut hasher = crc32fast::Hasher::new();
    hasher.update(buf);
    hasher.finalize()
}

#[cfg(any(test, feature = "lock_free_delays"))]
mod debug_delay;

#[cfg(any(test, feature = "lock_free_delays"))]
use debug_delay::debug_delay;

/// This function is useful for inducing random jitter into our atomic
/// operations, shaking out more possible interleavings quickly. It gets
/// fully eliminated by the compiler in non-test code.
#[cfg(not(any(test, feature = "lock_free_delays")))]
const fn debug_delay() {}

/// Frag denotes a tree node or its modification fragment such as
/// key addition or removal.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Frag {
    Set(IVec, IVec),
    Del(IVec),
    ParentMergeIntention(PageId),
    ParentMergeConfirm,
    ChildMergeCap,
}

/// A fast map that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastMap8<K, V> = std::collections::HashMap<
    K,
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// A fast set that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastSet8<V> = std::collections::HashSet<
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// Allows arbitrary logic to be injected into mere operations of the
/// `PageCache`.
pub type MergeOperator = fn(
    key: &[u8],
    last_value: Option<&[u8]>,
    new_merge: &[u8],
) -> Option<Vec<u8>>;

fn is_sorted<T: PartialOrd>(xs: &[T]) -> bool {
    xs.windows(2).all(|pair| pair[0] <= pair[1])
}
<commit_msg>Don't use non-existant frag module<commit_after>//! `sled` is a high-performance embedded database with
//! an API that is similar to a `BTreeMap<[u8], [u8]>`,
//! but with several additional capabilities for
//! assisting creators of stateful systems.
//!
//! It is fully thread-safe, and all operations are
//! atomic. Multiple `Tree`s are supported with the
//! [`Db::open_tree`](struct.Db.html#method.open_tree) method.
//!
//! ACID transactions involving reads and writes to
//! multiple items are supported with the
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! method. Transactions may also operate over
//! multiple `Tree`s (see
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! docs for more info).
//!
//! Users may also subscribe to updates on individual
//! `Tree`s by using the
//! [`Tree::watch_prefix`](struct.Tree.html#method.watch_prefix)
//! method, which returns a blocking `Iterator` over
//! updates to keys that begin with the provided
//! prefix. You may supply an empty prefix to subscribe
//! to everything.
//!
//! [Merge operators](https://github.com/spacejam/sled/wiki/merge-operators)
//! (aka read-modify-write operators) are supported. A
//! merge operator is a function that specifies
//! how new data can be merged into an existing value
//! without requiring both a read and a write.
//! Using the
//! [`Tree::merge`](struct.Tree.html#method.merge)
//! method, you may "push" data to a `Tree` value
//! and have the provided merge operator combine
//! it with the existing value, if there was one.
//! They are set on a per-`Tree` basis, and essentially
//! allow any sort of data structure to be built
//! using merges as an atomic high-level operation.
//!
//! `sled` is built by experienced database engineers
//! who think users should spend less time tuning and
//! working against high-friction APIs. Expect
//! significant ergonomic and performance improvements
//! over time. Most surprises are bugs, so please
//! [let us know](mailto:t@jujit.su?subject=sled%20sucks!!!) if something
//! is high friction.
//!
//! # Examples
//!
//! ```
//! use sled::Db;
//!
//! let t = Db::open("my_db").unwrap();
//!
//! // insert and get
//! t.insert(b"yo!", b"v1");
//! assert_eq!(&t.get(b"yo!").unwrap().unwrap(), b"v1");
//!
//! // Atomic compare-and-swap.
//! t.compare_and_swap(
//!     b"yo!",      // key
//!     Some(b"v1"), // old value, None for not present
//!     Some(b"v2"), // new value, None for delete
//! )
//! .unwrap();
//!
//! // Iterates over key-value pairs, starting at the given key.
//! let scan_key: &[u8] = b"a non-present key before yo!";
//! let mut iter = t.range(scan_key..);
//! assert_eq!(&iter.next().unwrap().unwrap().0, b"yo!");
//! assert_eq!(iter.next(), None);
//!
//! t.remove(b"yo!");
//! assert_eq!(t.get(b"yo!"), Ok(None));
//! ```
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/spacejam/sled/master/art/tree_face_anti-transphobia.png"
)]
#![cfg_attr(test, deny(warnings))]
#![deny(
    missing_docs,
    future_incompatible,
    nonstandard_style,
    rust_2018_idioms,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unused_qualifications
)]
#![deny(
    // clippy::else_if_without_else,
    // clippy::float_arithmetic,
    // clippy::indexing_slicing,
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
    clippy::cast_possible_wrap,
    clippy::cast_precision_loss,
    clippy::cast_sign_loss,
    clippy::checked_conversions,
    clippy::decimal_literal_representation,
    clippy::doc_markdown,
    clippy::empty_enum,
    clippy::expl_impl_clone_on_copy,
    clippy::explicit_into_iter_loop,
    clippy::explicit_iter_loop,
    clippy::explicit_iter_loop,
    clippy::fallible_impl_from,
    clippy::filter_map,
    clippy::filter_map_next,
    clippy::find_map,
    clippy::get_unwrap,
    clippy::if_not_else,
    clippy::inline_always,
    clippy::invalid_upcast_comparisons,
    clippy::items_after_statements,
    clippy::map_flatten,
    clippy::match_same_arms,
    clippy::maybe_infinite_iter,
    clippy::mem_forget,
    // clippy::missing_const_for_fn,
    // clippy::missing_docs_in_private_items,
    // clippy::module_name_repetitions,
    // clippy::multiple_crate_versions,
    clippy::multiple_inherent_impl,
    clippy::mut_mut,
    clippy::needless_borrow,
    clippy::needless_continue,
    clippy::needless_pass_by_value,
    clippy::non_ascii_literal,
    clippy::option_map_unwrap_or,
    clippy::option_map_unwrap_or_else,
    clippy::path_buf_push_overwrite,
    clippy::print_stdout,
    clippy::pub_enum_variant_names,
    clippy::redundant_closure_for_method_calls,
    clippy::replace_consts,
    clippy::result_map_unwrap_or_else,
    clippy::shadow_reuse,
    clippy::shadow_same,
    clippy::shadow_unrelated,
    clippy::single_match_else,
    clippy::string_add,
    clippy::string_add_assign,
    clippy::type_repetition_in_bounds,
    clippy::unicode_not_nfc,
    // clippy::unimplemented,
    clippy::unseparated_literal_suffix,
    clippy::used_underscore_binding,
    clippy::wildcard_dependencies,
    // clippy::wildcard_enum_match_arm,
    clippy::wrong_pub_self_convention,
)]

#[cfg(feature = "failpoints")]
use fail::fail_point;

macro_rules! maybe_fail {
    ($e:expr) => {
        #[cfg(feature = "failpoints")]
        fail_point!($e, |_| Err(Error::FailPoint));
    };
}

mod batch;
mod binary_search;
mod config;
mod context;
mod db;
mod dll;
mod histogram;
mod iter;
mod ivec;
mod lazy;
mod lru;
mod meta;
mod metrics;
mod node;
mod oneshot;
mod pagecache;
mod prefix;
mod result;
mod subscription;
mod sys_limits;
mod threadpool;
mod transaction;
mod tree;
mod vecset;

#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
mod flusher;

#[cfg(feature = "event_log")]
/// The event log helps debug concurrency issues.
pub mod event_log;

#[cfg(feature = "event_log")]
mod stack;

#[cfg(feature = "measure_allocs")]
mod measure_allocs;

#[cfg(feature = "measure_allocs")]
#[global_allocator]
static ALLOCATOR: measure_allocs::TrackingAllocator =
    measure_allocs::TrackingAllocator;

const DEFAULT_TREE_ID: &[u8] = b"__sled__default";

/// hidden re-export of items for testing purposes
#[doc(hidden)]
pub use {
    self::{
        config::RunningConfig,
        lazy::Lazy,
        pagecache::{
            constants::{
                MAX_SPACE_AMPLIFICATION, MINIMUM_ITEMS_PER_SEGMENT,
                MSG_HEADER_LEN, SEG_HEADER_LEN,
            },
            DiskPtr, Log, LogKind, LogOffset, LogRead, Lsn, PageCache, PageId,
            SegmentMode,
        },
    },
    crossbeam_epoch::{pin, Atomic, Guard, Owned, Shared},
};

pub use self::{
    batch::Batch,
    config::Config,
    db::Db,
    iter::Iter,
    ivec::IVec,
    result::{Error, Result},
    subscription::{Event, Subscriber},
    transaction::{
        abort, ConflictableTransactionError, ConflictableTransactionResult,
        TransactionError, TransactionResult, Transactional, TransactionalTree,
    },
    tree::{CompareAndSwapError, CompareAndSwapResult, Tree},
};

use {
    self::{
        binary_search::binary_search_lub,
        context::Context,
        histogram::Histogram,
        lru::Lru,
        meta::Meta,
        metrics::{clock, measure, Measure, M},
        node::{Data, Node},
        oneshot::{OneShot, OneShotFiller},
        result::CasResult,
        subscription::Subscriptions,
        tree::TreeInner,
        vecset::VecSet,
    },
    bincode::{deserialize, serialize},
    crossbeam_utils::{Backoff, CachePadded},
    log::{debug, error, trace, warn},
    pagecache::RecoveryGuard,
    parking_lot::{Condvar, Mutex, RwLock},
    serde::{Deserialize, Serialize},
    std::{
        collections::BTreeMap,
        convert::TryFrom,
        fmt::{self, Debug},
        io::{Read, Write},
        sync::{
            atomic::{
                AtomicI64 as AtomicLsn, AtomicU64, AtomicUsize,
                Ordering::{Acquire, Relaxed, Release, SeqCst},
            },
            Arc,
        },
    },
};

fn crc32(buf: &[u8]) -> u32 {
    let mut hasher = crc32fast::Hasher::new();
    hasher.update(buf);
    hasher.finalize()
}

#[cfg(any(test, feature = "lock_free_delays"))]
mod debug_delay;

#[cfg(any(test, feature = "lock_free_delays"))]
use debug_delay::debug_delay;

/// This function is useful for inducing random jitter into our atomic
/// operations, shaking out more possible interleavings quickly. It gets
/// fully eliminated by the compiler in non-test code.
#[cfg(not(any(test, feature = "lock_free_delays")))]
const fn debug_delay() {}

/// Frag denotes a tree node or its modification fragment such as
/// key addition or removal.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Frag {
    Set(IVec, IVec),
    Del(IVec),
    ParentMergeIntention(PageId),
    ParentMergeConfirm,
    ChildMergeCap,
}

/// A fast map that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastMap8<K, V> = std::collections::HashMap<
    K,
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// A fast set that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastSet8<V> = std::collections::HashSet<
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// Allows arbitrary logic to be injected into mere operations of the
/// `PageCache`.
pub type MergeOperator = fn(
    key: &[u8],
    last_value: Option<&[u8]>,
    new_merge: &[u8],
) -> Option<Vec<u8>>;

fn is_sorted<T: PartialOrd>(xs: &[T]) -> bool {
    xs.windows(2).all(|pair| pair[0] <= pair[1])
}
<|endoftext|>


<commit_before>#![no_std]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts at compile-time that the two types have equal sizes.
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate static_assertions;
///
/// struct Byte(u8);
///
/// fn main() {
///     assert_eq_size!(Byte, u8);
///     // assert_eq_size!(Byte, u16); // Fails to compile
///
///     // Supports unlimited arguments:
///     assert_eq_size!([Byte; 4], [u16; 2], u32);
/// }
/// ```
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $y:ty) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::mem::{forget, transmute, uninitialized};
            forget::<$y>(transmute(uninitialized::<$x>()));
        }
    };
    ($x:ty, $y:ty, $($rest:ty),+) => {
        assert_eq_size!($x, $y);
        assert_eq_size!($y, $($rest),+);
    };
}
<commit_msg>Make assert_eq_size doc refer to all arguments<commit_after>#![no_std]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts at compile-time that the types have equal sizes.
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate static_assertions;
///
/// struct Byte(u8);
///
/// fn main() {
///     assert_eq_size!(Byte, u8);
///     // assert_eq_size!(Byte, u16); // Fails to compile
///
///     // Supports unlimited arguments:
///     assert_eq_size!([Byte; 4], [u16; 2], u32);
/// }
/// ```
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $y:ty) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::mem::{forget, transmute, uninitialized};
            forget::<$y>(transmute(uninitialized::<$x>()));
        }
    };
    ($x:ty, $y:ty, $($rest:ty),+) => {
        assert_eq_size!($x, $y);
        assert_eq_size!($y, $($rest),+);
    };
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate url;

mod error;
mod client;

pub use error::Error;
pub use client::Client;
<commit_msg>re-export hyper Response type<commit_after>extern crate hyper;
extern crate url;

mod error;
mod client;

pub use error::Error;
pub use client::Client;
pub use hyper::client::Response;
<|endoftext|>


<commit_before>// I have no idea what I'm doing with these attributes. Are we using
// semantic versioning? Some packages include their full github URL.
// Documentation for this stuff is extremely scarce.
#[crate_id = "quickcheck#0.1.0"];
#[crate_type = "lib"];
#[license = "UNLICENSE"];
#[doc(html_root_url = "http://burntsushi.net/rustdoc/quickcheck")];

//! This crate is a port of
//! [Haskell's QuickCheck](http://hackage.haskell.org/package/QuickCheck).

extern crate collections;

pub use arbitrary::{Arbitrary, Gen, StdGen, gen};
pub use shrink::{ObjIter, Shrink};
pub use tester::{Testable, TestResult, Config, quickcheck, quickcheckConfig};

mod arbitrary;
mod shrink;

mod tester {
    use std::fmt::Show;
    use std::rand::task_rng;
    use super::{Arbitrary, Gen, gen};

    static DEFAULT_SIZE: uint = 20;

    static DEFAULT_CONFIG: Config = Config{
        tests: 100,
        max_tests: 1000,
    };

    /// Config contains various parameters for controlling automated testing.
    ///
    /// Note that the distribution of random values is controlled by the
    /// generator passed to `quickcheckConfig`.
    pub struct Config {
        /// The number of tests to run on a function where the result is
        /// either a pass or a failure. (i.e., This doesn't include discarded
        /// test results.)
        tests: uint,

        /// The maximum number of tests to run for each function including
        /// discarded test results. (Not currently used.)
        max_tests: uint,
    }

    #[deriving(Clone, Show)]
    pub struct TestResult {
        priv status: Status,
        priv arguments: ~[~str],
    }

    #[deriving(Clone, Show)]
    priv enum Status { Pass, Fail, Discard }

    impl TestResult {
        pub fn passed() -> ~TestResult { TestResult::from_bool(true) }
        pub fn failed() -> ~TestResult { TestResult::from_bool(false) }
        pub fn discard() -> ~TestResult {
            ~TestResult { status: Discard, arguments: ~[] }
        }
        pub fn from_bool(b: bool) -> ~TestResult {
            ~TestResult { status: if b { Pass } else { Fail }, arguments: ~[] }
        }
    }

    pub trait Testable {
        fn result<G: Gen>(&self, &mut G) -> ~TestResult;
    }

    impl Testable for bool {
        fn result<G: Gen>(&self, _: &mut G) -> ~TestResult {
            TestResult::from_bool(*self)
        }
    }

    impl Testable for ~TestResult {
        fn result<G: Gen>(&self, _: &mut G) -> ~TestResult { self.clone() }
    }

    // I should really figure out how to use macros. This is painful.
    // N.B. This isn't needed in Haskell because it's currying by default!
    // Perhaps there is a way to circumvent this in Rust too (without macros),
    // but I'm not sure.

    impl<A: Testable> Testable for 'static || -> A {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            (*self)().result(g)
        }
    }

    impl<A: Arbitrary + Show, B: Testable> Testable for 'static |A| -> B {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let a: A = Arbitrary::arbitrary(g);
            let arg: ~str = a.to_str();
            let mut r: ~TestResult = (*self)(a).result(g);
            r.arguments.unshift(arg);
            r
        }
    }

    impl<A: Arbitrary + Show, B: Arbitrary + Show, C: Testable>
        Testable for 'static |A, B| -> C {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let (a, b): (A, B) = (arby(g), arby(g));
            let (a_arg, b_arg) = (a.to_str(), b.to_str());
            let mut r: ~TestResult = (*self)(a, b).result(g);
            r.arguments.unshift(b_arg);
            r.arguments.unshift(a_arg);
            r
        }
    }

    impl<A: Arbitrary + Show,
         B: Arbitrary + Show,
         C: Arbitrary + Show,
         D: Testable>
        Testable for 'static |A, B, C| -> D {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let (a, b, c): (A, B, C) = (arby(g), arby(g), arby(g));
            let (a_arg, b_arg, c_arg) = (a.to_str(), b.to_str(), c.to_str());
            let mut r: ~TestResult = (*self)(a, b, c).result(g);
            r.arguments.unshift(c_arg);
            r.arguments.unshift(b_arg);
            r.arguments.unshift(a_arg);
            r
        }
    }

    impl<A: Testable> Testable for fn() -> A {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            (*self)().result(g)
        }
    }

    impl<A: Arbitrary + Show, B: Testable> Testable for fn(A) -> B {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let a: A = Arbitrary::arbitrary(g);
            let arg: ~str = a.to_str();
            let mut r: ~TestResult = (*self)(a).result(g);
            r.arguments.unshift(arg);
            r
        }
    }

    impl<A: Arbitrary + Show, B: Arbitrary + Show, C: Testable>
        Testable for fn(A, B) -> C {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let (a, b): (A, B) = (arby(g), arby(g));
            let (a_arg, b_arg) = (a.to_str(), b.to_str());
            let mut r: ~TestResult = (*self)(a, b).result(g);
            r.arguments.unshift(b_arg);
            r.arguments.unshift(a_arg);
            r
        }
    }

    impl<A: Arbitrary + Show,
         B: Arbitrary + Show,
         C: Arbitrary + Show,
         D: Testable>
        Testable for fn(A, B, C) -> D {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            let (a, b, c): (A, B, C) = (arby(g), arby(g), arby(g));
            let (a_arg, b_arg, c_arg) = (a.to_str(), b.to_str(), c.to_str());
            let mut r: ~TestResult = (*self)(a, b, c).result(g);
            r.arguments.unshift(c_arg);
            r.arguments.unshift(b_arg);
            r.arguments.unshift(a_arg);
            r
        }
    }

    pub fn quickcheck<A: Testable>(f: A) {
        let g = &mut gen(task_rng(), DEFAULT_SIZE);
        quickcheckConfig(DEFAULT_CONFIG, g, f)
    }

    pub fn quickcheckConfig<A: Testable, G: Gen>(c: Config, g: &mut G, f: A) {
        let r = f.result(g);
        debug!("{}", r);
    }

    /// Convenient alias.
    fn arby<A: Arbitrary, G: Gen>(g: &mut G) -> A { Arbitrary::arbitrary(g) }
}

#[cfg(test)]
mod test {
    use std::rand::task_rng;
    use super::{Config, Testable, TestResult, gen, quickcheckConfig};

    static CONFIG: Config = Config {
        tests: 100,
        max_tests: 1000,
    };

    // #[test]
    // fn reverse_reverse() {
        // let g = &mut gen(task_rng(), 20);
        // fn revrev(xs: ~[uint]) -> bool {
            // let rev = xs.clone().move_rev_iter().to_owned_vec()
                        // .move_rev_iter().to_owned_vec();
            // xs == rev
        // }
        // for _ in iter::range(0, 10) {
            // debug!("{}", (revrev).result(g));
        // }
    // }

    fn check<A: Testable>(f: A) {
        quickcheckConfig(CONFIG, &mut gen(task_rng(), 5), f)
    }

    #[test]
    fn reverse_single() {
        fn rev_single(xs: ~[uint]) -> ~TestResult {
            if xs.len() != 1 {
                return TestResult::discard()
            }
            return TestResult::from_bool(
                xs.clone().move_rev_iter().to_owned_vec()
                ==
                xs.clone().move_rev_iter().to_owned_vec()
            )
        }
        check(rev_single);
    }

    // #[test]
    // fn reverse_app() {
        // let g = &mut gen(task_rng(), 20);
        // fn revapp(xs: ~[uint], ys: ~[uint]) -> bool {
            // let app = ::std::vec::append(xs.clone(), ys);
            // let app_rev = app.move_rev_iter().to_owned_vec();
//
            // let rxs = xs.clone().move_rev_iter().to_owned_vec();
            // let rys = ys.clone().move_rev_iter().to_owned_vec();
            // let rev_app = ::std::vec::append(rys, rxs);
//
            // app_rev == rev_app
        // }
        // for _ in iter::range(0, 10) {
            // debug!("{}", (revapp).result(g));
        // }
    // }
}
<commit_msg>Basic quickcheck appears to work.<commit_after>// I have no idea what I'm doing with these attributes. Are we using
// semantic versioning? Some packages include their full github URL.
// Documentation for this stuff is extremely scarce.
#[crate_id = "quickcheck#0.1.0"];
#[crate_type = "lib"];
#[license = "UNLICENSE"];
#[doc(html_root_url = "http://burntsushi.net/rustdoc/quickcheck")];

//! This crate is a port of
//! [Haskell's QuickCheck](http://hackage.haskell.org/package/QuickCheck).

extern crate collections;

pub use arbitrary::{Arbitrary, Gen, StdGen, gen};
pub use shrink::{ObjIter, Shrink};
pub use tester::{Testable, TestResult, Config};
pub use tester::{quickcheck, quickcheckConfig, quicktest, quicktestConfig};
pub use tester::{DEFAULT_CONFIG, DEFAULT_SIZE};

mod arbitrary;
mod shrink;

mod tester {
    use std::fmt::Show;
    use std::iter;
    use std::rand::task_rng;
    use super::{Arbitrary, Gen, Shrink, gen};

    /// Default size hint used in `quickcheck` for sampling from a random
    /// distribution.
    pub static DEFAULT_SIZE: uint = 20;

    /// Default configuration used in `quickcheck`.
    pub static DEFAULT_CONFIG: Config = Config{
        tests: 100,
        max_tests: 10000,
    };

    /// Does randomized testing on `f` and produces a possibly minimal
    /// witness for test failures.
    ///
    /// This function is equivalent to calling `quickcheckConfig` with
    /// `DEFAULT_CONFIG` and a `Gen` with size `DEFAULT_SIZE`.
    ///
    /// As of now, it is intended for `quickcheck` to be used inside Rust's
    /// unit testing system. For example, to check if
    /// `reverse(reverse(xs)) == xs`, you could use:
    ///
    /// ```rust
    /// fn prop_reverse_reverse() {
    ///     fn revrev(xs: ~[uint]) -> bool {
    ///         let rev = xs.clone().move_rev_iter().to_owned_vec();
    ///         let revrev = rev.move_rev_iter().to_owned_vec();
    ///         xs == revrev
    ///     }
    ///     check(revrev);
    /// }
    /// ```
    ///
    /// In particular, `quickcheck` will call `fail!` if it finds a
    /// test failure. The failure message will include a witness to the
    /// failure.
    pub fn quickcheck<A: Testable>(f: A) {
        let g = &mut gen(task_rng(), DEFAULT_SIZE);
        quickcheckConfig(DEFAULT_CONFIG, g, f)
    }

    /// Does randomized testing on `f` with the given config and produces a
    /// possibly minimal witness for test failures.
    pub fn quickcheckConfig<A: Testable, G: Gen>(c: Config, g: &mut G, f: A) {
        match quicktestConfig(c, g, f) {
            Ok(ntests) => debug!("[quickcheck] Passed {:u} tests.", ntests),
            Err(err) => fail!(err),
        }
    }

    /// Like `quickcheck`, but returns either the number of tests passed
    /// or a witness of failure.
    pub fn quicktest<A: Testable>(f: A) -> Result<uint, ~str> {
        let g = &mut gen(task_rng(), DEFAULT_SIZE);
        quicktestConfig(DEFAULT_CONFIG, g, f)
    }

    /// Like `quickcheckConfig`, but returns either the number of tests passed
    /// or a witness of failure.
    pub fn quicktestConfig<A: Testable, G: Gen>
        (c: Config, g: &mut G, f: A) -> Result<uint, ~str> {
        let mut ntests: uint = 0;
        for _ in iter::range(0, c.max_tests) {
            if ntests >= c.tests {
                break
            }
            let r = f.result(g);
            match r.status {
                Pass => ntests = ntests + 1,
                Discard => continue,
                Fail => {
                    return Err(format!(
                        "[quickcheck] TEST FAILED. Arguments: ({})",
                        r.arguments.connect(", ")));
                }
            }
        }
        Ok(ntests)
    }

    /// Config contains various parameters for controlling automated testing.
    ///
    /// Note that the distribution of random values is controlled by the
    /// generator passed to `quickcheckConfig`.
    pub struct Config {
        /// The number of tests to run on a function where the result is
        /// either a pass or a failure. (i.e., This doesn't include discarded
        /// test results.)
        tests: uint,

        /// The maximum number of tests to run for each function including
        /// discarded test results.
        max_tests: uint,
    }

    #[deriving(Clone, Show)]
    pub struct TestResult {
        priv status: Status,
        priv arguments: ~[~str],
    }

    #[deriving(Clone, Show)]
    priv enum Status { Pass, Fail, Discard }

    impl TestResult {
        pub fn passed() -> ~TestResult { TestResult::from_bool(true) }
        pub fn failed() -> ~TestResult { TestResult::from_bool(false) }
        pub fn discard() -> ~TestResult {
            ~TestResult { status: Discard, arguments: ~[] }
        }
        pub fn from_bool(b: bool) -> ~TestResult {
            ~TestResult { status: if b { Pass } else { Fail }, arguments: ~[] }
        }

        pub fn is_failure(&self) -> bool {
            match self.status {
                Fail => true,
                Pass|Discard => false,
            }
        }
    }

    pub trait Testable {
        fn result<G: Gen>(&self, &mut G) -> ~TestResult;
    }

    impl Testable for bool {
        fn result<G: Gen>(&self, _: &mut G) -> ~TestResult {
            TestResult::from_bool(*self)
        }
    }

    impl Testable for ~TestResult {
        fn result<G: Gen>(&self, _: &mut G) -> ~TestResult { self.clone() }
    }

    // I should really figure out how to use macros. This is painful.
    // N.B. This isn't needed in Haskell because it's currying by default!
    // Perhaps there is a way to circumvent this in Rust too (without macros),
    // but I'm not sure.

    impl<A: Testable> Testable for 'static || -> A {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            apply0(g, || (*self)())
        }
    }

    impl<A: Arbitrary + Shrink + Show, B: Testable> Testable for 'static |A| -> B {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            apply1(g, |a| (*self)(a))
        }
    }

    impl<A: Arbitrary + Shrink + Show, B: Arbitrary + Shrink + Show, C: Testable>
        Testable for 'static |A, B| -> C {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            apply2(g, |a, b| (*self)(a, b))
        }
    }

    impl<A: Arbitrary + Shrink + Show,
         B: Arbitrary + Shrink + Show,
         C: Arbitrary + Shrink + Show,
         D: Testable>
        Testable for 'static |A, B, C| -> D {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            apply3(g, |a, b, c| (*self)(a, b, c))
        }
    }

    impl<A: Testable> Testable for fn() -> A {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            apply0(g, || (*self)())
        }
    }

    impl<A: Arbitrary + Shrink + Show, B: Testable> Testable for fn(A) -> B {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            apply1(g, |a| (*self)(a))
        }
    }

    impl<A: Arbitrary + Shrink + Show, B: Arbitrary + Shrink + Show, C: Testable>
        Testable for fn(A, B) -> C {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            apply2(g, |a, b| (*self)(a, b))
        }
    }

    impl<A: Arbitrary + Shrink + Show,
         B: Arbitrary + Shrink + Show,
         C: Arbitrary + Shrink + Show,
         D: Testable>
        Testable for fn(A, B, C) -> D {
        fn result<G: Gen>(&self, g: &mut G) -> ~TestResult {
            apply3(g, |a, b, c| (*self)(a, b, c))
        }
    }

    fn apply0<A: Testable,
              G: Gen
             >(g: &mut G, fun: || -> A)
             -> ~TestResult {
        shrink(0, (), (), (), |_: (), _: (), _: ()| fun().result(g))
    }

    fn apply1<A: Arbitrary + Shrink + Show,
              B: Testable,
              G: Gen
             >(g: &mut G, fun: |a: A| -> B)
             -> ~TestResult {
        let a = arby(g);
        shrink(1, a, (), (), |a: A, _: (), _: ()| {
            let mut r = fun(a.clone()).result(g);
            if r.is_failure() {
                r.arguments = ~[a.to_str()];
            }
            r
        })
    }

    fn apply2<A: Arbitrary + Shrink + Show,
              B: Arbitrary + Shrink + Show,
              C: Testable,
              G: Gen
             >(g: &mut G, fun: |a: A, b: B| -> C)
             -> ~TestResult {
        let (a, b): (A, B) = arby(g);
        shrink(2, a, b, (), |a: A, b: B, _: ()| {
            let mut r = fun(a.clone(), b.clone()).result(g);
            if r.is_failure() {
                r.arguments = ~[a.to_str(), b.to_str()];
            }
            r
        })
    }

    fn apply3<A: Arbitrary + Shrink + Show,
              B: Arbitrary + Shrink + Show,
              C: Arbitrary + Shrink + Show,
              D: Testable,
              G: Gen
             >(g: &mut G, fun: |a: A, b: B, c: C| -> D)
             -> ~TestResult {
        let (a, b, c): (A, B, C) = arby(g);
        shrink(3, a, b, c, |a: A, b: B, c: C| {
            let mut r = fun(a.clone(), b.clone(), c.clone()).result(g);
            if r.is_failure() {
                r.arguments = ~[a.to_str(), b.to_str(), c.to_str()];
            }
            r
        })
    }

    fn shrink<A: Shrink + Show, B: Shrink + Show, C: Shrink + Show>
             (n: uint, a: A, b: B, c: C, fun: |A, B, C| -> ~TestResult)
             -> ~TestResult {
        let toshrink = (a.clone(), b.clone(), c.clone());
        let mut r: ~TestResult = fun(a, b, c);
        match r.status {
            Pass|Discard => return r, // don't care about the args here
            Fail => {
                for (a, b, c) in toshrink.shrink() {
                    let r1 = fun(a.clone(), b.clone(), c.clone());
                    match r1.status {
                        Pass|Discard => continue,
                        Fail => {
                            let r2 = shrink(n, a, b, c, |a, b, c| fun(a, b, c));
                            match r2.status {
                                Pass|Discard => r = r1,
                                Fail => r = r2,
                            }
                            break;
                        },
                    }
                }
            },
        }
        r
    }

    /// Convenient alias.
    fn arby<A: Arbitrary, G: Gen>(g: &mut G) -> A { Arbitrary::arbitrary(g) }
}

#[cfg(test)]
mod test {
    use std::rand::task_rng;
    use super::{Config, Testable, TestResult, gen, quickcheckConfig};

    static CONFIG: Config = Config {
        tests: 100,
        max_tests: 10000,
    };

    fn check<A: Testable>(f: A) {
        quickcheckConfig(CONFIG, &mut gen(task_rng(), 50), f)
    }

    #[test]
    fn prop_reverse_reverse() {
        fn revrev(xs: ~[uint]) -> bool {
            let rev = xs.clone().move_rev_iter().to_owned_vec();
            let revrev = rev.move_rev_iter().to_owned_vec();
            xs == revrev
        }
        check(revrev);
    }

    #[test]
    fn reverse_single() {
        fn rev_single(xs: ~[uint]) -> ~TestResult {
            if xs.len() != 1 {
                return TestResult::discard()
            }
            return TestResult::from_bool(
                xs == xs.clone().move_rev_iter().to_owned_vec()
            )
        }
        check(rev_single);
    }

    #[test]
    fn reverse_app() {
        fn revapp(xs: ~[uint], ys: ~[uint]) -> bool {
            let app = ::std::vec::append(xs.clone(), ys);
            let app_rev = app.move_rev_iter().to_owned_vec();

            let rxs = xs.clone().move_rev_iter().to_owned_vec();
            let rys = ys.clone().move_rev_iter().to_owned_vec();
            let rev_app = ::std::vec::append(rys, rxs);

            app_rev == rev_app
        }
        check(revapp);
    }
}
<|endoftext|>


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

//! Library for retrieving and interacting with the [crates.io index].
//!
//! [crates.io index]: https://github.com/rust-lang/crates.io-index
//!
//! ## Examples
//!
//! ```rust
//! extern crate crates_index;
//!
//! let index = crates_index::Index::new("_index");
//! if !index.exists() {
//!    index.retrieve().expect("Could not fetch crates.io index");
//! }
//! for crate_ in index.crates() {
//!    let latest_version = crate_.latest_version();
//!    println!("crate name: {}", latest_version.name());
//!    println!("crate version: {}", latest_version.version());
//! }
//! ```

use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::io::{BufRead, BufReader};
use std::iter;
use std::path::{Path, PathBuf};

#[macro_use]
extern crate error_chain;
extern crate git2;
extern crate glob;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde;

error_chain! {
    foreign_links {
        Git(git2::Error);
    }
}

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of a crate published to the index
#[derive(Deserialize, Clone, Debug)]
pub struct Version {
    name: String,
    vers: String,
    deps: Vec<Dependency>,
    cksum: String,
    features: HashMap<String, Vec<String>>,
    yanked: bool,
}

impl Version {
    /// Name of the crate
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Name of this version
    pub fn version(&self) -> &str {
        &self.vers
    }

    /// Dependencies for this version
    pub fn dependencies(&self) -> &[Dependency] {
        &self.deps
    }

    /// Checksum of the package for this version
    pub fn checksum(&self) -> &str {
        &self.cksum
    }

    pub fn features(&self) -> &HashMap<String, Vec<String>> {
        &self.features
    }

    /// Whether this version was [yanked](http://doc.crates.io/crates-io.html#cargo-yank) from the
    /// index
    pub fn is_yanked(&self) -> bool {
        self.yanked
    }
}

/// A single dependency of a specific crate version
#[derive(Deserialize, Clone, Debug)]
pub struct Dependency {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>,
    package: Option<String>,
}

impl Dependency {
    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn requirement(&self) -> &str {
        &self.req
    }

    pub fn features(&self) -> &[String] {
        &self.features
    }

    pub fn is_optional(&self) -> bool {
        self.optional
    }

    pub fn has_default_features(&self) -> bool {
        self.default_features
    }

    pub fn target(&self) -> Option<&str> {
        match self.target {
            Some(ref s) => Some(s),
            None => None,
        }
    }

    pub fn kind(&self) -> Option<&str> {
        match self.kind {
            Some(ref s) => Some(s),
            None => None,
        }
    }

    pub fn package(&self) -> Option<&str> {
        match self.package {
            Some(ref s) => Some(s),
            None => None,
        }
    }

    /// Returns the name of the crate providing the dependency.
    /// This is equivalent to `name()` unless `self.package()`
    /// is not `None`, in which case it's equal to `self.package()`.
    ///
    /// Basically, you can define a dependency in your `Cargo.toml`
    /// like this:
    ///
    /// ```toml
    /// serde_lib = {version = "1", package = "serde"}
    /// ```
    ///
    /// ...which means that it uses the crate `serde` but imports
    /// it under the name `serde_lib`.
    pub fn crate_name(&self) -> &str {
        match self.package {
            Some(ref s) => s,
            None => self.name(),
        }
    }
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new<P: AsRef<Path>>(path: P) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;
        let path = path.as_ref();

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

/// Wrapper around managing the crates.io-index git repository
#[derive(Debug, Clone, PartialEq)]
pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new<P: Into<PathBuf>>(path: P) -> Index {
        Index { path: path.into() }
    }

    /// Determines if a crates.io repository exists at `self.path`
    pub fn exists(&self) -> bool {
        git2::Repository::discover(&self.path)
            .map(|repository| {
                repository
                    .find_remote("origin")
                    .map(|remote| remote.url() == Some(INDEX_GIT_URL))
                    .unwrap_or(false)
            })
            .unwrap_or(false)
    }

    /// Downloads the index to the path specified from the constructor
    pub fn retrieve(&self) -> Result<()> {
        let _ = git2::Repository::clone(INDEX_GIT_URL, &self.path)?;
        Ok(())
    }

    /// Assumes the index already exists at `self.path`, and updates it
    pub fn update(&self) -> Result<()> {
        debug_assert!(self.exists());
        let repo = git2::Repository::discover(&self.path)?;
        let mut origin_remote = repo.find_remote("origin")?;
        origin_remote.fetch(&["master"], None, None)?;
        let oid = repo.refname_to_id("refs/remotes/origin/master")?;
        let object = repo.find_object(oid, None).unwrap();
        repo.reset(&object, git2::ResetType::Hard, None)?;
        Ok(())
    }

    /// Downloads the index to the path specified from the constructor
    pub fn retrieve_or_update(&self) -> Result<()> {
        if self.exists() {
            self.update()
        } else {
            self.retrieve()
        }
    }

    /// Retrieve a single crate by name (case insensitive) from the index
    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| {
                      path.file_name()
                          .and_then(OsStr::to_str)
                          .map(|file_name| file_name.eq_ignore_ascii_case(crate_name))
                          .unwrap_or(false)
                  })
            .map(|p| Crate::new(&p))
    }

    /// Retrieve an iterator over all the crates in the index
    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone()) // TODO: remove this clone
    }

    /// Get the index directory.
    pub fn path(&self) -> &Path {
        &self.path
    }
}

/// A single crate that contains many published versions
#[derive(Debug)]
pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new<P: AsRef<Path>>(index_path: P) -> Crate {
        let index_path = index_path.as_ref();
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = serde_json::from_str(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate { versions: versions }
    }

    /// Published versions of this crate sorted chronologically by date published
    pub fn versions(&self) -> &[Version] {
        &self.versions
    }

    pub fn earliest_version(&self) -> &Version {
        &self.versions[0]
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }

    pub fn name(&self) -> &str {
        self.latest_version().name()
    }
}

#[cfg(test)]
mod test {
    use super::Index;
    extern crate tempdir;
    use self::tempdir::TempDir;

    #[test]
    fn test_dependencies() {
        let tmp_dir = TempDir::new("test1").unwrap();

        let index = Index::new(tmp_dir.path());
        index.retrieve_or_update().expect("could not fetch crates io index");
        // let crate_ = index.crates().nth(0).expect("could not find a crate in the index");
        let crate_ = index.crate_("sval").expect("Could not find the crate libnotify in the index");
        let _ = format!("supports debug {:?}", crate_);

        let version = crate_.versions().iter().find(|v| v.version() == "0.0.1")
            .expect("Version 0.0.1 of sval does not exist?");
        let dep_with_package_name = version.dependencies().iter().find(|d| d.name() == "serde_lib")
            .expect("sval does not have expected dependency?");
        assert_ne!(dep_with_package_name.name(), dep_with_package_name.package().unwrap());
        assert_eq!(dep_with_package_name.crate_name(), dep_with_package_name.package().unwrap());
    }

    #[test]
    fn test_retrieve_or_update() {
        let tmp_dir = TempDir::new("test2").unwrap();

        let index = Index::new(tmp_dir.path());
        index.retrieve_or_update().expect("could not fetch crates io index");
        assert!(index.exists());
        index.retrieve_or_update().expect("could not fetch crates io index");
        assert!(index.exists());
    }

    #[test]
    fn test_exists() {
        let tmp_dir = TempDir::new("test3").unwrap();

        let index = Index::new(tmp_dir.path());
        assert!(!index.exists());
        index.retrieve().unwrap();
        assert!(index.exists());
    }
}
<commit_msg>Allow data types to be serialized.<commit_after>// Copyright 2015 Corey Farwell
// Copyright 2015 Contributors of github.com/huonw/crates.io-graph
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Library for retrieving and interacting with the [crates.io index].
//!
//! [crates.io index]: https://github.com/rust-lang/crates.io-index
//!
//! ## Examples
//!
//! ```rust
//! extern crate crates_index;
//!
//! let index = crates_index::Index::new("_index");
//! if !index.exists() {
//!    index.retrieve().expect("Could not fetch crates.io index");
//! }
//! for crate_ in index.crates() {
//!    let latest_version = crate_.latest_version();
//!    println!("crate name: {}", latest_version.name());
//!    println!("crate version: {}", latest_version.version());
//! }
//! ```

use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::io::{BufRead, BufReader};
use std::iter;
use std::path::{Path, PathBuf};

#[macro_use]
extern crate error_chain;
extern crate git2;
extern crate glob;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde;

error_chain! {
    foreign_links {
        Git(git2::Error);
    }
}

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of a crate published to the index
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Version {
    name: String,
    vers: String,
    deps: Vec<Dependency>,
    cksum: String,
    features: HashMap<String, Vec<String>>,
    yanked: bool,
}

impl Version {
    /// Name of the crate
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Name of this version
    pub fn version(&self) -> &str {
        &self.vers
    }

    /// Dependencies for this version
    pub fn dependencies(&self) -> &[Dependency] {
        &self.deps
    }

    /// Checksum of the package for this version
    pub fn checksum(&self) -> &str {
        &self.cksum
    }

    pub fn features(&self) -> &HashMap<String, Vec<String>> {
        &self.features
    }

    /// Whether this version was [yanked](http://doc.crates.io/crates-io.html#cargo-yank) from the
    /// index
    pub fn is_yanked(&self) -> bool {
        self.yanked
    }
}

/// A single dependency of a specific crate version
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Dependency {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>,
    package: Option<String>,
}

impl Dependency {
    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn requirement(&self) -> &str {
        &self.req
    }

    pub fn features(&self) -> &[String] {
        &self.features
    }

    pub fn is_optional(&self) -> bool {
        self.optional
    }

    pub fn has_default_features(&self) -> bool {
        self.default_features
    }

    pub fn target(&self) -> Option<&str> {
        match self.target {
            Some(ref s) => Some(s),
            None => None,
        }
    }

    pub fn kind(&self) -> Option<&str> {
        match self.kind {
            Some(ref s) => Some(s),
            None => None,
        }
    }

    pub fn package(&self) -> Option<&str> {
        match self.package {
            Some(ref s) => Some(s),
            None => None,
        }
    }

    /// Returns the name of the crate providing the dependency.
    /// This is equivalent to `name()` unless `self.package()`
    /// is not `None`, in which case it's equal to `self.package()`.
    ///
    /// Basically, you can define a dependency in your `Cargo.toml`
    /// like this:
    ///
    /// ```toml
    /// serde_lib = {version = "1", package = "serde"}
    /// ```
    ///
    /// ...which means that it uses the crate `serde` but imports
    /// it under the name `serde_lib`.
    pub fn crate_name(&self) -> &str {
        match self.package {
            Some(ref s) => s,
            None => self.name(),
        }
    }
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new<P: AsRef<Path>>(path: P) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;
        let path = path.as_ref();

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

/// Wrapper around managing the crates.io-index git repository
#[derive(Debug, Clone, PartialEq)]
pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new<P: Into<PathBuf>>(path: P) -> Index {
        Index { path: path.into() }
    }

    /// Determines if a crates.io repository exists at `self.path`
    pub fn exists(&self) -> bool {
        git2::Repository::discover(&self.path)
            .map(|repository| {
                repository
                    .find_remote("origin")
                    .map(|remote| remote.url() == Some(INDEX_GIT_URL))
                    .unwrap_or(false)
            })
            .unwrap_or(false)
    }

    /// Downloads the index to the path specified from the constructor
    pub fn retrieve(&self) -> Result<()> {
        let _ = git2::Repository::clone(INDEX_GIT_URL, &self.path)?;
        Ok(())
    }

    /// Assumes the index already exists at `self.path`, and updates it
    pub fn update(&self) -> Result<()> {
        debug_assert!(self.exists());
        let repo = git2::Repository::discover(&self.path)?;
        let mut origin_remote = repo.find_remote("origin")?;
        origin_remote.fetch(&["master"], None, None)?;
        let oid = repo.refname_to_id("refs/remotes/origin/master")?;
        let object = repo.find_object(oid, None).unwrap();
        repo.reset(&object, git2::ResetType::Hard, None)?;
        Ok(())
    }

    /// Downloads the index to the path specified from the constructor
    pub fn retrieve_or_update(&self) -> Result<()> {
        if self.exists() {
            self.update()
        } else {
            self.retrieve()
        }
    }

    /// Retrieve a single crate by name (case insensitive) from the index
    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| {
                      path.file_name()
                          .and_then(OsStr::to_str)
                          .map(|file_name| file_name.eq_ignore_ascii_case(crate_name))
                          .unwrap_or(false)
                  })
            .map(|p| Crate::new(&p))
    }

    /// Retrieve an iterator over all the crates in the index
    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone()) // TODO: remove this clone
    }

    /// Get the index directory.
    pub fn path(&self) -> &Path {
        &self.path
    }
}

/// A single crate that contains many published versions
#[derive(Serialize, Debug)]
pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new<P: AsRef<Path>>(index_path: P) -> Crate {
        let index_path = index_path.as_ref();
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = serde_json::from_str(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate { versions: versions }
    }

    /// Published versions of this crate sorted chronologically by date published
    pub fn versions(&self) -> &[Version] {
        &self.versions
    }

    pub fn earliest_version(&self) -> &Version {
        &self.versions[0]
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }

    pub fn name(&self) -> &str {
        self.latest_version().name()
    }
}

#[cfg(test)]
mod test {
    use super::Index;
    extern crate tempdir;
    use self::tempdir::TempDir;

    #[test]
    fn test_dependencies() {
        let tmp_dir = TempDir::new("test1").unwrap();

        let index = Index::new(tmp_dir.path());
        index.retrieve_or_update().expect("could not fetch crates io index");
        // let crate_ = index.crates().nth(0).expect("could not find a crate in the index");
        let crate_ = index.crate_("sval").expect("Could not find the crate libnotify in the index");
        let _ = format!("supports debug {:?}", crate_);

        let version = crate_.versions().iter().find(|v| v.version() == "0.0.1")
            .expect("Version 0.0.1 of sval does not exist?");
        let dep_with_package_name = version.dependencies().iter().find(|d| d.name() == "serde_lib")
            .expect("sval does not have expected dependency?");
        assert_ne!(dep_with_package_name.name(), dep_with_package_name.package().unwrap());
        assert_eq!(dep_with_package_name.crate_name(), dep_with_package_name.package().unwrap());
    }

    #[test]
    fn test_retrieve_or_update() {
        let tmp_dir = TempDir::new("test2").unwrap();

        let index = Index::new(tmp_dir.path());
        index.retrieve_or_update().expect("could not fetch crates io index");
        assert!(index.exists());
        index.retrieve_or_update().expect("could not fetch crates io index");
        assert!(index.exists());
    }

    #[test]
    fn test_exists() {
        let tmp_dir = TempDir::new("test3").unwrap();

        let index = Index::new(tmp_dir.path());
        assert!(!index.exists());
        index.retrieve().unwrap();
        assert!(index.exists());
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Write, Read, BufRead};

pub use Either::{Left, Right};

/// `Either` represents an alternative holding one value out of
/// either of the two possible values.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Either<L, R> {
    Left(L),
    Right(R),
}

macro_rules! either {
    ($value:expr, $inner:ident => $result:expr) => (
        match $value {
            Either::Left(ref $inner) => $result,
            Either::Right(ref $inner) => $result,
        }
    )
}

macro_rules! either_mut {
    ($value:expr, $inner:ident => $result:expr) => (
        match $value {
            Either::Left(ref mut $inner) => $result,
            Either::Right(ref mut $inner) => $result,
        }
    )
}

impl<L, R> Either<L, R> {
    pub fn is_left(&self) -> bool {
        match *self {
            Left(_) => true,
            Right(_) => false,
        }
    }

    pub fn is_right(&self) -> bool {
        !self.is_left()
    }

    pub fn left(self) -> Option<L> {
        match self {
            Left(l) => Some(l),
            Right(_) => None,
        }
    }

    pub fn right(self) -> Option<R> {
        match self {
            Left(_) => None,
            Right(r) => Some(r),
        }
    }

    pub fn as_ref(&self) -> Either<&L, &R> {
        match *self {
            Left(ref inner) => Left(inner),
            Right(ref inner) => Right(inner),
        }
    }

    pub fn as_mut(&mut self) -> Either<&mut L, &mut R> {
        match *self {
            Left(ref mut inner) => Left(inner),
            Right(ref mut inner) => Right(inner),
        }
    }
}

/// Convert from `Result` to `Either` with `Ok => Right` and `Err => Left`.
impl<L, R> From<Result<R, L>> for Either<L, R> {
    fn from(r: Result<R, L>) -> Self {
        match r {
            Err(e) => Left(e),
            Ok(o) => Right(o),
        }
    }
}

/// Convert from `Either` to `Result` with `Right => Ok` and `Left => Err`.
impl<L, R> Into<Result<R, L>> for Either<L, R> {
    fn into(self) -> Result<R, L> {
        match self {
            Left(l) => Err(l),
            Right(r) => Ok(r),
        }
    }
}

impl<L, R> Iterator for Either<L, R>
    where L: Iterator, R: Iterator<Item=L::Item>
{
    type Item = L::Item;

    fn next(&mut self) -> Option<L::Item> {
        either_mut!(*self, inner => inner.next())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        either!(*self, inner => inner.size_hint())
    }
}

impl<L, R> DoubleEndedIterator for Either<L, R>
    where L: DoubleEndedIterator, R: DoubleEndedIterator<Item=L::Item>
{
    fn next_back(&mut self) -> Option<L::Item> {
        either_mut!(*self, inner => inner.next_back())
    }
}

impl<L, R> Read for Either<L, R>
    where L: Read, R: Read
{
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        either_mut!(*self, inner => inner.read(buf))
    }

    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        either_mut!(*self, inner => inner.read_to_end(buf))
    }
}

impl<L, R> BufRead for Either<L, R>
    where L: BufRead, R: BufRead
{
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        either_mut!(*self, inner => inner.fill_buf())
    }

    fn consume(&mut self, amt: usize) {
        either_mut!(*self, inner => inner.consume(amt))
    }
}

impl<L, R> Write for Either<L, R>
    where L: Write, R: Write
{
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        either_mut!(*self, inner => inner.write(buf))
    }

    fn flush(&mut self) -> io::Result<()> {
        either_mut!(*self, inner => inner.flush())
    }
}

#[test]
fn it_works() {
}
<commit_msg>Add simple tests<commit_after>use std::io::{self, Write, Read, BufRead};

pub use Either::{Left, Right};

/// `Either` represents an alternative holding one value out of
/// either of the two possible values.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Either<L, R> {
    Left(L),
    Right(R),
}

macro_rules! either {
    ($value:expr, $inner:ident => $result:expr) => (
        match $value {
            Either::Left(ref $inner) => $result,
            Either::Right(ref $inner) => $result,
        }
    )
}

macro_rules! either_mut {
    ($value:expr, $inner:ident => $result:expr) => (
        match $value {
            Either::Left(ref mut $inner) => $result,
            Either::Right(ref mut $inner) => $result,
        }
    )
}

impl<L, R> Either<L, R> {
    pub fn is_left(&self) -> bool {
        match *self {
            Left(_) => true,
            Right(_) => false,
        }
    }

    pub fn is_right(&self) -> bool {
        !self.is_left()
    }

    pub fn left(self) -> Option<L> {
        match self {
            Left(l) => Some(l),
            Right(_) => None,
        }
    }

    pub fn right(self) -> Option<R> {
        match self {
            Left(_) => None,
            Right(r) => Some(r),
        }
    }

    pub fn as_ref(&self) -> Either<&L, &R> {
        match *self {
            Left(ref inner) => Left(inner),
            Right(ref inner) => Right(inner),
        }
    }

    pub fn as_mut(&mut self) -> Either<&mut L, &mut R> {
        match *self {
            Left(ref mut inner) => Left(inner),
            Right(ref mut inner) => Right(inner),
        }
    }
}

/// Convert from `Result` to `Either` with `Ok => Right` and `Err => Left`.
impl<L, R> From<Result<R, L>> for Either<L, R> {
    fn from(r: Result<R, L>) -> Self {
        match r {
            Err(e) => Left(e),
            Ok(o) => Right(o),
        }
    }
}

/// Convert from `Either` to `Result` with `Right => Ok` and `Left => Err`.
impl<L, R> Into<Result<R, L>> for Either<L, R> {
    fn into(self) -> Result<R, L> {
        match self {
            Left(l) => Err(l),
            Right(r) => Ok(r),
        }
    }
}

impl<L, R> Iterator for Either<L, R>
    where L: Iterator, R: Iterator<Item=L::Item>
{
    type Item = L::Item;

    fn next(&mut self) -> Option<L::Item> {
        either_mut!(*self, inner => inner.next())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        either!(*self, inner => inner.size_hint())
    }
}

impl<L, R> DoubleEndedIterator for Either<L, R>
    where L: DoubleEndedIterator, R: DoubleEndedIterator<Item=L::Item>
{
    fn next_back(&mut self) -> Option<L::Item> {
        either_mut!(*self, inner => inner.next_back())
    }
}

impl<L, R> Read for Either<L, R>
    where L: Read, R: Read
{
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        either_mut!(*self, inner => inner.read(buf))
    }

    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        either_mut!(*self, inner => inner.read_to_end(buf))
    }
}

impl<L, R> BufRead for Either<L, R>
    where L: BufRead, R: BufRead
{
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        either_mut!(*self, inner => inner.fill_buf())
    }

    fn consume(&mut self, amt: usize) {
        either_mut!(*self, inner => inner.consume(amt))
    }
}

impl<L, R> Write for Either<L, R>
    where L: Write, R: Write
{
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        either_mut!(*self, inner => inner.write(buf))
    }

    fn flush(&mut self) -> io::Result<()> {
        either_mut!(*self, inner => inner.flush())
    }
}

#[test]
fn basic() {
    let mut e = Left(2);
    let r = Right(2);
    assert_eq!(e, Left(2));
    e = r;
    assert_eq!(e, Right(2));
    assert_eq!(e.left(), None);
    assert_eq!(e.right(), Some(2));
    assert_eq!(e.as_ref().right(), Some(&2));
    assert_eq!(e.as_mut().right(), Some(&mut 2));
}

#[test]
fn iter() {
    let x = 3;
    let mut iter = match x {
        1...3 => Left(0..10),
        _ => Right(17..),
    };

    assert_eq!(iter.next(), Some(0));
    assert_eq!(iter.count(), 9);
}
<|endoftext|>


<commit_before>// Copyright 2016 union-find-rs 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.

//! Struct and methods for union-find operation.

#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]
#![cfg_attr(all(test, feature = "nightly"), feature(test))]
#![cfg_attr(all(test, feature = "nightly"), feature(const_fn))]

#[cfg(all(test, feature = "nightly"))]
#[macro_use]
extern crate lazy_static;

mod traits;
pub use traits::{Union, UnionFind, UnionResult};

mod union;
pub use union::{UnionByRank, UnionByRankSize, UnionBySize, UnionBySizeRank};

mod quick_union;
pub use quick_union::QuickUnionUf;
mod quick_find;
pub use quick_find::QuickFindUf;

#[cfg(test)]
mod tests;
#[cfg(all(test, feature = "nightly"))]
mod bench;
<commit_msg>remove feature(const_fn)<commit_after>// Copyright 2016 union-find-rs 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.

//! Struct and methods for union-find operation.

#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]
#![cfg_attr(all(test, feature = "nightly"), feature(test))]

#[cfg(all(test, feature = "nightly"))]
#[macro_use]
extern crate lazy_static;

mod traits;
pub use traits::{Union, UnionFind, UnionResult};

mod union;
pub use union::{UnionByRank, UnionByRankSize, UnionBySize, UnionBySizeRank};

mod quick_union;
pub use quick_union::QuickUnionUf;
mod quick_find;
pub use quick_find::QuickFindUf;

#[cfg(test)]
mod tests;
#[cfg(all(test, feature = "nightly"))]
mod bench;
<|endoftext|>


<commit_before>#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>Add initial PascalString api<commit_after>extern crate ascii;

use ascii::{AsAsciiStrError, AsciiChar, AsciiStr, AsciiString, ToAsciiChar, ToAsciiCharError};
use std::convert::{AsRef, AsMut, From, Into};
use std::{fmt, ptr, slice, str};

const PASCAL_STRING_BUF_SIZE: usize = 255;

/// An owned `PascalString`. This string type stores its data the stack. It is always 256 bytes long, with
/// the first byte storing the length.
///
/// This string uses the Ascii encoding.
#[repr(C)]
pub struct PascalString {
    /// The length of this string.
    len: u8,
    /// The characters of this string, encoded as an ascii array.
    chars: [AsciiChar; PASCAL_STRING_BUF_SIZE]
}

impl PascalString {
    /// Creates a new, empty `PascalString`.
    #[inline]
    pub fn new() -> Self {
        Default::default()
    }

    #[inline]
    pub fn from_bytes<B: AsRef<[u8]>>(bytes: B) -> Result<Self, PascalStringError> {
        PascalString::_from_bytes(bytes.as_ref())
    }

    fn _from_bytes(bytes: &[u8]) -> Result<Self, PascalStringError>  {
        let len = bytes.len();
        if len > PASCAL_STRING_BUF_SIZE {
            return Err(PascalStringError::OutOfBounds);
        }
        // Perform ascii check
        let ascii = try!(AsciiStr::from_ascii(bytes));

        let mut string = PascalString::new();
        string.len = len as u8;
        for i in 0..len {
            string.chars[i] = ascii[i];
        }
        Ok(string)
    }

    /// Push an ascii convertible character onto this string.
    ///
    /// # Panics
    ///
    /// Panics if the string is full, of if the `character` is not a valid ascii character.
    #[inline]
    pub fn push<C: ToAsciiChar>(&mut self, character: C) {
        self.try_push(character).unwrap();
    }

    /// Attempt to push an ascii convertible character onto the end of this `PascalString`.
    ///
    /// Returns `Err(_)` if the character cannot be pushed because this `PascalString` is full, or if
    /// `character` is not a valid ascii character.
    #[inline]
    pub fn try_push<C: ToAsciiChar>(&mut self, character: C) -> Result<(), PascalStringError> {
        self._try_push(try!(AsciiChar::from(character)))
    }

    fn _try_push(&mut self, ch: AsciiChar) -> Result<(), PascalStringError> {
        if self.is_full() {
            return Err(PascalStringError::OutOfBounds)
        }
        self.chars[self.len as usize] = ch;
        self.len += 1;
        Ok(())
    }

    /// Append a given string slice onto the end of this `PascalString`.
    ///
    /// # Panics
    ///
    /// Panics if the string cannot be pushed to because this `PascalString` is full.
    #[inline]
    pub fn push_str<S: AsRef<str>>(&mut self, s: S) {
        self.try_push_str(s).unwrap();
    }

    /// Attempt to append a given string slice onto the end of this `PascalString`.
    ///
    /// Returns `Err(_)` if the string cannot be pushed because this `PascalString` is full.
    #[inline]
    pub fn try_push_str<S: AsRef<str>>(&mut self, s: S) -> Result<(), PascalStringError> {
        self._try_push_str(s.as_ref())
    }

    fn _try_push_str(&mut self, s: &str) -> Result<(), PascalStringError> {
        unimplemented!()
    }

    /// Removes the last character from the string buffer and returns it.
    ///
    /// Returns `None` if this `PascalString` is empty.
    pub fn pop(&mut self) -> Option<AsciiChar> {
        if self.is_empty() {
            return None;
        }
        let c = self.chars[self.len as usize];
        self.len -= 1;
        Some(c)
    }

    pub fn remove(&mut self, index: u8) -> AsciiChar {
        assert!(self.len < index);
        let len = self.len as usize;
        let index = index as isize;
        let c = self.chars[len];
        // Shift everything to the right of the removed character to the left to cover up the hole
        // left.
        unsafe {
            let ptr = self.as_mut_ptr().offset(index);
            ptr::copy(ptr.offset(1), ptr, len - index.abs() as usize - 1);
        }
        self.len -= 1;
        c
    }

    #[inline]
    pub fn insert<C: ToAsciiChar>(&mut self, ch: C, index: u8) {
        self._insert(AsciiChar::from(ch).unwrap(), index)
    }

    fn _insert(&mut self, ch: AsciiChar, index: u8) {
        assert!(self.len < index);
        assert!(!self.is_full());
        let len = self.len as usize;
        let index = index as isize;
        // Shift everything to the right of `index` 1 place to the right to make room for the
        // new character.
        unsafe {
            let ptr = self.as_mut_ptr().offset(index);
            ptr::copy(ptr, ptr.offset(1), len - index.abs() as usize - 1);
        }
        self.chars[len] = ch;
        self.len += 1;
    }

    /// Truncates this String, removing all contents.
    ///
    /// Does not zero the values of the string.
    #[inline]
    pub fn clear(&mut self) {
        self.len = 0;
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.len as usize
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    #[inline]
    pub fn is_full(&self) -> bool {
        self.len() == PASCAL_STRING_BUF_SIZE
    }

    /// Consumes this `PascalString`, and returns its inner state as a `[u8; 256]`, where the first byte
    /// is the length.
    ///
    /// Note that if the string has been truncated, bytes beyond the end of the string will not have been
    /// zeroed.
    #[inline]
    pub fn to_array(self) -> [u8; PASCAL_STRING_BUF_SIZE + 1] {
        self.into()
    }

    /// Get a pointer to the first byte of the string buffer.
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        &self.chars as *const _ as *const u8
    }

    /// Get a mutable pointer to the first byte of the string buffer.
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut u8 {
        &mut self.chars as *mut _ as *mut u8
    }
}

impl Default for PascalString {
    #[inline]
    fn default() -> Self {
        PascalString {
            len: 0,
            chars: [AsciiChar::Null; PASCAL_STRING_BUF_SIZE]
        }
    }
}

impl Clone for PascalString {
    fn clone(&self) -> Self {
        let mut clone = PascalString::default();
        clone.len = self.len;
        unsafe {
            ptr::copy_nonoverlapping(&self.chars, &mut clone.chars, PASCAL_STRING_BUF_SIZE);
        }
        clone
    }
}

impl fmt::Debug for PascalString {
    fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
        write!(fmtr, "{}", self)
    }
}

impl fmt::Display for PascalString {
    fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
        fmtr.pad(self.as_ref())
    }
}

impl AsRef<str> for PascalString {
    fn as_ref(&self) -> &str {
        let bytes: &[u8] = self.as_ref();
        str::from_utf8(bytes).unwrap()
    }
}

impl AsRef<[u8]> for PascalString {
    fn as_ref(&self) -> &[u8] {
        unsafe {
            slice::from_raw_parts(self.chars.as_ptr() as *const u8, self.len as usize)
        }
    }
}

impl AsRef<AsciiStr> for PascalString {
    fn as_ref(&self) -> &AsciiStr {
        let bytes: &[u8] = self.as_ref();
        AsciiStr::from_ascii(bytes).unwrap()
    }
}

impl AsRef<[AsciiChar]> for PascalString {
    fn as_ref(&self) -> &[AsciiChar] {
        unsafe {
            slice::from_raw_parts(self.chars.as_ptr(), self.len as usize)
        }
    }
}

impl AsMut<[AsciiChar]> for PascalString {
    fn as_mut(&mut self) -> &mut [AsciiChar] {
        unsafe {
            slice::from_raw_parts_mut(self.chars.as_mut_ptr(), self.len as usize)
        }
    }
}

impl Into<[u8; PASCAL_STRING_BUF_SIZE + 1]> for PascalString {
    fn into(self) -> [u8; PASCAL_STRING_BUF_SIZE + 1] {
        let mut array = [0u8; PASCAL_STRING_BUF_SIZE + 1];
        array[0] = self.len;
        unsafe {
            let chars_ptr = &self.chars as *const _ as *const [u8; PASCAL_STRING_BUF_SIZE];
            let array_ptr = (&mut array as *mut _).offset(1) as *mut [u8; PASCAL_STRING_BUF_SIZE];
            ptr::copy_nonoverlapping(chars_ptr, array_ptr, PASCAL_STRING_BUF_SIZE);
        }
        array
    }
}

impl Into<String> for PascalString {
    fn into(self) -> String {
        String::from_utf8_lossy(self.as_ref()).into_owned()
    }
}

#[derive(Debug, PartialEq)]
pub enum PascalStringError {
    OutOfBounds,
    InvalidChar(ToAsciiCharError),
    InvalidString(AsAsciiStrError)
}

impl From<ToAsciiCharError> for PascalStringError {
    fn from(e: ToAsciiCharError) -> Self {
        PascalStringError::InvalidChar(e)
    }
}

impl From<AsAsciiStrError> for PascalStringError {
    fn from(e: AsAsciiStrError) -> Self {
        PascalStringError::InvalidString(e)
    }
}

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


<commit_before>//! Immutable binary search tree.
//!
//! This crate provides functional programming style binary search trees which returns modified
//! copy of original map or set with the new data, and preserves the original. Many features and
//! algorithms are borrowed from `Data.Map` of Haskell's standard library.
//!
//! See https://yoichihirai.com/bst.pdf for the balancing algorithm.
//!
//! To share the data between the old and the new data structure after modification, most of the
//! functions require the key and value type to implement `Clone`. If you want to store non-
//! clonable data into this map, you can wrap it under shared pointer such as `Rc` or `Arc`.

#[cfg(test)]
#[macro_use]
extern crate quickcheck;
#[cfg(test)]
extern crate rand;

#[cfg(test)]
use quickcheck::{Arbitrary, Gen};

pub mod set;
pub mod map;
mod tree;

pub use set::TreeSet;
pub use map::TreeMap;

/// An endpoint of a range of keys.
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Bound<T> {
    /// An infinite endpoint. Indicates that there is no bound in this direction.
    Unbounded,
    /// An inclusive bound.
    Included(T),
    /// An exclusive bound.
    Excluded(T)
}

#[cfg(test)]
impl<T: Arbitrary> Arbitrary for Bound<T> {
    fn arbitrary<G: Gen>(g: &mut G) -> Bound<T> {
        match g.size() % 3 {
            0 => Bound::Unbounded,
            1 => Bound::Included(Arbitrary::arbitrary(g)),
            2 => Bound::Excluded(Arbitrary::arbitrary(g)),
            _ => panic!("remainder is greater than 3")
        }
    }
}
<commit_msg>Short module description<commit_after>//! Immutable binary search tree.
//!
//! This crate provides functional programming style binary search trees which returns modified
//! copy of original map or set with the new data, and preserves the original. Many features and
//! algorithms are borrowed from `Data.Map` of Haskell's standard library.
//!
//! See https://yoichihirai.com/bst.pdf for the balancing algorithm.
//!
//! To share the data between the old and the new data structure after modification, most of the
//! functions require the key and value type to implement `Clone`. If you want to store non-
//! clonable data into this map, you can wrap it under shared pointer such as `Rc` or `Arc`.

#[cfg(test)]
#[macro_use]
extern crate quickcheck;
#[cfg(test)]
extern crate rand;

#[cfg(test)]
use quickcheck::{Arbitrary, Gen};

/// An immutable set based on binary search tree
pub mod set;
/// An immutable map based on binary search tree
pub mod map;
mod tree;

pub use set::TreeSet;
pub use map::TreeMap;

/// An endpoint of a range of keys.
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Bound<T> {
    /// An infinite endpoint. Indicates that there is no bound in this direction.
    Unbounded,
    /// An inclusive bound.
    Included(T),
    /// An exclusive bound.
    Excluded(T)
}

#[cfg(test)]
impl<T: Arbitrary> Arbitrary for Bound<T> {
    fn arbitrary<G: Gen>(g: &mut G) -> Bound<T> {
        match g.size() % 3 {
            0 => Bound::Unbounded,
            1 => Bound::Included(Arbitrary::arbitrary(g)),
            2 => Bound::Excluded(Arbitrary::arbitrary(g)),
            _ => panic!("remainder is greater than 3")
        }
    }
}
<|endoftext|>


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

//! A micro-benchmarking library.

#![feature(test)]

#![warn(missing_copy_implementations, missing_debug_implementations, missing_docs)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", warn(clippy))]
#![cfg_attr(feature="clippy", allow(new_without_default_derive))]

extern crate test;
extern crate time;

//================================================
// Structs
//================================================

// Stopwatch _____________________________________

/// A high-precision stopwatch.
#[derive(Clone, Copy, Debug)]
pub struct Stopwatch {
    start: u64,
}

impl Stopwatch {
    //- Constructors -----------------------------

    /// Constructs a new `Stopwatch`.
    pub fn new() -> Self {
        Stopwatch { start: time::precise_time_ns() }
    }

    //- Accessors --------------------------------

    /// Returns the elapsed nanoseconds since this stopwatch was constructed or reset.
    pub fn elapsed(&self) -> u64 {
        time::precise_time_ns() - self.start
    }

    //- Mutators ---------------------------------

    /// Resets this stopwatch.
    pub fn reset(&mut self) {
        self.start = time::precise_time_ns();
    }
}

//================================================
// Functions
//================================================

/// A function that prevents the optimizer from eliminating the supplied value.
pub fn retain<T>(value: T) -> T {
    test::black_box(value)
}
<commit_msg>Add Options struct<commit_after>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A micro-benchmarking library.

#![feature(test)]

#![warn(missing_copy_implementations, missing_debug_implementations, missing_docs)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", warn(clippy))]
#![cfg_attr(feature="clippy", allow(new_without_default_derive))]

extern crate test;
extern crate time;

use std::time::{Duration};

//================================================
// Structs
//================================================

// Options _______________________________________

/// Micro-benchmarking options.
#[derive(Copy, Clone, Debug)]
pub struct Options {
    factor: f64,
    maximum: u64,
}

impl Default for Options {
    fn default() -> Options {
        Options { factor: 1.01, maximum: 5_000_000_000 }
    }
}

impl Options {
    //- Consumers --------------------------------

    /// Sets the geometric growth factor.
    ///
    /// **Default:** `1.01`
    pub fn factor(mut self, factor: f64) -> Self {
        self.factor = factor;
        self
    }

    /// Sets the maximum amount of time a micro-benchmark will run for.
    ///
    /// **Default:** `Duration::new(5, 0)`
    pub fn maximum(mut self, maximum: Duration) -> Self {
        self.maximum = (maximum.as_secs() * 1_000_000_000) + maximum.subsec_nanos() as u64;
        self
    }
}

// Stopwatch _____________________________________

/// A high-precision stopwatch.
#[derive(Clone, Copy, Debug)]
pub struct Stopwatch {
    start: u64,
}

impl Stopwatch {
    //- Constructors -----------------------------

    /// Constructs a new `Stopwatch`.
    pub fn new() -> Self {
        Stopwatch { start: time::precise_time_ns() }
    }

    //- Accessors --------------------------------

    /// Returns the elapsed nanoseconds since this stopwatch was constructed or reset.
    pub fn elapsed(&self) -> u64 {
        time::precise_time_ns() - self.start
    }

    //- Mutators ---------------------------------

    /// Resets this stopwatch.
    pub fn reset(&mut self) {
        self.start = time::precise_time_ns();
    }
}

//================================================
// Functions
//================================================

/// A function that prevents the optimizer from eliminating the supplied value.
pub fn retain<T>(value: T) -> T {
    test::black_box(value)
}
<|endoftext|>