<commit_before>#[derive(Debug)]
/// The wire format that postgres sends intervals in. Shouldn't be used directly.
pub struct PgInterval {
  months: i32
  days: i32,
  microseconds: i64,
}

impl PgInterval {
    /// Construct a new instance of a PgInterval.
    pub fn new(months: i32, days: i32, microseconds: i64) -> PgInterval {
        PgInterval {
            months: months,
            days: days,
            microseconds: days
        }
    }
}
<commit_msg>feat(*): replace pginterval with a single interval type<commit_after>mod helpers;

use helpers::*;

pub struct Interval {
    years: i32,
    months: i8,
    days: i32,
    hours: i64,
    minutes: i8,
    seconds: f64
}

impl Interval {
    pub fn new(years: i32,
               months: i8,
               days: i32,
               hours: i64,
               minutes: i8,
               seconds: f64) -> Interval {
        Interval {
            years: years,
            months: months,
            days: days,
            hours: hours,
            minutes: minutes,
            seconds: seconds
        }
    }

    /// Get the amount of years that the interval spans.
    pub fn get_years(&self) -> i32 {
        self.years
    }

    /// Get the amount of months that the interval spans.
    pub fn get_months(&self) -> i8 {
        self.months
    }

    /// Get the amount of days that the interval spans.
    pub fn get_days(&self) -> i32 {
        self.days
    }

    /// Get the amount of hourss that the interval spans.
    pub fn get_hours(&self) -> i64 {
        self.hours
    }

    /// Get the amount of minutes that the interval spans.
    pub fn get_minutes(&self) -> i8 {
        self.minutes
    }

    /// Get the amount of seconds that the interval spans. Anything smaller
    /// than a seconds is represented fractionally.
    pub fn get_seconds(&self) -> f64 {
        self.seconds
    }

    /// Map interval formats that use months, days, and microseconds to Interval.
    pub fn from_months_days_microseconds(months: i32,
                                        days: i32,
                                        microseconds: i64)
                                         -> Interval {
        let (years,months) = get_year_month_interval(months);
        let (hours, minutes, seconds) = get_day_time_interval(microseconds);
        Interval {
            years: years,
            months: months,
            days: days,
            hours: hours,
            minutes: minutes,
            seconds: seconds
        }
    }
}
<|endoftext|>


<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 with isolated keyspaces
//! 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
//!
//! ```
//! # let _ = std::fs::remove_dir_all("my_db");
//! let t = sled::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));
//! # let _ = std::fs::remove_dir_all("my_db");
//! ```
#![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(
    // over time, consider enabling the following commented-out lints:
    // clippy::missing_const_for_fn,
    // clippy::missing_docs_in_private_items,
    // clippy::module_name_repetitions,
    // clippy::multiple_crate_versions,
    // clippy::unimplemented,
    // clippy::wildcard_enum_match_arm,
    // 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::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::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::unseparated_literal_suffix,
    clippy::used_underscore_binding,
    clippy::wildcard_dependencies,
    clippy::wrong_pub_self_convention,
)]
#![recursion_limit = "128"]

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

macro_rules! testing_assert {
    ($($e:expr),*) => {
        #[cfg(feature = "lock_free_delays")]
        assert!($($e),*)
    };
}

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

mod batch;
mod binary_search;
mod concurrency_control;
mod config;
mod context;
mod db;
mod dll;
mod fastcmp;
mod fastlock;
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 serialization;
mod stack;
mod stackvec;
mod subscription;
mod sys_limits;
pub mod transaction;
mod tree;

#[cfg(not(any(windows, target_os = "linux", target_os = "macos")))]
mod threadpool {
    use super::OneShot;

    /// Just execute a task without involving threads.
    pub fn spawn<F, R>(work: F) -> OneShot<R>
    where
        F: FnOnce() -> R + Send + 'static,
        R: Send + 'static,
    {
        let (promise_filler, promise) = OneShot::pair();
        promise_filler.fill((work)());
        return promise;
    }
}

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

#[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 = "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_MSG_HEADER_LEN, MAX_SPACE_AMPLIFICATION,
                MINIMUM_ITEMS_PER_SEGMENT, SEG_HEADER_LEN,
            },
            BatchManifest, DiskPtr, Log, LogKind, LogOffset, LogRead, Lsn,
            PageCache, PageId,
        },
        serialization::Serialize,
    },
    crossbeam_epoch::{pin, Atomic, Guard, Owned, Shared},
};

pub use self::{
    batch::Batch,
    config::{Config, Mode},
    db::{open, Db},
    iter::Iter,
    ivec::IVec,
    result::{Error, Result},
    subscription::{Event, Subscriber},
    transaction::Transactional,
    tree::{CompareAndSwapError, Tree},
};

use {
    self::{
        binary_search::binary_search_lub,
        concurrency_control::{ConcurrencyControl, Protector},
        context::Context,
        fastcmp::fastcmp,
        histogram::Histogram,
        lru::Lru,
        meta::Meta,
        metrics::{clock, Measure, M},
        node::{Data, Node},
        oneshot::{OneShot, OneShotFiller},
        result::CasResult,
        stackvec::StackVec,
        subscription::Subscriptions,
        tree::TreeInner,
    },
    crossbeam_utils::{Backoff, CachePadded},
    log::{debug, error, trace, warn},
    pagecache::RecoveryGuard,
    parking_lot::{Condvar, Mutex, RwLock},
    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()
}

fn calculate_message_crc32(header: &[u8], body: &[u8]) -> u32 {
    let mut hasher = crc32fast::Hasher::new();
    hasher.update(body);
    hasher.update(&header[4..]);
    let crc32 = hasher.finalize();
    crc32 ^ 0xFFFF_FFFF
}

#[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() {}

/// Link denotes a tree node or its modification fragment such as
/// key addition or removal.
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum Link {
    /// A new value is set for a given key
    Set(IVec, IVec),
    /// The associated value is removed for a given key
    Del(IVec),
    /// A child of this Index node is marked as mergable
    ParentMergeIntention(PageId),
    /// The merging child has been completely merged into its left sibling
    ParentMergeConfirm,
    /// A Node is marked for being merged into its left sibling
    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>>;
<commit_msg>Added doc 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 with isolated keyspaces
//! 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
//!
//! ```
//! # let _ = std::fs::remove_dir_all("my_db");
//! let t = sled::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));
//! # let _ = std::fs::remove_dir_all("my_db");
//! ```
#![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(
    // over time, consider enabling the following commented-out lints:
    // clippy::missing_const_for_fn,
    // clippy::missing_docs_in_private_items,
    // clippy::module_name_repetitions,
    // clippy::multiple_crate_versions,
    // clippy::unimplemented,
    // clippy::wildcard_enum_match_arm,
    // 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::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::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::unseparated_literal_suffix,
    clippy::used_underscore_binding,
    clippy::wildcard_dependencies,
    clippy::wrong_pub_self_convention,
)]
#![recursion_limit = "128"]

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

macro_rules! testing_assert {
    ($($e:expr),*) => {
        #[cfg(feature = "lock_free_delays")]
        assert!($($e),*)
    };
}

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

mod batch;
mod binary_search;
mod concurrency_control;
mod config;
mod context;
mod db;
mod dll;
mod fastcmp;
mod fastlock;
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 serialization;
mod stack;
mod stackvec;
mod subscription;
mod sys_limits;
pub mod transaction;
mod tree;

#[cfg(feature = "docs")]
pub mod doc;

#[cfg(not(any(windows, target_os = "linux", target_os = "macos")))]
mod threadpool {
    use super::OneShot;

    /// Just execute a task without involving threads.
    pub fn spawn<F, R>(work: F) -> OneShot<R>
    where
        F: FnOnce() -> R + Send + 'static,
        R: Send + 'static,
    {
        let (promise_filler, promise) = OneShot::pair();
        promise_filler.fill((work)());
        return promise;
    }
}

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

#[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 = "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_MSG_HEADER_LEN, MAX_SPACE_AMPLIFICATION,
                MINIMUM_ITEMS_PER_SEGMENT, SEG_HEADER_LEN,
            },
            BatchManifest, DiskPtr, Log, LogKind, LogOffset, LogRead, Lsn,
            PageCache, PageId,
        },
        serialization::Serialize,
    },
    crossbeam_epoch::{pin, Atomic, Guard, Owned, Shared},
};

pub use self::{
    batch::Batch,
    config::{Config, Mode},
    db::{open, Db},
    iter::Iter,
    ivec::IVec,
    result::{Error, Result},
    subscription::{Event, Subscriber},
    transaction::Transactional,
    tree::{CompareAndSwapError, Tree},
};

