<commit_before>// Copyright © 2014, Simonas Kazlauskas <rdrand@kazlauskas.me>
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without
// fee is hereby granted, provided that the above copyright notice and this permission notice
// appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
//! An implementation of random number generators based on `rdrand` and `rdseed` instructions.

#![no_std]
#![feature(slice_align_to)]

extern crate rand_core;

use rand_core::{RngCore, CryptoRng, Error, ErrorKind};
use core::slice;

const RETRY_LIMIT: u8 = 127;

#[cold]
#[inline(never)]
pub fn busy_loop_fail() -> ! {
    panic!("hardware generator failure");
}

/// A cryptographically secure statistically uniform, non-periodic and non-deterministic random bit
/// generator.
///
/// Note that this generator may be implemented using a deterministic algorithm that is reseeded
/// routinely from a non-deterministic entropy source to achieve the desirable properties.
///
/// This generator is a viable replacement to any generator, however, since nobody has audited
/// Intel or AMD hardware yet, the usual disclaimers as to their suitability apply.
///
/// It is much faster than `OsRng`, but is only supported on more recent Intel
/// (Ivy Bridge and later) and AMD (Ryzen and later) processors.
#[derive(Clone, Copy)]
pub struct RdRand(());

/// A cryptographically secure non-deterministic random bit generator.
///
/// This generator produces high-entropy output and is suited to seed other pseudo-random
/// generators.
///
/// This instruction currently is only available in Intel Broadwell (and later) and AMD Ryzen
/// processors.
///
/// This generator is not intended for general random number generation purposes and should be used
/// to seed other generators implementing [SeedableRng].
#[derive(Clone, Copy)]
pub struct RdSeed(());

impl CryptoRng for RdRand {}
impl CryptoRng for RdSeed {}

mod arch {
    #[cfg(target_arch = "x86_64")]
    pub use core::arch::x86_64::*;
    #[cfg(target_arch = "x86")]
    pub use core::arch::x86::*;

    #[cfg(target_arch = "x86")]
    fn _rdrand64_step(dest: &mut u64) -> i32 {
        let mut ret1: u32 = ::core::mem::uninitialized();
        let mut ret2: u32 = ::core::mem::uninitialized();
        if _rdrand32_step(&mut ret1) != 0 && _rdrand32_step(&mut ret2) != 0 {
            *out = (ret1 as u64) << 32 | (ret2 as u64);
            1
        } else {
            0
        }
    }

    #[cfg(target_arch = "x86")]
    fn _rdseed64_step(dest: &mut u64) -> i32 {
        let mut ret1: u32 = ::core::mem::uninitialized();
        let mut ret2: u32 = ::core::mem::uninitialized();
        if _rdseed32_step(&mut ret1) != 0 && _rdseed32_step(&mut ret2) != 0 {
            *out = (ret1 as u64) << 32 | (ret2 as u64);
            1
        } else {
            0
        }
    }
}

macro_rules! check_cpuid {
    ("rdrand") => { {
        const FLAG : u32 = 1 << 30;
        ::arch::__cpuid(1).ecx & FLAG == FLAG
    } };
    ("rdseed") => { {
        const FLAG : u32 = 1 << 18;
        ::arch::__cpuid(7).ebx & FLAG == FLAG
    } };
}

macro_rules! loop_rand {
    ($feat: tt, $el: ty, $step: path) => { {
        #[target_feature(enable = $feat)]
        unsafe fn imp() -> Option<$el> {
            let mut ret: $el = ::core::mem::uninitialized();
            for _ in 0..RETRY_LIMIT {
                if $step(&mut ret) != 0 {
                    return Some(ret);
                }
            }
            return None;
        }
        unsafe { imp() }
    } }
}

macro_rules! impl_rand {
    ($gen:ident, $feat:tt, $step16: path, $step32:path, $step64:path,
     maxstep = $maxstep:path, maxty = $maxty: ty, next = $trynext:ident) => {
        impl $gen {
            pub fn new() -> Result<Self, Error> {
                unsafe {
                    if cfg!(target_feature=$feat) || check_cpuid!($feat) {
                        Ok($gen(()))
                    } else {
                        Err(Error::new(rand_core::ErrorKind::Unavailable,
                                       "the instruction is not supported"))
                    }
                }
            }

            #[inline(always)]
            pub fn try_next_u16(&self) -> Option<u16> {
                loop_rand!($feat, u16, $step16)
            }

            #[inline(always)]
            pub fn try_next_u32(&self) -> Option<u32> {
                loop_rand!($feat, u32, $step32)
            }

            #[inline(always)]
            pub fn try_next_u64(&self) -> Option<u64> {
                loop_rand!($feat, u64, $step64)
            }
        }

        impl RngCore for $gen {
            #[inline(always)]
            fn next_u32(&mut self) -> u32 {
                if let Some(result) = self.try_next_u32() {
                    result
                } else {
                    busy_loop_fail()
                }
            }

            #[inline(always)]
            fn next_u64(&mut self) -> u64 {
                if let Some(result) = self.try_next_u64() {
                    result
                } else {
                    busy_loop_fail()
                }
            }

            #[inline(always)]
            fn fill_bytes(&mut self, dest: &mut [u8]) {
                if let Err(_) = self.try_fill_bytes(dest) {
                    busy_loop_fail()
                }
            }

            fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
                #[target_feature(enable = $feat)]
                unsafe fn imp_fast(dest: &mut [$maxty])
                -> Result<(), Error>
                {
                    'outer: for el in dest {
                        for _ in 0..RETRY_LIMIT {
                            if $maxstep(el) != 0 {
                                continue 'outer;
                            }
                        }
                        return Err(Error::new(ErrorKind::Unexpected, "hardware generator failure"));
                    }
                    Ok(())
                }

                unsafe fn imp_slow(this: &mut $gen, mut dest: &mut [u8],
                                   word: &mut $maxty, buffer: &mut &[u8])
                -> Result<(), Error> {
                    while !dest.is_empty() {
                        if buffer.is_empty() {
                            if let Some(w) = $gen::$trynext(&*this) {
                                *word = w;
                                *buffer = slice::from_raw_parts(&word as *const _ as *const u8,
                                                                ::core::mem::size_of::<$maxty>());
                            } else {
                                return Err(Error::new(ErrorKind::Unexpected,
                                                      "hardware generator failure"));
                            }
                        }
                        let len = dest.len().min(buffer.len());
                        let (copy_src, leftover) = buffer.split_at(len);
                        let (copy_dest, dest_leftover) = { dest }.split_at_mut(len);
                        *buffer = leftover;
                        dest = dest_leftover;
                        copy_dest.copy_from_slice(copy_src);
                    }
                    Ok(())
                }

                unsafe {
                    let destlen = dest.len();
                    if destlen > ::core::mem::size_of::<$maxty>() {
                            let (left, mid, right) = dest.align_to_mut();
                            let mut word = 0;
                            let mut buffer: &[u8] = &[];
                            imp_fast(mid)?;
                            imp_slow(self, left, &mut word, &mut buffer)?;
                            imp_slow(self, right, &mut word, &mut buffer)
                    } else {
                        let mut word = 0;
                        let mut buffer: &[u8] = &[];
                        imp_slow(self, dest, &mut word, &mut buffer)
                    }
                }
            }
        }
    }
}

#[cfg(target_arch = "x86_64")]
impl_rand!(RdRand, "rdrand",
           ::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step,
           maxstep = ::arch::_rdrand64_step, maxty = u64, next = try_next_u64);
#[cfg(target_arch = "x86_64")]
impl_rand!(RdSeed, "rdseed",
           ::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step,
           maxstep = ::arch::_rdseed64_step, maxty = u64, next = try_next_u64);
#[cfg(target_arch = "x86")]
impl_rand!(RdRand, "rdrand",
           ::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step,
           maxstep = ::arch::_rdrand32_step, maxty = u32, next = try_next_u32);
#[cfg(target_arch = "x86")]
impl_rand!(RdSeed, "rdseed",
           ::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step,
           maxstep = ::arch::_rdseed32_step, maxty = u32, next = try_next_u32);

#[test]
fn rdrand_works() {
    let _ = RdRand::new().map(|mut r| {
        r.next_u32();
        r.next_u64();
    });
}

