<commit_before>extern crate fixedbitset;
extern crate rand;

pub mod dna_base;
pub mod base4;
pub mod graph;

use std::str::FromStr;
use std::ops::Deref;
use std::fmt::{self, Debug};
use fixedbitset::FixedBitSet;
use rand::{Rng, Rand};

/// Represents the bases used in the genome string.
/// For example the bases of the DNA are adenine (A),
/// thymine (T), guanine (G) and cytosine (C).
pub trait Base: Sized + PartialEq + Eq + Copy + Clone + Debug + Rand {
    /// Returns the "successor" base, wrapping around. Used
    /// to produce the gene product.
    fn succ(self) -> Self;

    fn from_char(c: char) -> Option<Self>;
}

// Locate ```substr``` in ```s```.
fn locate_substr<T: Eq>(s: &[T], substr: &[T]) -> Option<usize> {
    assert!(substr.len() > 0);

    if s.len() < substr.len() {
        return None;
    }

    for (i, window) in s.windows(substr.len()).enumerate() {
        if window == substr {
            return Some(i);
        }
    }

    return None;
}

// Count occurrence of ```substr``` in ```s```.
fn count_substr<T: Eq>(s: &[T], substr: &[T]) -> usize {
    assert!(substr.len() > 0);

    let mut cnt = 0;
    for window in s.windows(substr.len()) {
        if window == substr {
            cnt += 1;
        }
    }

    return cnt;
}

#[derive(Debug)]
pub struct Gene<'a, B: Base + 'a> {
    pub regulatory_region: &'a [B],
    pub gene: &'a [B],
}

impl<'a, B: Base + 'a> Gene<'a, B> {
    /// The gene product
    pub fn product(&self) -> BaseString<B> {
        BaseString { v: self.gene.iter().map(|b| b.succ()).collect() }
    }

    pub fn find_product_in_regulatory_region(&self, product: &[B]) -> bool {
        locate_substr(self.regulatory_region, product).is_some()
    }
    pub fn count_product_in_regulatory_region(&self, product: &[B]) -> usize {
        count_substr(self.regulatory_region, product)
    }
}

pub struct GeneIterator<'a, 'b, B: Base + 'a + 'b> {
    // Genes have fixed length
    length_of_gene: usize,
    sequence: &'a [B],
    promoter: &'b [B],
}

impl<'a, 'b, B: Base + 'a + 'b> Iterator for GeneIterator<'a, 'b, B> {
    type Item = Gene<'a, B>;

    fn next(&mut self) -> Option<Self::Item> {
        match locate_substr(self.sequence, self.promoter) {
            Some(pos) => {
                let gene_start = pos + self.promoter.len();
                let gene_end = gene_start + self.length_of_gene;

                // gene is not complete
                if gene_end > self.sequence.len() {
                    return None;
                }

                let gene = Gene {
                    regulatory_region: &self.sequence[..pos],
                    gene: &self.sequence[gene_start..gene_end],
                };
                self.sequence = &self.sequence[gene_end..];
                return Some(gene);
            }
            None => {
                return None;
            }
        }
    }
}

// A positive value enhances, a negative inhibits the expression of a gene.
#[derive(Debug)]
pub struct ProteinRegulator(i32);

impl ProteinRegulator {
    pub fn enhance() -> ProteinRegulator {
        ProteinRegulator(1)
    }

    pub fn inhibit() -> ProteinRegulator {
        ProteinRegulator(-1)
    }
}

#[derive(Clone)]
pub struct BaseString<B: Base> {
    v: Vec<B>,
}

impl<B: Base> FromStr for BaseString<B> {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(BaseString { v: s.chars().filter_map(|c| B::from_char(c)).collect() })
    }
}

impl<B: Base> Deref for BaseString<B> {
    type Target = [B];

    fn deref(&self) -> &Self::Target {
        &self.v
    }
}

impl<B: Base> Debug for BaseString<B> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "["));
        for base in &self.v {
            try!(write!(f, "{:?}", base));
        }
        write!(f, "]")
    }
}

impl<B: Base> BaseString<B> {
    pub fn random<R: Rng>(rng: &mut R, n: usize) -> BaseString<B> {
        assert!(n > 0);
        BaseString { v: (0..n).map(|_| rng.gen()).collect() }
    }
}

/// A Genome is a string of Base
#[derive(Clone)]
pub struct Genome<B: Base> {
    genome: BaseString<B>,
}

impl<B: Base> Genome<B> {
    pub fn random<R: Rng>(rng: &mut R, n: usize) -> Genome<B> {
        Genome { genome: BaseString::random(rng, n) }
    }
}

#[derive(Debug)]
struct Edge {
    src: usize,
    weight: ProteinRegulator,
}

#[derive(Debug)]
pub struct Node {
    incoming_edges: Vec<Edge>,
}

impl Node {
    fn new() -> Node {
        Node { incoming_edges: Vec::new() }
    }

    pub fn sum_edges(&self, network_state: &GeneNetworkState) -> i32 {
        let mut sum = 0;
        for edge in self.incoming_edges.iter() {
            let factor = if network_state.state.contains(edge.src) {
                1
            } else {
                0
            };
            sum += factor * edge.weight.0;
        }

        return sum;
    }
}

#[derive(Debug)]
pub struct GeneNetwork {
    nodes: Vec<Node>,
}

#[derive(Debug, Clone)]
pub struct GeneNetworkState {
    pub state: FixedBitSet,
}

impl GeneNetwork {
    fn new(num_nodes: usize) -> GeneNetwork {
        assert!(num_nodes > 0);
        GeneNetwork { nodes: (0..num_nodes).map(|_| Node::new()).collect() }
    }

    pub fn nodes(&self) -> &[Node] {
        &self.nodes
    }

    fn add_edge(&mut self, src: usize, dst: usize, weight: ProteinRegulator) {
        assert!(src < self.nodes.len());
        assert!(dst < self.nodes.len());
        self.nodes[dst].incoming_edges.push(Edge {
            src: src,
            weight: weight,
        });
    }

    pub fn new_state(&self) -> GeneNetworkState {
        GeneNetworkState { state: FixedBitSet::with_capacity(self.nodes.len()) }
    }
}

// Convert genome into sections, i.e. Split at the promoter.
impl<B: Base> Genome<B> {
    pub fn iter_genes<'a, 'b>(&'a self,
                              promoter: &'b [B],
                              length_of_gene: usize)
                              -> GeneIterator<'a, 'b, B> {
        GeneIterator {
            length_of_gene: length_of_gene,
            sequence: &self.genome,
            promoter: promoter,
        }
    }

    // Construct a dependency network between the genes
    pub fn construct_network<F>(&self,
                                promoter: &[B],
                                length_of_gene: usize,
                                protein_regulation: &F)
                                -> GeneNetwork
        where F: Fn(&[B]) -> ProteinRegulator
    {
        let genes: Vec<_> = self.iter_genes(promoter, length_of_gene).collect();
        let num_genes = genes.len();

        // each gene is a node in the boolean network
        let mut network = GeneNetwork::new(num_genes);

        for (src, gene) in genes.iter().enumerate() {
            let product = gene.product();
            // A gene product either enhances (> 0) or inyhibits (< 0) the expression of
            // another gene.
            let regulator = protein_regulation(&product);

            // determine which other genes ```gene``` regulates
            for (dst, gene2) in genes.iter().enumerate() {
                // XXX: Can a gene regulate itself?
                // if src != dst {
                let factor = gene2.count_product_in_regulatory_region(&product);
                if factor > 0 {
                    network.add_edge(src, dst, ProteinRegulator(regulator.0 * factor as i32));
                }
                // }
            }
        }

        return network;
    }
}

impl<B: Base> FromStr for Genome<B> {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        FromStr::from_str(s).map(|bs| Genome { genome: bs })
    }
}
<commit_msg>Add as_ref and from_vec for Genome<commit_after>extern crate fixedbitset;
extern crate rand;

pub mod dna_base;
pub mod base4;
pub mod graph;

use std::str::FromStr;
use std::ops::Deref;
use std::fmt::{self, Debug};
use fixedbitset::FixedBitSet;
use rand::{Rng, Rand};

/// Represents the bases used in the genome string.
/// For example the bases of the DNA are adenine (A),
/// thymine (T), guanine (G) and cytosine (C).
pub trait Base: Sized + PartialEq + Eq + Copy + Clone + Debug + Rand {
    /// Returns the "successor" base, wrapping around. Used
    /// to produce the gene product.
    fn succ(self) -> Self;

    fn from_char(c: char) -> Option<Self>;
}

// Locate ```substr``` in ```s```.
fn locate_substr<T: Eq>(s: &[T], substr: &[T]) -> Option<usize> {
    assert!(substr.len() > 0);

    if s.len() < substr.len() {
        return None;
    }

    for (i, window) in s.windows(substr.len()).enumerate() {
        if window == substr {
            return Some(i);
        }
    }

    return None;
}

// Count occurrence of ```substr``` in ```s```.
fn count_substr<T: Eq>(s: &[T], substr: &[T]) -> usize {
    assert!(substr.len() > 0);

    let mut cnt = 0;
    for window in s.windows(substr.len()) {
        if window == substr {
            cnt += 1;
        }
    }

    return cnt;
}

#[derive(Debug)]
pub struct Gene<'a, B: Base + 'a> {
    pub regulatory_region: &'a [B],
    pub gene: &'a [B],
}

impl<'a, B: Base + 'a> Gene<'a, B> {
    /// The gene product
    pub fn product(&self) -> BaseString<B> {
        BaseString { v: self.gene.iter().map(|b| b.succ()).collect() }
    }

    pub fn find_product_in_regulatory_region(&self, product: &[B]) -> bool {
        locate_substr(self.regulatory_region, product).is_some()
    }
    pub fn count_product_in_regulatory_region(&self, product: &[B]) -> usize {
        count_substr(self.regulatory_region, product)
    }
}

pub struct GeneIterator<'a, 'b, B: Base + 'a + 'b> {
    // Genes have fixed length
    length_of_gene: usize,
    sequence: &'a [B],
    promoter: &'b [B],
}

impl<'a, 'b, B: Base + 'a + 'b> Iterator for GeneIterator<'a, 'b, B> {
    type Item = Gene<'a, B>;

    fn next(&mut self) -> Option<Self::Item> {
        match locate_substr(self.sequence, self.promoter) {
            Some(pos) => {
                let gene_start = pos + self.promoter.len();
                let gene_end = gene_start + self.length_of_gene;

                // gene is not complete
                if gene_end > self.sequence.len() {
                    return None;
                }

                let gene = Gene {
                    regulatory_region: &self.sequence[..pos],
                    gene: &self.sequence[gene_start..gene_end],
                };
                self.sequence = &self.sequence[gene_end..];
                return Some(gene);
            }
            None => {
                return None;
            }
        }
    }
}