use {
    self::{
        binary_search::binary_search_lub,
        concurrency_control::{ConcurrencyControl, Protector},
        context::Context,
        fastcmp::fastcmp,
        histogram::Histogram,
        lru::Lru,
        meta::Meta,
        metrics::{clock, Measure, M},
        node::{Data, Node},
        oneshot::{OneShot, OneShotFiller},
        result::CasResult,
        stackvec::StackVec,
        subscription::Subscriptions,
        tree::TreeInner,
    },
    crossbeam_utils::{Backoff, CachePadded},
    log::{debug, error, trace, warn},
    pagecache::RecoveryGuard,
    parking_lot::{Condvar, Mutex, RwLock},
    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()
}

fn calculate_message_crc32(header: &[u8], body: &[u8]) -> u32 {
    let mut hasher = crc32fast::Hasher::new();
    hasher.update(body);
    hasher.update(&header[4..]);
    let crc32 = hasher.finalize();
    crc32 ^ 0xFFFF_FFFF
}

#[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() {}

/// Link denotes a tree node or its modification fragment such as
/// key addition or removal.
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum Link {
    /// A new value is set for a given key
    Set(IVec, IVec),
    /// The associated value is removed for a given key
    Del(IVec),
    /// A child of this Index node is marked as mergable
    ParentMergeIntention(PageId),
    /// The merging child has been completely merged into its left sibling
    ParentMergeConfirm,
    /// A Node is marked for being merged into its left sibling
    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>>;
<|endoftext|>


<commit_before>//! This crate provides safe bindings to
//! [wlroots](https://github.com/swaywm/wlroots).
//!
//! Start your [Compositor](struct.Compositor.html) by implementing an [input
//! manager](manager/struct.InputManager.html) and an [output
//! manager](manager/struct.OutputManager.html) on two separate structs.
//!
//! # Example
//! ```rust,no_run
//! extern crate wlroots;
//!
//! struct InputManager;
//! struct OutputManager;
//!
//! impl wlroots::OutputManagerHandler for OutputManager {}
//! impl wlroots::InputManagerHandler for InputManager {}
//!
//! fn main() {
//!     wlroots::CompositorBuilder::new()
//!          .build_auto((), // Dummy state
//!                      Box::new(InputManager),
//!                      Box::new(OutputManager))
//!          .run()
//! }
//! ```

#![allow(unused_unsafe)]
#[macro_use]
extern crate bitflags;
extern crate lazy_static;
extern crate libc;
#[macro_use]
pub extern crate wayland_sys;
pub extern crate wlroots_sys;
pub extern crate xkbcommon;

#[macro_use]
mod macros;
mod manager;
mod compositor;
pub mod events;
pub mod types;
pub mod extensions;
pub mod render;
mod utils;

pub use self::compositor::{terminate, Compositor, CompositorBuilder};
pub use self::events::key_events::*;
pub use self::events::pointer_events::*;
pub use self::manager::{InputManagerHandler, KeyboardHandler, OutputBuilder, OutputBuilderResult,
                        OutputHandler, OutputManagerHandler, PointerHandler};
pub use self::types::area::*;
pub use self::types::cursor::*;
pub use self::types::input_device::*;
pub use self::types::keyboard::*;
pub use self::types::output::*;
<commit_msg>Exposed utils in wlroots<commit_after>//! This crate provides safe bindings to
//! [wlroots](https://github.com/swaywm/wlroots).
//!
//! Start your [Compositor](struct.Compositor.html) by implementing an [input
//! manager](manager/struct.InputManager.html) and an [output
//! manager](manager/struct.OutputManager.html) on two separate structs.
//!
//! # Example
//! ```rust,no_run
//! extern crate wlroots;
//!
//! struct InputManager;
//! struct OutputManager;
//!
//! impl wlroots::OutputManagerHandler for OutputManager {}
//! impl wlroots::InputManagerHandler for InputManager {}
//!
//! fn main() {
//!     wlroots::CompositorBuilder::new()
//!          .build_auto((), // Dummy state
//!                      Box::new(InputManager),
//!                      Box::new(OutputManager))
//!          .run()
//! }
//! ```

#![allow(unused_unsafe)]
#[macro_use]
extern crate bitflags;
extern crate lazy_static;
extern crate libc;
#[macro_use]
pub extern crate wayland_sys;
pub extern crate wlroots_sys;
pub extern crate xkbcommon;

#[macro_use]
mod macros;
mod manager;
mod compositor;
pub mod events;
pub mod types;
pub mod extensions;
pub mod render;
pub mod utils;

pub use self::compositor::{terminate, Compositor, CompositorBuilder};
pub use self::events::key_events::*;
pub use self::events::pointer_events::*;
pub use self::manager::{InputManagerHandler, KeyboardHandler, OutputBuilder, OutputBuilderResult,
                        OutputHandler, OutputManagerHandler, PointerHandler};
pub use self::types::area::*;
pub use self::types::cursor::*;
pub use self::types::input_device::*;
pub use self::types::keyboard::*;
pub use self::types::output::*;
<|endoftext|>


<commit_before>#[test]
fn it_works() {
}
<commit_msg>Integer -> Roman<commit_after>static ROMAN: [(&'static str, u32); 13] = [
    ("M",  1000),
    ("CM", 900),
    ("D",  500),
    ("CD", 400),
    ("C",  100),
    ("XC", 90),
    ("L",  50),
    ("XL", 40),
    ("X",  10),
    ("IX", 9),
    ("V",  5),
    ("IV", 4),
    ("I",  1) ];

pub fn to_roman(n: u32) -> Option<String> {
    if n == 0 || n > 10000 { return None }
    let mut out = String::new();
    let mut n = n;
    for i in ROMAN.iter() {
        let (name, value) = *i;
        while n >= value {
            n -= value;
            out.push_str(name);
        }
    }
    assert!(n == 0);
    Some(out)
}

#[test]
fn test_to_roman() {
    assert_eq!(to_roman(1984).unwrap(), "MCMLXXXIV")
}
<|endoftext|>


<commit_before>//! Hash-consing with automated release of unused values

#[macro_use]
extern crate log;

use std::ops::{Deref, Drop};
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::fmt::{self, Debug};
use std::cell::UnsafeCell;

/// Box that encapsulates a value to hash-cons, a reference to the conser,
/// and a reference counter
struct HashConsedBox<T>
    where T: Eq + Hash
{
    value: T,
    conser: HashConser<T>,
    refs: usize,
}

/// Unsafed reference to a hash-consed value
///
/// It is simply a pointer to the hash-consed box that encapsulate the raw value,
/// a reference to the conser and the current number of references.
///
/// **N.B.:** An unsafed hash-consed value:
///
///   * may or may not be in the conser's map,
///
///   * should be `destroy()`-ed manually,
///
///   * does not update automatically the ref count,
///
///   * inherits PartialEq, Eq, and Hash from the raw value.
struct UnsafeRef<T>(*mut UnsafeCell<HashConsedBox<T>>) where T: Eq + Hash;

impl<T> UnsafeRef<T> where T: Eq + Hash {

    /// Make an unsafed reference to a owned hash-consed box
    #[inline]
    fn make(conser: &HashConser<T>, value: T) -> Self {
        UnsafeRef(Box::into_raw(Box::new(UnsafeCell::new(HashConsedBox {
            value: value,
            conser: conser.clone(),
            refs: 0,
        }))))
    }

    /// Destroy (drop) the underlying hash-consed box
    #[inline]
    fn destroy(&self) {
        drop(unsafe { Box::from_raw(self.0) });
    }

    /// Get pointer to conser
    #[inline]
    fn conser<'a>(&self) -> &'a mut HashConser<T> {
        unsafe { &mut (*self.as_ptr()).conser }
    }

    #[inline]
    fn refs(&self) -> usize {
        unsafe { (*self.as_ptr()).refs }
    }

    #[inline]
    fn inc_refs(&self) {
        let refs = unsafe { &mut (*self.as_ptr()).refs };
        *refs += 1;
    }

    #[inline]
    fn dec_refs(&self) {
        let refs = unsafe { &mut (*self.as_ptr()).refs };
        *refs -= 1;
    }

    #[inline]
    fn value(&self) -> &T {
        unsafe { &(*self.as_ptr()).value }
    }

    #[inline]
    fn as_ptr(&self) -> *mut HashConsedBox<T> {
        unsafe { (*self.0).get() }
    }
}

/// Hash the underlying value
impl<T> Hash for UnsafeRef<T> where T: Eq + Hash {

    #[inline]
    fn hash<H>(&self, h: &mut H)
        where H: Hasher
    {
        self.value().hash(h);
    }

}

/// Compare the underlying values
impl<T> PartialEq<UnsafeRef<T>> for UnsafeRef<T> where T: Eq + Hash {

    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.value() == other.value()
    }

}

impl<T> Eq for UnsafeRef<T> where T: Eq + Hash {
}

/// Clone a new reference to the hash-consed value
impl<T> Clone for UnsafeRef<T> where T: Eq + Hash {

    #[inline]
    fn clone(&self) -> Self {
        UnsafeRef(self.0)
    }

}

impl<T> Copy for UnsafeRef<T> where T: Eq + Hash {}

/// Reference to a hash-consed value.
///
/// Built through a `HashConser`, it points to a single copy of the raw value existing in the
/// `HashConser`.
///
/// Uses fast pointer equality and hash.
pub struct HashConsed<T>(UnsafeRef<T>) where T: Eq + Hash;

impl<T> HashConsed<T> where T: Eq + Hash {

    /// Wrap an unsafe reference
    fn from_unsafe(u: &UnsafeRef<T>) -> Self {
        u.inc_refs();
        debug!("new ref {:p} ({} ref total)", u.value(), u.refs());
        HashConsed(*u)
    }

    /// Get parent conser
    pub fn conser(this: &Self) -> &HashConser<T> {
        this.0.conser()
    }
}

/// Get reference to the raw value
impl<T> Deref for HashConsed<T> where T: Eq + Hash {

    type Target = T;

    fn deref(&self) -> &T {
        return self.0.value();
    }

}

/// Fast hash (pointer-based)
///
/// Beware that it does not make any sense if the compared values where built through different
/// `HashConser`.
impl<T> Hash for HashConsed<T> where T: Eq + Hash {

    fn hash<H>(&self, h: &mut H)
        where H: Hasher
    {
        self.0.as_ptr().hash(h);
    }

}

/// Fast comparison (pointer-based)
///
/// Beware that it does not make any sense if the compared values where built through different
/// `HashConser`
impl<T> PartialEq<HashConsed<T>> for HashConsed<T> where T: Eq + Hash {

    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.0.as_ptr() == other.0.as_ptr()
    }

}