#[test]
fn rdseed_works() {
    let _ = RdSeed::new().map(|mut r| {
        r.next_u32();
        r.next_u64();
    });
}
<commit_msg>Fix up 32-bit version<commit_after>// Copyright © 2014, Simonas Kazlauskas <rdrand@kazlauskas.me>
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without
// fee is hereby granted, provided that the above copyright notice and this permission notice
// appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
//! An implementation of random number generators based on `rdrand` and `rdseed` instructions.

#![no_std]
#![feature(slice_align_to)]

extern crate rand_core;

use rand_core::{RngCore, CryptoRng, Error, ErrorKind};
use core::slice;

const RETRY_LIMIT: u8 = 127;

#[cold]
#[inline(never)]
pub fn busy_loop_fail() -> ! {
    panic!("hardware generator failure");
}

/// A cryptographically secure statistically uniform, non-periodic and non-deterministic random bit
/// generator.
///
/// Note that this generator may be implemented using a deterministic algorithm that is reseeded
/// routinely from a non-deterministic entropy source to achieve the desirable properties.
///
/// This generator is a viable replacement to any generator, however, since nobody has audited
/// Intel or AMD hardware yet, the usual disclaimers as to their suitability apply.
///
/// It is much faster than `OsRng`, but is only supported on more recent Intel
/// (Ivy Bridge and later) and AMD (Ryzen and later) processors.
#[derive(Clone, Copy)]
pub struct RdRand(());

/// A cryptographically secure non-deterministic random bit generator.
///
/// This generator produces high-entropy output and is suited to seed other pseudo-random
/// generators.
///
/// This instruction currently is only available in Intel Broadwell (and later) and AMD Ryzen
/// processors.
///
/// This generator is not intended for general random number generation purposes and should be used
/// to seed other generators implementing [SeedableRng].
#[derive(Clone, Copy)]
pub struct RdSeed(());

impl CryptoRng for RdRand {}
impl CryptoRng for RdSeed {}

mod arch {
    #[cfg(target_arch = "x86_64")]
    pub use core::arch::x86_64::*;
    #[cfg(target_arch = "x86")]
    pub use core::arch::x86::*;

    #[cfg(target_arch = "x86")]
    pub(crate) unsafe fn _rdrand64_step(dest: &mut u64) -> i32 {
        let mut ret1: u32 = ::core::mem::uninitialized();
        let mut ret2: u32 = ::core::mem::uninitialized();
        if _rdrand32_step(&mut ret1) != 0 && _rdrand32_step(&mut ret2) != 0 {
            *dest = (ret1 as u64) << 32 | (ret2 as u64);
            1
        } else {
            0
        }
    }

    #[cfg(target_arch = "x86")]
    pub(crate) unsafe fn _rdseed64_step(dest: &mut u64) -> i32 {
        let mut ret1: u32 = ::core::mem::uninitialized();
        let mut ret2: u32 = ::core::mem::uninitialized();
        if _rdseed32_step(&mut ret1) != 0 && _rdseed32_step(&mut ret2) != 0 {
            *dest = (ret1 as u64) << 32 | (ret2 as u64);
            1
        } else {
            0
        }
    }
}

macro_rules! check_cpuid {
    ("rdrand") => { {
        const FLAG : u32 = 1 << 30;
        ::arch::__cpuid(1).ecx & FLAG == FLAG
    } };
    ("rdseed") => { {
        const FLAG : u32 = 1 << 18;
        ::arch::__cpuid(7).ebx & FLAG == FLAG
    } };
}

macro_rules! loop_rand {
    ($feat: tt, $el: ty, $step: path) => { {
        #[target_feature(enable = $feat)]
        unsafe fn imp() -> Option<$el> {
            let mut ret: $el = ::core::mem::uninitialized();
            for _ in 0..RETRY_LIMIT {
                if $step(&mut ret) != 0 {
                    return Some(ret);
                }
            }
            return None;
        }
        unsafe { imp() }
    } }
}

macro_rules! impl_rand {
    ($gen:ident, $feat:tt, $step16: path, $step32:path, $step64:path,
     maxstep = $maxstep:path, maxty = $maxty: ty, next = $trynext:ident) => {
        impl $gen {
            pub fn new() -> Result<Self, Error> {
                unsafe {
                    if cfg!(target_feature=$feat) || check_cpuid!($feat) {
                        Ok($gen(()))
                    } else {
                        Err(Error::new(rand_core::ErrorKind::Unavailable,
                                       "the instruction is not supported"))
                    }
                }
            }

            #[inline(always)]
            pub fn try_next_u16(&self) -> Option<u16> {
                loop_rand!($feat, u16, $step16)
            }

            #[inline(always)]
            pub fn try_next_u32(&self) -> Option<u32> {
                loop_rand!($feat, u32, $step32)
            }

            #[inline(always)]
            pub fn try_next_u64(&self) -> Option<u64> {
                loop_rand!($feat, u64, $step64)
            }
        }

        impl RngCore for $gen {
            #[inline(always)]
            fn next_u32(&mut self) -> u32 {
                if let Some(result) = self.try_next_u32() {
                    result
                } else {
                    busy_loop_fail()
                }
            }

            #[inline(always)]
            fn next_u64(&mut self) -> u64 {
                if let Some(result) = self.try_next_u64() {
                    result
                } else {
                    busy_loop_fail()
                }
            }

            #[inline(always)]
            fn fill_bytes(&mut self, dest: &mut [u8]) {
                if let Err(_) = self.try_fill_bytes(dest) {
                    busy_loop_fail()
                }
            }

            fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
                #[target_feature(enable = $feat)]
                unsafe fn imp_fast(dest: &mut [$maxty])
                -> Result<(), Error>
                {
                    'outer: for el in dest {
                        for _ in 0..RETRY_LIMIT {
                            if $maxstep(el) != 0 {
                                continue 'outer;
                            }
                        }
                        return Err(Error::new(ErrorKind::Unexpected, "hardware generator failure"));
                    }
                    Ok(())
                }

                unsafe fn imp_slow(this: &mut $gen, mut dest: &mut [u8],
                                   word: &mut $maxty, buffer: &mut &[u8])
                -> Result<(), Error> {
                    while !dest.is_empty() {
                        if buffer.is_empty() {
                            if let Some(w) = $gen::$trynext(&*this) {
                                *word = w;
                                *buffer = slice::from_raw_parts(&word as *const _ as *const u8,
                                                                ::core::mem::size_of::<$maxty>());
                            } else {
                                return Err(Error::new(ErrorKind::Unexpected,
                                                      "hardware generator failure"));
                            }
                        }
                        let len = dest.len().min(buffer.len());
                        let (copy_src, leftover) = buffer.split_at(len);
                        let (copy_dest, dest_leftover) = { dest }.split_at_mut(len);
                        *buffer = leftover;
                        dest = dest_leftover;
                        copy_dest.copy_from_slice(copy_src);
                    }
                    Ok(())
                }

                unsafe {
                    let destlen = dest.len();
                    if destlen > ::core::mem::size_of::<$maxty>() {
                            let (left, mid, right) = dest.align_to_mut();
                            let mut word = 0;
                            let mut buffer: &[u8] = &[];
                            imp_fast(mid)?;
                            imp_slow(self, left, &mut word, &mut buffer)?;
                            imp_slow(self, right, &mut word, &mut buffer)
                    } else {
                        let mut word = 0;
                        let mut buffer: &[u8] = &[];
                        imp_slow(self, dest, &mut word, &mut buffer)
                    }
                }
            }
        }
    }
}

#[cfg(target_arch = "x86_64")]
impl_rand!(RdRand, "rdrand",
           ::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step,
           maxstep = ::arch::_rdrand64_step, maxty = u64, next = try_next_u64);
#[cfg(target_arch = "x86_64")]
impl_rand!(RdSeed, "rdseed",
           ::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step,
           maxstep = ::arch::_rdseed64_step, maxty = u64, next = try_next_u64);
#[cfg(target_arch = "x86")]
impl_rand!(RdRand, "rdrand",
           ::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step,
           maxstep = ::arch::_rdrand32_step, maxty = u32, next = try_next_u32);
#[cfg(target_arch = "x86")]
impl_rand!(RdSeed, "rdseed",
           ::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step,
           maxstep = ::arch::_rdseed32_step, maxty = u32, next = try_next_u32);