// A positive value enhances, a negative inhibits the expression of a gene.
#[derive(Debug)]
pub struct ProteinRegulator(i32);

impl ProteinRegulator {
    pub fn enhance() -> ProteinRegulator {
        ProteinRegulator(1)
    }

    pub fn inhibit() -> ProteinRegulator {
        ProteinRegulator(-1)
    }
}

#[derive(Clone)]
pub struct BaseString<B: Base> {
    v: Vec<B>,
}

impl<B: Base> FromStr for BaseString<B> {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(BaseString { v: s.chars().filter_map(|c| B::from_char(c)).collect() })
    }
}

impl<B: Base> Deref for BaseString<B> {
    type Target = [B];

    fn deref(&self) -> &Self::Target {
        &self.v
    }
}

impl<B: Base> Debug for BaseString<B> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "["));
        for base in &self.v {
            try!(write!(f, "{:?}", base));
        }
        write!(f, "]")
    }
}

impl<B: Base> BaseString<B> {
    pub fn random<R: Rng>(rng: &mut R, n: usize) -> BaseString<B> {
        assert!(n > 0);
        BaseString { v: (0..n).map(|_| rng.gen()).collect() }
    }
}

/// A Genome is a string of Base
#[derive(Clone)]
pub struct Genome<B: Base> {
    genome: BaseString<B>,
}

impl<B: Base> Genome<B> {
    pub fn from_vec(v: Vec<B>) -> Genome<B> {
        Genome {
            genome: BaseString {
                v: v
            }
        }
    }

    pub fn random<R: Rng>(rng: &mut R, n: usize) -> Genome<B> {
        Genome { genome: BaseString::random(rng, n) }
    }
}

impl<B: Base> Deref for Genome<B> {
    type Target = [B];

    fn deref(&self) -> &Self::Target {
        &self.genome
    }
}

#[derive(Debug)]
struct Edge {
    src: usize,
    weight: ProteinRegulator,
}

#[derive(Debug)]
pub struct Node {
    incoming_edges: Vec<Edge>,
}

impl Node {
    fn new() -> Node {
        Node { incoming_edges: Vec::new() }
    }

    pub fn sum_edges(&self, network_state: &GeneNetworkState) -> i32 {
        let mut sum = 0;
        for edge in self.incoming_edges.iter() {
            let factor = if network_state.state.contains(edge.src) {
                1
            } else {
                0
            };
            sum += factor * edge.weight.0;
        }

        return sum;
    }
}

#[derive(Debug)]
pub struct GeneNetwork {
    nodes: Vec<Node>,
}

#[derive(Debug, Clone)]
pub struct GeneNetworkState {
    pub state: FixedBitSet,
}

impl GeneNetwork {
    fn new(num_nodes: usize) -> GeneNetwork {
        assert!(num_nodes > 0);
        GeneNetwork { nodes: (0..num_nodes).map(|_| Node::new()).collect() }
    }

    pub fn nodes(&self) -> &[Node] {
        &self.nodes
    }

    fn add_edge(&mut self, src: usize, dst: usize, weight: ProteinRegulator) {
        assert!(src < self.nodes.len());
        assert!(dst < self.nodes.len());
        self.nodes[dst].incoming_edges.push(Edge {
            src: src,
            weight: weight,
        });
    }

    pub fn new_state(&self) -> GeneNetworkState {
        GeneNetworkState { state: FixedBitSet::with_capacity(self.nodes.len()) }
    }
}

// Convert genome into sections, i.e. Split at the promoter.
impl<B: Base> Genome<B> {
    pub fn iter_genes<'a, 'b>(&'a self,
                              promoter: &'b [B],
                              length_of_gene: usize)
                              -> GeneIterator<'a, 'b, B> {
        GeneIterator {
            length_of_gene: length_of_gene,
            sequence: &self.genome,
            promoter: promoter,
        }
    }

    // Construct a dependency network between the genes
    pub fn construct_network<F>(&self,
                                promoter: &[B],
                                length_of_gene: usize,
                                protein_regulation: &F)
                                -> GeneNetwork
        where F: Fn(&[B]) -> ProteinRegulator
    {
        let genes: Vec<_> = self.iter_genes(promoter, length_of_gene).collect();
        let num_genes = genes.len();

        // each gene is a node in the boolean network
        let mut network = GeneNetwork::new(num_genes);

        for (src, gene) in genes.iter().enumerate() {
            let product = gene.product();
            // A gene product either enhances (> 0) or inyhibits (< 0) the expression of
            // another gene.
            let regulator = protein_regulation(&product);

            // determine which other genes ```gene``` regulates
            for (dst, gene2) in genes.iter().enumerate() {
                // XXX: Can a gene regulate itself?
                // if src != dst {
                let factor = gene2.count_product_in_regulatory_region(&product);
                if factor > 0 {
                    network.add_edge(src, dst, ProteinRegulator(regulator.0 * factor as i32));
                }
                // }
            }
        }

        return network;
    }
}

impl<B: Base> FromStr for Genome<B> {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        FromStr::from_str(s).map(|bs| Genome { genome: bs })
    }
}
<|endoftext|>


<commit_before>#![feature(core,io,net)]
extern crate "rustc-serialize" as rustc_serialize;
extern crate hyper;

mod error;
mod errorcode;
mod response;

use std::io::Read;
use std::collections::HashSet;
use std::net::IpAddr;

pub use error::RecaptchaError;
pub use errorcode::RecaptchaErrorCode;

use rustc_serialize::json;
use response::RecaptchaResponse;

/// Verify a recaptcha user response
pub fn verify(key: &str, response: &str, user_ip: Option<&IpAddr>) -> Result<(), RecaptchaError> {
    use hyper::{Client, Url};

    let user_ip = user_ip.map(ToString::to_string);
    let user_ip = user_ip.as_ref().map(|s| &**s);

    let mut query = vec![
        ("secret", key),
        ("response", response),
    ];

    if let Some(user_ip) = user_ip {
        query.push(("remoteip", &user_ip));
    }

    let mut url = Url::parse("https://www.google.com/recaptcha/api/siteverify").unwrap();

    url.set_query_from_pairs(query.into_iter());

    let mut client = Client::new();

    let mut response = try!(client.get(url).send());
    let ref mut body = String::new();
    try!(response.read_to_string(body));
    let recaptcha_response = try!(json::decode::<RecaptchaResponse>(&body));

    match (recaptcha_response.success, recaptcha_response.error_codes) {
        (true, _) => Ok(()),
        (false, Some(errors)) => Err(RecaptchaError::Codes(errors)),
        (false, _) => Err(RecaptchaError::Codes(HashSet::new()))
    }
}

#[test]
fn test_invalid_secret_missing_response() {
    use RecaptchaError::*;
    use RecaptchaErrorCode::*;
    let resp = verify("", "", None);

    match resp {
        Ok(()) => panic!("unexpected response: Ok(())"),
        Err(Codes(ref errors)) => {
            assert!(errors.contains(&InvalidSecret));
            assert!(errors.contains(&MissingResponse));
        }
        Err(e) => panic!("unexpected error: {}", e),
    };

    println!("{:?}", resp);
}
<commit_msg>Update rustc_serialize name<commit_after>#![feature(core,io,net)]
extern crate rustc_serialize;
extern crate hyper;

mod error;
mod errorcode;
mod response;

use std::io::Read;
use std::collections::HashSet;
use std::net::IpAddr;

pub use error::RecaptchaError;
pub use errorcode::RecaptchaErrorCode;

use rustc_serialize::json;
use response::RecaptchaResponse;

/// Verify a recaptcha user response
pub fn verify(key: &str, response: &str, user_ip: Option<&IpAddr>) -> Result<(), RecaptchaError> {
    use hyper::{Client, Url};

    let user_ip = user_ip.map(ToString::to_string);
    let user_ip = user_ip.as_ref().map(|s| &**s);

    let mut query = vec![
        ("secret", key),
        ("response", response),
    ];

    if let Some(user_ip) = user_ip {
        query.push(("remoteip", &user_ip));
    }

    let mut url = Url::parse("https://www.google.com/recaptcha/api/siteverify").unwrap();

    url.set_query_from_pairs(query.into_iter());

    let mut client = Client::new();

    let mut response = try!(client.get(url).send());
    let ref mut body = String::new();
    try!(response.read_to_string(body));
    let recaptcha_response = try!(json::decode::<RecaptchaResponse>(&body));

    match (recaptcha_response.success, recaptcha_response.error_codes) {
        (true, _) => Ok(()),
        (false, Some(errors)) => Err(RecaptchaError::Codes(errors)),
        (false, _) => Err(RecaptchaError::Codes(HashSet::new()))
    }
}