impl<T> Eq for HashConsed<T> where T: Eq + Hash {}

impl<T> Drop for HashConsed<T> where T: Eq + Hash {

    fn drop(&mut self) {
        self.0.dec_refs();
        debug!("del ref {:p} ({} refs remaining)",
               self.0.value(),
               self.0.refs());
        if self.0.refs() == 0 {
            debug!("del val {:p}", self.0.value());
            self.0.conser().remove(&self.0);
            self.0.destroy();
        }
    }

}

impl<T> Debug for HashConsed<T> where T: Eq + Hash + Debug {

    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self.0.value(), fmt)
    }

}

/// Get a new reference to this hash-consed value.
impl<T> Clone for HashConsed<T> where T: Eq + Hash {
    fn clone(&self) -> Self {
        self.0.inc_refs();
        debug!("new ref {:p} (clone, {} refs total)",
               self.0.value(),
               self.0.refs());
        HashConsed(self.0)
    }
}

type HM<T> where T: Eq + Hash = HashMap<UnsafeRef<T>, UnsafeRef<T>>;

struct HashConserBox<T> where T: Eq + Hash {
    map: HM<T>,
    refs: usize,
}

/// Hash-conser, i.e. hash-consed value factory and cache.
pub struct HashConser<T>(*mut UnsafeCell<HashConserBox<T>>) where T: Eq + Hash;

impl<T> HashConser<T> where T: Eq + Hash {

    /// Create a hash-conser.
    pub fn new() -> Self {
        HashConser(Box::into_raw(Box::new(UnsafeCell::new(HashConserBox {
            map: HashMap::new(),
            refs: 1,
        }))))
    }

    #[inline]
    fn map(&self) -> &mut HM<T> {
        unsafe { &mut (*(*self.0).get()).map }
    }

    #[inline]
    fn refs(&self) -> usize {
        unsafe { (*(*self.0).get()).refs }
    }

    #[inline]
    fn inc_refs(&self) {
        unsafe {
            let box_ptr = (*self.0).get();
            (*box_ptr).refs += 1;
        }
    }

    #[inline]
    fn dec_refs(&self) {
        unsafe {
            let box_ptr = (*self.0).get();
            (*box_ptr).refs -= 1;
        }
    }

    /// Make a hash-consed value from an unwrapped value
    pub fn make(&mut self, obj: T) -> HashConsed<T> {
        debug!("h-cons  {:p} in {:p}", &obj, self);
        let input = UnsafeRef::make(self, obj);
        let map = self.map();
        let safe = match map.get(&input) {
            Some(output) => {
                debug!("recycle {:p} (already {} refs)",
                       output.value(),
                       output.refs());
                input.destroy();
                HashConsed::from_unsafe(output)
            }
            None => {
                debug!("new val {:p} in {:p}", input.value(), self);
                self.map().insert(input.clone(), input);
                HashConsed::from_unsafe(&input)
            }
        };
        debug!("/h-cons");
        safe
    }

    #[inline]
    fn remove(&mut self, hc: &UnsafeRef<T>) {
        self.map().remove(hc);
    }

}

impl<T> Clone for HashConser<T> where T: Eq + Hash {

    #[inline]
    fn clone(&self) -> Self {
        self.inc_refs();
        HashConser(self.0)
    }

}

impl<T> Drop for HashConser<T> where T: Eq + Hash {

    fn drop(&mut self) {
        self.dec_refs();
        debug!("del ref HashConser({:p}) ({} refs remaining)",
               self.0,
               self.refs());
        if self.refs() == 0 {
            assert!(self.map().len() == 0);
            debug!("del val HashConser({:p})", self.0);
            let b = unsafe { Box::from_raw(self.0) };
            drop(b);
        }
    }

}

impl<T> Debug for HashConser<T> where T: Eq + Hash + Debug {

    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(fmt.write_str("{"));
        for (i, k) in self.map().keys().enumerate() {
            if i != 0 {
                try!(fmt.write_str(", "));
            }
            try!(write!(fmt, "{:?} ({})", k.value(), k.refs()));
        }
        fmt.write_str("}")
    }

}

#[test]
fn it_works() {}
<commit_msg>Add test for equality<commit_after>//! Hash-consing with automated release of unused values

#[macro_use]
extern crate log;

use std::ops::{Deref, Drop};
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::fmt::{self, Debug};
use std::cell::UnsafeCell;

/// Box that encapsulates a value to hash-cons, a reference to the conser,
/// and a reference counter
struct HashConsedBox<T>
    where T: Eq + Hash
{
    value: T,
    conser: HashConser<T>,
    refs: usize,
}

/// Unsafed reference to a hash-consed value
///
/// It is simply a pointer to the hash-consed box that encapsulate the raw value,
/// a reference to the conser and the current number of references.
///
/// **N.B.:** An unsafed hash-consed value:
///
///   * may or may not be in the conser's map,
///
///   * should be `destroy()`-ed manually,
///
///   * does not update automatically the ref count,
///
///   * inherits PartialEq, Eq, and Hash from the raw value.
struct UnsafeRef<T>(*mut UnsafeCell<HashConsedBox<T>>) where T: Eq + Hash;

impl<T> UnsafeRef<T> where T: Eq + Hash {

    /// Make an unsafed reference to a owned hash-consed box
    #[inline]
    fn make(conser: &HashConser<T>, value: T) -> Self {
        UnsafeRef(Box::into_raw(Box::new(UnsafeCell::new(HashConsedBox {
            value: value,
            conser: conser.clone(),
            refs: 0,
        }))))
    }

    /// Destroy (drop) the underlying hash-consed box
    #[inline]
    fn destroy(&self) {
        drop(unsafe { Box::from_raw(self.0) });
    }

    /// Get pointer to conser
    #[inline]
    fn conser<'a>(&self) -> &'a mut HashConser<T> {
        unsafe { &mut (*self.as_ptr()).conser }
    }

    #[inline]
    fn refs(&self) -> usize {
        unsafe { (*self.as_ptr()).refs }
    }

    #[inline]
    fn inc_refs(&self) {
        let refs = unsafe { &mut (*self.as_ptr()).refs };
        *refs += 1;
    }

    #[inline]
    fn dec_refs(&self) {
        let refs = unsafe { &mut (*self.as_ptr()).refs };
        *refs -= 1;
    }

    #[inline]
    fn value(&self) -> &T {
        unsafe { &(*self.as_ptr()).value }
    }

    #[inline]
    fn as_ptr(&self) -> *mut HashConsedBox<T> {
        unsafe { (*self.0).get() }
    }
}

/// Hash the underlying value
impl<T> Hash for UnsafeRef<T> where T: Eq + Hash {

    #[inline]
    fn hash<H>(&self, h: &mut H)
        where H: Hasher
    {
        self.value().hash(h);
    }

}

/// Compare the underlying values
impl<T> PartialEq<UnsafeRef<T>> for UnsafeRef<T> where T: Eq + Hash {

    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.value() == other.value()
    }

}

impl<T> Eq for UnsafeRef<T> where T: Eq + Hash {
}

/// Clone a new reference to the hash-consed value
impl<T> Clone for UnsafeRef<T> where T: Eq + Hash {

    #[inline]
    fn clone(&self) -> Self {
        UnsafeRef(self.0)
    }

}

impl<T> Copy for UnsafeRef<T> where T: Eq + Hash {}