#[test]
fn rdrand_works() {
    let _ = RdRand::new().map(|mut r| {
        r.next_u32();
        r.next_u64();
    });
}

#[test]
fn rdseed_works() {
    let _ = RdSeed::new().map(|mut r| {
        r.next_u32();
        r.next_u64();
    });
}
<|endoftext|>


<commit_before>//! Struct and methods for union-find operation.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

use std::{mem, usize};
use std::default::Default;
use std::iter::FromIterator;

#[derive(Clone, Debug)]
enum UFNode<T> {
    Key(usize),
    Value(T)
}

impl<T> UFNode<T> {
    fn get(&self) -> &T {
        match self {
            &UFNode::Value(ref val) => val,
            &UFNode::Key(_) => panic!()
        }
    }
    fn get_mut(&mut self) -> &mut T {
        match self {
            &mut UFNode::Value(ref mut val) => val,
            &mut UFNode::Key(_) => panic!()
        }
    }
    fn unwrap(self) -> T {
        match self {
            UFNode::Value(val) => val,
            UFNode::Key(_) => panic!()
        }
    }
}

/// The value that can be contained with `UFValue`.
pub trait UFValue: Sized {
    /// Merge two value into one.
    ///
    /// This is used by `UnionFind::union` operation.
    fn merge(lval: Self, rval: Self) -> Merge<Self>;
}

/// Return value of the `UFValue::merege`
#[allow(missing_docs)]
pub enum Merge<T> {
    Left(T), Right(T)
}

/// Reperesents the size of the group.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Size(usize);

impl UFValue for Size {
    fn merge(Size(lval): Size, Size(rval): Size) -> Merge<Size> {
        if lval >= rval {
            Merge::Left(Size(lval + rval))
        } else {
            Merge::Right(Size(lval + rval))
        }
    }
}

impl Default for Size {
    fn default() -> Size { Size(1) }
}

/// Struct for union-find operation.
#[derive(Clone, Debug)]
pub struct UnionFind<V = Size> {
    data: Vec<UFNode<V>>
}

impl<T: UFValue = Size> UnionFind<T> {
    /// Creates empty `UnionFind` struct.
    #[inline]
    pub fn new(len: usize) -> UnionFind<T>
        where T: Default
    {
        UnionFind {
            data: (0 .. len)
                .map(|_| UFNode::Value(Default::default()))
                .collect()
        }
    }

    /// Join two sets that contains given keys (Union operation).
    ///
    /// Returns `true` if these keys are belonged to different sets.
    #[inline]
    pub fn union(&mut self, key0: usize, key1: usize) -> bool {
        let k0 = self.get_key(key0);
        let k1 = self.get_key(key1);
        if k0 == k1 { return false; }

        // Temporary replace with dummy to move out the elements of the vector.
        let v0 = mem::replace(&mut self.data[k0], UFNode::Key(usize::MAX)).unwrap();
        let v1 = mem::replace(&mut self.data[k1], UFNode::Key(usize::MAX)).unwrap();

        match UFValue::merge(v0, v1) {
            Merge::Left(val) => {
                self.data[k0] = UFNode::Value(val);
                self.data[k1] = UFNode::Key(k0);
            }
            Merge::Right(val) => {
                self.data[k1] = UFNode::Value(val);
                self.data[k0] = UFNode::Key(k1);
            }
        }

        true
    }

    /// Returns `true` if two keys contained by the same set (find operation).
    #[inline]
    pub fn find(&mut self, key0: usize, key1: usize) -> bool {
         self.get_key(key0) == self.get_key(key1)
    }

    /// Returns the reference to the value of the set that the key belongs to.
    #[inline]
    pub fn get(&mut self, key: usize) -> &T {
        let root_key = self.get_key(key);
        self.data[root_key].get()
    }

    /// Returns the mutable reference to the value of the set that the key belongs to.
    #[inline]
    pub fn get_mut(&mut self, key: usize) -> &mut T {
        let root_key = self.get_key(key);
        self.data[root_key].get_mut()
    }

    fn get_key(&mut self, key: usize) -> usize {
        let root_key = match self.data[key] {
            UFNode::Value(_) => return key,
            UFNode::Key(key) => self.get_key(key)
        };

        self.data[key] = UFNode::Key(root_key);
        root_key
    }
}

impl<T: UFValue> FromIterator<T> for UnionFind<T> {
    #[inline]
    fn from_iter<I: Iterator<Item = T>>(iterator: I) -> UnionFind<T> {
        UnionFind { data: iterator.map(UFNode::Value).collect() }
    }
}

#[cfg(test)]
mod tests {
    use super::{UnionFind, Size};

    #[test]
    fn test_union_find() {
        let mut uf = UnionFind::new(100);
        assert_eq!(&Size(1), uf.get(0));
        assert_eq!(&Size(1), uf.get(1));
        assert!(!uf.find(0, 1));
        assert!(!uf.find(1, 2));
        assert!(uf.union(0, 1));
        assert!(uf.find(0, 1));
        assert_eq!(&Size(2), uf.get(0));
        assert_eq!(&Size(2), uf.get(1));
        assert_eq!(&Size(1), uf.get(2));
        assert!(!uf.union(0, 1));
        assert_eq!(&Size(2), uf.get(0));
        assert_eq!(&Size(2), uf.get(1));
        assert_eq!(&Size(1), uf.get(2));
        assert!(uf.union(1, 2));
        assert_eq!(&Size(3), uf.get(0));
        assert_eq!(&Size(3), uf.get(1));
        assert_eq!(&Size(3), uf.get(2));
        assert!(uf.find(0, 1));
        assert!(uf.find(2, 1));
    }
}
<commit_msg>Add `size` method<commit_after>//! Struct and methods for union-find operation.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

use std::{mem, usize};
use std::default::Default;
use std::iter::FromIterator;

#[derive(Clone, Debug)]
enum UFNode<T> {
    Key(usize),
    Value(T)
}

impl<T> UFNode<T> {
    fn get(&self) -> &T {
        match self {
            &UFNode::Value(ref val) => val,
            &UFNode::Key(_) => panic!()
        }
    }
    fn get_mut(&mut self) -> &mut T {
        match self {
            &mut UFNode::Value(ref mut val) => val,
            &mut UFNode::Key(_) => panic!()
        }
    }
    fn unwrap(self) -> T {
        match self {
            UFNode::Value(val) => val,
            UFNode::Key(_) => panic!()
        }
    }
}

/// The value that can be contained with `UFValue`.
pub trait UFValue: Sized {
    /// Merge two value into one.
    ///
    /// This is used by `UnionFind::union` operation.
    fn merge(lval: Self, rval: Self) -> Merge<Self>;
}

/// Return value of the `UFValue::merege`
#[allow(missing_docs)]
pub enum Merge<T> {
    Left(T), Right(T)
}

/// Reperesents the size of the group.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Size(usize);

impl UFValue for Size {
    fn merge(Size(lval): Size, Size(rval): Size) -> Merge<Size> {
        if lval >= rval {
            Merge::Left(Size(lval + rval))
        } else {
            Merge::Right(Size(lval + rval))
        }
    }
}

impl Default for Size {
    fn default() -> Size { Size(1) }
}

/// Struct for union-find operation.
#[derive(Clone, Debug)]
pub struct UnionFind<V = Size> {
    data: Vec<UFNode<V>>
}

impl<T: UFValue = Size> UnionFind<T> {
    /// Creates empty `UnionFind` struct.
    #[inline]
    pub fn new(len: usize) -> UnionFind<T>
        where T: Default
    {
        UnionFind {
            data: (0 .. len)
                .map(|_| UFNode::Value(Default::default()))
                .collect()
        }
    }

    /// Returns the size of `self`.
    #[inline]
    pub fn size(&self) -> usize { self.data.len() }

    /// Join two sets that contains given keys (Union operation).
    ///
    /// Returns `true` if these keys are belonged to different sets.
    #[inline]
    pub fn union(&mut self, key0: usize, key1: usize) -> bool {
        let k0 = self.get_key(key0);
        let k1 = self.get_key(key1);
        if k0 == k1 { return false; }

        // Temporary replace with dummy to move out the elements of the vector.
        let v0 = mem::replace(&mut self.data[k0], UFNode::Key(usize::MAX)).unwrap();
        let v1 = mem::replace(&mut self.data[k1], UFNode::Key(usize::MAX)).unwrap();

        match UFValue::merge(v0, v1) {
            Merge::Left(val) => {
                self.data[k0] = UFNode::Value(val);
                self.data[k1] = UFNode::Key(k0);
            }
            Merge::Right(val) => {
                self.data[k1] = UFNode::Value(val);
                self.data[k0] = UFNode::Key(k1);
            }
        }

        true
    }