#[test]
fn test_invalid_secret_missing_response() {
    use RecaptchaError::*;
    use RecaptchaErrorCode::*;
    let resp = verify("", "", None);

    match resp {
        Ok(()) => panic!("unexpected response: Ok(())"),
        Err(Codes(ref errors)) => {
            assert!(errors.contains(&InvalidSecret));
            assert!(errors.contains(&MissingResponse));
        }
        Err(e) => panic!("unexpected error: {}", e),
    };

    println!("{:?}", resp);
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt;
use std::ops::{Drop, Deref, DerefMut};
use std::convert::{AsRef, AsMut};
use std::borrow::Borrow;

/// In order to be managed by a `Pool`, values must be of a type that
/// implements the `Recycleable` trait. This allows the `Pool` to create
/// new instances as well as reset existing instances to a like-new state.
pub trait Recycleable {
  /// Allocates a new instance of the implementing type.
  fn new() -> Self;
  /// Sets the state of the modified instance to be that of a freshly
  /// allocated instance, thereby allowing it to be reused.
  fn reset(&mut self);
}

/// Informs how an already allocated value should be initialized
/// when provided with a model value or other meaningful input.
pub trait InitializeWith<T> {
  fn initialize_with(&mut self, source: T);
}

impl Recycleable for String {
  #[inline]
  fn new() -> String {
    String::new()
  }
  #[inline]
  fn reset(&mut self) {
    self.clear();
  }
}

impl <T> Recycleable for Vec<T> {
  #[inline]
  fn new() -> Vec<T> {
    Vec::new()
  }
  #[inline]
  fn reset(&mut self) {
    self.clear();
  }
}

impl <A> InitializeWith<A> for String where A : AsRef<str> {
  #[inline]
  fn initialize_with(&mut self, source: A) {
    let s : &str = source.as_ref();
    self.push_str(s);
  }
}

/// A smartpointer which uses reference counting (`Rc`) to know
/// when to move its wrapped value back to the `Pool` that
/// issued it.
pub struct RcRecycled<T> where T: Recycleable {
  value: RecycledInner<Rc<RefCell<CappedCollection<T>>>, T>
}

/// A smartpointer which uses a shared reference (`&`) to know
/// when to move its wrapped value back to the `Pool` that
/// issued it.
pub struct Recycled<'a, T: 'a> where T: Recycleable {
  value: RecycledInner<&'a RefCell<CappedCollection<T>>, T>
}

macro_rules! impl_recycled {
  ($name: ident, $typ: ty, $pool: ty) => {
  impl <'a, T> AsRef<T> for $typ where T : Recycleable {
     /// Gets a shared reference to the value wrapped by the smartpointer.
     fn as_ref(&self) -> &T {
      self.value.as_ref()
    }
  }

  impl <'a, T> AsMut<T> for $typ where T : Recycleable {
     /// Gets a mutable reference to the value wrapped by the smartpointer.
     fn as_mut(&mut self) -> &mut T {
      self.value.as_mut()
    }
  }

  impl <'a, T> fmt::Debug for $typ where T : fmt::Debug + Recycleable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
      self.value.fmt(f)
    }
  }

  impl <'a, T> fmt::Display for $typ where T : fmt::Display + Recycleable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
      self.value.fmt(f)
    }
  }

  impl <'a, T> Deref for $typ where T : Recycleable {
    type Target = T;
    #[inline]
    fn deref(&self) -> &T {
      self.as_ref()
    }
  }

  impl <'a, T> DerefMut for $typ where T : Recycleable {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
      self.as_mut()
    }
  }

  impl <'a, T> $typ where T: Recycleable {
    fn new(pool: $pool, value: T) -> $typ {
      $name { value: RecycledInner::new(pool, value) }
    }

    #[inline]
    fn new_from<A>(pool: $pool, value: T, source: A) -> $typ where T : InitializeWith<A> {
      $name { value: RecycledInner::new_from(pool, value, source) }
    }

    #[inline]
    /// Disassociates the value from the `Pool` that issued it. This
    /// destroys the smartpointer and returns the previously wrapped value.
    pub fn detach(self) -> T {
      self.value.detach()
    }
  }
}
}
impl_recycled!{ RcRecycled, RcRecycled<T>, Rc<RefCell<CappedCollection<T>>> }
impl_recycled!{ Recycled, Recycled<'a, T>, &'a RefCell<CappedCollection<T>> }

struct RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
  value: Option<T>,
  pool: P
}

impl <P, T> Drop for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
  #[inline]
  fn drop(&mut self) {
    if let Some(value) = self.value.take() {
      self.pool.borrow().borrow_mut().insert_or_drop(value);
    }
  }
}

impl <P, T> AsRef<T> for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
   fn as_ref(&self) -> &T {
    match self.value.as_ref() {
      Some(v) => v,
      None => panic!("Recycled<T> smartpointer missing its value.")
    }
  }
}

impl <P, T> AsMut<T> for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
   fn as_mut(&mut self) -> &mut T {
    match self.value.as_mut() {
      Some(v) => v,
      None => panic!("Recycled<T> smartpointer missing its value.")
    }
  }
}

impl <P, T> fmt::Debug for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : fmt::Debug + Recycleable {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self.value {
      Some(ref s) => s.fmt(f),
      None => write!(f, "Empty Recycled<T>")
    }
  }
}

impl <P, T> fmt::Display for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : fmt::Display + Recycleable {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self.value {
      Some(ref s) => s.fmt(f),
      None => write!(f, "Empty Recycled<T>")
    }
  }
}

impl <P, T> Deref for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
  type Target = T;
  #[inline]
  fn deref<'a>(&'a self) -> &'a T {
    self.as_ref()
  }
}

impl <P, T> DerefMut for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
  #[inline]
  fn deref_mut<'a>(&'a mut self) -> &'a mut T {
    self.as_mut()
  }
}

impl <P, T> RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
  #[inline]
  fn new(pool: P, value: T) -> RecycledInner<P, T> {
    RecycledInner {
      value: Some(value),
      pool: pool
    }
  }

  #[inline]
  fn new_from<A>(pool: P, mut value: T, source: A) -> RecycledInner<P, T> where T : InitializeWith<A> {
    value.initialize_with(source);
    RecycledInner {
      value: Some(value),
      pool: pool
    }
  }

  #[inline]
  fn detach(mut self) -> T {
    let value = self.value.take().unwrap();
    drop(self);
    value
  }
}

struct CappedCollection <T> where T: Recycleable {
  values: Vec<T>,
  cap: usize
}

impl <T> CappedCollection <T> where T: Recycleable {
  #[inline]
  pub fn new(starting_size: usize, max_size: usize) -> CappedCollection<T> {
    use std::cmp;
    let starting_size = cmp::min(starting_size, max_size);
    let values: Vec<T> =
      (0..starting_size)
      .map(|_| T::new() )
      .collect();
    CappedCollection {
      values: values,
      cap: max_size
    }
  }

  #[inline]
  pub fn insert_or_drop(&mut self, mut value: T) {
    match self.is_full() {
      true => drop(value),
      false => {
        value.reset();
        self.values.push(value)
      }
    }
  }

  #[inline]
  pub fn remove(&mut self) -> Option<T> {
    self.values.pop()
  }

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

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

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

/// A collection of values that can be reused without requiring new allocations.
///
/// `Pool` issues each value wrapped in a smartpointer. When the smartpointer goes out of
/// scope, the wrapped value is automatically returned to the pool.
pub struct Pool <T> where T : Recycleable {
  values: Rc<RefCell<CappedCollection<T>>>
}

impl <T> Pool <T> where T: Recycleable {

  /// Creates a pool with `size` elements of type `T` allocated.
  #[inline]
  pub fn with_size(size: usize) -> Pool <T> {
    use std::usize;
    Pool::with_size_and_max(size, usize::max_value())
  }

  /// Creates a pool with `size` elements of type `T` allocated.
  #[inline]
  pub fn with_size_and_max(starting_size: usize, max_size: usize) -> Pool <T> {
    let values: CappedCollection<T> = CappedCollection::new(starting_size, max_size);
    Pool {
      values: Rc::new(RefCell::new(values))
    }
  }

  /// Returns the number of values remaining in the pool.
  #[inline]
  pub fn size(&self) -> usize {
    (*self.values).borrow().len()
  }

  /// Removes a value from the pool and returns it wrapped in
  /// a `Recycled smartpointer. If the pool is empty when the
  /// method is called, a new value will be allocated.
  #[inline]
  pub fn new(&self) -> Recycled<T> {
    let t = self.detached();
    Recycled { value: RecycledInner::new(&*self.values, t) }
  }

  /// Removes a value from the pool, initializes it using the provided
  /// source value, and returns it wrapped in a `Recycled` smartpointer.
  /// If the pool is empty when the method is called, a new value will be
  /// allocated.
  #[inline(always)]
  pub fn new_from<A>(&self, source: A) -> Recycled<T> where T: InitializeWith<A> {
    let t = self.detached();
    Recycled { value: RecycledInner::new_from(&*self.values, t, source) }
  }

  /// Associates the provided value with the pool by wrapping it in a
  /// `Recycled` smartpointer.
  #[inline]
  pub fn attach(&self, value: T) -> Recycled<T> {
    Recycled { value: RecycledInner::new(&*self.values, value) }
  }

  /// Removes a value from the pool and returns it without wrapping it in
  /// a smartpointer. When the value goes out of scope it will not be
  /// returned to the pool.
  #[inline]
  pub fn detached(&self) -> T {
    match self.values.borrow_mut().remove() {
      Some(v) => v,
      None => T::new()
    }
  }

  /// Removes a value from the pool and returns it wrapped in
  /// an `RcRecycled` smartpointer. If the pool is empty when the
  /// method is called, a new value will be allocated.
  #[inline]
  pub fn new_rc(&self) -> RcRecycled<T> {
    let t = self.detached();
    let pool_reference = self.values.clone();
    RcRecycled { value: RecycledInner::new(pool_reference, t) }
  }

  /// Removes a value from the pool, initializes it using the provided
  /// source value, and returns it wrapped in an `RcRecycled` smartpointer.
  /// If the pool is empty when the method is called, a new value will be
  /// allocated.
  #[inline(always)]
  pub fn new_rc_from<A>(&self, source: A) -> RcRecycled<T> where T: InitializeWith<A> {
    let t = self.detached();
    let pool_reference = self.values.clone();
    RcRecycled { value: RecycledInner::new_from(pool_reference, t, source) }
  }

  /// Associates the provided value with the pool by wrapping it in an
  /// `RcRecycled` smartpointer.
  #[inline]
  pub fn attach_rc(&self, value: T) -> RcRecycled<T> {
    let pool_reference = self.values.clone();
    RcRecycled { value: RecycledInner::new(pool_reference, value) }
  }
}
<commit_msg>Added doc for new with_size_and_max method of Pool.<commit_after>#![allow(dead_code)]
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt;
use std::ops::{Drop, Deref, DerefMut};
use std::convert::{AsRef, AsMut};
use std::borrow::Borrow;

/// In order to be managed by a `Pool`, values must be of a type that
/// implements the `Recycleable` trait. This allows the `Pool` to create
/// new instances as well as reset existing instances to a like-new state.
pub trait Recycleable {
  /// Allocates a new instance of the implementing type.
  fn new() -> Self;
  /// Sets the state of the modified instance to be that of a freshly
  /// allocated instance, thereby allowing it to be reused.
  fn reset(&mut self);
}

/// Informs how an already allocated value should be initialized
/// when provided with a model value or other meaningful input.
pub trait InitializeWith<T> {
  fn initialize_with(&mut self, source: T);
}

impl Recycleable for String {
  #[inline]
  fn new() -> String {
    String::new()
  }
  #[inline]
  fn reset(&mut self) {
    self.clear();
  }
}

impl <T> Recycleable for Vec<T> {
  #[inline]
  fn new() -> Vec<T> {
    Vec::new()
  }
  #[inline]
  fn reset(&mut self) {
    self.clear();
  }
}

impl <A> InitializeWith<A> for String where A : AsRef<str> {
  #[inline]
  fn initialize_with(&mut self, source: A) {
    let s : &str = source.as_ref();
    self.push_str(s);
  }
}

/// A smartpointer which uses reference counting (`Rc`) to know
/// when to move its wrapped value back to the `Pool` that
/// issued it.
pub struct RcRecycled<T> where T: Recycleable {
  value: RecycledInner<Rc<RefCell<CappedCollection<T>>>, T>
}

/// A smartpointer which uses a shared reference (`&`) to know
/// when to move its wrapped value back to the `Pool` that
/// issued it.
pub struct Recycled<'a, T: 'a> where T: Recycleable {
  value: RecycledInner<&'a RefCell<CappedCollection<T>>, T>
}

macro_rules! impl_recycled {
  ($name: ident, $typ: ty, $pool: ty) => {
  impl <'a, T> AsRef<T> for $typ where T : Recycleable {
     /// Gets a shared reference to the value wrapped by the smartpointer.
     fn as_ref(&self) -> &T {
      self.value.as_ref()
    }
  }

  impl <'a, T> AsMut<T> for $typ where T : Recycleable {
     /// Gets a mutable reference to the value wrapped by the smartpointer.
     fn as_mut(&mut self) -> &mut T {
      self.value.as_mut()
    }
  }