/// Reference to a hash-consed value.
///
/// Built through a `HashConser`, it points to a single copy of the raw value existing in the
/// `HashConser`.
///
/// Uses fast pointer equality and hash.
pub struct HashConsed<T>(UnsafeRef<T>) where T: Eq + Hash;

impl<T> HashConsed<T> where T: Eq + Hash {

    /// Wrap an unsafe reference
    fn from_unsafe(u: &UnsafeRef<T>) -> Self {
        u.inc_refs();
        debug!("new ref {:p} ({} ref total)", u.value(), u.refs());
        HashConsed(*u)
    }

    /// Get parent conser
    pub fn conser(this: &Self) -> &HashConser<T> {
        this.0.conser()
    }
}

/// Get reference to the raw value
impl<T> Deref for HashConsed<T> where T: Eq + Hash {

    type Target = T;

    fn deref(&self) -> &T {
        return self.0.value();
    }

}

/// Fast hash (pointer-based)
///
/// Beware that it does not make any sense if the compared values where built through different
/// `HashConser`.
impl<T> Hash for HashConsed<T> where T: Eq + Hash {

    fn hash<H>(&self, h: &mut H)
        where H: Hasher
    {
        self.0.as_ptr().hash(h);
    }

}

/// Fast comparison (pointer-based)
///
/// Beware that it does not make any sense if the compared values where built through different
/// `HashConser`
impl<T> PartialEq<HashConsed<T>> for HashConsed<T> where T: Eq + Hash {

    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.0.as_ptr() == other.0.as_ptr()
    }

}

impl<T> Eq for HashConsed<T> where T: Eq + Hash {}

impl<T> Drop for HashConsed<T> where T: Eq + Hash {

    fn drop(&mut self) {
        self.0.dec_refs();
        debug!("del ref {:p} ({} refs remaining)",
               self.0.value(),
               self.0.refs());
        if self.0.refs() == 0 {
            debug!("del val {:p}", self.0.value());
            self.0.conser().remove(&self.0);
            self.0.destroy();
        }
    }

}

impl<T> Debug for HashConsed<T> where T: Eq + Hash + Debug {

    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self.0.value(), fmt)
    }

}

/// Get a new reference to this hash-consed value.
impl<T> Clone for HashConsed<T> where T: Eq + Hash {
    fn clone(&self) -> Self {
        self.0.inc_refs();
        debug!("new ref {:p} (clone, {} refs total)",
               self.0.value(),
               self.0.refs());
        HashConsed(self.0)
    }
}

type HM<T> where T: Eq + Hash = HashMap<UnsafeRef<T>, UnsafeRef<T>>;

struct HashConserBox<T> where T: Eq + Hash {
    map: HM<T>,
    refs: usize,
}

/// Hash-conser, i.e. hash-consed value factory and cache.
pub struct HashConser<T>(*mut UnsafeCell<HashConserBox<T>>) where T: Eq + Hash;

impl<T> HashConser<T> where T: Eq + Hash {

    /// Create a hash-conser.
    pub fn new() -> Self {
        HashConser(Box::into_raw(Box::new(UnsafeCell::new(HashConserBox {
            map: HashMap::new(),
            refs: 1,
        }))))
    }

    #[inline]
    fn map(&self) -> &mut HM<T> {
        unsafe { &mut (*(*self.0).get()).map }
    }

    #[inline]
    fn refs(&self) -> usize {
        unsafe { (*(*self.0).get()).refs }
    }

    #[inline]
    fn inc_refs(&self) {
        unsafe {
            let box_ptr = (*self.0).get();
            (*box_ptr).refs += 1;
        }
    }

    #[inline]
    fn dec_refs(&self) {
        unsafe {
            let box_ptr = (*self.0).get();
            (*box_ptr).refs -= 1;
        }
    }

    /// Make a hash-consed value from an unwrapped value
    pub fn make(&mut self, obj: T) -> HashConsed<T> {
        debug!("h-cons  {:p} in {:p}", &obj, self);
        let input = UnsafeRef::make(self, obj);
        let map = self.map();
        let safe = match map.get(&input) {
            Some(output) => {
                debug!("recycle {:p} (already {} refs)",
                       output.value(),
                       output.refs());
                input.destroy();
                HashConsed::from_unsafe(output)
            }
            None => {
                debug!("new val {:p} in {:p}", input.value(), self);
                self.map().insert(input.clone(), input);
                HashConsed::from_unsafe(&input)
            }
        };
        debug!("/h-cons");
        safe
    }

    #[inline]
    fn remove(&mut self, hc: &UnsafeRef<T>) {
        self.map().remove(hc);
    }

}

impl<T> Clone for HashConser<T> where T: Eq + Hash {

    #[inline]
    fn clone(&self) -> Self {
        self.inc_refs();
        HashConser(self.0)
    }

}

impl<T> Drop for HashConser<T> where T: Eq + Hash {

    fn drop(&mut self) {
        self.dec_refs();
        debug!("del ref HashConser({:p}) ({} refs remaining)",
               self.0,
               self.refs());
        if self.refs() == 0 {
            assert!(self.map().len() == 0);
            debug!("del val HashConser({:p})", self.0);
            let b = unsafe { Box::from_raw(self.0) };
            drop(b);
        }
    }

}

impl<T> Debug for HashConser<T> where T: Eq + Hash + Debug {

    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(fmt.write_str("{"));
        for (i, k) in self.map().keys().enumerate() {
            if i != 0 {
                try!(fmt.write_str(", "));
            }
            try!(write!(fmt, "{:?} ({})", k.value(), k.refs()));
        }
        fmt.write_str("}")
    }

}

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

    #[derive(Debug,PartialEq,Eq,Hash)]
    struct Pair(u8, u8);
    type HCPair = HashConsed<Pair>;

    #[test]
    fn test_equality() {
        let mut conser = HashConser::new();
        let a: HCPair = conser.make(Pair(0,1));
        let b: HCPair = conser.make(Pair(0,1));
        assert_eq!(a, b);
        assert_eq!(&*a as *const Pair, &*b as *const Pair);
    }

}
<|endoftext|>


<commit_before>//! Crate retry provides functionality for retrying an operation until its return value satisfies a
//! specific condition.
//!
//! # Usage
//!
//! Create a retryable operation by passing two mutable closure references to `Retry::new`. The
//! first argument, `value_fn`, will be executed to produce a value. The second argument,
//! `condition_fn`, takes the value produced by `value_fn` and returns a boolean indicating whether
//! or not some desired condition is true. Call `execute` on the returned `Retry` object to begin
//! executing the operation, ultimately returning a `Result` containing the final value or an
//! error.
//!
//! By default, the operation will be retried an infinite number of times with no delay between
//! tries. To change either of these values, you may call the following two methods on the `Retry`
//! object:
//!
//! 1. `try`: The maximum number of tries to make.  If the operation reaches this number of tries
//!    without passsing the condition, an error will be returned.
//! 2. `wait` The number of milliseconds to wait after each unsuccessful try.
//!
//! # Failures
//!
//! Executing a `Retry` will fail when:
//!
//! 1. The operation reaches the maximum number of tries without success.
//! 2. A value of 0 is supplied to `try`. It must be at least 1.
//!
//! # Examples
//!
//! Imagine an HTTP API with an endpoint that returns 204 No Content while a job is processing, and
//! eventually 200 OK when the job has completed. Retrying until the job is finished would be
//! written:
//!
//! ```
//! # use retry::Retry;
//! # struct Client;
//! # impl Client {
//! #     fn query_job_status(&self) -> Response {
//! #         Response {
//! #             code: 200,
//! #             body: "success",
//! #         }
//! #     }
//! # }
//! # struct Response {
//! #     code: u16,
//! #     body: &'static str,
//! # }
//! # let api_client = Client;
//! match Retry::new(
//!     &mut || api_client.query_job_status(),
//!     &mut |response| response.code == 200
//! ).try(10).wait(500).execute() {
//!     Ok(response) => println!("Job completed with result: {}", response.body),
//!     Err(error) => println!("Job completion could not be verified: {}", error),
//! }
//! ```
//!
//! This retries the API call up to 10 times, waiting 500 milliseconds after each unsuccessful
//! attempt.

use std::error::Error;
use std::fmt::{Display,Formatter};
use std::fmt::Error as FmtError;
use std::thread::sleep_ms;

/// Builder object for a retryable operation.
#[derive(Debug)]
pub struct Retry<'a, F: FnMut() -> R + 'a, G: FnMut(&R) -> bool + 'a, R> {
    condition_fn: &'a mut G,
    tries: Option<u32>,
    value_fn: &'a mut F,
    wait: u32,
}