    /// Returns `true` if two keys contained by the same set (find operation).
    #[inline]
    pub fn find(&mut self, key0: usize, key1: usize) -> bool {
         self.get_key(key0) == self.get_key(key1)
    }

    /// Returns the reference to the value of the set that the key belongs to.
    #[inline]
    pub fn get(&mut self, key: usize) -> &T {
        let root_key = self.get_key(key);
        self.data[root_key].get()
    }

    /// Returns the mutable reference to the value of the set that the key belongs to.
    #[inline]
    pub fn get_mut(&mut self, key: usize) -> &mut T {
        let root_key = self.get_key(key);
        self.data[root_key].get_mut()
    }

    fn get_key(&mut self, key: usize) -> usize {
        let root_key = match self.data[key] {
            UFNode::Value(_) => return key,
            UFNode::Key(key) => self.get_key(key)
        };

        self.data[key] = UFNode::Key(root_key);
        root_key
    }
}

impl<T: UFValue> FromIterator<T> for UnionFind<T> {
    #[inline]
    fn from_iter<I: Iterator<Item = T>>(iterator: I) -> UnionFind<T> {
        UnionFind { data: iterator.map(UFNode::Value).collect() }
    }
}

#[cfg(test)]
mod tests {
    use super::{UnionFind, Size};

    #[test]
    fn test_union_find() {
        let mut uf = UnionFind::new(100);
        assert_eq!(&Size(1), uf.get(0));
        assert_eq!(&Size(1), uf.get(1));
        assert!(!uf.find(0, 1));
        assert!(!uf.find(1, 2));
        assert!(uf.union(0, 1));
        assert!(uf.find(0, 1));
        assert_eq!(&Size(2), uf.get(0));
        assert_eq!(&Size(2), uf.get(1));
        assert_eq!(&Size(1), uf.get(2));
        assert!(!uf.union(0, 1));
        assert_eq!(&Size(2), uf.get(0));
        assert_eq!(&Size(2), uf.get(1));
        assert_eq!(&Size(1), uf.get(2));
        assert!(uf.union(1, 2));
        assert_eq!(&Size(3), uf.get(0));
        assert_eq!(&Size(3), uf.get(1));
        assert_eq!(&Size(3), uf.get(2));
        assert!(uf.find(0, 1));
        assert!(uf.find(2, 1));
    }
}
<|endoftext|>


<commit_before>//! This crate provides x86_64 specific functions and data structures,
//! and access to various system registers.

#![feature(const_fn)]
#![feature(asm)]
#![feature(abi_x86_interrupt)]
#![feature(try_from)]
#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![cfg_attr(feature = "deny-warnings", deny(missing_docs))]
#![cfg_attr(not(feature = "deny-warnings"), warn(missing_docs))]
#![deny(missing_debug_implementations)]

/// Provides the non-standard-width integer types `u2`–`u63`.
///
/// We use these integer types in various APIs, for example `u9` for page tables indices.
pub use ux;

pub use crate::addr::{align_down, align_up, PhysAddr, VirtAddr};

pub mod instructions;
pub mod registers;
pub mod structures;

mod addr;

/// Represents a protection ring level.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum PrivilegeLevel {
    /// Privilege-level 0 (most privilege): This level is used by critical system-software
    /// components that require direct access to, and control over, all processor and system
    /// resources. This can include BIOS, memory-management functions, and interrupt handlers.
    Ring0 = 0,

    /// Privilege-level 1 (moderate privilege): This level is used by less-critical system-
    /// software services that can access and control a limited scope of processor and system
    /// resources. Software running at these privilege levels might include some device drivers
    /// and library routines. The actual privileges of this level are defined by the
    /// operating system.
    Ring1 = 1,

    /// Privilege-level 2 (moderate privilege): Like level 1, this level is used by
    /// less-critical system-software services that can access and control a limited scope of
    /// processor and system resources. The actual privileges of this level are defined by the
    /// operating system.
    Ring2 = 2,

    /// Privilege-level 3 (least privilege): This level is used by application software.
    /// Software running at privilege-level 3 is normally prevented from directly accessing
    /// most processor and system resources. Instead, applications request access to the
    /// protected processor and system resources by calling more-privileged service routines
    /// to perform the accesses.
    Ring3 = 3,
}

impl PrivilegeLevel {
    /// Creates a `PrivilegeLevel` from a numeric value. The value must be in the range 0..4.
    ///
    /// This function panics if the passed value is >3.
    pub fn from_u16(value: u16) -> PrivilegeLevel {
        match value {
            0 => PrivilegeLevel::Ring0,
            1 => PrivilegeLevel::Ring1,
            2 => PrivilegeLevel::Ring2,
            3 => PrivilegeLevel::Ring3,
            i => panic!("{} is not a valid privilege level", i),
        }
    }
}
<commit_msg>Remove stabilized try_from feature<commit_after>//! This crate provides x86_64 specific functions and data structures,
//! and access to various system registers.

#![feature(const_fn)]
#![feature(asm)]
#![feature(abi_x86_interrupt)]
#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![cfg_attr(feature = "deny-warnings", deny(missing_docs))]
#![cfg_attr(not(feature = "deny-warnings"), warn(missing_docs))]
#![deny(missing_debug_implementations)]

/// Provides the non-standard-width integer types `u2`–`u63`.
///
/// We use these integer types in various APIs, for example `u9` for page tables indices.
pub use ux;

pub use crate::addr::{align_down, align_up, PhysAddr, VirtAddr};

pub mod instructions;
pub mod registers;
pub mod structures;

mod addr;

/// Represents a protection ring level.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum PrivilegeLevel {
    /// Privilege-level 0 (most privilege): This level is used by critical system-software
    /// components that require direct access to, and control over, all processor and system
    /// resources. This can include BIOS, memory-management functions, and interrupt handlers.
    Ring0 = 0,

    /// Privilege-level 1 (moderate privilege): This level is used by less-critical system-
    /// software services that can access and control a limited scope of processor and system
    /// resources. Software running at these privilege levels might include some device drivers
    /// and library routines. The actual privileges of this level are defined by the
    /// operating system.
    Ring1 = 1,

    /// Privilege-level 2 (moderate privilege): Like level 1, this level is used by
    /// less-critical system-software services that can access and control a limited scope of
    /// processor and system resources. The actual privileges of this level are defined by the
    /// operating system.
    Ring2 = 2,

    /// Privilege-level 3 (least privilege): This level is used by application software.
    /// Software running at privilege-level 3 is normally prevented from directly accessing
    /// most processor and system resources. Instead, applications request access to the
    /// protected processor and system resources by calling more-privileged service routines
    /// to perform the accesses.
    Ring3 = 3,
}

impl PrivilegeLevel {
    /// Creates a `PrivilegeLevel` from a numeric value. The value must be in the range 0..4.
    ///
    /// This function panics if the passed value is >3.
    pub fn from_u16(value: u16) -> PrivilegeLevel {
        match value {
            0 => PrivilegeLevel::Ring0,
            1 => PrivilegeLevel::Ring1,
            2 => PrivilegeLevel::Ring2,
            3 => PrivilegeLevel::Ring3,
            i => panic!("{} is not a valid privilege level", i),
        }
    }
}
<|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.

use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

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

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

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

pub struct Index {
    path: PathBuf,
}

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

    /// Determines if *anything* exists at the path specified from the constructor
    pub fn exists(&self) -> bool {
        fs::metadata(&self.path).is_ok()
    }

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

    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .iter()
            .find(|path| path.file_name().unwrap().to_str().unwrap().eq_ignore_ascii_case(crate_name))
            .map(Crate::from_crate_index_path)
    }

    // TODO: this should be crate_iter that returns an Iterator
    pub fn crates(&self) -> Vec<Crate> {
        self.crate_index_paths()
            .iter()
            .map(Crate::from_crate_index_path)
            .collect::<Vec<_>>()
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> Vec<PathBuf> {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;

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

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

        let index_paths = index_paths1.chain(index_paths2);
        index_paths.map(|glob_result| glob_result.unwrap()).collect()
    }

    /// Generates a map of dependencies where the keys are crate names and the values are vectors
    /// of crate names that are its dependencies
    pub fn dependency_map(&self) -> HashMap<String, Vec<String>> {
        let mut map = HashMap::new();
        for crate_ in self.crates().iter() {
            let version = crate_.latest_version();
            let mut deps_names = version.deps.iter().map(|d| d.name.clone()).collect::<Vec<_>>();
            deps_names.sort_by(|a, b| a.cmp(b));
            deps_names.dedup();
            map.insert(version.name.clone(), deps_names);
        }

        map
    }
}

pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn from_crate_index_path(index_path: &PathBuf) -> Crate {
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate {versions: versions}
    }

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

#[test]
fn test_dependencies() {
    let index = Index::new("_test".into());
    if !index.exists() {
        index.clone().unwrap();
    }
}
<commit_msg>Fewer Vecs and more Iterators<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.

use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

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

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

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

/// 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::from_crate_index_path(&p))
    }
}

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

impl CrateIndexPaths {
    fn new(path: PathBuf) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;

        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())
    }
}

pub struct Index {
    path: PathBuf,
}

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

    /// Determines if *anything* exists at the path specified from the constructor
    pub fn exists(&self) -> bool {
        fs::metadata(&self.path).is_ok()
    }

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

    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| path.file_name().unwrap().to_str().unwrap().eq_ignore_ascii_case(crate_name))
            .map(|p| Crate::from_crate_index_path(&p))
    }

    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
    }

    /// Generates a map of dependencies where the keys are crate names and the values are vectors
    /// of crate names that are its dependencies
    pub fn dependency_map(&self) -> HashMap<String, Vec<String>> {
        let mut map = HashMap::new();
        for crate_ in self.crates() {
            let version = crate_.latest_version();
            let mut deps_names = version.deps.iter().map(|d| d.name.clone()).collect::<Vec<_>>();
            deps_names.sort_by(|a, b| a.cmp(b));
            deps_names.dedup();
            map.insert(version.name.clone(), deps_names);
        }

        map
    }
}

pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn from_crate_index_path(index_path: &PathBuf) -> Crate {
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate {versions: versions}
    }

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

#[test]
fn test_dependencies() {
    let index = Index::new("_test".into());
    if !index.exists() {
        index.clone().unwrap();
    }
}
<|endoftext|>


<commit_before>//! A generic connection pool.
//!
//! Opening a new database connection every time one is needed is both
//! inefficient and can lead to resource exhaustion under high traffic
//! conditions. A connection pool maintains a set of open connections to a
//! database, handing them out for repeated use.
//!
//! r2d2 is agnostic to the connection type it is managing. Implementors of the
//! `ManageConnection` trait provide the database-specific logic to create and
//! check the health of connections.
//!
//! # Example
//!
//! Using an imaginary "foodb" database.
//!
//! ```rust,ignore
//! use std::thread;
//!
//! extern crate r2d2;
//! extern crate r2d2_foodb;
//!
//! fn main() {
//!     let config = r2d2::Config::builder()
//!         .pool_size(15)
//!         .error_handler(Box::new(r2d2::LoggingErrorHandler))
//!         .build();
//!     let manager = r2d2_foodb::FooConnectionManager::new("localhost:1234");
//!
//!     let pool = r2d2::Pool::new(config, manager).unwrap();
//!
//!     for _ in 0..20 {
//!         let pool = pool.clone();
//!         thread::spawn(move || {
//!             let conn = pool.get().unwrap();
//!             // use the connection
//!             // it will be returned to the pool when it falls out of scope.
//!         })
//!     }
//! }
//! ```
#![warn(missing_docs)]
#![doc(html_root_url="https://sfackler.github.io/r2d2/doc/v0.6.2")]

#[macro_use]
extern crate log;
extern crate time;

use std::cmp;
use std::collections::VecDeque;
use std::error::Error;
use std::fmt;
use std::ops::{Deref, DerefMut};
use std::mem;
use std::sync::{Arc, Mutex, Condvar};
use time::{Duration, SteadyTime};

#[doc(inline)]
pub use config::Config;

use task::ScheduledThreadPool;

pub mod config;
mod task;
mod thunk;

#[cfg(test)]
mod test;

/// A trait which provides connection-specific functionality.
pub trait ManageConnection: Send + Sync + 'static {
    /// The connection type this manager deals with.
    type Connection: Send + 'static;

    /// The error type returned by `Connection`s.
    type Error: 'static;

    /// Attempts to create a new connection.
    fn connect(&self) -> Result<Self::Connection, Self::Error>;

    /// Determines if the connection is still connected to the database.
    ///
    /// A standard implementation would check if a simple query like `SELECT 1`
    /// succeeds.
    fn is_valid(&self, conn: &mut Self::Connection) -> Result<(), Self::Error>;

    /// *Quickly* determines if the connection is no longer usable.
    ///
    /// This will be called synchronously every time a connection is returned
    /// to the pool, so it should *not* block. If it returns `true`, the
    /// connection will be discarded.
    ///
    /// For example, an implementation might check if the underlying TCP socket
    /// has disconnected. Implementations that do not support this kind of
    /// fast health check may simply return `false`.
    fn has_broken(&self, conn: &mut Self::Connection) -> bool;
}

/// A trait which handles errors reported by the `ManageConnection`.
pub trait HandleError<E>: Send+Sync+'static {
    /// Handles an error.
    fn handle_error(&self, error: E);
}

/// A `HandleError` implementation which does nothing.
#[derive(Copy, Clone, Debug)]
pub struct NopErrorHandler;

impl<E> HandleError<E> for NopErrorHandler {
    fn handle_error(&self, _: E) {}
}

/// A `HandleError` implementation which logs at the error level.
#[derive(Copy, Clone, Debug)]
pub struct LoggingErrorHandler;

impl<E> HandleError<E> for LoggingErrorHandler where E: Error
{
    fn handle_error(&self, error: E) {
        error!("{}", error);
    }
}

/// A trait which allows for customization of connections.
pub trait CustomizeConnection<C, E>: Send+Sync+'static {
    /// Called with connections immediately after they are returned from
    /// `ManageConnection::connect`.
    ///
    /// The default implementation simply returns `Ok(())`.
    ///
    /// # Errors
    ///
    /// If this method returns an error, the connection will be discarded.
    #[allow(unused_variables)]
    fn on_acquire(&self, conn: &mut C) -> Result<(), E> {
        Ok(())
    }
}

/// A `CustomizeConnection` which does nothing.
#[derive(Copy, Clone, Debug)]
pub struct NopConnectionCustomizer;

impl<C, E> CustomizeConnection<C, E> for NopConnectionCustomizer {}

struct Conn<C> {
    conn: C,
    birth: SteadyTime,
    idle_start: SteadyTime,
}

impl<C> Conn<C> {
    fn new(conn: C) -> Conn<C> {
        let now = SteadyTime::now();
        Conn {
            conn: conn,
            birth: now,
            idle_start: now,
        }
    }
}

struct PoolInternals<C> {
    conns: VecDeque<Conn<C>>,
    num_conns: u32,
    pending_conns: u32,
}

struct SharedPool<M>
    where M: ManageConnection
{
    config: Config<M::Connection, M::Error>,
    manager: M,
    internals: Mutex<PoolInternals<M::Connection>>,
    cond: Condvar,
    thread_pool: ScheduledThreadPool,
}

impl<M> Drop for SharedPool<M> where M: ManageConnection
{
    fn drop(&mut self) {
        self.thread_pool.clear();
    }
}

fn drop_conn<M>(shared: &Arc<SharedPool<M>>, internals: &mut PoolInternals<M::Connection>)
    where M: ManageConnection
{
    internals.num_conns -= 1;

    let min = shared.config.min_idle().unwrap_or(shared.config.pool_size());
    if internals.num_conns + internals.pending_conns < min {
        add_connection(shared, internals);
    }
}