  impl <'a, T> fmt::Debug for $typ where T : fmt::Debug + Recycleable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
      self.value.fmt(f)
    }
  }

  impl <'a, T> fmt::Display for $typ where T : fmt::Display + Recycleable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
      self.value.fmt(f)
    }
  }

  impl <'a, T> Deref for $typ where T : Recycleable {
    type Target = T;
    #[inline]
    fn deref(&self) -> &T {
      self.as_ref()
    }
  }

  impl <'a, T> DerefMut for $typ where T : Recycleable {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
      self.as_mut()
    }
  }

  impl <'a, T> $typ where T: Recycleable {
    fn new(pool: $pool, value: T) -> $typ {
      $name { value: RecycledInner::new(pool, value) }
    }

    #[inline]
    fn new_from<A>(pool: $pool, value: T, source: A) -> $typ where T : InitializeWith<A> {
      $name { value: RecycledInner::new_from(pool, value, source) }
    }

    #[inline]
    /// Disassociates the value from the `Pool` that issued it. This
    /// destroys the smartpointer and returns the previously wrapped value.
    pub fn detach(self) -> T {
      self.value.detach()
    }
  }
}
}
impl_recycled!{ RcRecycled, RcRecycled<T>, Rc<RefCell<CappedCollection<T>>> }
impl_recycled!{ Recycled, Recycled<'a, T>, &'a RefCell<CappedCollection<T>> }

struct RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
  value: Option<T>,
  pool: P
}

impl <P, T> Drop for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
  #[inline]
  fn drop(&mut self) {
    if let Some(value) = self.value.take() {
      self.pool.borrow().borrow_mut().insert_or_drop(value);
    }
  }
}

impl <P, T> AsRef<T> for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
   fn as_ref(&self) -> &T {
    match self.value.as_ref() {
      Some(v) => v,
      None => panic!("Recycled<T> smartpointer missing its value.")
    }
  }
}

impl <P, T> AsMut<T> for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
   fn as_mut(&mut self) -> &mut T {
    match self.value.as_mut() {
      Some(v) => v,
      None => panic!("Recycled<T> smartpointer missing its value.")
    }
  }
}

impl <P, T> fmt::Debug for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : fmt::Debug + Recycleable {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self.value {
      Some(ref s) => s.fmt(f),
      None => write!(f, "Empty Recycled<T>")
    }
  }
}

impl <P, T> fmt::Display for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : fmt::Display + Recycleable {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self.value {
      Some(ref s) => s.fmt(f),
      None => write!(f, "Empty Recycled<T>")
    }
  }
}

impl <P, T> Deref for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
  type Target = T;
  #[inline]
  fn deref<'a>(&'a self) -> &'a T {
    self.as_ref()
  }
}

impl <P, T> DerefMut for RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
  #[inline]
  fn deref_mut<'a>(&'a mut self) -> &'a mut T {
    self.as_mut()
  }
}

impl <P, T> RecycledInner<P, T> where P: Borrow<RefCell<CappedCollection<T>>>, T : Recycleable {
  #[inline]
  fn new(pool: P, value: T) -> RecycledInner<P, T> {
    RecycledInner {
      value: Some(value),
      pool: pool
    }
  }

  #[inline]
  fn new_from<A>(pool: P, mut value: T, source: A) -> RecycledInner<P, T> where T : InitializeWith<A> {
    value.initialize_with(source);
    RecycledInner {
      value: Some(value),
      pool: pool
    }
  }

  #[inline]
  fn detach(mut self) -> T {
    let value = self.value.take().unwrap();
    drop(self);
    value
  }
}

struct CappedCollection <T> where T: Recycleable {
  values: Vec<T>,
  cap: usize
}

impl <T> CappedCollection <T> where T: Recycleable {
  #[inline]
  pub fn new(starting_size: usize, max_size: usize) -> CappedCollection<T> {
    use std::cmp;
    let starting_size = cmp::min(starting_size, max_size);
    let values: Vec<T> =
      (0..starting_size)
      .map(|_| T::new() )
      .collect();
    CappedCollection {
      values: values,
      cap: max_size
    }
  }

  #[inline]
  pub fn insert_or_drop(&mut self, mut value: T) {
    match self.is_full() {
      true => drop(value),
      false => {
        value.reset();
        self.values.push(value)
      }
    }
  }

  #[inline]
  pub fn remove(&mut self) -> Option<T> {
    self.values.pop()
  }

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

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

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

/// A collection of values that can be reused without requiring new allocations.
///
/// `Pool` issues each value wrapped in a smartpointer. When the smartpointer goes out of
/// scope, the wrapped value is automatically returned to the pool.
pub struct Pool <T> where T : Recycleable {
  values: Rc<RefCell<CappedCollection<T>>>
}

impl <T> Pool <T> where T: Recycleable {

  /// Creates a pool with `size` elements of type `T` allocated.
  #[inline]
  pub fn with_size(size: usize) -> Pool <T> {
    use std::usize;
    Pool::with_size_and_max(size, usize::max_value())
  }

  /// Creates a pool with `size` elements of type `T` allocated
  /// and sets a maximum pool size of `max_size`. Values being
  /// added to the pool via `Pool::attach` or being returned to
  /// the pool upon dropping will instead be discarded if the pool
  /// is full.
  #[inline]
  pub fn with_size_and_max(starting_size: usize, max_size: usize) -> Pool <T> {
    let values: CappedCollection<T> = CappedCollection::new(starting_size, max_size);
    Pool {
      values: Rc::new(RefCell::new(values))
    }
  }

  /// Returns the number of values remaining in the pool.
  #[inline]
  pub fn size(&self) -> usize {
    (*self.values).borrow().len()
  }

  /// Removes a value from the pool and returns it wrapped in
  /// a `Recycled smartpointer. If the pool is empty when the
  /// method is called, a new value will be allocated.
  #[inline]
  pub fn new(&self) -> Recycled<T> {
    let t = self.detached();
    Recycled { value: RecycledInner::new(&*self.values, t) }
  }

  /// Removes a value from the pool, initializes it using the provided
  /// source value, and returns it wrapped in a `Recycled` smartpointer.
  /// If the pool is empty when the method is called, a new value will be
  /// allocated.
  #[inline(always)]
  pub fn new_from<A>(&self, source: A) -> Recycled<T> where T: InitializeWith<A> {
    let t = self.detached();
    Recycled { value: RecycledInner::new_from(&*self.values, t, source) }
  }

  /// Associates the provided value with the pool by wrapping it in a
  /// `Recycled` smartpointer.
  #[inline]
  pub fn attach(&self, value: T) -> Recycled<T> {
    Recycled { value: RecycledInner::new(&*self.values, value) }
  }

  /// Removes a value from the pool and returns it without wrapping it in
  /// a smartpointer. When the value goes out of scope it will not be
  /// returned to the pool.
  #[inline]
  pub fn detached(&self) -> T {
    match self.values.borrow_mut().remove() {
      Some(v) => v,
      None => T::new()
    }
  }

  /// Removes a value from the pool and returns it wrapped in
  /// an `RcRecycled` smartpointer. If the pool is empty when the
  /// method is called, a new value will be allocated.
  #[inline]
  pub fn new_rc(&self) -> RcRecycled<T> {
    let t = self.detached();
    let pool_reference = self.values.clone();
    RcRecycled { value: RecycledInner::new(pool_reference, t) }
  }

  /// Removes a value from the pool, initializes it using the provided
  /// source value, and returns it wrapped in an `RcRecycled` smartpointer.
  /// If the pool is empty when the method is called, a new value will be
  /// allocated.
  #[inline(always)]
  pub fn new_rc_from<A>(&self, source: A) -> RcRecycled<T> where T: InitializeWith<A> {
    let t = self.detached();
    let pool_reference = self.values.clone();
    RcRecycled { value: RecycledInner::new_from(pool_reference, t, source) }
  }

  /// Associates the provided value with the pool by wrapping it in an
  /// `RcRecycled` smartpointer.
  #[inline]
  pub fn attach_rc(&self, value: T) -> RcRecycled<T> {
    let pool_reference = self.values.clone();
    RcRecycled { value: RecycledInner::new(pool_reference, value) }
  }
}
<|endoftext|>


<commit_before>#![feature(test)]
#[cfg(test)]
extern crate test;
#[cfg(test)]
extern crate rand;
#[cfg(test)]
extern crate quickcheck;
#[cfg(test)]
extern crate regex;

pub mod afsort {

    pub fn sort<'a, T>(vec: &'a mut [T])
    where
        T: AsRef<[u8]>,
    {
        sort_by(vec, (|s| s.as_ref()));
    }

    pub fn sort_by<T, F>(vec: &mut [T], to_slice: F)
    where
        F: Fn(&T) -> &[u8],
    {
        sort_req(vec, &to_slice, 0);
    }

    fn sort_req<T, F>(vec: &mut [T], to_slice: &F, depth: usize)
    where
        F: Fn(&T) -> &[u8],
    {
        if vec.len() <= 32 {
            vec.sort_unstable_by(|e1, e2| to_slice(e1).cmp(to_slice(e2)));
            return;
        }
        let mut min = u16::max_value();
        let mut max = 0u16;
        for elem in vec.iter() {
            let val = to_slice(elem);
            if val.len() > depth {
                let radix_val = val[depth] as u16;
                if radix_val < min {
                    min = radix_val;
                }
                if radix_val > max {
                    max = radix_val;
                }
            }
        }
        if min == u16::max_value() {
            return;
        }

        let num_items = (max - min + 2) as usize;
        let mut counts: Vec<usize> = vec![0usize; num_items as usize];

        for elem in vec.iter() {
            let radix_val = radix_for_str(to_slice(elem), depth, min);
            counts[radix_val as usize] += 1;
        }

        let mut sum = 0usize;
        let mut offsets: Vec<usize> = vec![0usize; num_items as usize];
        for i in 0..num_items {
            offsets[i as usize] = sum;
            sum += counts[i as usize];
        }
        let mut next_free = offsets.clone();

        let mut block = 0usize;
        let mut i = 0usize;
        while block < num_items - 1 {
            if i >= offsets[block as usize + 1] as usize {
                block += 1;
            } else {
                let radix_val = radix_for_str(to_slice(&vec[i]), depth, min);
                if radix_val == block as u16 {
                    i += 1;
                } else {
                    vec.swap(i as usize, next_free[radix_val as usize] as usize);
                    next_free[radix_val as usize] += 1;
                }
            }
        }
        for i in 0..num_items - 1 {
            sort_req(
                &mut vec[offsets[i as usize] as usize..offsets[i as usize + 1] as usize],
                to_slice,
                depth + 1,
            );
        }
        sort_req(&mut vec[offsets[num_items - 1]..], to_slice, depth + 1);
    }