impl<'a, F: FnMut() -> R, G: FnMut(&R) -> bool, R> Retry<'a, F, G, R> {
    /// Build a new `Retry` object.
    pub fn new(
        value_fn: &'a mut F,
        condition_fn: &'a mut G
    ) -> Retry<'a, F, G, R> where F: FnMut() -> R, G: FnMut(&R) -> bool {
        Retry {
            condition_fn: condition_fn,
            tries: None,
            value_fn: value_fn,
            wait: 0,
        }
    }

    /// Begin executing the retryable operation.
    pub fn execute(self) -> Result<R, RetryError> {
        if self.tries.is_some() && self.tries.unwrap() == 0 {
            return Err(RetryError { message: "tries must be non-zero" });
        }

        match self.tries {
            Some(tries) => {
                for _ in 0..tries {
                    let value = (self.value_fn)();

                    if (self.condition_fn)(&value) {
                        return Ok(value);
                    }

                    sleep_ms(self.wait);
                }

                Err(RetryError { message: "reached last try without condition match" })
            },
            None => {
                loop {
                    let value = (self.value_fn)();

                    if (self.condition_fn)(&value) {
                        return Ok(value);
                    }

                    sleep_ms(self.wait);
                }
            }
        }
    }

    /// Set a maximum number of tries to make before failing.
    pub fn try(mut self, tries: u32) -> Retry<'a, F, G, R> {
        self.tries = Some(tries);

        self
    }

    /// Set the number of milliseconds to wait after an unsuccesful try before trying again.
    pub fn wait(mut self, wait: u32) -> Retry<'a, F, G, R> {
        self.wait = wait;

        self
    }
}

/// An error indicating that a retry call failed.
#[derive(Debug)]
pub struct RetryError {
    message: &'static str
}

impl Display for RetryError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> {
        write!(formatter, "{}", self.message)
    }
}

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

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

    #[test]
    fn succeeds_without_try_count() {
        let mut collection = vec![1, 2, 3, 4, 5].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 5
        ).execute().unwrap();

        assert_eq!(value, 5);
    }

    #[test]
    fn succeeds_on_first_try() {
        let value = Retry::new(&mut || 1, &mut |value| *value == 1).try(1).execute().ok().unwrap();

        assert_eq!(value, 1);
    }

    #[test]
    fn requires_non_zero_tries() {
        let error = Retry::new(&mut || 1, &mut |value| *value == 1).try(0).execute().err().unwrap();

        assert_eq!(error.message, "tries must be non-zero");
    }

    #[test]
    fn succeeds_on_subsequent_try() {
        let mut collection = vec![1, 2].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(2).execute().ok().unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn fails_after_last_try() {
        let mut collection = vec![1].into_iter();

        let error = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(1).execute().err().unwrap();

        assert_eq!(error.message, "reached last try without condition match");
    }

    #[test]
    fn sets_custom_wait_time() {
        let mut collection = vec![1, 2].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(2).wait(1).execute().ok().unwrap();

        assert_eq!(value, 2);
    }
}
<commit_msg>Reduce duplication in execute.<commit_after>//! Crate retry provides functionality for retrying an operation until its return value satisfies a
//! specific condition.
//!
//! # Usage
//!
//! Create a retryable operation by passing two mutable closure references to `Retry::new`. The
//! first argument, `value_fn`, will be executed to produce a value. The second argument,
//! `condition_fn`, takes the value produced by `value_fn` and returns a boolean indicating whether
//! or not some desired condition is true. Call `execute` on the returned `Retry` object to begin
//! executing the operation, ultimately returning a `Result` containing the final value or an
//! error.
//!
//! By default, the operation will be retried an infinite number of times with no delay between
//! tries. To change either of these values, you may call the following two methods on the `Retry`
//! object:
//!
//! 1. `try`: The maximum number of tries to make.  If the operation reaches this number of tries
//!    without passsing the condition, an error will be returned.
//! 2. `wait` The number of milliseconds to wait after each unsuccessful try.
//!
//! # Failures
//!
//! Executing a `Retry` will fail when:
//!
//! 1. The operation reaches the maximum number of tries without success.
//! 2. A value of 0 is supplied to `try`. It must be at least 1.
//!
//! # Examples
//!
//! Imagine an HTTP API with an endpoint that returns 204 No Content while a job is processing, and
//! eventually 200 OK when the job has completed. Retrying until the job is finished would be
//! written:
//!
//! ```
//! # use retry::Retry;
//! # struct Client;
//! # impl Client {
//! #     fn query_job_status(&self) -> Response {
//! #         Response {
//! #             code: 200,
//! #             body: "success",
//! #         }
//! #     }
//! # }
//! # struct Response {
//! #     code: u16,
//! #     body: &'static str,
//! # }
//! # let api_client = Client;
//! match Retry::new(
//!     &mut || api_client.query_job_status(),
//!     &mut |response| response.code == 200
//! ).try(10).wait(500).execute() {
//!     Ok(response) => println!("Job completed with result: {}", response.body),
//!     Err(error) => println!("Job completion could not be verified: {}", error),
//! }
//! ```
//!
//! This retries the API call up to 10 times, waiting 500 milliseconds after each unsuccessful
//! attempt.

use std::error::Error;
use std::fmt::{Display,Formatter};
use std::fmt::Error as FmtError;
use std::thread::sleep_ms;

/// Builder object for a retryable operation.
#[derive(Debug)]
pub struct Retry<'a, F: FnMut() -> R + 'a, G: FnMut(&R) -> bool + 'a, R> {
    condition_fn: &'a mut G,
    tries: Option<u32>,
    value_fn: &'a mut F,
    wait: u32,
}

impl<'a, F: FnMut() -> R, G: FnMut(&R) -> bool, R> Retry<'a, F, G, R> {
    /// Build a new `Retry` object.
    pub fn new(
        value_fn: &'a mut F,
        condition_fn: &'a mut G
    ) -> Retry<'a, F, G, R> where F: FnMut() -> R, G: FnMut(&R) -> bool {
        Retry {
            condition_fn: condition_fn,
            tries: None,
            value_fn: value_fn,
            wait: 0,
        }
    }

    /// Begin executing the retryable operation.
    pub fn execute(self) -> Result<R, RetryError> {
        if self.tries.is_some() && self.tries.unwrap() == 0 {
            return Err(RetryError { message: "tries must be non-zero" });
        }

        let mut try = 0;

        loop {
            if self.tries.is_some() && self.tries.unwrap() == try {
                return Err(RetryError { message: "reached last try without condition match" })
            }

            let value = (self.value_fn)();

            if (self.condition_fn)(&value) {
                return Ok(value);
            }

            sleep_ms(self.wait);
            try += 1;
        }
    }

    /// Set a maximum number of tries to make before failing.
    pub fn try(mut self, tries: u32) -> Retry<'a, F, G, R> {
        self.tries = Some(tries);

        self
    }

    /// Set the number of milliseconds to wait after an unsuccesful try before trying again.
    pub fn wait(mut self, wait: u32) -> Retry<'a, F, G, R> {
        self.wait = wait;

        self
    }
}

/// An error indicating that a retry call failed.
#[derive(Debug)]
pub struct RetryError {
    message: &'static str
}

impl Display for RetryError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> {
        write!(formatter, "{}", self.message)
    }
}

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

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

    #[test]
    fn succeeds_without_try_count() {
        let mut collection = vec![1, 2, 3, 4, 5].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 5
        ).execute().unwrap();

        assert_eq!(value, 5);
    }

    #[test]
    fn succeeds_on_first_try() {
        let value = Retry::new(&mut || 1, &mut |value| *value == 1).try(1).execute().ok().unwrap();

        assert_eq!(value, 1);
    }

    #[test]
    fn requires_non_zero_tries() {
        let error = Retry::new(&mut || 1, &mut |value| *value == 1).try(0).execute().err().unwrap();

        assert_eq!(error.message, "tries must be non-zero");
    }

    #[test]
    fn succeeds_on_subsequent_try() {
        let mut collection = vec![1, 2].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(2).execute().ok().unwrap();

        assert_eq!(value, 2);
    }

    #[test]
    fn fails_after_last_try() {
        let mut collection = vec![1].into_iter();

        let error = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(1).execute().err().unwrap();

        assert_eq!(error.message, "reached last try without condition match");
    }

    #[test]
    fn sets_custom_wait_time() {
        let mut collection = vec![1, 2].into_iter();

        let value = Retry::new(
            &mut || collection.next().unwrap(),
            &mut |value| *value == 2
        ).try(2).wait(1).execute().ok().unwrap();

        assert_eq!(value, 2);
    }
}
<|endoftext|>


<commit_before>#![no_std]

extern crate num;

mod create;
pub use create::*;

mod set;
pub use set::*;

mod add;
pub use add::*;

mod sub;
pub use sub::*;

mod mul;
pub use mul::*;

mod div;
pub use div::*;

mod length;
pub use length::*;

mod misc;
pub use misc::*;

mod transform;
pub use transform::*;
<commit_msg>pub mod bug fix<commit_after>#![no_std]

extern crate num;

pub mod create;
pub use create::*;

pub mod set;
pub use set::*;