fn add_connection<M>(shared: &Arc<SharedPool<M>>, internals: &mut PoolInternals<M::Connection>)
    where M: ManageConnection
{
    internals.pending_conns += 1;
    inner(Duration::zero(), shared);

    fn inner<M>(delay: Duration, shared: &Arc<SharedPool<M>>)
        where M: ManageConnection
    {
        let new_shared = shared.clone();
        shared.thread_pool.run_after(delay, move || {
            let shared = new_shared;
            let conn = shared.manager.connect().and_then(|mut conn| {
                shared.config.connection_customizer().on_acquire(&mut conn).map(|_| conn)
            });
            match conn {
                Ok(conn) => {
                    let mut internals = shared.internals.lock().unwrap();
                    internals.conns.push_back(Conn::new(conn));
                    internals.pending_conns -= 1;
                    internals.num_conns += 1;
                    shared.cond.notify_one();
                }
                Err(err) => {
                    shared.config.error_handler().handle_error(err);
                    let delay = cmp::max(Duration::milliseconds(200), delay);
                    let delay = cmp::min(cvt(shared.config.connection_timeout()) / 2, delay * 2);
                    inner(delay, &shared);
                }
            }
        });
    }
}

fn reap_connections<M>(shared: &Arc<SharedPool<M>>)
    where M: ManageConnection
{
    let mut old = VecDeque::with_capacity(shared.config.pool_size() as usize);
    let mut to_drop = vec![];

    let mut internals = shared.internals.lock().unwrap();
    mem::swap(&mut old, &mut internals.conns);
    let now = SteadyTime::now();
    for conn in old {
        let mut reap = false;
        if let Some(timeout) = shared.config.idle_timeout() {
            reap |= now - conn.idle_start >= cvt(timeout);
        }
        if let Some(lifetime) = shared.config.max_lifetime() {
            reap |= now - conn.birth >= cvt(lifetime);
        }
        if reap {
            drop_conn(shared, &mut internals);
            to_drop.push(conn.conn);
        } else {
            internals.conns.push_back(conn);
        }
    }
    drop(internals); // make sure we run to_drop destructors without this locked
}

/// A generic connection pool.
pub struct Pool<M>
    where M: ManageConnection
{
    shared: Arc<SharedPool<M>>,
}

/// Returns a new `Pool` referencing the same state as `self`.
impl<M> Clone for Pool<M> where M: ManageConnection
{
    fn clone(&self) -> Pool<M> {
        Pool { shared: self.shared.clone() }
    }
}

impl<M> fmt::Debug for Pool<M> where M: ManageConnection + fmt::Debug
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let inner = self.shared.internals.lock().unwrap();

        fmt.debug_struct("Pool")
           .field("connections", &inner.num_conns)
           .field("idle_connections", &inner.conns.len())
           .field("config", &self.shared.config)
           .field("manager", &self.shared.manager)
           .finish()
    }
}

/// An error returned by `Pool::new` if it fails to initialize connections.
#[derive(Debug)]
pub struct InitializationError(());

impl fmt::Display for InitializationError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for InitializationError {
    fn description(&self) -> &str {
        "Unable to initialize connections"
    }
}

/// An error returned by `Pool::get` if it times out without retrieving a connection.
#[derive(Debug)]
pub struct GetTimeout(());

impl fmt::Display for GetTimeout {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for GetTimeout {
    fn description(&self) -> &str {
        "Timed out while waiting for a connection"
    }
}

impl<M> Pool<M> where M: ManageConnection
{
    /// Creates a new connection pool.
    ///
    /// Returns an `Err` value if `initialization_fail_fast` is set to true in
    /// the configuration and the pool is unable to open all of its
    /// connections.
    pub fn new(config: Config<M::Connection, M::Error>,
               manager: M)
               -> Result<Pool<M>, InitializationError> {
        Pool::new_inner(config, manager, 30)
    }

    // for testing
    fn new_inner(config: Config<M::Connection, M::Error>,
                 manager: M,
                 reaper_rate: i64)
                 -> Result<Pool<M>, InitializationError> {
        let internals = PoolInternals {
            conns: VecDeque::with_capacity(config.pool_size() as usize),
            num_conns: 0,
            pending_conns: 0,
        };

        let shared = Arc::new(SharedPool {
            thread_pool: ScheduledThreadPool::new(config.helper_threads() as usize),
            config: config,
            manager: manager,
            internals: Mutex::new(internals),
            cond: Condvar::new(),
        });

        {
            let mut inner = shared.internals.lock().unwrap();
            for _ in 0..shared.config.min_idle().unwrap_or(shared.config.pool_size()) {
                add_connection(&shared, &mut inner);
            }
            drop(inner);
        }

        if shared.config.initialization_fail_fast() {
            let end = SteadyTime::now() + cvt(shared.config.connection_timeout());
            let mut internals = shared.internals.lock().unwrap();

            while internals.num_conns != shared.config.pool_size() {
                let wait = end - SteadyTime::now();
                if wait <= Duration::zero() {
                    return Err(InitializationError(()));
                }
                internals = shared.cond
                                  .wait_timeout_ms(internals, wait.num_milliseconds() as u32)
                                  .unwrap()
                                  .0;
            }
        }

        if shared.config.max_lifetime().is_some() || shared.config.idle_timeout().is_some() {
            let s = shared.clone();
            shared.thread_pool
                  .run_at_fixed_rate(Duration::seconds(reaper_rate), move || reap_connections(&s));
        }

        Ok(Pool { shared: shared })
    }

    fn get_inner(&self) -> Result<Conn<M::Connection>, GetTimeout> {
        let end = SteadyTime::now() + cvt(self.shared.config.connection_timeout());
        let mut internals = self.shared.internals.lock().unwrap();

        loop {
            match internals.conns.pop_front() {
                Some(mut conn) => {
                    drop(internals);

                    if self.shared.config.test_on_check_out() {
                        if let Err(e) = self.shared.manager.is_valid(&mut conn.conn) {
                            self.shared.config.error_handler().handle_error(e);
                            internals = self.shared.internals.lock().unwrap();
                            drop_conn(&self.shared, &mut internals);
                            continue;
                        }
                    }

                    return Ok(conn);
                }
                None => {
                    if internals.num_conns + internals.pending_conns <
                       self.shared.config.pool_size() {
                        add_connection(&self.shared, &mut internals);
                    }

                    let now = SteadyTime::now();
                    let mut timeout = (end - now).num_milliseconds();
                    if timeout < 0 {
                        timeout = 0
                    };
                    let (new_internals, no_timeout) = self.shared
                                                          .cond
                                                          .wait_timeout_ms(internals,
                                                                           timeout as u32)
                                                          .unwrap();
                    internals = new_internals;

                    if !no_timeout {
                        return Err(GetTimeout(()));
                    }
                }
            }
        }
    }

    /// Retrieves a connection from the pool.
    ///
    /// Waits for at most `Config::connection_timeout` before returning an
    /// error.
    pub fn get(&self) -> Result<PooledConnection<M>, GetTimeout> {
        Ok(PooledConnection {
            pool: self.clone(),
            conn: Some(try!(self.get_inner())),
        })
    }

    fn put_back(&self, mut conn: Conn<M::Connection>) {
        // This is specified to be fast, but call it before locking anyways
        let broken = self.shared.manager.has_broken(&mut conn.conn);

        let mut internals = self.shared.internals.lock().unwrap();
        if broken {
            drop_conn(&self.shared, &mut internals);
        } else {
            conn.idle_start = SteadyTime::now();
            internals.conns.push_back(conn);
            self.shared.cond.notify_one();
        }
    }
}

/// A smart pointer wrapping a connection.
pub struct PooledConnection<M>
    where M: ManageConnection
{
    pool: Pool<M>,
    conn: Option<Conn<M::Connection>>,
}

impl<M> fmt::Debug for PooledConnection<M>
    where M: ManageConnection + fmt::Debug,
          M::Connection: fmt::Debug
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("PooledConnection")
           .field("pool", &self.pool)
           .field("connection", &self.conn.as_ref().unwrap().conn)
           .finish()
    }
}

impl<M> Drop for PooledConnection<M> where M: ManageConnection
{
    fn drop(&mut self) {
        self.pool.put_back(self.conn.take().unwrap());
    }
}

impl<M> Deref for PooledConnection<M> where M: ManageConnection
{
    type Target = M::Connection;

    fn deref(&self) -> &M::Connection {
        &self.conn.as_ref().unwrap().conn
    }
}

impl<M> DerefMut for PooledConnection<M> where M: ManageConnection
{
    fn deref_mut(&mut self) -> &mut M::Connection {
        &mut self.conn.as_mut().unwrap().conn
    }
}