    fn radix_for_str(s: &[u8], d: usize, base: u16) -> u16 {
        if s.len() > d {
            s[d] as u16 + 1 - base
        } else {
            0
        }
    }
}

#[cfg(test)]
mod tests {

    use afsort;
    use quickcheck::QuickCheck;
    use test::Bencher;
    use std::fs::File;
    use std::io::{BufRead, BufReader};
    use rand::{self, Rng};
    use regex::Regex;
    use std::path::PathBuf;

    #[test]
    fn sorts_strings_same_as_unstable() {
        fn compare_sort(mut strings: Vec<String>) -> bool {
            let mut copy = strings.clone();
            copy.sort_unstable();
            afsort::sort(&mut strings);
            strings == copy
        }
        QuickCheck::new().tests(1000).quickcheck(
            compare_sort as
                fn(Vec<String>) -> bool,
        );
    }

    #[test]
    fn sorts_tuples_same_as_unstable() {
        fn compare_sort(mut tuples: Vec<(String, u8)>) -> bool {
            let mut copy = tuples.clone();
            copy.sort_unstable_by(|t1, t2| t1.0.cmp(&t2.0));
            afsort::sort_by(&mut tuples, |t| t.0.as_bytes());
            tuples.into_iter().map(|t| t.0).collect::<Vec<String>>() ==
                copy.into_iter().map(|t| t.0).collect::<Vec<String>>()
        }
        QuickCheck::new().tests(1000).quickcheck(
            compare_sort as
                fn(Vec<(String, u8)>) -> bool,
        );
    }

    #[bench]
    fn std_sort(b: &mut Bencher) {
        let strings = strings_en(&Regex::new(r".*").unwrap());
        b.iter(|| strings.clone().sort_unstable())
    }

    #[bench]
    fn af_sort(b: &mut Bencher) {
        let strings = strings_en(&Regex::new(r".*").unwrap());
        b.iter(|| afsort::sort(&mut strings.clone()))
    }

    #[bench]
    fn std_sort_sorted(b: &mut Bencher) {
        let mut strings = strings_en(&Regex::new(r".*").unwrap());
        strings.sort_unstable();
        b.iter(|| strings.clone().sort_unstable())
    }

    #[bench]
    fn af_sort_sorted(b: &mut Bencher) {
        let mut strings = strings_en(&Regex::new(r".*").unwrap());
        strings.sort_unstable();
        b.iter(|| afsort::sort(&mut strings.clone()))
    }

    #[bench]
    fn std_sort_only_lower(b: &mut Bencher) {
        let strings = strings_en(&Regex::new(r"^[a-z]+$").unwrap());
        b.iter(|| strings.clone().sort_unstable())
    }

    #[bench]
    fn af_sort_only_lower(b: &mut Bencher) {
        let strings = strings_en(&Regex::new(r"^[a-z]+$").unwrap());
        b.iter(|| afsort::sort(&mut strings.clone()))
    }

    fn strings_en(re: &Regex) -> Vec<String> {
        let d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        let f = File::open(d.join("test_resources/american-english.txt")).unwrap();
        let b = BufReader::new(f);
        let mut strings = b.lines()
            .map(|l| l.unwrap())
            .filter(|l| re.is_match(l))
            .collect::<Vec<String>>();
        let mut rng = rand::thread_rng();
        rng.shuffle(&mut strings);
        strings.into_iter().take(10000).collect::<Vec<String>>()
    }

}
<commit_msg>Renamed and added benchmark tests for readability.<commit_after>#![feature(test)]
#[cfg(test)]
extern crate test;
#[cfg(test)]
extern crate rand;
#[cfg(test)]
extern crate quickcheck;
#[cfg(test)]
extern crate regex;

pub mod afsort {

    pub fn sort<'a, T>(vec: &'a mut [T])
    where
        T: AsRef<[u8]>,
    {
        sort_by(vec, (|s| s.as_ref()));
    }

    pub fn sort_by<T, F>(vec: &mut [T], to_slice: F)
    where
        F: Fn(&T) -> &[u8],
    {
        sort_req(vec, &to_slice, 0);
    }

    fn sort_req<T, F>(vec: &mut [T], to_slice: &F, depth: usize)
    where
        F: Fn(&T) -> &[u8],
    {
        if vec.len() <= 32 {
            vec.sort_unstable_by(|e1, e2| to_slice(e1).cmp(to_slice(e2)));
            return;
        }
        let mut min = u16::max_value();
        let mut max = 0u16;
        for elem in vec.iter() {
            let val = to_slice(elem);
            if val.len() > depth {
                let radix_val = val[depth] as u16;
                if radix_val < min {
                    min = radix_val;
                }
                if radix_val > max {
                    max = radix_val;
                }
            }
        }
        if min == u16::max_value() {
            return;
        }

        let num_items = (max - min + 2) as usize;
        let mut counts: Vec<usize> = vec![0usize; num_items as usize];

        for elem in vec.iter() {
            let radix_val = radix_for_str(to_slice(elem), depth, min);
            counts[radix_val as usize] += 1;
        }

        let mut sum = 0usize;
        let mut offsets: Vec<usize> = vec![0usize; num_items as usize];
        for i in 0..num_items {
            offsets[i as usize] = sum;
            sum += counts[i as usize];
        }
        let mut next_free = offsets.clone();

        let mut block = 0usize;
        let mut i = 0usize;
        while block < num_items - 1 {
            if i >= offsets[block as usize + 1] as usize {
                block += 1;
            } else {
                let radix_val = radix_for_str(to_slice(&vec[i]), depth, min);
                if radix_val == block as u16 {
                    i += 1;
                } else {
                    vec.swap(i as usize, next_free[radix_val as usize] as usize);
                    next_free[radix_val as usize] += 1;
                }
            }
        }
        for i in 0..num_items - 1 {
            sort_req(
                &mut vec[offsets[i as usize] as usize..offsets[i as usize + 1] as usize],
                to_slice,
                depth + 1,
            );
        }
        sort_req(&mut vec[offsets[num_items - 1]..], to_slice, depth + 1);
    }

    fn radix_for_str(s: &[u8], d: usize, base: u16) -> u16 {
        if s.len() > d {
            s[d] as u16 + 1 - base
        } else {
            0
        }
    }
}

#[cfg(test)]
mod tests {

    use afsort;
    use quickcheck::QuickCheck;
    use test::Bencher;
    use std::fs::File;
    use std::io::{BufRead, BufReader};
    use rand::{self, Rng};
    use regex::Regex;
    use std::path::PathBuf;

    #[test]
    fn sorts_strings_same_as_unstable() {
        fn compare_sort(mut strings: Vec<String>) -> bool {
            let mut copy = strings.clone();
            copy.sort_unstable();
            afsort::sort(&mut strings);
            strings == copy
        }
        QuickCheck::new().tests(1000).quickcheck(
            compare_sort as
                fn(Vec<String>) -> bool,
        );
    }

    #[test]
    fn sorts_tuples_same_as_unstable() {
        fn compare_sort(mut tuples: Vec<(String, u8)>) -> bool {
            let mut copy = tuples.clone();
            copy.sort_unstable_by(|t1, t2| t1.0.cmp(&t2.0));
            afsort::sort_by(&mut tuples, |t| t.0.as_bytes());
            tuples.into_iter().map(|t| t.0).collect::<Vec<String>>() ==
                copy.into_iter().map(|t| t.0).collect::<Vec<String>>()
        }
        QuickCheck::new().tests(1000).quickcheck(
            compare_sort as
                fn(Vec<(String, u8)>) -> bool,
        );
    }

    #[bench]
    fn sort_1000_en_std(b: &mut Bencher) {
        let strings = strings_en(&Regex::new(r".*").unwrap(), 1_000);
        b.iter(|| strings.clone().sort_unstable())
    }

    #[bench]
    fn sort_1000_en_af(b: &mut Bencher) {
        let strings = strings_en(&Regex::new(r".*").unwrap(), 1_000);
        b.iter(|| afsort::sort(&mut strings.clone()))
    }

    #[bench]
    fn sort_10000_en_std(b: &mut Bencher) {
        let strings = strings_en(&Regex::new(r".*").unwrap(), 10_000);
        b.iter(|| strings.clone().sort_unstable())
    }

    #[bench]
    fn sort_10000_en_af(b: &mut Bencher) {
        let strings = strings_en(&Regex::new(r".*").unwrap(), 10_000);
        b.iter(|| afsort::sort(&mut strings.clone()))
    }

    #[bench]
    fn sort_100000_en_std(b: &mut Bencher) {
        let strings = strings_en(&Regex::new(r".*").unwrap(), 100_000);
        b.iter(|| strings.clone().sort_unstable())
    }

    #[bench]
    fn sort_100000_en_af(b: &mut Bencher) {
        let strings = strings_en(&Regex::new(r".*").unwrap(), 100_000);
        b.iter(|| afsort::sort(&mut strings.clone()))
    }

    #[bench]
    fn sort_10000_en_sorted_std(b: &mut Bencher) {
        let mut strings = strings_en(&Regex::new(r".*").unwrap(), 10_000);
        strings.sort_unstable();
        b.iter(|| strings.clone().sort_unstable())
    }

    #[bench]
    fn sort_10000_en_sorted_af(b: &mut Bencher) {
        let mut strings = strings_en(&Regex::new(r".*").unwrap(), 10_000);
        strings.sort_unstable();
        b.iter(|| afsort::sort(&mut strings.clone()))
    }

    #[bench]
    fn sort_10000_en_lower_std(b: &mut Bencher) {
        let strings = strings_en(&Regex::new(r"^[a-z]+$").unwrap(), 10000);
        b.iter(|| strings.clone().sort_unstable())
    }

    #[bench]
    fn sort_10000_en_lower_af(b: &mut Bencher) {
        let strings = strings_en(&Regex::new(r"^[a-z]+$").unwrap(), 10000);
        b.iter(|| afsort::sort(&mut strings.clone()))
    }

    fn strings_en(re: &Regex, n: usize) -> Vec<String> {
        let d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        let f = File::open(d.join("test_resources/american-english.txt")).unwrap();
        let b = BufReader::new(f);
        let mut strings = b.lines()
            .map(|l| l.unwrap())
            .filter(|l| re.is_match(l))
            .collect::<Vec<String>>();
        let mut rng = rand::thread_rng();
        rng.shuffle(&mut strings);
        strings.into_iter().take(n).collect::<Vec<String>>()
    }

}
<|endoftext|>