pub mod add;
pub use add::*;

pub mod sub;
pub use sub::*;

pub mod mul;
pub use mul::*;

pub mod div;
pub use div::*;

pub mod length;
pub use length::*;

pub mod misc;
pub use misc::*;

pub mod transform;
pub use transform::*;
<|endoftext|>


<commit_before>use anyhow::Result;
use bytes::Bytes;
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::Arc;
use std::time::Duration;
use tide::Request;

use async_std::sync::{channel, Receiver, Sender};
use futures::sink::SinkExt;
use futures::stream::StreamExt;
use tungstenite::Message;

use async_std::task;

#[derive(Clone, Copy)]
#[repr(u8)]
enum SystemCommand {
    WakeUp = 1,
    Disconnect = 2,
}

#[derive(Clone)]
enum ReceiverType {
    System,
    Hypercore,
}

#[derive(Clone)]
struct State {
    system_commands: Receiver<Bytes>,
    writers: HashMap<String, Sender<Bytes>>,
    readers: HashMap<String, Receiver<Bytes>>,
}

#[derive(Clone)]
struct WrappedData {
    data: Bytes,
    receiver_type: ReceiverType,
    id: Option<String>,
}

type WrappedDataClosure = Box<dyn Fn(Bytes) -> WrappedData + Send + Sync>;

async fn async_main(initial_state: State) -> Result<()> {
    let mut app = tide::with_state(initial_state);

    app.at("/ws").get(|req: Request<State>| async move {
        tide::websocket::upgrade(req, |_req, handle| async move {
            // https://docs.rs/async-tungstenite/0.10.0/async_tungstenite/struct.WebSocketStream.html
            let mut ws = handle.into_inner();
            // Handshake the inner protocol
            let init_msg: Arc<String> = Arc::new(ws.next().await.unwrap().unwrap().to_string());

            let system_commands =
                _req.state()
                    .system_commands
                    .clone()
                    .map(Box::new(|data| WrappedData {
                        data,
                        receiver_type: ReceiverType::System,
                        id: None,
                    }) as WrappedDataClosure);
            dbg!(&init_msg);
            let writer = _req.state().writers[&*init_msg].clone();
            let reader = _req.state().readers[&*init_msg]
                .clone()
                .map(Box::new(move |data| WrappedData {
                    data,
                    receiver_type: ReceiverType::System,
                    id: Some((&*init_msg).to_string()),
                }) as WrappedDataClosure);
            ws.send(Message::Text("reply-to-init".to_string()))
                .await
                .unwrap();

            let streams = vec![system_commands, reader];

            // Start polling
            //
            // Use https://docs.rs/futures/0.3.7/futures/stream/fn.select_all.html
            // to merge many streams.
            futures::stream::select_all(streams).next().await.unwrap();
            let msg = ws.next().await.unwrap().unwrap();
            dbg!(&msg);
            ws.send(msg).await.unwrap();

            loop {
                let msg = Arc::new(ws.next().await.unwrap().unwrap());
                dbg!(&msg);
                // Send somehow!
                // writer.send(Bytes::from_static(&msg.into_data())).await;
            }
        })
    });

    app.listen("0.0.0.0:8080").await?;
    Ok(())
}

fn main() -> Result<()> {
    fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d %H:%M:%S]"),
                record.target(),
                record.level(),
                message
            ))
        })
        .level(log::LevelFilter::Debug)
        .chain(std::io::stdout())
        .apply()?;
    let (ping_sender, system_command_receiver) = channel(1000);
    let (demo_sender, demo_receiver) = channel(1000);
    let initial_state = State {
        system_commands: system_command_receiver,
        writers: [("demo".to_string(), demo_sender)]
            .iter()
            .cloned()
            .collect(),
        readers: [("demo".to_string(), demo_receiver)]
            .iter()
            .cloned()
            .collect(),
    };

    // TODO: This should be used on SIGINT/SIGTERM
    let disconnect_sender = ping_sender.clone();

    // Need to start a system executor to send the WakeUp command, we send it once per 5 seconds so
    // that the listener will send a WS Ping every 30 to 35 seconds.
    task::spawn(async move {
        loop {
            task::sleep(Duration::from_millis(5000)).await;
            dbg!("Sending WakeUp");
            ping_sender
                .send(Bytes::from_static(&[SystemCommand::WakeUp as u8]))
                .await;
        }
    });

    futures::executor::block_on(async_main(initial_state))?;

    Ok(())
}
<commit_msg>A compiling version of using streams<commit_after>use anyhow::Result;
use bytes::Bytes;
use std::collections::HashMap;
use std::time::Duration;
use tide::Request;

use async_std::sync::{channel, Arc, Receiver, Sender};
use futures::sink::SinkExt;
use futures::stream::StreamExt;
// use futures_util::stream::StreamExt as UtilsStreamExt;
use tungstenite::Message;

use async_std::task;

#[derive(Clone, Copy)]
#[repr(u8)]
enum SystemCommand {
    WakeUp = 1,
    Disconnect = 2,
}

#[derive(Clone, Debug)]
enum ReceiverType {
    System,
    Hypercore,
    Client,
}

#[derive(Clone)]
struct State {
    system_commands: Receiver<Bytes>,
    writers: HashMap<String, Sender<Bytes>>,
    readers: HashMap<String, Receiver<Bytes>>,
}

#[derive(Clone)]
struct WrappedData {
    data: Bytes,
    receiver_type: ReceiverType,
    id: Option<String>,
}

type WrappedBytesClosure = Box<dyn Fn(Bytes) -> WrappedData + Send + Sync>;
// type WrappedWebSocketClosure =
//     Box<dyn Fn(Result<tungstenite::Message, std::io::Error>) -> WrappedData + Send + Sync>;

async fn async_main(initial_state: State) -> Result<()> {
    let mut app = tide::with_state(initial_state);

    app.at("/ws").get(|req: Request<State>| async move {
        tide::websocket::upgrade(req, |_req, handle| async move {
            // https://docs.rs/async-tungstenite/0.10.0/async_tungstenite/struct.WebSocketStream.html
            let (mut ws_writer, mut ws_reader) = handle.into_inner().split();
            // Handshake the inner protocol
            // let init_msg: Arc<String> =
            //     Arc::new(ws_reader.next().await.unwrap().unwrap().to_string());

            let init_msg: String = ws_reader.next().await.unwrap().unwrap().to_string();

            // let system_command_reader =
            //     _req.state()
            //         .system_commands
            //         .clone()
            //         .map(Box::new(|data| WrappedData {
            //             data,
            //             receiver_type: ReceiverType::System,
            //             id: None,
            //         }) as WrappedBytesClosure);
            // let system_command_reader = ;
            dbg!(&init_msg);
            let hypercore_writer = _req.state().writers[&*init_msg].clone();
            // let reader = _req.state().readers[&*init_msg]
            //     .clone()
            //     .map(Box::new(move |data| WrappedData {
            //         data,
            //         receiver_type: ReceiverType::System,
            //         id: Some((&*init_msg).to_string()),
            //     }) as WrappedBytesClosure);
            ws_writer
                .send(Message::Text("reply-to-init".to_string()))
                .await
                .unwrap();

            // use futures::future::Either;
            // let client_reader_writer =
            //     ws.get_ref()
            //         .clone()
            //         .map(
            //             Box::new(move |_msg: Result<tungstenite::Message, _>| WrappedData {
            //                 data: Bytes::from(_msg.ok().unwrap().into_data()),
            //                 receiver_type: ReceiverType::Client,
            //                 id: None,
            //             }) as WrappedWebSocketClosure,
            //         );

            // let streams: Vec<
            //     Either<
            //         futures::stream::Map<
            //             async_std::sync::Receiver<bytes::Bytes>,
            //             std::boxed::Box<
            //                 dyn std::ops::Fn(bytes::Bytes) -> WrappedData
            //                     + std::marker::Send
            //                     + std::marker::Sync,
            //             >,
            //         >,
            //         futures::stream::Map<
            //             async_std::sync::Receiver<bytes::Bytes>,
            //             std::boxed::Box<
            //                 dyn std::ops::Fn(bytes::Bytes) -> WrappedData
            //                     + std::marker::Send
            //                     + std::marker::Sync,
            //             >,
            //         >,
            //     >,
            // > = vec![
            //     Either::Left(system_command_reader),
            //     Either::Left(reader),
            //     Either::Right(client_reader_writer),
            // ];
            //
            //
            let (client_sender, client_receiver): (Sender<Bytes>, Receiver<Bytes>) = channel(1000);
            // let client_reader = client_receiver
            //     .clone()
            //     .map(Box::new(move |data| WrappedData {
            //         data,
            //         receiver_type: ReceiverType::Client,
            //         id: None,
            //     }) as WrappedBytesClosure);

            // Start polling
            //
            // Use https://docs.rs/futures/0.3.7/futures/stream/fn.select_all.html
            // to merge many streams.
            //

            task::Builder::new()
                .name(init_msg.clone())
                .spawn(async move {
                    while let Some(wrapped_value) = futures::stream::select_all(vec![
                        _req.state()
                            .system_commands
                            .clone()
                            .map(Box::new(|data| WrappedData {
                                data,
                                receiver_type: ReceiverType::System,
                                id: None,
                            }) as WrappedBytesClosure),
                        _req.state().readers[&String::from(task::current().name().unwrap())]
                            .clone()
                            .map(Box::new(move |data| WrappedData {
                                data,
                                receiver_type: ReceiverType::Hypercore,
                                id: Some(String::from(task::current().name().unwrap())),
                            }) as WrappedBytesClosure), /*, reader, client_reader*/
                        client_receiver
                            .clone()
                            .map(Box::new(move |data| WrappedData {
                                data,
                                receiver_type: ReceiverType::Client,
                                id: None,
                            }) as WrappedBytesClosure),
                    ])
                    .next()
                    .await
                    {
                        dbg!("got value of type {}", wrapped_value.receiver_type);
                        ws_writer
                            .send(tungstenite::Message::Binary(
                                wrapped_value.data.as_ref().to_vec(),
                            ))
                            .await
                            .unwrap();
                        dbg!("got result");
                    }
                })
                .unwrap();

            // let msg = ws.next().await.unwrap().unwrap();
            // dbg!(&msg);
            // ws.send(msg).await.unwrap();
            loop {
                let incoming_msg = ws_reader.next().await;
                let msg = incoming_msg.unwrap().unwrap();
                client_sender.send(Bytes::from(msg.into_data())).await;
            }
        })
    });

    app.listen("0.0.0.0:8080").await?;
    Ok(())
}