fn cvt(d: std::time::Duration) -> Duration {
    Duration::seconds(d.as_secs() as i64) + Duration::nanoseconds(d.subsec_nanos() as i64)
}
<commit_msg>inline get_inner<commit_after>//! A generic connection pool.
//!
//! Opening a new database connection every time one is needed is both
//! inefficient and can lead to resource exhaustion under high traffic
//! conditions. A connection pool maintains a set of open connections to a
//! database, handing them out for repeated use.
//!
//! r2d2 is agnostic to the connection type it is managing. Implementors of the
//! `ManageConnection` trait provide the database-specific logic to create and
//! check the health of connections.
//!
//! # Example
//!
//! Using an imaginary "foodb" database.
//!
//! ```rust,ignore
//! use std::thread;
//!
//! extern crate r2d2;
//! extern crate r2d2_foodb;
//!
//! fn main() {
//!     let config = r2d2::Config::builder()
//!         .pool_size(15)
//!         .error_handler(Box::new(r2d2::LoggingErrorHandler))
//!         .build();
//!     let manager = r2d2_foodb::FooConnectionManager::new("localhost:1234");
//!
//!     let pool = r2d2::Pool::new(config, manager).unwrap();
//!
//!     for _ in 0..20 {
//!         let pool = pool.clone();
//!         thread::spawn(move || {
//!             let conn = pool.get().unwrap();
//!             // use the connection
//!             // it will be returned to the pool when it falls out of scope.
//!         })
//!     }
//! }
//! ```
#![warn(missing_docs)]
#![doc(html_root_url="https://sfackler.github.io/r2d2/doc/v0.6.2")]

#[macro_use]
extern crate log;
extern crate time;

use std::cmp;
use std::collections::VecDeque;
use std::error::Error;
use std::fmt;
use std::ops::{Deref, DerefMut};
use std::mem;
use std::sync::{Arc, Mutex, Condvar};
use time::{Duration, SteadyTime};

#[doc(inline)]
pub use config::Config;

use task::ScheduledThreadPool;

pub mod config;
mod task;
mod thunk;

#[cfg(test)]
mod test;

/// A trait which provides connection-specific functionality.
pub trait ManageConnection: Send + Sync + 'static {
    /// The connection type this manager deals with.
    type Connection: Send + 'static;

    /// The error type returned by `Connection`s.
    type Error: 'static;

    /// Attempts to create a new connection.
    fn connect(&self) -> Result<Self::Connection, Self::Error>;

    /// Determines if the connection is still connected to the database.
    ///
    /// A standard implementation would check if a simple query like `SELECT 1`
    /// succeeds.
    fn is_valid(&self, conn: &mut Self::Connection) -> Result<(), Self::Error>;

    /// *Quickly* determines if the connection is no longer usable.
    ///
    /// This will be called synchronously every time a connection is returned
    /// to the pool, so it should *not* block. If it returns `true`, the
    /// connection will be discarded.
    ///
    /// For example, an implementation might check if the underlying TCP socket
    /// has disconnected. Implementations that do not support this kind of
    /// fast health check may simply return `false`.
    fn has_broken(&self, conn: &mut Self::Connection) -> bool;
}

/// A trait which handles errors reported by the `ManageConnection`.
pub trait HandleError<E>: Send+Sync+'static {
    /// Handles an error.
    fn handle_error(&self, error: E);
}

/// A `HandleError` implementation which does nothing.
#[derive(Copy, Clone, Debug)]
pub struct NopErrorHandler;

impl<E> HandleError<E> for NopErrorHandler {
    fn handle_error(&self, _: E) {}
}

/// A `HandleError` implementation which logs at the error level.
#[derive(Copy, Clone, Debug)]
pub struct LoggingErrorHandler;

impl<E> HandleError<E> for LoggingErrorHandler where E: Error
{
    fn handle_error(&self, error: E) {
        error!("{}", error);
    }
}

/// A trait which allows for customization of connections.
pub trait CustomizeConnection<C, E>: Send+Sync+'static {
    /// Called with connections immediately after they are returned from
    /// `ManageConnection::connect`.
    ///
    /// The default implementation simply returns `Ok(())`.
    ///
    /// # Errors
    ///
    /// If this method returns an error, the connection will be discarded.
    #[allow(unused_variables)]
    fn on_acquire(&self, conn: &mut C) -> Result<(), E> {
        Ok(())
    }
}

/// A `CustomizeConnection` which does nothing.
#[derive(Copy, Clone, Debug)]
pub struct NopConnectionCustomizer;

impl<C, E> CustomizeConnection<C, E> for NopConnectionCustomizer {}

struct Conn<C> {
    conn: C,
    birth: SteadyTime,
    idle_start: SteadyTime,
}

impl<C> Conn<C> {
    fn new(conn: C) -> Conn<C> {
        let now = SteadyTime::now();
        Conn {
            conn: conn,
            birth: now,
            idle_start: now,
        }
    }
}

struct PoolInternals<C> {
    conns: VecDeque<Conn<C>>,
    num_conns: u32,
    pending_conns: u32,
}

struct SharedPool<M>
    where M: ManageConnection
{
    config: Config<M::Connection, M::Error>,
    manager: M,
    internals: Mutex<PoolInternals<M::Connection>>,
    cond: Condvar,
    thread_pool: ScheduledThreadPool,
}

impl<M> Drop for SharedPool<M> where M: ManageConnection
{
    fn drop(&mut self) {
        self.thread_pool.clear();
    }
}

fn drop_conn<M>(shared: &Arc<SharedPool<M>>, internals: &mut PoolInternals<M::Connection>)
    where M: ManageConnection
{
    internals.num_conns -= 1;

    let min = shared.config.min_idle().unwrap_or(shared.config.pool_size());
    if internals.num_conns + internals.pending_conns < min {
        add_connection(shared, internals);
    }
}

fn add_connection<M>(shared: &Arc<SharedPool<M>>, internals: &mut PoolInternals<M::Connection>)
    where M: ManageConnection
{
    internals.pending_conns += 1;
    inner(Duration::zero(), shared);

    fn inner<M>(delay: Duration, shared: &Arc<SharedPool<M>>)
        where M: ManageConnection
    {
        let new_shared = shared.clone();
        shared.thread_pool.run_after(delay, move || {
            let shared = new_shared;
            let conn = shared.manager.connect().and_then(|mut conn| {
                shared.config.connection_customizer().on_acquire(&mut conn).map(|_| conn)
            });
            match conn {
                Ok(conn) => {
                    let mut internals = shared.internals.lock().unwrap();
                    internals.conns.push_back(Conn::new(conn));
                    internals.pending_conns -= 1;
                    internals.num_conns += 1;
                    shared.cond.notify_one();
                }
                Err(err) => {
                    shared.config.error_handler().handle_error(err);
                    let delay = cmp::max(Duration::milliseconds(200), delay);
                    let delay = cmp::min(cvt(shared.config.connection_timeout()) / 2, delay * 2);
                    inner(delay, &shared);
                }
            }
        });
    }
}

fn reap_connections<M>(shared: &Arc<SharedPool<M>>)
    where M: ManageConnection
{
    let mut old = VecDeque::with_capacity(shared.config.pool_size() as usize);
    let mut to_drop = vec![];

    let mut internals = shared.internals.lock().unwrap();
    mem::swap(&mut old, &mut internals.conns);
    let now = SteadyTime::now();
    for conn in old {
        let mut reap = false;
        if let Some(timeout) = shared.config.idle_timeout() {
            reap |= now - conn.idle_start >= cvt(timeout);
        }
        if let Some(lifetime) = shared.config.max_lifetime() {
            reap |= now - conn.birth >= cvt(lifetime);
        }
        if reap {
            drop_conn(shared, &mut internals);
            to_drop.push(conn.conn);
        } else {
            internals.conns.push_back(conn);
        }
    }
    drop(internals); // make sure we run to_drop destructors without this locked
}

/// A generic connection pool.
pub struct Pool<M>
    where M: ManageConnection
{
    shared: Arc<SharedPool<M>>,
}

/// Returns a new `Pool` referencing the same state as `self`.
impl<M> Clone for Pool<M> where M: ManageConnection
{
    fn clone(&self) -> Pool<M> {
        Pool { shared: self.shared.clone() }
    }
}