<commit_before>extern crate byteorder;
#[macro_use]
extern crate slog;

use byteorder::ReadBytesExt;

use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Error;
use std::io::ErrorKind;
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;
use std::string::String;

const GZIP_IDENTIFIER: [u8; 2] = [0x1f, 0x8b];
const BGZF_IDENTIFIER: [u8; 2] = [0x42, 0x43];

const DEFLATE: u8 = 8;

const FHCRC: u8 = 1 << 1;
const FEXTRA: u8 = 1 << 2;
const FNAME: u8 = 1 << 3;
const FCOMMENT: u8 = 1 << 4;

pub fn version() -> &'static str {
    return option_env!("CARGO_PKG_VERSION").unwrap_or("unknown");
}

enum BGZFBlockInformation {
    EOF,
    Size(u32)
}

fn check_block(reader: &mut BufReader<File>, blocks_count: &mut u64, logger: &slog::Logger) -> Result<BGZFBlockInformation, Error> {
    let mut gzip_identifier = [0u8; 2];
    let read_bytes = reader.read(&mut gzip_identifier)?;
    if read_bytes == 0 {
        return Ok(BGZFBlockInformation::EOF);
    }
    if read_bytes != 2 || gzip_identifier != GZIP_IDENTIFIER {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: gzip identitifer not found"));
    }
    *blocks_count += 1;
    debug!(logger, "Checking block {}", blocks_count);

    let mut compression_method = [0u8; 1];
    reader.read_exact(&mut compression_method)?;
    if compression_method[0] != DEFLATE {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: gzip compression method is not deflate"));
    }

    let mut flags = [0u8; 1];
    reader.read_exact(&mut flags)?;

    let mut modification_time = [0u8; 4];
    reader.read_exact(&mut modification_time)?;

    let mut extra_flags = [0u8; 1];
    reader.read_exact(&mut extra_flags)?;

    let mut operating_system = [0u8; 1];
    reader.read_exact(&mut operating_system)?;

    let mut block_size = 0u16;
    let mut extra_field_length = 0;
    if (flags[0] & FEXTRA) != 0 {
        extra_field_length = reader.read_u16::<byteorder::LittleEndian>()?;
        debug!(logger, "\tExtra field length of {} bytes", extra_field_length);

        while extra_field_length > 0 {
            let mut subfield_identifier = [0u8; 2];
            reader.read_exact(&mut subfield_identifier)?;

            let subfield_length = reader.read_u16::<byteorder::LittleEndian>()?;
            debug!(logger, "\t\tSubfield length of {} bytes", subfield_length);

            if subfield_identifier == BGZF_IDENTIFIER {
                debug!(logger, "\t\t\tSubfield is bgzf metadata");

                if subfield_length != 2 {
                    return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: bgzf block size is not a 16 bits number"));
                }

                block_size = reader.read_u16::<byteorder::LittleEndian>()? + 1;
                debug!(logger, "\t\t\t\tbgzf block size is {} bytes", block_size);
            } else {
                reader.seek(SeekFrom::Current(subfield_length as i64))?;
            }

            extra_field_length -= 4 + subfield_length;
        }
    }
    if block_size == 0 {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: bgzf block size not found in gzip extra field"));
    }

    if (flags[0] & FNAME) != 0 {
        let mut file_name = vec![];
        reader.read_until(0u8, &mut file_name)?;
        debug!(logger, "\tFile name is \"{}\"", String::from_utf8(file_name).unwrap_or(String::from("<invalid_encoding>")));
    }

    if (flags[0] & FCOMMENT) != 0 {
        let mut file_comment = vec![];
        reader.read_until(0u8, &mut file_comment)?;
        debug!(logger, "\tFile comment is \"{}\"", String::from_utf8(file_comment).unwrap_or(String::from("<invalid_encoding>")));
    }

    if (flags[0] & FHCRC) != 0 {
        let mut header_crc16 = [0u8; 2];
        reader.read_exact(&mut header_crc16)?;
        // TODO check the CRC16 against the 2 least signigicant bytes of the CRC32 of the header
    }

    reader.seek(SeekFrom::Current((block_size - extra_field_length - 26u16) as i64))?;
    // TODO actually read data to compute its CRC32

    let mut data_crc32 = [0u8; 4];
    reader.read_exact(&mut data_crc32)?;
    // TODO check the CRC32 against the uncompressed data

    let data_size = reader.read_u32::<byteorder::LittleEndian>()?;
    debug!(logger, "\tData size is {} bytes", data_size);

    debug!(logger, "\tAt offset {}", reader.seek(SeekFrom::Current(0))?);

    return Ok(BGZFBlockInformation::Size(data_size));
}

pub fn check(bamfile: &str, logger: &slog::Logger) -> Result<(), Error> {
    info!(logger, "Checking integrity of {}…", bamfile);

    let mut reader = BufReader::new(File::open(bamfile)?);

    let mut blocks_count = 0u64;
    let mut data_size = 0u32;
    loop {
        data_size = match check_block(&mut reader, &mut blocks_count, &logger)? {
            BGZFBlockInformation::EOF => if data_size == 0u32 { break } else { return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: unexpected end of file while last bgzf block was not empty")); },
            BGZFBlockInformation::Size(data_size) => data_size,
        };
    }

    println!("bam file statistics:");
    println!("{: >7} bgzf blocks found", blocks_count);
    println!("{: >7} corrupted blocks found", 0);
    Ok(())
}

pub fn repair(bamfile: &str, output: &str, logger: &slog::Logger) -> Result<(), Error> {
    info!(logger, "Repairing {} and writing output to {}…", bamfile, output);

    error!(logger, "bamrescue::repair() is not yet implemented");
    unimplemented!();
}
<commit_msg>Take gzip extra field length into account when skipping bgzf<commit_after>extern crate byteorder;
#[macro_use]
extern crate slog;

use byteorder::ReadBytesExt;

use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Error;
use std::io::ErrorKind;
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;
use std::string::String;

const GZIP_IDENTIFIER: [u8; 2] = [0x1f, 0x8b];
const BGZF_IDENTIFIER: [u8; 2] = [0x42, 0x43];

const DEFLATE: u8 = 8;

const FHCRC: u8 = 1 << 1;
const FEXTRA: u8 = 1 << 2;
const FNAME: u8 = 1 << 3;
const FCOMMENT: u8 = 1 << 4;

pub fn version() -> &'static str {
    return option_env!("CARGO_PKG_VERSION").unwrap_or("unknown");
}

enum BGZFBlockInformation {
    EOF,
    Size(u32)
}

fn check_block(reader: &mut BufReader<File>, blocks_count: &mut u64, logger: &slog::Logger) -> Result<BGZFBlockInformation, Error> {
    let mut gzip_identifier = [0u8; 2];
    let read_bytes = reader.read(&mut gzip_identifier)?;
    if read_bytes == 0 {
        return Ok(BGZFBlockInformation::EOF);
    }
    if read_bytes != 2 || gzip_identifier != GZIP_IDENTIFIER {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: gzip identitifer not found"));
    }
    *blocks_count += 1;
    debug!(logger, "Checking block {}", blocks_count);

    let mut compression_method = [0u8; 1];
    reader.read_exact(&mut compression_method)?;
    if compression_method[0] != DEFLATE {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: gzip compression method is not deflate"));
    }

    let mut flags = [0u8; 1];
    reader.read_exact(&mut flags)?;

    let mut modification_time = [0u8; 4];
    reader.read_exact(&mut modification_time)?;

    let mut extra_flags = [0u8; 1];
    reader.read_exact(&mut extra_flags)?;

    let mut operating_system = [0u8; 1];
    reader.read_exact(&mut operating_system)?;

    let mut block_size = 0u16;
    let mut extra_field_length = 0;
    if (flags[0] & FEXTRA) != 0 {
        extra_field_length = reader.read_u16::<byteorder::LittleEndian>()?;
        debug!(logger, "\tExtra field length of {} bytes", extra_field_length);

        let mut remaining_extra_field_length = extra_field_length;
        while remaining_extra_field_length > 0 {
            let mut subfield_identifier = [0u8; 2];
            reader.read_exact(&mut subfield_identifier)?;

            let subfield_length = reader.read_u16::<byteorder::LittleEndian>()?;
            debug!(logger, "\t\tSubfield length of {} bytes", subfield_length);

            if subfield_identifier == BGZF_IDENTIFIER {
                debug!(logger, "\t\t\tSubfield is bgzf metadata");

                if subfield_length != 2 {
                    return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: bgzf block size is not a 16 bits number"));
                }

                block_size = reader.read_u16::<byteorder::LittleEndian>()? + 1;
                debug!(logger, "\t\t\t\tbgzf block size is {} bytes", block_size);
            } else {
                reader.seek(SeekFrom::Current(subfield_length as i64))?;
            }

            remaining_extra_field_length -= 4 + subfield_length;
        }
    }
    if block_size == 0 {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: bgzf block size not found in gzip extra field"));
    }

    if (flags[0] & FNAME) != 0 {
        let mut file_name = vec![];
        reader.read_until(0u8, &mut file_name)?;
        debug!(logger, "\tFile name is \"{}\"", String::from_utf8(file_name).unwrap_or(String::from("<invalid_encoding>")));
    }

    if (flags[0] & FCOMMENT) != 0 {
        let mut file_comment = vec![];
        reader.read_until(0u8, &mut file_comment)?;
        debug!(logger, "\tFile comment is \"{}\"", String::from_utf8(file_comment).unwrap_or(String::from("<invalid_encoding>")));
    }

    if (flags[0] & FHCRC) != 0 {
        let mut header_crc16 = [0u8; 2];
        reader.read_exact(&mut header_crc16)?;
        // TODO check the CRC16 against the 2 least signigicant bytes of the CRC32 of the header
    }

    reader.seek(SeekFrom::Current((block_size - extra_field_length - 20u16) as i64))?;
    // TODO actually read data to compute its CRC32

    let mut data_crc32 = [0u8; 4];
    reader.read_exact(&mut data_crc32)?;
    // TODO check the CRC32 against the uncompressed data

    let data_size = reader.read_u32::<byteorder::LittleEndian>()?;
    debug!(logger, "\tData size is {} bytes", data_size);

    debug!(logger, "\tAt offset {}", reader.seek(SeekFrom::Current(0))?);

    return Ok(BGZFBlockInformation::Size(data_size));
}