fn main() -> Result<()> {
    fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d %H:%M:%S]"),
                record.target(),
                record.level(),
                message
            ))
        })
        .level(log::LevelFilter::Debug)
        .chain(std::io::stdout())
        .apply()?;
    let (ping_sender, system_command_receiver) = channel(1000);
    let (demo_sender, demo_receiver) = channel(1000);
    let initial_state = State {
        system_commands: system_command_receiver,
        writers: [("demo".to_string(), demo_sender)]
            .iter()
            .cloned()
            .collect(),
        readers: [("demo".to_string(), demo_receiver)]
            .iter()
            .cloned()
            .collect(),
    };

    // TODO: This should be used on SIGINT/SIGTERM
    let disconnect_sender = ping_sender.clone();

    // Need to start a system executor to send the WakeUp command, we send it once per 5 seconds so
    // that the listener will send a WS Ping every 30 to 35 seconds.
    task::spawn(async move {
        loop {
            task::sleep(Duration::from_millis(5000)).await;
            dbg!("Sending WakeUp");
            ping_sender
                .send(Bytes::from_static(&[SystemCommand::WakeUp as u8]))
                .await;
        }
    });

    futures::executor::block_on(async_main(initial_state))?;

    Ok(())
}
<|endoftext|>


<commit_before>

use super::{BaseNum, PartialOrd};
use std::ops::{Div, Mul};
use num_traits::Zero;

/// A two-dimensional dimension.
#[derive(Debug,Clone,Copy)]
pub struct Dimension2<T: BaseNum> {
    pub width: T,
    pub height: T,
}

pub type Dimension2f = Dimension2<super::DefaultFloat>;
pub type Dimension2i = Dimension2<super::DefaultInt>;
pub type Dimension2u = Dimension2<super::DefaultUnsigned>;

impl<T: BaseNum> Dimension2<T> {
    pub fn new(width: T, height: T) -> Self {
        Dimension2 {
            width: width,
            height: height,
        }
    }
    /// returns the area of a Dimension<T>
    pub fn area(&self) -> <T as Mul>::Output {
        self.width * self.height
    }
    /// scales the Dimension2 with a scalar
    pub fn scale(&self, scale: T) -> Dimension2<T> {
        Dimension2 {
            width: self.width * scale,
            height: self.height * scale,
        }
    }
    pub fn aspect_ratio(&self) -> <T as Div>::Output {
        assert!(!self.height.is_zero());
        self.width / self.height
    }
    pub fn fitting(&self, other: Dimension2<T>) -> Dimension2<T> {
        let scale = PartialOrd::partial_min(other.width / self.width, other.height / self.height);
        self.scale(scale)

    }
    pub fn filling(&self, other: Dimension2<T>) -> Dimension2<T> {
        let scale = PartialOrd::partial_max(other.width / self.width, other.height / self.height);
        self.scale(scale)
    }
}

#[test]
fn test_area() {
    let test1 = Dimension2 {
        width: 3,
        height: 5,
    };
    let test2 = Dimension2 {
        width: 0,
        height: 0,
    };
    assert_eq!(test2.area(), 0);
    assert_eq!(test1.area(), 15);
}
fn test_scale() {
    let test1 = Dimension2 {
        width: 3,
        height: 5,
    };
    let test2 = Dimension2 {
        width: 12,
        height: 20,
    };
    let scale = 4;
    let scale1 = 0;
    assert_eq!(test1.scale(scale).width, 12);
    assert_eq!(test2.scale(scale1).width, 0);
}
fn test_aspect_ratio() {
    let test1 = Dimension2 {
        width: 3,
        height: 5,
    };
    // let test2 = Dimension2 {
    //     width: 3,
    //     height: 0,
    // };

    assert_eq!(test1.aspect_ratio(), 3 / 5);
}
fn test_fitting() {
    let test1 = Dimension2 {
        width: 2.0,
        height: 1.0,
    };
    let test2 = Dimension2 {
        width: 4.0,
        height: 3.0,
    };
    assert_eq!(test2.fitting(test1).width, 2.0);
    assert_eq!(test2.fitting(test1).height, 1.5);
}
fn test_filling() {
    let test1 = Dimension2 {
        width: 2.0,
        height: 1.0,
    };
    let test2 = Dimension2 {
        width: 4.0,
        height: 3.0,
    };
    assert_eq!(test1.filling(test2).width, 6.0);
    assert_eq!(test1.filling(test2).height, 3.0);
}
<commit_msg>added comments<commit_after>

use super::{BaseNum, PartialOrd};
use std::ops::{Div, Mul};
use num_traits::Zero;

/// A two-dimensional dimension.
#[derive(Debug,Clone,Copy)]
pub struct Dimension2<T: BaseNum> {
    pub width: T,
    pub height: T,
}

pub type Dimension2f = Dimension2<super::DefaultFloat>;
pub type Dimension2i = Dimension2<super::DefaultInt>;
pub type Dimension2u = Dimension2<super::DefaultUnsigned>;

impl<T: BaseNum> Dimension2<T> {
    pub fn new(width: T, height: T) -> Self {
        Dimension2 {
            width: width,
            height: height,
        }
    }
    /// returns the area of a Dimension<T>
    pub fn area(&self) -> <T as Mul>::Output {
        self.width * self.height
    }
    /// scales the Dimension2 with a scalar
    pub fn scale(&self, scale: T) -> Dimension2<T> {
        Dimension2 {
            width: self.width * scale,
            height: self.height * scale,
        }
    }
    /// calculates the aspectratio of a Dimension
    pub fn aspect_ratio(&self) -> <T as Div>::Output {
        assert!(!self.height.is_zero());
        self.width / self.height
    }
    /// Shrinks a dimension until it fits into another dimension
    pub fn fitting(&self, other: Dimension2<T>) -> Dimension2<T> {
        let scale = PartialOrd::partial_min(other.width / self.width, other.height / self.height);
        self.scale(scale)

    }

    /// Expands a dimension until it fills another dimension
    pub fn filling(&self, other: Dimension2<T>) -> Dimension2<T> {
        let scale = PartialOrd::partial_max(other.width / self.width, other.height / self.height);
        self.scale(scale)
    }
}

#[test]
fn test_area() {
    let test1 = Dimension2 {
        width: 3,
        height: 5,
    };
    let test2 = Dimension2 {
        width: 0,
        height: 0,
    };
    assert_eq!(test2.area(), 0);
    assert_eq!(test1.area(), 15);
}
#[test]
fn test_scale() {
    let test1 = Dimension2 {
        width: 3,
        height: 5,
    };
    let test2 = Dimension2 {
        width: 12,
        height: 20,
    };
    let scale = 4;
    let scale1 = 0;
    assert_eq!(test1.scale(scale).width, 12);
    assert_eq!(test2.scale(scale1).width, 0);
}
#[test]
fn test_aspect_ratio() {
    let test1 = Dimension2 {
        width: 3,
        height: 5,
    };
    // let test2 = Dimension2 {
    //     width: 3,
    //     height: 0,
    // };

    assert_eq!(test1.aspect_ratio(), 3 / 5);
}
#[test]
fn test_fitting() {
    let test1 = Dimension2 {
        width: 2.0,
        height: 1.0,
    };
    let test2 = Dimension2 {
        width: 4.0,
        height: 3.0,
    };
    assert_eq!(test2.fitting(test1).width, 2.0);
    assert_eq!(test2.fitting(test1).height, 1.5);
}
#[test]
fn test_filling() {
    let test1 = Dimension2 {
        width: 2.0,
        height: 1.0,
    };
    let test2 = Dimension2 {
        width: 4.0,
        height: 3.0,
    };
    assert_eq!(test1.filling(test2).width, 6.0);
    assert_eq!(test1.filling(test2).height, 3.0);
}
<|endoftext|>