impl<M> fmt::Debug for Pool<M> where M: ManageConnection + fmt::Debug
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let inner = self.shared.internals.lock().unwrap();

        fmt.debug_struct("Pool")
           .field("connections", &inner.num_conns)
           .field("idle_connections", &inner.conns.len())
           .field("config", &self.shared.config)
           .field("manager", &self.shared.manager)
           .finish()
    }
}

/// An error returned by `Pool::new` if it fails to initialize connections.
#[derive(Debug)]
pub struct InitializationError(());

impl fmt::Display for InitializationError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for InitializationError {
    fn description(&self) -> &str {
        "Unable to initialize connections"
    }
}

/// An error returned by `Pool::get` if it times out without retrieving a connection.
#[derive(Debug)]
pub struct GetTimeout(());

impl fmt::Display for GetTimeout {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for GetTimeout {
    fn description(&self) -> &str {
        "Timed out while waiting for a connection"
    }
}

impl<M> Pool<M> where M: ManageConnection
{
    /// Creates a new connection pool.
    ///
    /// Returns an `Err` value if `initialization_fail_fast` is set to true in
    /// the configuration and the pool is unable to open all of its
    /// connections.
    pub fn new(config: Config<M::Connection, M::Error>,
               manager: M)
               -> Result<Pool<M>, InitializationError> {
        Pool::new_inner(config, manager, 30)
    }

    // for testing
    fn new_inner(config: Config<M::Connection, M::Error>,
                 manager: M,
                 reaper_rate: i64)
                 -> Result<Pool<M>, InitializationError> {
        let internals = PoolInternals {
            conns: VecDeque::with_capacity(config.pool_size() as usize),
            num_conns: 0,
            pending_conns: 0,
        };

        let shared = Arc::new(SharedPool {
            thread_pool: ScheduledThreadPool::new(config.helper_threads() as usize),
            config: config,
            manager: manager,
            internals: Mutex::new(internals),
            cond: Condvar::new(),
        });

        {
            let mut inner = shared.internals.lock().unwrap();
            for _ in 0..shared.config.min_idle().unwrap_or(shared.config.pool_size()) {
                add_connection(&shared, &mut inner);
            }
            drop(inner);
        }

        if shared.config.initialization_fail_fast() {
            let end = SteadyTime::now() + cvt(shared.config.connection_timeout());
            let mut internals = shared.internals.lock().unwrap();

            while internals.num_conns != shared.config.pool_size() {
                let wait = end - SteadyTime::now();
                if wait <= Duration::zero() {
                    return Err(InitializationError(()));
                }
                internals = shared.cond
                                  .wait_timeout_ms(internals, wait.num_milliseconds() as u32)
                                  .unwrap()
                                  .0;
            }
        }

        if shared.config.max_lifetime().is_some() || shared.config.idle_timeout().is_some() {
            let s = shared.clone();
            shared.thread_pool
                  .run_at_fixed_rate(Duration::seconds(reaper_rate), move || reap_connections(&s));
        }

        Ok(Pool { shared: shared })
    }

    /// Retrieves a connection from the pool.
    ///
    /// Waits for at most `Config::connection_timeout` before returning an
    /// error.
    pub fn get(&self) -> Result<PooledConnection<M>, GetTimeout> {
        let end = SteadyTime::now() + cvt(self.shared.config.connection_timeout());
        let mut internals = self.shared.internals.lock().unwrap();

        let connection;
        loop {
            match internals.conns.pop_front() {
                Some(mut conn) => {
                    drop(internals);

                    if self.shared.config.test_on_check_out() {
                        if let Err(e) = self.shared.manager.is_valid(&mut conn.conn) {
                            self.shared.config.error_handler().handle_error(e);
                            internals = self.shared.internals.lock().unwrap();
                            drop_conn(&self.shared, &mut internals);
                            continue;
                        }
                    }

                    connection = conn;
                    break;
                }
                None => {
                    if internals.num_conns + internals.pending_conns <
                       self.shared.config.pool_size() {
                        add_connection(&self.shared, &mut internals);
                    }

                    let now = SteadyTime::now();
                    let mut timeout = (end - now).num_milliseconds();
                    if timeout < 0 {
                        timeout = 0
                    };
                    let (new_internals, no_timeout) = self.shared
                                                          .cond
                                                          .wait_timeout_ms(internals,
                                                                           timeout as u32)
                                                          .unwrap();
                    internals = new_internals;

                    if !no_timeout {
                        return Err(GetTimeout(()));
                    }
                }
            }
        }

        Ok(PooledConnection {
            pool: self.clone(),
            conn: Some(connection),
        })
    }

    fn put_back(&self, mut conn: Conn<M::Connection>) {
        // This is specified to be fast, but call it before locking anyways
        let broken = self.shared.manager.has_broken(&mut conn.conn);

        let mut internals = self.shared.internals.lock().unwrap();
        if broken {
            drop_conn(&self.shared, &mut internals);
        } else {
            conn.idle_start = SteadyTime::now();
            internals.conns.push_back(conn);
            self.shared.cond.notify_one();
        }
    }
}

/// A smart pointer wrapping a connection.
pub struct PooledConnection<M>
    where M: ManageConnection
{
    pool: Pool<M>,
    conn: Option<Conn<M::Connection>>,
}

impl<M> fmt::Debug for PooledConnection<M>
    where M: ManageConnection + fmt::Debug,
          M::Connection: fmt::Debug
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("PooledConnection")
           .field("pool", &self.pool)
           .field("connection", &self.conn.as_ref().unwrap().conn)
           .finish()
    }
}

impl<M> Drop for PooledConnection<M> where M: ManageConnection
{
    fn drop(&mut self) {
        self.pool.put_back(self.conn.take().unwrap());
    }
}

impl<M> Deref for PooledConnection<M> where M: ManageConnection
{
    type Target = M::Connection;

    fn deref(&self) -> &M::Connection {
        &self.conn.as_ref().unwrap().conn
    }
}

impl<M> DerefMut for PooledConnection<M> where M: ManageConnection
{
    fn deref_mut(&mut self) -> &mut M::Connection {
        &mut self.conn.as_mut().unwrap().conn
    }
}

fn cvt(d: std::time::Duration) -> Duration {
    Duration::seconds(d.as_secs() as i64) + Duration::nanoseconds(d.subsec_nanos() as i64)
}
<|endoftext|>


<commit_before>use clap::Clap;

pub(crate) mod format;
pub mod generate;
pub(crate) mod graph;
pub(crate) mod options;
pub(crate) mod orphans;
pub(crate) mod printer;
pub(crate) mod runner;
pub(crate) mod theme;

#[clap(
    name = "cargo-modules",
    about = "Print a crate's module tree or graph.",
    after_help = r#"
    If neither `--bin` nor `--example` are given,
    then if the project only has one bin target it will be run.
    Otherwise `--bin` specifies the bin target to run.
    At most one `--bin` can be provided.
    "#
)]
#[derive(Clap, Clone, PartialEq, Debug)]
pub enum Command {
    #[clap(
        name = "generate",
        about = "Generate a visualization for a crate's structure."
    )]
    Generate(generate::Command),
}

impl Command {
    pub fn run(&self) -> Result<(), anyhow::Error> {
        match &self {
            Self::Generate(cmd) => cmd.run(),
        }
    }
}
<commit_msg>Disabled help hint (for now)<commit_after>use clap::Clap;

pub(crate) mod format;
pub mod generate;
pub(crate) mod graph;
pub(crate) mod options;
pub(crate) mod orphans;
pub(crate) mod printer;
pub(crate) mod runner;
pub(crate) mod theme;

#[clap(
    name = "cargo-modules",
    about = "Print a crate's module tree or graph.",
    // after_help = r#"
    // If neither `--bin` nor `--example` are given,
    // then if the project only has one bin target it will be run.
    // Otherwise `--bin` specifies the bin target to run.
    // At most one `--bin` can be provided.
    // "#
)]
#[derive(Clap, Clone, PartialEq, Debug)]
pub enum Command {
    #[clap(
        name = "generate",
        about = "Generate a visualization for a crate's structure."
    )]
    Generate(generate::Command),
}

impl Command {
    pub fn run(&self) -> Result<(), anyhow::Error> {
        match &self {
            Self::Generate(cmd) => cmd.run(),
        }
    }
}
<|endoftext|>