pub fn check(bamfile: &str, logger: &slog::Logger) -> Result<(), Error> {
    info!(logger, "Checking integrity of {}…", bamfile);

    let mut reader = BufReader::new(File::open(bamfile)?);

    let mut blocks_count = 0u64;
    let mut data_size = 0u32;
    loop {
        data_size = match check_block(&mut reader, &mut blocks_count, &logger)? {
            BGZFBlockInformation::EOF => if data_size == 0u32 { break } else { return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: unexpected end of file while last bgzf block was not empty")); },
            BGZFBlockInformation::Size(data_size) => data_size,
        };
    }

    println!("bam file statistics:");
    println!("{: >7} bgzf blocks found", blocks_count);
    println!("{: >7} corrupted blocks found", 0);
    Ok(())
}

pub fn repair(bamfile: &str, output: &str, logger: &slog::Logger) -> Result<(), Error> {
    info!(logger, "Repairing {} and writing output to {}…", bamfile, output);

    error!(logger, "bamrescue::repair() is not yet implemented");
    unimplemented!();
}
<|endoftext|>


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

//!
//! `simplelog` provides a series of logging facilities, that can be easily combined.
//!
//! - `SimpleLogger` (very basic logger that logs to stdout)
//! - `TermLogger` (advanced terminal logger, that splits to stdout/err and has color support) (can be excluded on unsupported platforms)
//! - `WriteLogger` (logs to a given struct implementing `Write`, e.g. a file)
//! - `CombinedLogger` (can be used to form combinations of the above loggers)
//! - `TestLogger` (specialized logger for tests. Uses print!() / println!() for tests to be able to capture the output)
//!
//! Only one Logger should be initialized of the start of your program
//! through the `Logger::init(...)` method. For the actual calling syntax
//! take a look at the documentation of the specific implementation(s) you wanna use.
//!

#![deny(missing_docs, rust_2018_idioms)]

mod config;
mod loggers;

pub use self::config::{Config, ConfigBuilder, LevelPadding};
#[cfg(feature = "test")]
pub use self::loggers::TestLogger;
pub use self::loggers::{CombinedLogger, SimpleLogger, WriteLogger};
#[cfg(feature = "term")]
pub use self::loggers::{TermLogError, TermLogger, TerminalMode};

pub use log::{Level, LevelFilter};

use log::Log;
#[cfg(test)]
use log::*;

/// Trait to have a common interface to obtain the Level of Loggers
///
/// Necessary for CombinedLogger to calculate
/// the lowest used Level.
///
pub trait SharedLogger: Log {
    /// Returns the set Level for this Logger
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate simplelog;
    /// # use simplelog::*;
    /// # fn main() {
    /// let logger = SimpleLogger::new(LevelFilter::Info, Config::default());
    /// println!("{}", logger.level());
    /// # }
    /// ```
    fn level(&self) -> LevelFilter;

    /// Inspect the config of a running Logger
    ///
    /// An Option is returned, because some Logger may not contain a Config
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate simplelog;
    /// # use simplelog::*;
    /// # fn main() {
    /// let logger = SimpleLogger::new(LevelFilter::Info, Config::default());
    /// println!("{:?}", logger.config());
    /// # }
    /// ```
    fn config(&self) -> Option<&Config>;

    /// Returns the logger as a Log trait object
    fn as_log(self: Box<Self>) -> Box<dyn Log>;
}

#[cfg(test)]
mod tests {
    use std::fs::File;
    use std::io::Read;

    use super::*;

    #[test]
    fn test() {
        let mut i = 0;

        CombinedLogger::init({
            let mut vec = Vec::new();
            let mut conf_builder = ConfigBuilder::new();

            for elem in vec![
                LevelFilter::Off,
                LevelFilter::Trace,
                LevelFilter::Debug,
                LevelFilter::Info,
                LevelFilter::Warn,
                LevelFilter::Error,
            ] {
                let conf = conf_builder
                    .set_location_level(elem)
                    .set_target_level(elem)
                    .set_max_level(elem)
                    .set_time_level(elem)
                    .build();
                i += 1;

                //error
                vec.push(
                    SimpleLogger::new(LevelFilter::Error, conf.clone()) as Box<dyn SharedLogger>
                );
                vec.push(
                    TermLogger::new(LevelFilter::Error, conf.clone(), TerminalMode::Mixed).unwrap()
                        as Box<dyn SharedLogger>,
                );
                vec.push(WriteLogger::new(
                    LevelFilter::Error,
                    conf.clone(),
                    File::create(&format!("error_{}.log", i)).unwrap(),
                ) as Box<dyn SharedLogger>);

                //warn
                vec.push(
                    SimpleLogger::new(LevelFilter::Warn, conf.clone()) as Box<dyn SharedLogger>
                );
                vec.push(
                    TermLogger::new(LevelFilter::Warn, conf.clone(), TerminalMode::Mixed).unwrap()
                        as Box<dyn SharedLogger>,
                );
                vec.push(WriteLogger::new(
                    LevelFilter::Warn,
                    conf.clone(),
                    File::create(&format!("warn_{}.log", i)).unwrap(),
                ) as Box<dyn SharedLogger>);

                //info
                vec.push(
                    SimpleLogger::new(LevelFilter::Info, conf.clone()) as Box<dyn SharedLogger>
                );
                vec.push(
                    TermLogger::new(LevelFilter::Info, conf.clone(), TerminalMode::Mixed).unwrap()
                        as Box<dyn SharedLogger>,
                );
                vec.push(WriteLogger::new(
                    LevelFilter::Info,
                    conf.clone(),
                    File::create(&format!("info_{}.log", i)).unwrap(),
                ) as Box<dyn SharedLogger>);

                //debug
                vec.push(
                    SimpleLogger::new(LevelFilter::Debug, conf.clone()) as Box<dyn SharedLogger>
                );
                vec.push(
                    TermLogger::new(LevelFilter::Debug, conf.clone(), TerminalMode::Mixed).unwrap()
                        as Box<dyn SharedLogger>,
                );
                vec.push(WriteLogger::new(
                    LevelFilter::Debug,
                    conf.clone(),
                    File::create(&format!("debug_{}.log", i)).unwrap(),
                ) as Box<dyn SharedLogger>);

                //trace
                vec.push(
                    SimpleLogger::new(LevelFilter::Trace, conf.clone()) as Box<dyn SharedLogger>
                );
                vec.push(
                    TermLogger::new(LevelFilter::Trace, conf.clone(), TerminalMode::Mixed).unwrap()
                        as Box<dyn SharedLogger>,
                );
                vec.push(WriteLogger::new(
                    LevelFilter::Trace,
                    conf.clone(),
                    File::create(&format!("trace_{}.log", i)).unwrap(),
                ) as Box<dyn SharedLogger>);
            }

            vec
        })
        .unwrap();

        error!("Test Error");
        warn!("Test Warning");
        info!("Test Information");
        debug!("Test Debug");
        trace!("Test Trace");

        for j in 1..i {
            let mut error = String::new();
            File::open(&format!("error_{}.log", j))
                .unwrap()
                .read_to_string(&mut error)
                .unwrap();
            let mut warn = String::new();
            File::open(&format!("warn_{}.log", j))
                .unwrap()
                .read_to_string(&mut warn)
                .unwrap();
            let mut info = String::new();
            File::open(&format!("info_{}.log", j))
                .unwrap()
                .read_to_string(&mut info)
                .unwrap();
            let mut debug = String::new();
            File::open(&format!("debug_{}.log", j))
                .unwrap()
                .read_to_string(&mut debug)
                .unwrap();
            let mut trace = String::new();
            File::open(&format!("trace_{}.log", j))
                .unwrap()
                .read_to_string(&mut trace)
                .unwrap();

            assert!(error.contains("Test Error"));
            assert!(!error.contains("Test Warning"));
            assert!(!error.contains("Test Information"));
            assert!(!error.contains("Test Debug"));
            assert!(!error.contains("Test Trace"));

            assert!(warn.contains("Test Error"));
            assert!(warn.contains("Test Warning"));
            assert!(!warn.contains("Test Information"));
            assert!(!warn.contains("Test Debug"));
            assert!(!warn.contains("Test Trace"));

            assert!(info.contains("Test Error"));
            assert!(info.contains("Test Warning"));
            assert!(info.contains("Test Information"));
            assert!(!info.contains("Test Debug"));
            assert!(!info.contains("Test Trace"));

            assert!(debug.contains("Test Error"));
            assert!(debug.contains("Test Warning"));
            assert!(debug.contains("Test Information"));
            assert!(debug.contains("Test Debug"));
            assert!(!debug.contains("Test Trace"));

            assert!(trace.contains("Test Error"));
            assert!(trace.contains("Test Warning"));
            assert!(trace.contains("Test Information"));
            assert!(trace.contains("Test Debug"));
            assert!(trace.contains("Test Trace"));
        }
    }
}
<commit_msg>Add TestLogger to tests<commit_after>// Copyright 2016 Victor Brekenfeld
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//!
//! `simplelog` provides a series of logging facilities, that can be easily combined.
//!
//! - `SimpleLogger` (very basic logger that logs to stdout)
//! - `TermLogger` (advanced terminal logger, that splits to stdout/err and has color support) (can be excluded on unsupported platforms)
//! - `WriteLogger` (logs to a given struct implementing `Write`, e.g. a file)
//! - `CombinedLogger` (can be used to form combinations of the above loggers)
//! - `TestLogger` (specialized logger for tests. Uses print!() / println!() for tests to be able to capture the output)
//!
//! Only one Logger should be initialized of the start of your program
//! through the `Logger::init(...)` method. For the actual calling syntax
//! take a look at the documentation of the specific implementation(s) you wanna use.
//!

#![deny(missing_docs, rust_2018_idioms)]

mod config;
mod loggers;

pub use self::config::{Config, ConfigBuilder, LevelPadding};
#[cfg(feature = "test")]
pub use self::loggers::TestLogger;
pub use self::loggers::{CombinedLogger, SimpleLogger, WriteLogger};
#[cfg(feature = "term")]
pub use self::loggers::{TermLogError, TermLogger, TerminalMode};

pub use log::{Level, LevelFilter};

use log::Log;
#[cfg(test)]
use log::*;

/// Trait to have a common interface to obtain the Level of Loggers
///
/// Necessary for CombinedLogger to calculate
/// the lowest used Level.
///
pub trait SharedLogger: Log {
    /// Returns the set Level for this Logger
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate simplelog;
    /// # use simplelog::*;
    /// # fn main() {
    /// let logger = SimpleLogger::new(LevelFilter::Info, Config::default());
    /// println!("{}", logger.level());
    /// # }
    /// ```
    fn level(&self) -> LevelFilter;

    /// Inspect the config of a running Logger
    ///
    /// An Option is returned, because some Logger may not contain a Config
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate simplelog;
    /// # use simplelog::*;
    /// # fn main() {
    /// let logger = SimpleLogger::new(LevelFilter::Info, Config::default());
    /// println!("{:?}", logger.config());
    /// # }
    /// ```
    fn config(&self) -> Option<&Config>;

    /// Returns the logger as a Log trait object
    fn as_log(self: Box<Self>) -> Box<dyn Log>;
}

#[cfg(test)]
mod tests {
    use std::fs::File;
    use std::io::Read;

    use super::*;

    #[test]
    fn test() {
        let mut i = 0;

        CombinedLogger::init({
            let mut vec = Vec::new();
            let mut conf_builder = ConfigBuilder::new();

            for elem in vec![
                LevelFilter::Off,
                LevelFilter::Trace,
                LevelFilter::Debug,
                LevelFilter::Info,
                LevelFilter::Warn,
                LevelFilter::Error,
            ] {
                let conf = conf_builder
                    .set_location_level(elem)
                    .set_target_level(elem)
                    .set_max_level(elem)
                    .set_time_level(elem)
                    .build();
                i += 1;

                //error
                vec.push(
                    SimpleLogger::new(LevelFilter::Error, conf.clone()) as Box<dyn SharedLogger>
                );
                vec.push(
                    TermLogger::new(LevelFilter::Error, conf.clone(), TerminalMode::Mixed).unwrap()
                        as Box<dyn SharedLogger>,
                );
                vec.push(WriteLogger::new(
                    LevelFilter::Error,
                    conf.clone(),
                    File::create(&format!("error_{}.log", i)).unwrap(),
                ) as Box<dyn SharedLogger>);
                vec.push(TestLogger::new(LevelFilter::Error, conf.clone()));

                //warn
                vec.push(
                    SimpleLogger::new(LevelFilter::Warn, conf.clone()) as Box<dyn SharedLogger>
                );
                vec.push(
                    TermLogger::new(LevelFilter::Warn, conf.clone(), TerminalMode::Mixed).unwrap()
                        as Box<dyn SharedLogger>,
                );
                vec.push(WriteLogger::new(
                    LevelFilter::Warn,
                    conf.clone(),
                    File::create(&format!("warn_{}.log", i)).unwrap(),
                ) as Box<dyn SharedLogger>);
                vec.push(TestLogger::new(LevelFilter::Warn, conf.clone()));

                //info
                vec.push(
                    SimpleLogger::new(LevelFilter::Info, conf.clone()) as Box<dyn SharedLogger>
                );
                vec.push(
                    TermLogger::new(LevelFilter::Info, conf.clone(), TerminalMode::Mixed).unwrap()
                        as Box<dyn SharedLogger>,
                );
                vec.push(WriteLogger::new(
                    LevelFilter::Info,
                    conf.clone(),
                    File::create(&format!("info_{}.log", i)).unwrap(),
                ) as Box<dyn SharedLogger>);
                vec.push(TestLogger::new(LevelFilter::Info, conf.clone()));

                //debug
                vec.push(
                    SimpleLogger::new(LevelFilter::Debug, conf.clone()) as Box<dyn SharedLogger>
                );
                vec.push(
                    TermLogger::new(LevelFilter::Debug, conf.clone(), TerminalMode::Mixed).unwrap()
                        as Box<dyn SharedLogger>,
                );
                vec.push(WriteLogger::new(
                    LevelFilter::Debug,
                    conf.clone(),
                    File::create(&format!("debug_{}.log", i)).unwrap(),
                ) as Box<dyn SharedLogger>);
                vec.push(TestLogger::new(LevelFilter::Debug, conf.clone()));

                //trace
                vec.push(
                    SimpleLogger::new(LevelFilter::Trace, conf.clone()) as Box<dyn SharedLogger>
                );
                vec.push(
                    TermLogger::new(LevelFilter::Trace, conf.clone(), TerminalMode::Mixed).unwrap()
                        as Box<dyn SharedLogger>,
                );
                vec.push(WriteLogger::new(
                    LevelFilter::Trace,
                    conf.clone(),
                    File::create(&format!("trace_{}.log", i)).unwrap(),
                ) as Box<dyn SharedLogger>);
                vec.push(TestLogger::new(LevelFilter::Trace, conf.clone()));
            }

            vec
        })
        .unwrap();

        error!("Test Error");
        warn!("Test Warning");
        info!("Test Information");
        debug!("Test Debug");
        trace!("Test Trace");

        for j in 1..i {
            let mut error = String::new();
            File::open(&format!("error_{}.log", j))
                .unwrap()
                .read_to_string(&mut error)
                .unwrap();
            let mut warn = String::new();
            File::open(&format!("warn_{}.log", j))
                .unwrap()
                .read_to_string(&mut warn)
                .unwrap();
            let mut info = String::new();
            File::open(&format!("info_{}.log", j))
                .unwrap()
                .read_to_string(&mut info)
                .unwrap();
            let mut debug = String::new();
            File::open(&format!("debug_{}.log", j))
                .unwrap()
                .read_to_string(&mut debug)
                .unwrap();
            let mut trace = String::new();
            File::open(&format!("trace_{}.log", j))
                .unwrap()
                .read_to_string(&mut trace)
                .unwrap();

            assert!(error.contains("Test Error"));
            assert!(!error.contains("Test Warning"));
            assert!(!error.contains("Test Information"));
            assert!(!error.contains("Test Debug"));
            assert!(!error.contains("Test Trace"));

            assert!(warn.contains("Test Error"));
            assert!(warn.contains("Test Warning"));
            assert!(!warn.contains("Test Information"));
            assert!(!warn.contains("Test Debug"));
            assert!(!warn.contains("Test Trace"));

            assert!(info.contains("Test Error"));
            assert!(info.contains("Test Warning"));
            assert!(info.contains("Test Information"));
            assert!(!info.contains("Test Debug"));
            assert!(!info.contains("Test Trace"));

            assert!(debug.contains("Test Error"));
            assert!(debug.contains("Test Warning"));
            assert!(debug.contains("Test Information"));
            assert!(debug.contains("Test Debug"));
            assert!(!debug.contains("Test Trace"));

            assert!(trace.contains("Test Error"));
            assert!(trace.contains("Test Warning"));
            assert!(trace.contains("Test Information"));
            assert!(trace.contains("Test Debug"));
            assert!(trace.contains("Test Trace"));
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// 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.
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

extern crate kernel32;
#[macro_use]
extern crate log;
extern crate widestring;
extern crate winapi;

pub mod account;
pub mod sid;
<commit_msg>[win-users] Allow this crate to build on non-Windows platforms.<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// 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.
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

#[cfg(windows)]
extern crate kernel32;
#[cfg(windows)]
#[macro_use]
extern crate log;
#[cfg(windows)]
extern crate widestring;
#[cfg(windows)]
extern crate winapi;

#[cfg(windows)]
pub mod account;
#[cfg(windows)]
pub mod sid;
<|endoftext|>


<commit_before>#![feature(min_const_generics)]
#![cfg_attr(not(feature = "std"), no_std)]
#![forbid(unsafe_code)]

//! This crate provides you with the ability to parse ASN.1 encoded data. More precisely, it
//! provides you with the ability to parse data encoded with ASN.1's DER (Distinguished Encoding
//! Rules) encoding. It does not support BER (Basic Encoding Rules), CER (Canonical Encoding
//! Rules), XER (XML Encoding Rules), CXER (Canonical XML Encoding Rules), or any other alphabet
//! soup encodings -- and it never will.
//!
//! This crate does not, yet, provide the ability to generate ASN.1, only parse it.
//!
//! If you wanted to parse an ASN.1 structure like this:
//! ```text
//! Signature ::= SEQUENCE {
//!     r INTEGER,
//!     s INTEGER
//! }
//!
//! Then you'd write the following code:
//! ```
//! use asn1;
//! let result = asn1::parse(data, |d| {
//!     return d.read_element::<asn1::Sequence>()?.parse(|d| {
//!         let r = d.read_element::<u64>()?;
//!         let s = d.read_element::<u64>()?;
//!         return Ok((r, s));
//!     })
//! });
//!
//! In general everything about parsing is driven by providing different type parameters to
//! `Parser.read_element`. Some types directly implement the `Asn1Element` trait, as seen with
//! `u64` or `&[u8]` (`OCTET STRING`), while others use placeholder types which differ from the
//! return type (`PrintableString` or `UtcTime`). There are also types such as `Implicit` and
//! `Explicit` for handling tagged values, `Choice1`, `Choice2`, and `Choice3` available for
//! choices, and `Option<T>` for handling `OPTIONAL` values.

extern crate alloc;

mod bit_string;
mod object_identitifer;
mod parser;
mod types;
mod writer;

pub use crate::bit_string::BitString;
pub use crate::object_identitifer::ObjectIdentifier;
pub use crate::parser::{parse, ParseError, ParseResult};
pub use crate::types::{
    Choice1, Choice2, Choice3, Explicit, Implicit, PrintableString, Sequence, UtcTime,
};
pub use crate::writer::{write, Writer};
<commit_msg>Update comments for new generation API<commit_after>#![feature(min_const_generics)]
#![cfg_attr(not(feature = "std"), no_std)]
#![forbid(unsafe_code)]

//! This crate provides you with the ability to generate and parse ASN.1
//! encoded data. More precisely, it provides you with the ability to generate
//! and parse data encoded with ASN.1's DER (Distinguished Encoding Rules)
//! encoding. It does not support BER (Basic Encoding Rules), CER (Canonical
//! Encoding Rules), XER (XML Encoding Rules), CXER (Canonical XML Encoding
//! Rules), or any other alphabet soup encodings -- and it never will.
//!
//! If you wanted to parse an ASN.1 structure like this:
//! ```text
//! Signature ::= SEQUENCE {
//!     r INTEGER,
//!     s INTEGER
//! }
//!
//! Then you'd write the following code:
//! ```
//! use asn1;
//! let result = asn1::parse(data, |d| {
//!     return d.read_element::<asn1::Sequence>()?.parse(|d| {
//!         let r = d.read_element::<u64>()?;
//!         let s = d.read_element::<u64>()?;
//!         return Ok((r, s));
//!     })
//! });
//!
//! In general everything about parsing is driven by providing different type
//! parameters to `Parser.read_element`. Some types directly implement the
//! `Asn1Element` trait, as seen with `u64` or `&[u8]` (`OCTET STRING`), while
//! others use placeholder types which differ from the return type
//! (`PrintableString` or `UtcTime`). There are also types such as `Implicit`
//! and `Explicit` for handling tagged values, `Choice1`, `Choice2`, and
//! `Choice3` available for choices, and `Option<T>` for handling `OPTIONAL`
//!  values.

extern crate alloc;

mod bit_string;
mod object_identitifer;
mod parser;
mod types;
mod writer;

pub use crate::bit_string::BitString;
pub use crate::object_identitifer::ObjectIdentifier;
pub use crate::parser::{parse, ParseError, ParseResult};
pub use crate::types::{
    Choice1, Choice2, Choice3, Explicit, Implicit, PrintableString, Sequence, UtcTime,
};
pub use crate::writer::{write, Writer};
<|endoftext|>