<commit_before>pub use self::net::*;

mod net;

pub type c_char = i8;
pub type c_long = i64;
pub type c_ulong = u64;

pub type wchar_t = i16;

pub type off_t = c_long;
pub type mode_t = u16;
pub type time_t = i64;
pub type pid_t = usize;
pub type gid_t = usize;
pub type uid_t = usize;

pub type suseconds_t = i64;

pub const STDIN_FILENO: ::c_int = 0;
pub const STDOUT_FILENO: ::c_int = 1;
pub const STDERR_FILENO: ::c_int = 2;

pub const EXIT_FAILURE: ::c_int = 1;
pub const EXIT_SUCCESS: ::c_int = 0;

pub const S_ISUID: ::c_int = 0x800;
pub const S_ISGID: ::c_int = 0x400;
pub const S_ISVTX: ::c_int = 0x200;

pub const S_IFIFO: mode_t = 0x1000;
pub const S_IFCHR: mode_t = 0x2000;
pub const S_IFBLK: mode_t = 0x6000;
pub const S_IFDIR: mode_t = 0x4000;
pub const S_IFREG: mode_t = 0x8000;
pub const S_IFLNK: mode_t = 0xA000;
pub const S_IFSOCK: mode_t = 0xC000;
pub const S_IFMT: mode_t = 0xF000;
pub const S_IEXEC: mode_t = 0x40;
pub const S_IWRITE: mode_t = 0x80;
pub const S_IREAD: mode_t = 0x100;
pub const S_IRWXU: mode_t = 0x1C0;
pub const S_IXUSR: mode_t = 0x40;
pub const S_IWUSR: mode_t = 0x80;
pub const S_IRUSR: mode_t = 0x100;
pub const S_IRWXG: mode_t = 0x38;
pub const S_IXGRP: mode_t = 0x8;
pub const S_IWGRP: mode_t = 0x10;
pub const S_IRGRP: mode_t = 0x20;
pub const S_IRWXO: mode_t = 0x7;
pub const S_IXOTH: mode_t = 0x1;
pub const S_IWOTH: mode_t = 0x2;
pub const S_IROTH: mode_t = 0x4;

pub const F_DUPFD: ::c_int = 0;
pub const F_GETFD: ::c_int = 1;
pub const F_SETFD: ::c_int = 2;
pub const F_GETFL: ::c_int = 3;
pub const F_SETFL: ::c_int = 4;

pub const O_RDONLY: ::c_int =     0x0001_0000;
pub const O_WRONLY: ::c_int =     0x0002_0000;
pub const O_RDWR: ::c_int =       0x0003_0000;
pub const O_NONBLOCK: ::c_int =   0x0004_0000;
pub const O_APPEND: ::c_int =     0x0008_0000;
pub const O_SHLOCK: ::c_int =     0x0010_0000;
pub const O_EXLOCK: ::c_int =     0x0020_0000;
pub const O_ASYNC: ::c_int =      0x0040_0000;
pub const O_FSYNC: ::c_int =      0x0080_0000;
pub const O_CLOEXEC: ::c_int =    0x0100_0000;
pub const O_CREAT: ::c_int =      0x0200_0000;
pub const O_TRUNC: ::c_int =      0x0400_0000;
pub const O_EXCL: ::c_int =       0x0800_0000;
pub const O_DIRECTORY: ::c_int =  0x1000_0000;
pub const O_STAT: ::c_int =       0x2000_0000;
pub const O_SYMLINK: ::c_int =    0x4000_0000;
pub const O_NOFOLLOW: ::c_int =   0x8000_0000;
pub const O_ACCMODE: ::c_int =    O_RDONLY | O_WRONLY | O_RDWR;

s! {
    pub struct timeval {
        pub tv_sec: time_t,
        pub tv_usec: suseconds_t,
    }

    pub struct timespec {
        pub tv_sec: time_t,
        pub tv_nsec: c_long,
    }
}

extern {
    pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
    pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t)
                -> ::ssize_t;
    pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t)
                 -> ::ssize_t;
    pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int;
    pub fn close(fd: ::c_int) -> ::c_int;
}

#[link(name = "c")]
#[link(name = "m")]
extern {}
<commit_msg>Fix style<commit_after>pub type c_char = i8;
pub type c_long = i64;
pub type c_ulong = u64;

pub type wchar_t = i16;

pub type off_t = c_long;
pub type mode_t = u16;
pub type time_t = i64;
pub type pid_t = usize;
pub type gid_t = usize;
pub type uid_t = usize;

pub type suseconds_t = i64;

s! {
    pub struct timeval {
        pub tv_sec: time_t,
        pub tv_usec: suseconds_t,
    }

    pub struct timespec {
        pub tv_sec: time_t,
        pub tv_nsec: c_long,
    }
}

pub const STDIN_FILENO: ::c_int = 0;
pub const STDOUT_FILENO: ::c_int = 1;
pub const STDERR_FILENO: ::c_int = 2;

pub const EXIT_FAILURE: ::c_int = 1;
pub const EXIT_SUCCESS: ::c_int = 0;

pub const S_ISUID: ::c_int = 0x800;
pub const S_ISGID: ::c_int = 0x400;
pub const S_ISVTX: ::c_int = 0x200;

pub const S_IFIFO: mode_t = 0x1000;
pub const S_IFCHR: mode_t = 0x2000;
pub const S_IFBLK: mode_t = 0x6000;
pub const S_IFDIR: mode_t = 0x4000;
pub const S_IFREG: mode_t = 0x8000;
pub const S_IFLNK: mode_t = 0xA000;
pub const S_IFSOCK: mode_t = 0xC000;
pub const S_IFMT: mode_t = 0xF000;
pub const S_IEXEC: mode_t = 0x40;
pub const S_IWRITE: mode_t = 0x80;
pub const S_IREAD: mode_t = 0x100;
pub const S_IRWXU: mode_t = 0x1C0;
pub const S_IXUSR: mode_t = 0x40;
pub const S_IWUSR: mode_t = 0x80;
pub const S_IRUSR: mode_t = 0x100;
pub const S_IRWXG: mode_t = 0x38;
pub const S_IXGRP: mode_t = 0x8;
pub const S_IWGRP: mode_t = 0x10;
pub const S_IRGRP: mode_t = 0x20;
pub const S_IRWXO: mode_t = 0x7;
pub const S_IXOTH: mode_t = 0x1;
pub const S_IWOTH: mode_t = 0x2;
pub const S_IROTH: mode_t = 0x4;

pub const F_DUPFD: ::c_int = 0;
pub const F_GETFD: ::c_int = 1;
pub const F_SETFD: ::c_int = 2;
pub const F_GETFL: ::c_int = 3;
pub const F_SETFL: ::c_int = 4;

pub const O_RDONLY: ::c_int =     0x0001_0000;
pub const O_WRONLY: ::c_int =     0x0002_0000;
pub const O_RDWR: ::c_int =       0x0003_0000;
pub const O_NONBLOCK: ::c_int =   0x0004_0000;
pub const O_APPEND: ::c_int =     0x0008_0000;
pub const O_SHLOCK: ::c_int =     0x0010_0000;
pub const O_EXLOCK: ::c_int =     0x0020_0000;
pub const O_ASYNC: ::c_int =      0x0040_0000;
pub const O_FSYNC: ::c_int =      0x0080_0000;
pub const O_CLOEXEC: ::c_int =    0x0100_0000;
pub const O_CREAT: ::c_int =      0x0200_0000;
pub const O_TRUNC: ::c_int =      0x0400_0000;
pub const O_EXCL: ::c_int =       0x0800_0000;
pub const O_DIRECTORY: ::c_int =  0x1000_0000;
pub const O_STAT: ::c_int =       0x2000_0000;
pub const O_SYMLINK: ::c_int =    0x4000_0000;
pub const O_NOFOLLOW: ::c_int =   0x8000_0000;
pub const O_ACCMODE: ::c_int =    O_RDONLY | O_WRONLY | O_RDWR;

extern {
    pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
    pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t)
                -> ::ssize_t;
    pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t)
                 -> ::ssize_t;
    pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int;
    pub fn close(fd: ::c_int) -> ::c_int;
}

#[link(name = "c")]
#[link(name = "m")]
extern {}

pub use self::net::*;

mod net;
<|endoftext|>