<commit_before>mod tokens;
pub use tokens::Tokens;

mod to_tokens;
pub use to_tokens::{ToTokens, ByteStr};

#[macro_export]
macro_rules! quote {
    ($($tt:tt)+) => {
        {
            #[allow(unused_imports)]
            use $crate::ToTokens;
            let mut _s = $crate::Tokens::new();
            quote_each_token!(_s $($tt)*);
            _s
        }
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! pounded_var_names {
    ($finish:ident ($($found:ident)*) # ( $($inner:tt)* ) $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) # [ $($inner:tt)* ] $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) # { $($inner:tt)* } $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) # $first:ident $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)* $first) $($rest)*)
    };

    ($finish:ident ($($found:ident)*) ( $($inner:tt)* ) $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) [ $($inner:tt)* ] $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) { $($inner:tt)* } $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) $ignore:tt $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($rest)*)
    };

    ($finish:ident ()) => {
        #"no variables in #(...)* repetition"
    };

    ($finish:ident ($($found:ident)*)) => {
        $finish!(() $($found)*)
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! nested_tuples_pat {
    (() $first:ident $($rest:ident)*) => {
        nested_tuples_pat!(($first) $($rest)*)
    };

    (($pat:pat) $first:ident $($rest:ident)*) => {
        nested_tuples_pat!((($pat, $first)) $($rest)*)
    };

    (($done:pat)) => {
        $done
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! multi_zip_expr {
    (() $single:ident) => {
        $single
    };

    (() $first:ident $($rest:ident)*) => {
        multi_zip_expr!(($first.into_iter()) $($rest)*)
    };

    (($zips:expr) $first:ident $($rest:ident)*) => {
        multi_zip_expr!(($zips.zip($first)) $($rest)*)
    };

    (($done:expr)) => {
        $done
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! quote_each_token {
    ($tokens:ident) => {};

    ($tokens:ident # ! $($rest:tt)*) => {
        $tokens.append("#");
        $tokens.append("!");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # ( $($inner:tt)* ) * $($rest:tt)*) => {
        for pounded_var_names!(nested_tuples_pat () $($inner)*)
        in pounded_var_names!(multi_zip_expr () $($inner)*) {
            quote_each_token!($tokens $($inner)*);
        }
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # ( $($inner:tt)* ) $sep:tt * $($rest:tt)*) => {
        for (i, pounded_var_names!(nested_tuples_pat () $($inner)*))
        in pounded_var_names!(multi_zip_expr () $($inner)*).into_iter().enumerate() {
            if i > 0 {
                $tokens.append(stringify!($sep));
            }
            quote_each_token!($tokens $($inner)*);
        }
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # [ $($inner:tt)* ] $($rest:tt)*) => {
        $tokens.append("#");
        $tokens.append("[");
        quote_each_token!($tokens $($inner)*);
        $tokens.append("]");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # $first:ident $($rest:tt)*) => {
        $first.to_tokens(&mut $tokens);
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident ( $($first:tt)* ) $($rest:tt)*) => {
        $tokens.append("(");
        quote_each_token!($tokens $($first)*);
        $tokens.append(")");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident [ $($first:tt)* ] $($rest:tt)*) => {
        $tokens.append("[");
        quote_each_token!($tokens $($first)*);
        $tokens.append("]");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident { $($first:tt)* } $($rest:tt)*) => {
        $tokens.append("{");
        quote_each_token!($tokens $($first)*);
        $tokens.append("}");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident $first:tt $($rest:tt)*) => {
        $tokens.append(stringify!($first));
        quote_each_token!($tokens $($rest)*);
    };
}
<commit_msg>Comment the helper macros<commit_after>mod tokens;
pub use tokens::Tokens;

mod to_tokens;
pub use to_tokens::{ToTokens, ByteStr};

#[macro_export]
macro_rules! quote {
    ($($tt:tt)+) => {
        {
            #[allow(unused_imports)]
            use $crate::ToTokens;
            let mut _s = $crate::Tokens::new();
            quote_each_token!(_s $($tt)*);
            _s
        }
    };
}

// Extract the names of all #metavariables and pass them to the $finish macro.
//
// in:   pounded_var_names!(then () a #b c #( #d )* #e)
// out:  then!(() b d e)
#[macro_export]
#[doc(hidden)]
macro_rules! pounded_var_names {
    ($finish:ident ($($found:ident)*) # ( $($inner:tt)* ) $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) # [ $($inner:tt)* ] $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) # { $($inner:tt)* } $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) # $first:ident $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)* $first) $($rest)*)
    };

    ($finish:ident ($($found:ident)*) ( $($inner:tt)* ) $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) [ $($inner:tt)* ] $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) { $($inner:tt)* } $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) $ignore:tt $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($rest)*)
    };

    ($finish:ident ()) => {
        #"no variables in #(...)* repetition"
    };

    ($finish:ident ($($found:ident)*)) => {
        $finish!(() $($found)*)
    };
}

// in:   nested_tuples_pat!(() a b c d e)
// out:  ((((a b) c) d) e)
//
// in:   nested_tuples_pat!(() a)
// out:  a
#[macro_export]
#[doc(hidden)]
macro_rules! nested_tuples_pat {
    (() $first:ident $($rest:ident)*) => {
        nested_tuples_pat!(($first) $($rest)*)
    };

    (($pat:pat) $first:ident $($rest:ident)*) => {
        nested_tuples_pat!((($pat, $first)) $($rest)*)
    };

    (($done:pat)) => {
        $done
    };
}

// in:   multi_zip_expr!(() a b c d e)
// out:  a.into_iter().zip(b).zip(c).zip(d).zip(e)
//
// in:   multi_zip_iter!(() a)
// out:  a
#[macro_export]
#[doc(hidden)]
macro_rules! multi_zip_expr {
    (() $single:ident) => {
        $single
    };

    (() $first:ident $($rest:ident)*) => {
        multi_zip_expr!(($first.into_iter()) $($rest)*)
    };

    (($zips:expr) $first:ident $($rest:ident)*) => {
        multi_zip_expr!(($zips.zip($first)) $($rest)*)
    };

    (($done:expr)) => {
        $done
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! quote_each_token {
    ($tokens:ident) => {};

    ($tokens:ident # ! $($rest:tt)*) => {
        $tokens.append("#");
        $tokens.append("!");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # ( $($inner:tt)* ) * $($rest:tt)*) => {
        for pounded_var_names!(nested_tuples_pat () $($inner)*)
        in pounded_var_names!(multi_zip_expr () $($inner)*) {
            quote_each_token!($tokens $($inner)*);
        }
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # ( $($inner:tt)* ) $sep:tt * $($rest:tt)*) => {
        for (i, pounded_var_names!(nested_tuples_pat () $($inner)*))
        in pounded_var_names!(multi_zip_expr () $($inner)*).into_iter().enumerate() {
            if i > 0 {
                $tokens.append(stringify!($sep));
            }
            quote_each_token!($tokens $($inner)*);
        }
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # [ $($inner:tt)* ] $($rest:tt)*) => {
        $tokens.append("#");
        $tokens.append("[");
        quote_each_token!($tokens $($inner)*);
        $tokens.append("]");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # $first:ident $($rest:tt)*) => {
        $first.to_tokens(&mut $tokens);
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident ( $($first:tt)* ) $($rest:tt)*) => {
        $tokens.append("(");
        quote_each_token!($tokens $($first)*);
        $tokens.append(")");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident [ $($first:tt)* ] $($rest:tt)*) => {
        $tokens.append("[");
        quote_each_token!($tokens $($first)*);
        $tokens.append("]");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident { $($first:tt)* } $($rest:tt)*) => {
        $tokens.append("{");
        quote_each_token!($tokens $($first)*);
        $tokens.append("}");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident $first:tt $($rest:tt)*) => {
        $tokens.append(stringify!($first));
        quote_each_token!($tokens $($rest)*);
    };
}
<|endoftext|>


<commit_before>extern crate rand;
use std::str;
use std::fmt;
use rand::Rng;

#[derive(Debug, Eq, PartialEq, PartialOrd)]
pub struct Card {
    suit:  String,
    value: String,
}

#[derive(Debug, Eq, PartialEq, PartialOrd)]
pub struct Deck {
    cards: Vec<Card>
}

impl Card {
    pub fn new(suit: String, value: String) -> Card {
        Card { suit: suit, value: value.to_string() }
    }

    pub fn new_from_str(suit: &str, value: &str) -> Card {
        Card::new(suit.to_string(), value.to_string())
    }
}

impl Ord for Card {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.value.cmp(&other.value)
    }
}

impl fmt::Display for Card {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Suit: {}, Value: {}", self.suit, self.value)
    }
}

impl Deck {
    pub fn new_from_vec(input: Vec<Card>) -> Deck {
        Deck { cards: input }
    }

    pub fn make_standard() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠"];
        let values = &["2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Queen", "King", "Ace"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    pub fn make_fifth_dimension() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠", "★"];
        let values = &["1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Princess", "Queen", "King", "Joker"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    pub fn shuffle(&mut self) {
        rand::thread_rng().shuffle(&mut self.cards);
    }

    pub fn len(&self) {
        self.cards.len();
    }
}

impl Ord for Deck {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.cards.cmp(&other.cards)
    }
}
<commit_msg>derive clone<commit_after>extern crate rand;
use std::str;
use std::fmt;
use rand::Rng;

#[derive(Debug, Eq, PartialEq, PartialOrd, Clone)]
pub struct Card {
    suit:  String,
    value: String,
}

#[derive(Debug, Eq, PartialEq, PartialOrd, Clone)]
pub struct Deck {
    cards: Vec<Card>
}

impl Card {
    pub fn new(suit: String, value: String) -> Card {
        Card { suit: suit, value: value.to_string() }
    }

    pub fn new_from_str(suit: &str, value: &str) -> Card {
        Card::new(suit.to_string(), value.to_string())
    }
}

impl Ord for Card {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.value.cmp(&other.value)
    }
}

impl fmt::Display for Card {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Suit: {}, Value: {}", self.suit, self.value)
    }
}

impl Deck {
    pub fn new_from_vec(input: Vec<Card>) -> Deck {
        Deck { cards: input }
    }

    pub fn make_standard() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠"];
        let values = &["2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Queen", "King", "Ace"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    pub fn make_fifth_dimension() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠", "★"];
        let values = &["1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Princess", "Queen", "King", "Joker"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    pub fn shuffle(&mut self) {
        rand::thread_rng().shuffle(&mut self.cards);
    }

    pub fn len(&self) {
        self.cards.len();
    }
}

impl Ord for Deck {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.cards.cmp(&other.cards)
    }
}
<|endoftext|>


<commit_before>/// Sorter functions

/// Implementation of insertion sort
/// @victim Mutable array
pub fn insertion_sort<T: Ord>(victim: &mut [T]) {
    for i in 1..victim.len() {
        for j in (0..i).rev() {
            if victim[j+1] < victim[j] { victim.swap(j+1, j); }
            else { break; }
        }
    }
}

/// Implementation of shell sort
pub fn shell_sort<T: Ord + Clone>(victim: &mut [T]) {
    let gaps = [701, 301, 132, 57, 23, 10, 4, 1];

    for gap in gaps.iter() {
        for i in *gap..victim.len() {
            let mut j = i;
            let temp = victim[i].clone();
            while j >= *gap && victim[j-*gap] > temp {
                victim.swap(j, j-*gap);
                j -= *gap;
            }
            victim[j] = temp;
        }
    }
}

/// Implementation of shaker sort
pub fn shaker_sort<T: Ord>(victim: &mut [T]) {
    for _ in 0..victim.len() / 2 + 1 {
        let mut begin: usize = 0;
        let mut ending: usize = victim.len() - 1;

        while begin <= ending {
            if victim[begin] > victim[begin+1] { victim.swap(begin, begin+1); }
            if victim[ending-1] > victim[ending] { victim.swap(ending, ending-1); }
            begin += 1;
            ending -= 1;
        }
    }
}

/// ShiftDown for heap sort
fn shift_down<T: Ord>(victim: &mut [T], start: usize, ending: usize) {
    let mut root = start;
    loop {
        let mut child = root * 2 + 1;

        if child > ending { break; }
        else if child != ending && victim[child] < victim[child+1] { child += 1; }

        if victim[root] < victim[child] {
            victim.swap(root, child);
            root = child;
        }
        else { break; }
    }
}

/// Implementation of heap sort
pub fn heap_sort<T: Ord>(victim: &mut [T]) {
    let mut last = victim.len() - 1;
    //remember that range is exclusive for right element
    for i in (0..(last+1) / 2).rev() { shift_down(victim, i, last); }

    last += 1;
    for i in (1..last).rev() {
        victim.swap(0, i);
        shift_down(victim, 0, i-1); }
}

/// Implementation of quick sort
pub fn quick_sort<T: Ord>(victim: &mut [T]) {
    let mut last: usize = victim.len();
    if last < 2 { return; }

    let middle = last / 2;
    last -= 1;

    //choice of pivot and partition
    victim.swap(middle, last);

    let mut pivot_index = 0;
    for i in 0..last {
        if victim[i] <= victim[last] {
            victim.swap(i, pivot_index);
            pivot_index += 1;
        }
    }

    victim.swap(pivot_index, last);

    //next sort
    quick_sort(&mut victim[0..pivot_index]);
    quick_sort(&mut victim[pivot_index+1..last+1]);
}

/// Implementation of bubble sort
pub fn bubble_sort<T: Ord>(victim: &mut [T]) {
    for _ in 0..victim.len() {
        for j in 1..victim.len() {
            if victim[j-1] > victim[j] { victim.swap(j-1, j); }
        }
    }
}
<commit_msg>minor changes<commit_after>/// Sorter functions

/// Implementation of insertion sort
/// @victim Mutable array
pub fn insertion_sort<T: Ord>(victim: &mut [T]) {
    for i in 1..victim.len() {
        for j in (0..i).rev() {
            if victim[j+1] < victim[j] { victim.swap(j+1, j); }
            else { break; }
        }
    }
}

/// Implementation of shell sort
pub fn shell_sort<T: Ord + Clone>(victim: &mut [T]) {
    let gaps = [701, 301, 132, 57, 23, 10, 4, 1];

    for gap in gaps.iter() {
        for i in *gap..victim.len() {
            let mut j = i;
            let temp = victim[i].clone();
            while j >= *gap && victim[j-*gap] > temp {
                victim.swap(j, j-*gap);
                j -= *gap;
            }
            victim[j] = temp;
        }
    }
}

/// Implementation of shaker sort
pub fn shaker_sort<T: Ord>(victim: &mut [T]) {
    for _ in 0..victim.len() / 2 + 1 {
        let mut begin: usize = 0;
        let mut ending: usize = victim.len() - 1;

        while begin <= ending {
            if victim[begin] > victim[begin+1] { victim.swap(begin, begin+1); }
            if victim[ending-1] > victim[ending] { victim.swap(ending, ending-1); }
            begin += 1;
            ending -= 1;
        }
    }
}

/// ShiftDown for heap sort
#[inline(always)]
fn shift_down<T: Ord>(victim: &mut [T], start: usize, ending: usize) {
    let mut root = start;
    loop {
        let mut child = root * 2 + 1;

        if child > ending { break; }
        else if child != ending && victim[child] < victim[child+1] { child += 1; }

        if victim[root] < victim[child] {
            victim.swap(root, child);
            root = child;
        }
        else { break; }
    }
}

/// Implementation of heap sort
pub fn heap_sort<T: Ord>(victim: &mut [T]) {
    let last = victim.len() - 1;
    //remember that range is exclusive for right element
    for i in (0..(last+1) / 2).rev() { shift_down(victim, i, last); }

    let last = last + 1;
    for i in (1..last).rev() {
        victim.swap(0, i);
        shift_down(victim, 0, i-1); }
}

/// Implementation of quick sort
pub fn quick_sort<T: Ord>(victim: &mut [T]) {
    let last: usize = victim.len();
    if last < 2 { return; }

    let middle = last / 2;
    let last = last - 1;

    //choice of pivot and partition
    victim.swap(middle, last);

    let mut pivot_index = 0;
    for i in 0..last {
        if victim[i] <= victim[last] {
            victim.swap(i, pivot_index);
            pivot_index += 1;
        }
    }

    victim.swap(pivot_index, last);

    //next sort
    quick_sort(&mut victim[0..pivot_index]);
    quick_sort(&mut victim[pivot_index+1..last+1]);
}

/// Implementation of bubble sort
pub fn bubble_sort<T: Ord>(victim: &mut [T]) {
    for _ in 0..victim.len() {
        for j in 1..victim.len() {
            if victim[j-1] > victim[j] { victim.swap(j-1, j); }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(core_intrinsics)]
#![feature(stmt_expr_attributes)]

extern crate rand;
#[cfg(unix)] extern crate libc;
#[cfg(windows)] extern crate kernel32;
#[cfg(all(unix, test))] extern crate nix;

mod alloc;

pub use alloc::{ unprotected_mprotect, malloc, allocarray, free };

// -- memcmp --

/// Constant time memcmp.
pub unsafe fn memcmp<T>(b1: *const T, b2: *const T, len: usize) -> i32 {
    let b1 = b1 as *const u8;
    let b2 = b2 as *const u8;
    let mut d = 0;
    for i in 0..len as isize {
        d |= *b1.offset(i) ^ *b2.offset(i);
    }
    (1 & (d as i32 - 1) >> 8) - 1
}

// -- memset / memzero --

/// General memset.
#[cfg(not(HAVE_MEMSET_S))]
pub unsafe fn memset<T>(s: *mut T, c: i32, n: usize) {
    let s = s as *mut u8;
    let mut i = 0;
    while i < n {
        *s.offset(i as isize) = c as u8;
        i += 1;
    }
}

/// Call memset_s.
#[cfg(HAVE_MEMSET_S)]
pub unsafe fn memset<T>(s: *mut T, c: i32, n: usize) {
    extern {
        fn memset_s(s: *mut libc::c_void, smax: libc::size_t, c: libc::c_int, n: libc::size_t) -> libc::c_int;
    }
    memset_s(s as libc::c_void, n, c, n);
}

/// General memzero.
#[cfg(all(unix, not(HAVE_EXPLICIT_BZERO)))]
pub unsafe fn memzero<T>(dest: *mut T, n: usize) {
    memset(dest, 0, n);
}

/// Call explicit_bzero.
#[cfg(all(unix, HAVE_EXPLICIT_BZERO))]
pub unsafe fn memzero<T>(dest: *mut T, n: usize) {
    extern {
        fn explicit_bzero(s: *mut libc::c_void, n: libc::size_t);
    }
    explicit_bzero(dest as *mut libc::c_void, n);
}

/// call SecureZeroMemory.
#[cfg(windows)]
pub unsafe fn memzero<T>(s: *mut T, n: usize) {
    extern "system" {
        fn SecureZeroMemory(ptr: winapi::PVOID, cnt: winapi::SIZE_T);
    }
    SecureZeroMemory(s as winapi::PVOID, n as winapi::SIZE_T);
}

// -- mlock / munlock --

#[cfg(target_os = "linux")]
unsafe fn dontdump<T>(addr: *mut T, len: usize) {
    libc::madvise(addr as *mut libc::c_void, len, libc::MADV_DONTDUMP);
}

#[cfg(target_os = "linux")]
unsafe fn dodump<T>(addr: *mut T, len: usize) {
    libc::madvise(addr as *mut libc::c_void, len, libc::MADV_DODUMP);
}

#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
unsafe fn dontdump<T>(addr: *mut T, len: usize) {
    libc::madvise(addr as *mut libc::c_void, len, libc::MADV_NOCORE);
}

#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
unsafe fn dodump<T>(addr: *mut T, len: usize) {
    libc::madvise(addr as *mut libc::c_void, len, libc::MADV_CORE);
}

#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly")))]
fn dontdump<T>(_addr: *mut T, _len: usize) { }

#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly")))]
fn dodump<T>(_addr: *mut T, _len: usize) { }

/// Unix mlock.
#[cfg(unix)]
pub unsafe fn mlock<T>(addr: *mut T, len: usize) -> bool {
    dontdump(addr, len);
    libc::mlock(addr as *mut libc::c_void, len) == 0
}

/// Windows VirtualLock.
#[cfg(windows)]
pub unsafe fn mlock<T>(addr: *mut T, len: usize) -> bool {
    kernel32::VirtualLock(addr as winapi::LPVOID, len as winapi::SIZE_T) != 0
}

/// Unix munlock.
#[cfg(unix)]
pub unsafe fn munlock<T>(addr: *mut T, len: usize) -> bool {
    memzero(addr, len);
    dodump(addr, len);
    libc::munlock(addr as *mut libc::c_void, len) == 0
}

/// Windows VirtualUnlock.
#[cfg(windows)]
pub unsafe fn munlock<T>(addr: *mut T, len: usize) -> bool {
    memzero(addr, len);
    kernel32::VirtualUnlock(addr as winapi::LPVOID, len as winapi::SIZE_T) != 0
}

// -- mprotect --

/// Prot enum.
#[derive(Debug, Clone, PartialEq)]
pub enum Prot {
    #[cfg(unix)] NoAccess = libc::PROT_NONE as isize,
    #[cfg(unix)] ReadOnly = libc::PROT_READ as isize,
    #[cfg(unix)] WriteOnly = libc::PROT_WRITE as isize,
    #[cfg(unix)] ReadWrite = (libc::PROT_READ | libc::PROT_WRITE) as isize,
    #[cfg(unix)] Execute = libc::PROT_EXEC as isize,
    #[cfg(unix)] ReadExec = (libc::PROT_READ | libc::PROT_EXEC) as isize,
    #[cfg(unix)] WriteExec = (libc::PROT_WRITE | libc::PROT_EXEC) as isize,
    #[cfg(unix)] ReadWriteExec = (libc::PROT_READ | libc::PROT_WRITE | libc::PROT_EXEC) as isize,

    #[cfg(windows)] NoAccess = winapi::PAGE_NOACCESS as isize,
    #[cfg(windows)] ReadOnly = winapi::PAGE_READONLY as isize,
    #[cfg(windows)] ReadWrite = winapi::PAGE_READWRITE as isize,
    #[cfg(windows)] WriteCopy = winapi::PAGE_WRITECOPY as isize,
    #[cfg(windows)] Execute = winapi::PAGE_EXECUTE as isize,
    #[cfg(windows)] ReadExec = winapi::PAGE_EXECUTE_READ as isize,
    #[cfg(windows)] ReadWriteExec = winapi::PAGE_EXECUTE_READWRITE as isize,
    #[cfg(windows)] WriteCopyExec = winapi::PAGE_EXECUTE_WRITECOPY as isize,
    #[cfg(windows)] Guard = winapi::PAGE_GUARD as isize,
    #[cfg(windows)] NoCache = winapi::PAGE_NOCACHE as isize,
    #[cfg(windows)] WriteCombine = winapi::PAGE_WRITECOMBINE as isize,
    #[cfg(windows)] RevertToFileMap = winapi::PAGE_REVERT_TO_FILE_MAP as isize,
    #[cfg(windows)] TargetsNoUpdate = winapi::PAGE_TARGETS_NO_UPDATE as isize,
    #[cfg(windows)] TargetsInvalid = winapi::PAGE_TARGETS_INVALID as isize,
}

/// Unix mprotect.
#[cfg(unix)]
pub unsafe fn mprotect<T>(ptr: *mut T, len: usize, prot: Prot) -> bool {
    libc::mprotect(ptr as *mut libc::c_void, len, prot as libc::c_int) == 0
}

/// Windows VirtualProtect.
#[cfg(windows)]
pub unsafe fn mprotect<T>(ptr: *mut T, len: usize, prot: Prot) -> bool {
    kernel32::VirtualProtect(
        ptr as winapi::LPVOID,
        len as winapi::SIZE_T,
        prot as winapi::DWORD,
        core::mem::uninitialized()
    ) != 0
}
<commit_msg>fix cfg(windows)<commit_after>#![feature(core_intrinsics)]
#![feature(stmt_expr_attributes)]

extern crate rand;
#[cfg(unix)] extern crate libc;
#[cfg(windows)] extern crate winapi;
#[cfg(windows)] extern crate kernel32;
#[cfg(all(unix, test))] extern crate nix;

mod alloc;

pub use alloc::{ unprotected_mprotect, malloc, allocarray, free };

// -- memcmp --

/// Constant time memcmp.
pub unsafe fn memcmp<T>(b1: *const T, b2: *const T, len: usize) -> i32 {
    let b1 = b1 as *const u8;
    let b2 = b2 as *const u8;
    let mut d = 0;
    for i in 0..len as isize {
        d |= *b1.offset(i) ^ *b2.offset(i);
    }
    (1 & (d as i32 - 1) >> 8) - 1
}

// -- memset / memzero --

/// General memset.
#[cfg(not(HAVE_MEMSET_S))]
pub unsafe fn memset<T>(s: *mut T, c: i32, n: usize) {
    let s = s as *mut u8;
    let mut i = 0;
    while i < n {
        *s.offset(i as isize) = c as u8;
        i += 1;
    }
}

/// Call memset_s.
#[cfg(HAVE_MEMSET_S)]
pub unsafe fn memset<T>(s: *mut T, c: i32, n: usize) {
    extern {
        fn memset_s(s: *mut libc::c_void, smax: libc::size_t, c: libc::c_int, n: libc::size_t) -> libc::c_int;
    }
    memset_s(s as libc::c_void, n, c, n);
}

/// General memzero.
#[cfg(all(unix, not(HAVE_EXPLICIT_BZERO)))]
pub unsafe fn memzero<T>(dest: *mut T, n: usize) {
    memset(dest, 0, n);
}

/// Call explicit_bzero.
#[cfg(all(unix, HAVE_EXPLICIT_BZERO))]
pub unsafe fn memzero<T>(dest: *mut T, n: usize) {
    extern {
        fn explicit_bzero(s: *mut libc::c_void, n: libc::size_t);
    }
    explicit_bzero(dest as *mut libc::c_void, n);
}

/// call SecureZeroMemory.
#[cfg(windows)]
pub unsafe fn memzero<T>(s: *mut T, n: usize) {
    extern "system" {
        fn SecureZeroMemory(ptr: winapi::PVOID, cnt: winapi::SIZE_T);
    }
    SecureZeroMemory(s as winapi::PVOID, n as winapi::SIZE_T);
}

// -- mlock / munlock --

#[cfg(target_os = "linux")]
unsafe fn dontdump<T>(addr: *mut T, len: usize) {
    libc::madvise(addr as *mut libc::c_void, len, libc::MADV_DONTDUMP);
}

#[cfg(target_os = "linux")]
unsafe fn dodump<T>(addr: *mut T, len: usize) {
    libc::madvise(addr as *mut libc::c_void, len, libc::MADV_DODUMP);
}

#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
unsafe fn dontdump<T>(addr: *mut T, len: usize) {
    libc::madvise(addr as *mut libc::c_void, len, libc::MADV_NOCORE);
}

#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
unsafe fn dodump<T>(addr: *mut T, len: usize) {
    libc::madvise(addr as *mut libc::c_void, len, libc::MADV_CORE);
}

#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly")))]
fn dontdump<T>(_addr: *mut T, _len: usize) { }

#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly")))]
fn dodump<T>(_addr: *mut T, _len: usize) { }

/// Unix mlock.
#[cfg(unix)]
pub unsafe fn mlock<T>(addr: *mut T, len: usize) -> bool {
    dontdump(addr, len);
    libc::mlock(addr as *mut libc::c_void, len) == 0
}

/// Windows VirtualLock.
#[cfg(windows)]
pub unsafe fn mlock<T>(addr: *mut T, len: usize) -> bool {
    kernel32::VirtualLock(addr as winapi::LPVOID, len as winapi::SIZE_T) != 0
}

/// Unix munlock.
#[cfg(unix)]
pub unsafe fn munlock<T>(addr: *mut T, len: usize) -> bool {
    memzero(addr, len);
    dodump(addr, len);
    libc::munlock(addr as *mut libc::c_void, len) == 0
}

/// Windows VirtualUnlock.
#[cfg(windows)]
pub unsafe fn munlock<T>(addr: *mut T, len: usize) -> bool {
    memzero(addr, len);
    kernel32::VirtualUnlock(addr as winapi::LPVOID, len as winapi::SIZE_T) != 0
}

// -- mprotect --

/// Prot enum.
#[derive(Debug, Clone, PartialEq)]
pub enum Prot {
    #[cfg(unix)] NoAccess = libc::PROT_NONE as isize,
    #[cfg(unix)] ReadOnly = libc::PROT_READ as isize,
    #[cfg(unix)] WriteOnly = libc::PROT_WRITE as isize,
    #[cfg(unix)] ReadWrite = (libc::PROT_READ | libc::PROT_WRITE) as isize,
    #[cfg(unix)] Execute = libc::PROT_EXEC as isize,
    #[cfg(unix)] ReadExec = (libc::PROT_READ | libc::PROT_EXEC) as isize,
    #[cfg(unix)] WriteExec = (libc::PROT_WRITE | libc::PROT_EXEC) as isize,
    #[cfg(unix)] ReadWriteExec = (libc::PROT_READ | libc::PROT_WRITE | libc::PROT_EXEC) as isize,

    #[cfg(windows)] NoAccess = winapi::PAGE_NOACCESS as isize,
    #[cfg(windows)] ReadOnly = winapi::PAGE_READONLY as isize,
    #[cfg(windows)] ReadWrite = winapi::PAGE_READWRITE as isize,
    #[cfg(windows)] WriteCopy = winapi::PAGE_WRITECOPY as isize,
    #[cfg(windows)] Execute = winapi::PAGE_EXECUTE as isize,
    #[cfg(windows)] ReadExec = winapi::PAGE_EXECUTE_READ as isize,
    #[cfg(windows)] ReadWriteExec = winapi::PAGE_EXECUTE_READWRITE as isize,
    #[cfg(windows)] WriteCopyExec = winapi::PAGE_EXECUTE_WRITECOPY as isize,
    #[cfg(windows)] Guard = winapi::PAGE_GUARD as isize,
    #[cfg(windows)] NoCache = winapi::PAGE_NOCACHE as isize,
    #[cfg(windows)] WriteCombine = winapi::PAGE_WRITECOMBINE as isize,
    #[cfg(windows)] RevertToFileMap = winapi::PAGE_REVERT_TO_FILE_MAP as isize,
    #[cfg(windows)] TargetsNoUpdate = winapi::PAGE_TARGETS_NO_UPDATE as isize,
    #[cfg(windows)] TargetsInvalid = winapi::PAGE_TARGETS_INVALID as isize,
}

/// Unix mprotect.
#[cfg(unix)]
pub unsafe fn mprotect<T>(ptr: *mut T, len: usize, prot: Prot) -> bool {
    libc::mprotect(ptr as *mut libc::c_void, len, prot as libc::c_int) == 0
}

/// Windows VirtualProtect.
#[cfg(windows)]
pub unsafe fn mprotect<T>(ptr: *mut T, len: usize, prot: Prot) -> bool {
    kernel32::VirtualProtect(
        ptr as winapi::LPVOID,
        len as winapi::SIZE_T,
        prot as winapi::DWORD,
        std::ptr::null_mut()
    ) != 0
}
<|endoftext|>


<commit_before>extern crate librsync_sys as raw;

mod job;

use job::{Job, JobDriver};

use std::error;
use std::fmt::{self, Display, Formatter};
use std::io::{self, Read};
use std::ptr;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SignatureType {
    MD4,
    Blake2,
}

#[derive(Debug)]
pub enum Error {
    Done,
    Blocked,
    Running,
    TestSkipped,
    Io(io::Error),
    Syntax,
    Mem,
    InputEnded,
    BadMagic,
    Unimplemented,
    Corrupt,
    Internal,
    Param,
    Unknown(i32),
}

pub type Result<T> = std::result::Result<T, Error>;

pub struct Signature<R: Read> {
    driver: JobDriver<R>,
}

pub struct Delta<R: Read> {
    driver: JobDriver<R>,
    sumset: Sumset,
}

struct Sumset(*mut raw::rs_signature_t);

impl<R: Read> Signature<R> {
    pub fn new(old: R,
               new_block_len: usize,
               strong_len: usize,
               sig_magic: SignatureType)
               -> Result<Self> {
        let job = unsafe { raw::rs_sig_begin(new_block_len, strong_len, sig_magic.as_raw()) };
        if job.is_null() {
            return Err(Error::BadMagic);
        }
        Ok(Signature { driver: JobDriver::new(old, Job(job)), })
    }

    pub fn into_inner(self) -> R {
        self.driver.into_inner()
    }
}

impl<R: Read> Read for Signature<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.driver.read(buf)
    }
}

impl<R: Read> Delta<R> {
    pub fn new<R2: Read>(input: R, signature: R2) -> Result<Self> {
        let sumset = unsafe {
            let mut sumset = ptr::null_mut();
            let job = raw::rs_loadsig_begin(&mut sumset);
            assert!(!job.is_null());
            let mut job = JobDriver::new(signature, Job(job));
            try!(job.consume_input());
            Sumset(sumset)
        };
        unimplemented!()
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        ""
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref e) => write!(fmt, "{}", e),
            Error::Unknown(n) => write!(fmt, "Unknown error {} from librsync", n),
            _ => write!(fmt, "Error {:?} from librsync", self),
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<raw::rs_result> for Error {
    fn from(err: raw::rs_result) -> Error {
        match err {
            raw::RS_DONE => Error::Done,
            raw::RS_BLOCKED => Error::Blocked,
            raw::RS_RUNNING => Error::Running,
            raw::RS_TEST_SKIPPED => Error::TestSkipped,
            raw::RS_IO_ERROR => Error::Io(other_io_err("Unknown IO error from librsync")),
            raw::RS_SYNTAX_ERROR => Error::Syntax,
            raw::RS_MEM_ERROR => Error::Mem,
            raw::RS_INPUT_ENDED => Error::InputEnded,
            raw::RS_BAD_MAGIC => Error::BadMagic,
            raw::RS_UNIMPLEMENTED => Error::Unimplemented,
            raw::RS_CORRUPT => Error::Corrupt,
            raw::RS_INTERNAL_ERROR => Error::Internal,
            raw::RS_PARAM_ERROR => Error::Param,
            n => Error::Unknown(n),
        }
    }
}

impl SignatureType {
    pub fn from_raw(raw: raw::rs_magic_number) -> Option<Self> {
        match raw {
            raw::RS_MD4_SIG_MAGIC => Some(SignatureType::MD4),
            raw::RS_BLAKE2_SIG_MAGIC => Some(SignatureType::Blake2),
            _ => None,
        }
    }

    fn as_raw(&self) -> raw::rs_magic_number {
        match *self {
            SignatureType::MD4 => raw::RS_MD4_SIG_MAGIC,
            SignatureType::Blake2 => raw::RS_BLAKE2_SIG_MAGIC,
        }
    }
}

impl Drop for Sumset {
    fn drop(&mut self) {
        unsafe {
            if !self.0.is_null() {
                raw::rs_free_sumset(self.0);
            }
        }
    }
}

fn other_io_err<T: AsRef<str>>(msg: T) -> io::Error {
    io::Error::new(io::ErrorKind::Other, msg.as_ref())
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::{Cursor, Read};

    #[test]
    fn signature() {
        let data = "this is a string to be tested";
        let cursor = Cursor::new(data);
        let mut sig = Signature::new(cursor, 10, 5, SignatureType::MD4).unwrap();
        let mut signature = Vec::new();
        let read = sig.read_to_end(&mut signature).unwrap();
        assert_eq!(read, signature.len());
        let expected = vec![0x72, 0x73, 0x01, 0x36, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
                            0x05, 0x1b, 0x21, 0x04, 0x8b, 0xad, 0x3c, 0xbd, 0x19, 0x09, 0x1d,
                            0x1b, 0x04, 0xf0, 0x9d, 0x1f, 0x64, 0x31, 0xde, 0x15, 0xf4, 0x04,
                            0x87, 0x60, 0x96, 0x19, 0x50, 0x39];
        assert_eq!(signature, expected);
    }
}
<commit_msg>Better errors description<commit_after>extern crate librsync_sys as raw;

mod job;

use job::{Job, JobDriver};

use std::error;
use std::fmt::{self, Display, Formatter};
use std::io::{self, Read};
use std::ptr;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SignatureType {
    MD4,
    Blake2,
}

#[derive(Debug)]
pub enum Error {
    Blocked,
    Io(io::Error),
    Syntax,
    Mem,
    InputEnded,
    BadMagic,
    Unimplemented,
    Corrupt,
    Internal,
    Param,
    Unknown(i32),
}

pub type Result<T> = std::result::Result<T, Error>;

pub struct Signature<R: Read> {
    driver: JobDriver<R>,
}

pub struct Delta<R: Read> {
    driver: JobDriver<R>,
    sumset: Sumset,
}

struct Sumset(*mut raw::rs_signature_t);

impl<R: Read> Signature<R> {
    pub fn new(old: R,
               new_block_len: usize,
               strong_len: usize,
               sig_magic: SignatureType)
               -> Result<Self> {
        let job = unsafe { raw::rs_sig_begin(new_block_len, strong_len, sig_magic.as_raw()) };
        if job.is_null() {
            return Err(Error::BadMagic);
        }
        Ok(Signature { driver: JobDriver::new(old, Job(job)), })
    }

    pub fn into_inner(self) -> R {
        self.driver.into_inner()
    }
}

impl<R: Read> Read for Signature<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.driver.read(buf)
    }
}

impl<R: Read> Delta<R> {
    pub fn new<R2: Read>(input: R, signature: R2) -> Result<Self> {
        let sumset = unsafe {
            let mut sumset = ptr::null_mut();
            let job = raw::rs_loadsig_begin(&mut sumset);
            assert!(!job.is_null());
            let mut job = JobDriver::new(signature, Job(job));
            try!(job.consume_input());
            Sumset(sumset)
        };
        unimplemented!()
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Blocked => "blocked waiting for more data",
            Error::Io(ref err) => err.description(),
            Error::Syntax => "syntax error",
            Error::Mem => "out of memory",
            Error::InputEnded => "unexpected end of input file",
            Error::BadMagic => "bad magic number given",
            Error::Unimplemented => "unimplemented feature",
            Error::Corrupt => "unbelievable value in stream",
            Error::Internal => "internal error",
            Error::Param => "bad parameter",
            Error::Unknown(_) => "unknown error from librsync",
        }
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref e) => write!(fmt, "{}", e),
            Error::Unknown(n) => write!(fmt, "unknown error {} from native library", n),
            _ => write!(fmt, "{}", std::error::Error::description(self)),
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<raw::rs_result> for Error {
    fn from(err: raw::rs_result) -> Error {
        match err {
            raw::RS_BLOCKED => Error::Blocked,
            raw::RS_IO_ERROR => Error::Io(other_io_err("Unknown IO error from librsync")),
            raw::RS_SYNTAX_ERROR => Error::Syntax,
            raw::RS_MEM_ERROR => Error::Mem,
            raw::RS_INPUT_ENDED => Error::InputEnded,
            raw::RS_BAD_MAGIC => Error::BadMagic,
            raw::RS_UNIMPLEMENTED => Error::Unimplemented,
            raw::RS_CORRUPT => Error::Corrupt,
            raw::RS_INTERNAL_ERROR => Error::Internal,
            raw::RS_PARAM_ERROR => Error::Param,
            n => Error::Unknown(n),
        }
    }
}

impl SignatureType {
    pub fn from_raw(raw: raw::rs_magic_number) -> Option<Self> {
        match raw {
            raw::RS_MD4_SIG_MAGIC => Some(SignatureType::MD4),
            raw::RS_BLAKE2_SIG_MAGIC => Some(SignatureType::Blake2),
            _ => None,
        }
    }

    fn as_raw(&self) -> raw::rs_magic_number {
        match *self {
            SignatureType::MD4 => raw::RS_MD4_SIG_MAGIC,
            SignatureType::Blake2 => raw::RS_BLAKE2_SIG_MAGIC,
        }
    }
}

impl Drop for Sumset {
    fn drop(&mut self) {
        unsafe {
            if !self.0.is_null() {
                raw::rs_free_sumset(self.0);
            }
        }
    }
}

fn other_io_err<T: AsRef<str>>(msg: T) -> io::Error {
    io::Error::new(io::ErrorKind::Other, msg.as_ref())
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::{Cursor, Read};

    #[test]
    fn signature() {
        let data = "this is a string to be tested";
        let cursor = Cursor::new(data);
        let mut sig = Signature::new(cursor, 10, 5, SignatureType::MD4).unwrap();
        let mut signature = Vec::new();
        let read = sig.read_to_end(&mut signature).unwrap();
        assert_eq!(read, signature.len());
        let expected = vec![0x72, 0x73, 0x01, 0x36, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
                            0x05, 0x1b, 0x21, 0x04, 0x8b, 0xad, 0x3c, 0xbd, 0x19, 0x09, 0x1d,
                            0x1b, 0x04, 0xf0, 0x9d, 0x1f, 0x64, 0x31, 0xde, 0x15, 0xf4, 0x04,
                            0x87, 0x60, 0x96, 0x19, 0x50, 0x39];
        assert_eq!(signature, expected);
    }
}
<|endoftext|>


<commit_before>//! Leaf is a open, modular and clear-designed Machine Intelligence Framework providing
//! state-of-the-art performance for distributed (Deep|Machine) Learning - sharing concepts from
//! Tensorflow and Caffe.
//!
//! An important module in Leaf is the backend-agnostic, high-performance computation Framework
//! [Collenchyma][collenchyma], which combines performance and usability for Leaf Networks.
//! This allows you to run and deploy Leaf Networks to servers, desktops or even mobiles
//! using the full available computation power of GPUs or other CUDA/OpenCL supported
//! devices for the learning of your Networks. And if your machine does not have a GPU or you do
//! not want to install CUDA/OpenCL on your local machine, Leaf will gracefully fall back to
//! your native host CPU.
//!
//! ## Architecture
//!
//! Leaf's Networks are a compositional model, representing a collection of connected
//! [layers][layers], making operations over numerical data.
//!
//! Layers, the building block of a Leaf Network, are small units, describing computation over
//! numerical input data. Generally speaking Layers take input and produce an output, but
//! essentially a Layer can describe any functionality e.g. logging as long as it obeys to the
//! general behaviour specifications of a Layer. A Layer can be grouped in one of four
//! Layer types which are closer defined at the [Layers page][layers]. Every
//! layer serves a special purpose and can occur zero, one or many times inside a Network.
//!
//! Leaf uses [Collenchymas'][collenchyma] SharedTensor, an N-dimensional array
//! for a unified memory interface over the actual data for automatic synchronization between
//! different devices (CUDA, OpenCL, host CPU). A SharedTensor stores the actual data flowing
//! through the system and the weights required for some Layers.
//! The data in a SharedTensor can be copied from backend to backend
//! and can be used for computations on CUDA, OpenCL and native host CPU.
//! It provides performance optimizations and automatically takes care of memory management and synchronization.
//!
//! A neural network can be created by combining container layers like the `Sequential` Layer.
//! Those can be nested and allow for bigger neural networks to be constructed while still
//! retaining the interface of a Layer.
//!
//! The learning and optimization of the Network happens at the [Solver][solver] and is decoupled
//! from the network making the setup clean and flexible. One of the four layer types is a Loss
//! Layer, which is used for the interaction of Network and Solver. The Network produces the loss
//! and gradients, which the Solver uses to optimize the Network through parameter updates. Beside
//! that, the Solver provides housekeeping and other evaluations of the Network. All operation
//! on the Solver happen through Collenchyma, therefore can be executed on Cuda, OpenCL or native
//! host CPU as well.
//!
//! Leaf provides a robust and modular design, which allows to express almost any numerical
//! computation including SVMs, RNNs and other popular learning algorithms. We hope that Leaf can
//! help future research and production development alike as it combines expressiveness,
//! performance and usability.
//!
//! ## Philosophy
//!
//! We are strong believers in the technology of Machine Learning.
//!
//! We put our experience in software engineering into Leaf, to solve our own
//! need for a modern, performant and easy-to-use Deep Learning Framework.
//! These principles direct our decisions on Leaf and related projects.
//!
//! * __Cutting Edge Performance__:

//! For research and industry speed and efficency are curcial for
//! state-of-the-art machine learning over massive data and networks.
//! * __Open and Expressive Architecture__:

//! Designing an open architecture that follows best practices and concepts in
//! Engineering such as modularity, flexibility and expressiveness is critical
//! to stimulate future innovation.
//! * __Clear and Transparent Documentation__:

//! A well-written documentation that addresses both concepts and
//! implementations, empowers developers and researchers to contribute their
//! unique experience to the project for the benefit of everyone.
//!
//! ## Development
//!
//! The implementation of various Layers is pretty scarce at the moment.

//! There are around a dozen layers, which are really important and would
//! increase the value and functionality of Leaf tremendously.

//! Progress is tracked at

//!
//! - [Issue #18 for Loss Layers][issue-loss]
//! - [Issue #19 for Activation Layers][issue-activation]
//! - [Issue #20 for Common Layers][issue-common]
//!
//! [collenchyma]: https://github.com/autumnai/collenchyma
//! [network]: ./network/index.html
//! [layers]: ./layers/index.html
//! [activation]: ./layers/activation/index.html
//! [loss]: ./layers/loss/index.html
//! [solvers]: ./solvers/index.html
//! [optimization]: https://en.wikipedia.org/wiki/Stochastic_optimization
//!
//! [issue-loss]: https://github.com/autumnai/leaf/issues/18
//! [issue-activation]: https://github.com/autumnai/leaf/issues/19
//! [issue-common]: https://github.com/autumnai/leaf/issues/20
#![cfg_attr(feature="lint", feature(plugin))]
#![cfg_attr(feature="lint", plugin(clippy))]
#![cfg_attr(feature="lint", allow(type_complexity))]

#![allow(dead_code)]
#![allow(unused_variables)]
#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unused_import_braces, unused_qualifications)]

// used when run with  cargo test --no-run --features clippy
// or cargo build --features clippy
#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", deny(clippy, clippy_pedantic))]

#[macro_use]
extern crate timeit;
#[macro_use]
extern crate log;
extern crate rand;
extern crate num;
extern crate collenchyma as co;
extern crate collenchyma_blas as coblas;
extern crate collenchyma_nn as conn;
pub mod layer;
pub mod layers;
pub mod solver;
pub mod solvers;
pub mod weight;

pub mod util;
<commit_msg>Auto merge of #83 - palerdot:patch-2, r=hobofan<commit_after>//! Leaf is a open, modular and clear-designed Machine Intelligence Framework providing
//! state-of-the-art performance for distributed (Deep|Machine) Learning - sharing concepts from
//! Tensorflow and Caffe.
//!
//! An important module in Leaf is the backend-agnostic, high-performance computation Framework
//! [Collenchyma][collenchyma], which combines performance and usability for Leaf Networks.
//! This allows you to run and deploy Leaf Networks to servers, desktops or even mobiles
//! using the full available computation power of GPUs or other CUDA/OpenCL supported
//! devices for the learning of your Networks. And if your machine does not have a GPU or you do
//! not want to install CUDA/OpenCL on your local machine, Leaf will gracefully fall back to
//! your native host CPU.
//!
//! ## Architecture
//!
//! Leaf's Networks are a compositional model, representing a collection of connected
//! [layers][layers], making operations over numerical data.
//!
//! Layers, the building block of a Leaf Network, are small units, describing computation over
//! numerical input data. Generally speaking Layers take input and produce an output, but
//! essentially a Layer can describe any functionality e.g. logging as long as it obeys to the
//! general behaviour specifications of a Layer. A Layer can be grouped in one of four
//! Layer types which are closer defined at the [Layers page][layers]. Every
//! layer serves a special purpose and can occur zero, one or many times inside a Network.
//!
//! Leaf uses [Collenchymas'][collenchyma] SharedTensor, an N-dimensional array
//! for a unified memory interface over the actual data for automatic synchronization between
//! different devices (CUDA, OpenCL, host CPU). A SharedTensor stores the actual data flowing
//! through the system and the weights required for some Layers.
//! The data in a SharedTensor can be copied from backend to backend
//! and can be used for computations on CUDA, OpenCL and native host CPU.
//! It provides performance optimizations and automatically takes care of memory management and synchronization.
//!
//! A neural network can be created by combining container layers like the `Sequential` Layer.
//! Those can be nested and allow for bigger neural networks to be constructed while still
//! retaining the interface of a Layer.
//!
//! The learning and optimization of the Network happens at the [Solver][solver] and is decoupled
//! from the network making the setup clean and flexible. One of the four layer types is a Loss
//! Layer, which is used for the interaction of Network and Solver. The Network produces the loss
//! and gradients, which the Solver uses to optimize the Network through parameter updates. Beside
//! that, the Solver provides housekeeping and other evaluations of the Network. All operation
//! on the Solver happen through Collenchyma, therefore can be executed on Cuda, OpenCL or native
//! host CPU as well.
//!
//! Leaf provides a robust and modular design, which allows to express almost any numerical
//! computation including SVMs, RNNs and other popular learning algorithms. We hope that Leaf can
//! help future research and production development alike as it combines expressiveness,
//! performance and usability.
//!
//! ## Philosophy
//!
//! We are strong believers in the technology of Machine Learning.
//!
//! We put our experience in software engineering into Leaf, to solve our own
//! need for a modern, performant and easy-to-use Deep Learning Framework.
//! These principles direct our decisions on Leaf and related projects.
//!
//! * __Cutting Edge Performance__:

//! For research and industry speed and efficency are crucial for
//! state-of-the-art machine learning over massive data and networks.
//! * __Open and Expressive Architecture__:

//! Designing an open architecture that follows best practices and concepts in
//! Engineering such as modularity, flexibility and expressiveness is critical
//! to stimulate future innovation.
//! * __Clear and Transparent Documentation__:

//! A well-written documentation that addresses both concepts and
//! implementations, empowers developers and researchers to contribute their
//! unique experience to the project for the benefit of everyone.
//!
//! ## Development
//!
//! The implementation of various Layers is pretty scarce at the moment.

//! There are around a dozen layers, which are really important and would
//! increase the value and functionality of Leaf tremendously.

//! Progress is tracked at

//!
//! - [Issue #18 for Loss Layers][issue-loss]
//! - [Issue #19 for Activation Layers][issue-activation]
//! - [Issue #20 for Common Layers][issue-common]
//!
//! [collenchyma]: https://github.com/autumnai/collenchyma
//! [network]: ./network/index.html
//! [layers]: ./layers/index.html
//! [activation]: ./layers/activation/index.html
//! [loss]: ./layers/loss/index.html
//! [solvers]: ./solvers/index.html
//! [optimization]: https://en.wikipedia.org/wiki/Stochastic_optimization
//!
//! [issue-loss]: https://github.com/autumnai/leaf/issues/18
//! [issue-activation]: https://github.com/autumnai/leaf/issues/19
//! [issue-common]: https://github.com/autumnai/leaf/issues/20
#![cfg_attr(feature="lint", feature(plugin))]
#![cfg_attr(feature="lint", plugin(clippy))]
#![cfg_attr(feature="lint", allow(type_complexity))]

#![allow(dead_code)]
#![allow(unused_variables)]
#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unused_import_braces, unused_qualifications)]

// used when run with  cargo test --no-run --features clippy
// or cargo build --features clippy
#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", deny(clippy, clippy_pedantic))]

#[macro_use]
extern crate timeit;
#[macro_use]
extern crate log;
extern crate rand;
extern crate num;
extern crate collenchyma as co;
extern crate collenchyma_blas as coblas;
extern crate collenchyma_nn as conn;
pub mod layer;
pub mod layers;
pub mod solver;
pub mod solvers;
pub mod weight;

pub mod util;
<|endoftext|>


<commit_before>//! It can be useful to not have to worry about missing keys in a map.
//! If a key is requested that doesn't have a value a default value is simply returned.
//! This is exactly what this library provides.
//!
//! ## Examples

//! ### Counter
//! A clear use case of this is when counting the unique elements in a list.
//! Here you want to add one to the existing value in the map for that key.
//! This is a problem for the first addition when there's no value for the key yet.
//! With this library you can specify when creating the map that the default value should be zero.
//!

//! ```rust
//! # use defaultmap::*;
//! let nums = [1, 4, 3, 3, 4, 2, 4];
//! let mut counts:  DefaultHashMap<i32, i32> = DefaultHashMap::new(0);
//! // DefaultHashMap::default() is equivalent.
//!
//! for num in nums.into_iter() {
//!     counts[*num] += 1;
//! }
//!
//! println!("{:?}", counts);
//! // DefaultHashMap { map: {1: 1, 3: 2, 2: 1, 4: 3}, default: 0 }
//!
//! # assert_eq!(1, counts[1]);
//! # assert_eq!(1, counts[2]);
//! # assert_eq!(2, counts[3]);
//! # assert_eq!(3, counts[4]);
//! ```
//!

//! ### Synonym lists
//!
//! Another way the default map can be used is using a map filled with other collections, such as a
//! a `Vec`, a `HashMap` or even another default map.
//! Next follows some code to create a map where we start with tuples of synonyms and we end with a
//! map that contains the list of synonyms for each word.
//!
//! ```rust
//! # use defaultmap::*;
//!
//! let synonym_tuples = [
//!     ("nice", "sweet"),
//!     ("sweet", "candy"),
//!     ("nice", "entertaining"),
//!     ("nice", "good"),
//!     ("entertaining", "absorbing"),
//! ];
//!
//! let mut synonym_map: DefaultHashMap<&str, Vec<&str>> = DefaultHashMap::new(vec![]);
//! // DefaultHashMap::default() is equivalent.
//!
//! for &(l, r) in synonym_tuples.into_iter() {
//!     synonym_map[l].push(r);
//!     synonym_map[r].push(l);
//! }
//!
//! assert_eq!(synonym_map["good"], vec!["nice"]);
//! assert_eq!(synonym_map["nice"], vec!["sweet", "entertaining", "good"]);
//! assert_eq!(synonym_map["evil"], Vec::<&str>::new());
//! ```
//!

pub use hashmap::DefaultHashMap;

mod hashmap {
    use std::hash::Hash;
    use std::collections::HashMap;
    use std::collections::hash_map::*;
    use std::borrow::Borrow;
    use std::ops::{Index, IndexMut};

    /// A `HashMap` that has returns a default when keys are accessed that are not present.
    #[derive(PartialEq, Eq, Debug)]
    pub struct DefaultHashMap<K: Eq + Hash, V: Clone> {
        map: HashMap<K, V>,
        default: V,
    }

    impl<K: Eq + Hash, V: Default + Clone> Default for DefaultHashMap<K, V> {
        fn default() -> DefaultHashMap<K, V> {
            DefaultHashMap {
                map: HashMap::default(),
                default: V::default(),
            }
        }
    }

    impl<K: Eq + Hash, V: Clone> DefaultHashMap<K, V> {
        /// Creates an empty `DefaultHashmap` with `default` as the default for missing keys.
        /// When the provided `default` is equivalent to `V::default()` it is preferred to use
        /// `DefaultHashMap::default()` instead.
        pub fn new(default: V) -> DefaultHashMap<K, V> {
            DefaultHashMap {
                map: HashMap::new(),
                default: default,
            }
        }

        /// Creates a `DefaultHashMap` based on a default and an already existiting `HashMap`.
        pub fn new_with_map(default: V, map: HashMap<K, V>) -> DefaultHashMap<K, V> {
            DefaultHashMap {
                map: map,
                default: default,
            }
        }

        /// Returns a reference to the value stored for the provided key.
        /// If the key is not in the `DefaultHashMap` a reference to the default value is returned.
        /// Usually the `map[key]` method of retrieving keys is prefered over using `get` directly.
        /// This method accepts both references and owned values as the key.
        pub fn get<Q, QB: Borrow<Q>>(&self, key: QB) -> &V
            where K: Borrow<Q>,
                  Q: ?Sized + Hash + Eq
        {
            self.map.get(key.borrow()).unwrap_or(&self.default)
        }

        /// Returns a mutable reference to the value stored for the provided key.
        /// If there is no value stored for the key the default value is first inserted for this
        /// key before returning the reference.
        /// Usually the `map[key] = new_val` is prefered over using `get_mut` directly.
        /// This method only accepts owned values as the key.
        pub fn get_mut(&mut self, key: K) -> &mut V {
            self.map.entry(key).or_insert(self.default.clone())
        }
    }

    /// Implements the `Index` trait so you can do `map[key]`.
    /// Nonmutable indexing can be done both by passing a reference or an owned value as the key.
    impl<'a, K: Eq + Hash, KB: Borrow<K>, V: Clone> Index<KB> for DefaultHashMap<K, V> {
        type Output = V;

        fn index(&self, index: KB) -> &V {
            self.get(index)
        }
    }

    /// Implements the `IndexMut` trait so you can do `map[key] = val`.
    /// Mutably indexing can only be done when passing an owned value as the key.
    impl<K: Eq + Hash, V: Clone> IndexMut<K> for DefaultHashMap<K, V> {
        #[inline]
        fn index_mut(&mut self, index: K) -> &mut V {
            self.get_mut(index)
        }
    }

    /// These methods simply forward to the underlying `HashMap`, see that
    /// [documentation](https://doc.rust-lang.org/std/collections/struct.HashMap.html) for
    /// the usage of these methods.
    impl<K: Eq + Hash, V: Clone> DefaultHashMap<K, V> {
        pub fn capacity(&self) -> usize {
            self.map.capacity()
        }
        #[inline]
        pub fn reserve(&mut self, additional: usize) {
            self.map.reserve(additional)
        }
        #[inline]
        pub fn shrink_to_fit(&mut self) {
            self.map.shrink_to_fit()
        }
        #[inline]
        pub fn keys(&self) -> Keys<K, V> {
            self.map.keys()
        }
        #[inline]
        pub fn values(&self) -> Values<K, V> {
            self.map.values()
        }
        #[inline]
        pub fn values_mut(&mut self) -> ValuesMut<K, V> {
            self.map.values_mut()
        }
        #[inline]
        pub fn iter(&self) -> Iter<K, V> {
            self.map.iter()
        }
        #[inline]
        pub fn iter_mut(&mut self) -> IterMut<K, V> {
            self.map.iter_mut()
        }
        #[inline]
        pub fn entry(&mut self, key: K) -> Entry<K, V> {
            self.map.entry(key)
        }
        #[inline]
        pub fn len(&self) -> usize {
            self.map.len()
        }
        #[inline]
        pub fn is_empty(&self) -> bool {
            self.map.is_empty()
        }
        #[inline]
        pub fn drain(&mut self) -> Drain<K, V> {
            self.map.drain()
        }
        #[inline]
        pub fn clear(&mut self) {
            self.map.clear()
        }
        #[inline]
        pub fn insert(&mut self, k: K, v: V) -> Option<V> {
            self.map.insert(k, v)
        }
        #[inline]
        pub fn contains_key<Q>(&self, k: &Q) -> (bool)
            where K: Borrow<Q>,
                  Q: Hash + Eq
        {
            self.map.contains_key(k)
        }
        #[inline]
        pub fn remove<Q>(&mut self, k: &Q) -> (Option<V>)
            where K: Borrow<Q>,
                  Q: Hash + Eq
        {
            self.map.remove(k)
        }

    }

}

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

    #[test]
    fn add() {
        let mut map: DefaultHashMap<i32, i32> = DefaultHashMap::default();
        *map.get_mut(0) += 1;
        map[1] += 4;
        map[2] = map[0] + map.get(&1);
        assert_eq!(*map.get(0), 1);
        assert_eq!(*map.get(&0), 1);
        assert_eq!(map[0], 1);
        assert_eq!(map[&0], 1);
        assert_eq!(*map.get(&1), 4);
        assert_eq!(*map.get(&2), 5);
        assert_eq!(*map.get(999), 0);
        assert_eq!(*map.get(&999), 0);
        assert_eq!(map[999], 0);
        assert_eq!(map[&999], 0);
    }

    #[test]
    fn counter() {
        let nums = [1, 4, 3, 3, 4, 2, 4];
        let mut counts: DefaultHashMap<i32, i32> = DefaultHashMap::default();
        for num in nums.into_iter() {
            counts[*num] += 1;
        }

        assert_eq!(1, counts[1]);
        assert_eq!(1, counts[2]);
        assert_eq!(2, counts[3]);
        assert_eq!(3, counts[4]);
        assert_eq!(0, counts[5]);
    }

    #[test]
    fn synonyms() {
        let synonym_tuples = [
            ("nice", "sweet"),
            ("sweet", "candy"),
            ("nice", "entertaining"),
            ("nice", "good"),
            ("entertaining", "absorbing"),
        ];

        let mut synonym_map: DefaultHashMap<&str, Vec<&str>> = DefaultHashMap::default();

        for &(l, r) in synonym_tuples.into_iter() {
            synonym_map[l].push(r);
            synonym_map[r].push(l);
        }

        println!("{:#?}", synonym_map);
        assert_eq!(synonym_map["good"], vec!["nice"]);
        assert_eq!(synonym_map["nice"], vec!["sweet", "entertaining", "good"]);
        assert_eq!(synonym_map["evil"], Vec::<&str>::new());
        // assert!(false)
    }

    #[derive(Clone)]
    struct Clonable;

    #[derive(Default, Clone)]
    struct DefaultableValue;

    #[derive(Hash, Eq, PartialEq)]
    struct Hashable(i32);

    #[test]
    fn minimal_derives() {
        let minimal: DefaultHashMap<Hashable, Clonable> = DefaultHashMap::new(Clonable);
        let clonable: DefaultHashMap<Hashable, DefaultableValue> = DefaultHashMap::default();
    }

}
<commit_msg>Add forgotten ?Sized constraint to forwarding methods<commit_after>//! It can be useful to not have to worry about missing keys in a map.
//! If a key is requested that doesn't have a value a default value is simply returned.
//! This is exactly what this library provides.
//!
//! ## Examples

//! ### Counter
//! A clear use case of this is when counting the unique elements in a list.
//! Here you want to add one to the existing value in the map for that key.
//! This is a problem for the first addition when there's no value for the key yet.
//! With this library you can specify when creating the map that the default value should be zero.
//!

//! ```rust
//! # use defaultmap::*;
//! let nums = [1, 4, 3, 3, 4, 2, 4];
//! let mut counts:  DefaultHashMap<i32, i32> = DefaultHashMap::new(0);
//! // DefaultHashMap::default() is equivalent.
//!
//! for num in nums.into_iter() {
//!     counts[*num] += 1;
//! }
//!
//! println!("{:?}", counts);
//! // DefaultHashMap { map: {1: 1, 3: 2, 2: 1, 4: 3}, default: 0 }
//!
//! # assert_eq!(1, counts[1]);
//! # assert_eq!(1, counts[2]);
//! # assert_eq!(2, counts[3]);
//! # assert_eq!(3, counts[4]);
//! ```
//!

//! ### Synonym lists
//!
//! Another way the default map can be used is using a map filled with other collections, such as a
//! a `Vec`, a `HashMap` or even another default map.
//! Next follows some code to create a map where we start with tuples of synonyms and we end with a
//! map that contains the list of synonyms for each word.
//!
//! ```rust
//! # use defaultmap::*;
//!
//! let synonym_tuples = [
//!     ("nice", "sweet"),
//!     ("sweet", "candy"),
//!     ("nice", "entertaining"),
//!     ("nice", "good"),
//!     ("entertaining", "absorbing"),
//! ];
//!
//! let mut synonym_map: DefaultHashMap<&str, Vec<&str>> = DefaultHashMap::new(vec![]);
//! // DefaultHashMap::default() is equivalent.
//!
//! for &(l, r) in synonym_tuples.into_iter() {
//!     synonym_map[l].push(r);
//!     synonym_map[r].push(l);
//! }
//!
//! assert_eq!(synonym_map["good"], vec!["nice"]);
//! assert_eq!(synonym_map["nice"], vec!["sweet", "entertaining", "good"]);
//! assert_eq!(synonym_map["evil"], Vec::<&str>::new());
//! ```
//!

pub use hashmap::DefaultHashMap;

mod hashmap {
    use std::hash::Hash;
    use std::collections::HashMap;
    use std::collections::hash_map::*;
    use std::borrow::Borrow;
    use std::ops::{Index, IndexMut};

    /// A `HashMap` that has returns a default when keys are accessed that are not present.
    #[derive(PartialEq, Eq, Debug)]
    pub struct DefaultHashMap<K: Eq + Hash, V: Clone> {
        map: HashMap<K, V>,
        default: V,
    }

    impl<K: Eq + Hash, V: Default + Clone> Default for DefaultHashMap<K, V> {
        fn default() -> DefaultHashMap<K, V> {
            DefaultHashMap {
                map: HashMap::default(),
                default: V::default(),
            }
        }
    }

    impl<K: Eq + Hash, V: Clone> DefaultHashMap<K, V> {
        /// Creates an empty `DefaultHashmap` with `default` as the default for missing keys.
        /// When the provided `default` is equivalent to `V::default()` it is preferred to use
        /// `DefaultHashMap::default()` instead.
        pub fn new(default: V) -> DefaultHashMap<K, V> {
            DefaultHashMap {
                map: HashMap::new(),
                default: default,
            }
        }

        /// Creates a `DefaultHashMap` based on a default and an already existiting `HashMap`.
        pub fn new_with_map(default: V, map: HashMap<K, V>) -> DefaultHashMap<K, V> {
            DefaultHashMap {
                map: map,
                default: default,
            }
        }

        /// Returns a reference to the value stored for the provided key.
        /// If the key is not in the `DefaultHashMap` a reference to the default value is returned.
        /// Usually the `map[key]` method of retrieving keys is prefered over using `get` directly.
        /// This method accepts both references and owned values as the key.
        pub fn get<Q, QB: Borrow<Q>>(&self, key: QB) -> &V
            where K: Borrow<Q>,
                  Q: ?Sized + Hash + Eq
        {
            self.map.get(key.borrow()).unwrap_or(&self.default)
        }

        /// Returns a mutable reference to the value stored for the provided key.
        /// If there is no value stored for the key the default value is first inserted for this
        /// key before returning the reference.
        /// Usually the `map[key] = new_val` is prefered over using `get_mut` directly.
        /// This method only accepts owned values as the key.
        pub fn get_mut(&mut self, key: K) -> &mut V {
            self.map.entry(key).or_insert(self.default.clone())
        }
    }

    /// Implements the `Index` trait so you can do `map[key]`.
    /// Nonmutable indexing can be done both by passing a reference or an owned value as the key.
    impl<'a, K: Eq + Hash, KB: Borrow<K>, V: Clone> Index<KB> for DefaultHashMap<K, V> {
        type Output = V;

        fn index(&self, index: KB) -> &V {
            self.get(index)
        }
    }

    /// Implements the `IndexMut` trait so you can do `map[key] = val`.
    /// Mutably indexing can only be done when passing an owned value as the key.
    impl<K: Eq + Hash, V: Clone> IndexMut<K> for DefaultHashMap<K, V> {
        #[inline]
        fn index_mut(&mut self, index: K) -> &mut V {
            self.get_mut(index)
        }
    }

    /// These methods simply forward to the underlying `HashMap`, see that
    /// [documentation](https://doc.rust-lang.org/std/collections/struct.HashMap.html) for
    /// the usage of these methods.
    impl<K: Eq + Hash, V: Clone> DefaultHashMap<K, V> {
        pub fn capacity(&self) -> usize {
            self.map.capacity()
        }
        #[inline]
        pub fn reserve(&mut self, additional: usize) {
            self.map.reserve(additional)
        }
        #[inline]
        pub fn shrink_to_fit(&mut self) {
            self.map.shrink_to_fit()
        }
        #[inline]
        pub fn keys(&self) -> Keys<K, V> {
            self.map.keys()
        }
        #[inline]
        pub fn values(&self) -> Values<K, V> {
            self.map.values()
        }
        #[inline]
        pub fn values_mut(&mut self) -> ValuesMut<K, V> {
            self.map.values_mut()
        }
        #[inline]
        pub fn iter(&self) -> Iter<K, V> {
            self.map.iter()
        }
        #[inline]
        pub fn iter_mut(&mut self) -> IterMut<K, V> {
            self.map.iter_mut()
        }
        #[inline]
        pub fn entry(&mut self, key: K) -> Entry<K, V> {
            self.map.entry(key)
        }
        #[inline]
        pub fn len(&self) -> usize {
            self.map.len()
        }
        #[inline]
        pub fn is_empty(&self) -> bool {
            self.map.is_empty()
        }
        #[inline]
        pub fn drain(&mut self) -> Drain<K, V> {
            self.map.drain()
        }
        #[inline]
        pub fn clear(&mut self) {
            self.map.clear()
        }
        #[inline]
        pub fn insert(&mut self, k: K, v: V) -> Option<V> {
            self.map.insert(k, v)
        }
        #[inline]
        pub fn contains_key<Q>(&self, k: &Q) -> (bool)
            where K: Borrow<Q>,
                  Q: ?Sized + Hash + Eq
        {
            self.map.contains_key(k)
        }
        #[inline]
        pub fn remove<Q>(&mut self, k: &Q) -> (Option<V>)
            where K: Borrow<Q>,
                  Q: ?Sized + Hash + Eq
        {
            self.map.remove(k)
        }
    }

}

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

    #[test]
    fn add() {
        let mut map: DefaultHashMap<i32, i32> = DefaultHashMap::default();
        *map.get_mut(0) += 1;
        map[1] += 4;
        map[2] = map[0] + map.get(&1);
        assert_eq!(*map.get(0), 1);
        assert_eq!(*map.get(&0), 1);
        assert_eq!(map[0], 1);
        assert_eq!(map[&0], 1);
        assert_eq!(*map.get(&1), 4);
        assert_eq!(*map.get(&2), 5);
        assert_eq!(*map.get(999), 0);
        assert_eq!(*map.get(&999), 0);
        assert_eq!(map[999], 0);
        assert_eq!(map[&999], 0);
    }

    #[test]
    fn counter() {
        let nums = [1, 4, 3, 3, 4, 2, 4];
        let mut counts: DefaultHashMap<i32, i32> = DefaultHashMap::default();
        for num in nums.into_iter() {
            counts[*num] += 1;
        }

        assert_eq!(1, counts[1]);
        assert_eq!(1, counts[2]);
        assert_eq!(2, counts[3]);
        assert_eq!(3, counts[4]);
        assert_eq!(0, counts[5]);
    }

    #[test]
    fn synonyms() {
        let synonym_tuples = [
            ("nice", "sweet"),
            ("sweet", "candy"),
            ("nice", "entertaining"),
            ("nice", "good"),
            ("entertaining", "absorbing"),
        ];

        let mut synonym_map: DefaultHashMap<&str, Vec<&str>> = DefaultHashMap::default();

        for &(l, r) in synonym_tuples.into_iter() {
            synonym_map[l].push(r);
            synonym_map[r].push(l);
        }

        println!("{:#?}", synonym_map);
        assert_eq!(synonym_map["good"], vec!["nice"]);
        assert_eq!(synonym_map["nice"], vec!["sweet", "entertaining", "good"]);
        assert_eq!(synonym_map["evil"], Vec::<&str>::new());
        // assert!(false)
    }

    #[derive(Clone)]
    struct Clonable;

    #[derive(Default, Clone)]
    struct DefaultableValue;

    #[derive(Hash, Eq, PartialEq)]
    struct Hashable(i32);

    #[test]
    fn minimal_derives() {
        let minimal: DefaultHashMap<Hashable, Clonable> = DefaultHashMap::new(Clonable);
        let clonable: DefaultHashMap<Hashable, DefaultableValue> = DefaultHashMap::default();
    }

}
<|endoftext|>


<commit_before>#![crate_type = "lib"]
#![warn(missing_docs)]

//! Synchronization primitives based on spinning

#![feature(no_std, const_fn, asm)]
#![no_std]

#[cfg(test)]
extern crate std;

pub use mutex::*;
pub use rw_lock::*;

mod mutex;
mod rw_lock;
<commit_msg>Remove feature no_std<commit_after>#![crate_type = "lib"]
#![warn(missing_docs)]

//! Synchronization primitives based on spinning

#![feature(const_fn, asm)]
#![no_std]

#[cfg(test)]
extern crate std;

pub use mutex::*;
pub use rw_lock::*;

mod mutex;
mod rw_lock;
<|endoftext|>


<commit_before>#![feature(macro_rules)]

pub struct Slide<T: Iterator, A> {
  iter: T,
  n: uint,
  window: Vec
}

macro_rules! return_if(
  ($cond:expr, $value:expr) => (
    if $cond {
      return $value;
    }
  );
)

impl<A: Clone, T: Iterator> Slide<T, A> {
  fn push_window(&mut self) -> bool {
    let iter_next = self.iter.next();
    let is_some = iter_next.is_some();

    if is_some {
      self.window.push(iter_next.unwrap());
    }

    is_some
  }

  fn new(iter: T, n: uint) -> Slide<T, A> {
    Slide{
      iter: iter,
      n: n,
      window: Vec::with_capacity(n + 1)
    }
  }
}

impl<A: Clone, T: Iterator> Iterator<Vec> for Slide<T, A> {
  fn next(&mut self) -> Option<Vec> {
    return_if!(self.n == 0, None);
    return_if!(!self.push_window(), None);

    loop {
      let window_status = self.window.len().cmp(&self.n);

      match window_status {
        Greater => { self.window.remove(0); }
        Equal => { return Some(self.window.clone()); }
        Less => { return_if!(!self.push_window(), None); }
      }
    }
  }
}

pub trait SlideIterator<T: Iterator, A> {
  fn slide(self, n: uint) -> Slide<T, A>;
}

impl<A: Clone, T: Iterator> SlideIterator<T, A> for T {
  fn slide(self, n: uint) -> Slide<T, A> {
    Slide::new(self, n)
  }
}

#[test]
fn test_slide() {
  let mut slide_iter = vec![1i, 2, 3, 4, 5].into_iter().slide(3);
  assert_eq!(slide_iter.next().unwrap(), vec![1, 2, 3])
  assert_eq!(slide_iter.next().unwrap(), vec![2, 3, 4])
  assert_eq!(slide_iter.next().unwrap(), vec![3, 4, 5])
  assert!(slide_iter.next().is_none())
}

#[test]
fn test_slide_equal_window() {
  let mut slide_iter = vec![1i, 2, 3, 4, 5].into_iter().slide(5);
  assert_eq!(slide_iter.next().unwrap(), vec![1, 2, 3, 4, 5])
  assert!(slide_iter.next().is_none())
}

#[test]
fn test_slide_zero_window() {
  let mut slide_iter = vec![1i, 2, 3, 4, 5].into_iter().slide(0);
  assert!(slide_iter.next().is_none())
}

#[test]
fn test_slide_overlong_window() {
  let mut slide_iter = vec![1i, 2, 3, 4, 5].into_iter().slide(7);
  assert!(slide_iter.next().is_none())
}
<commit_msg>Made it compile on latest nightly<commit_after>#![feature(macro_rules)]

pub struct Slide<T: Iterator, A> {
  iter: T,
  n: uint,
  window: Vec
}

macro_rules! return_if(
  ($cond:expr, $value:expr) => (
    if $cond {
      return $value;
    }
  );
);

impl<A: Clone, T: Iterator> Slide<T, A> {
  fn push_window(&mut self) -> bool {
    let iter_next = self.iter.next();
    let is_some = iter_next.is_some();

    if is_some {
      self.window.push(iter_next.unwrap());
    }

    is_some
  }

  fn new(iter: T, n: uint) -> Slide<T, A> {
    Slide{
      iter: iter,
      n: n,
      window: Vec::with_capacity(n + 1)
    }
  }
}

impl<A: Clone, T: Iterator> Iterator<Vec> for Slide<T, A> {
  fn next(&mut self) -> Option<Vec> {
    return_if!(self.n == 0, None);
    return_if!(!self.push_window(), None);

    loop {
      let window_status = self.window.len().cmp(&self.n);

      match window_status {
        Greater => { self.window.remove(0); }
        Equal => { return Some(self.window.clone()); }
        Less => { return_if!(!self.push_window(), None); }
      }
    }
  }
}

pub trait SlideIterator<T: Iterator, A> {
  fn slide(self, n: uint) -> Slide<T, A>;
}

impl<A: Clone, T: Iterator> SlideIterator<T, A> for T {
  fn slide(self, n: uint) -> Slide<T, A> {
    Slide::new(self, n)
  }
}

#[test]
fn test_slide() {
  let mut slide_iter = vec![1i, 2, 3, 4, 5].into_iter().slide(3);
  assert_eq!(slide_iter.next().unwrap(), vec![1, 2, 3]);
  assert_eq!(slide_iter.next().unwrap(), vec![2, 3, 4]);
  assert_eq!(slide_iter.next().unwrap(), vec![3, 4, 5]);
  assert!(slide_iter.next().is_none());
}

#[test]
fn test_slide_equal_window() {
  let mut slide_iter = vec![1i, 2, 3, 4, 5].into_iter().slide(5);
  assert_eq!(slide_iter.next().unwrap(), vec![1, 2, 3, 4, 5]);
  assert!(slide_iter.next().is_none());
}

#[test]
fn test_slide_zero_window() {
  let mut slide_iter = vec![1i, 2, 3, 4, 5].into_iter().slide(0);
  assert!(slide_iter.next().is_none());
}

#[test]
fn test_slide_overlong_window() {
  let mut slide_iter = vec![1i, 2, 3, 4, 5].into_iter().slide(7);
  assert!(slide_iter.next().is_none());
}
<|endoftext|>


<commit_before>#![feature(plugin_registrar)]
#![feature(box_syntax, rustc_private)]

extern crate syntax;
extern crate syntax_pos;

// Load rustc as a plugin to get macros
#[macro_use]
extern crate rustc;
extern crate rustc_plugin;

extern crate ispell;
extern crate markdown;

use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass,
                  LateLintPassObject, LintArray};
use rustc::hir;
// use rustc::hir::attr;
use rustc::hir::map as hir_map;
use rustc_plugin::Registry;
use syntax::ast;
use syntax::ast::MetaItemKind;
use syntax::ast::LitKind;
use syntax::attr;
use syntax_pos::Span;

use std::collections::HashSet;

use ispell::{SpellLauncher, SpellChecker};
use markdown::{Block, ListItem, Span as MdSpan};

declare_lint!(SPELLING_ERROR, Warn, "Warn about spelling errors.");

pub struct SpellingError {
    /// Stack of IDs of struct definitions.
    struct_def_stack: Vec<ast::NodeId>,

    /// True if inside variant definition
    in_variant: bool,

    /// Stack of whether #[doc(hidden)] is set
    /// at each level which has lint attributes.
    doc_hidden_stack: Vec<bool>,

    /// Private traits or trait items that leaked through. Don't check their methods.
    private_traits: HashSet<ast::NodeId>,
}

impl SpellingError {
    pub fn new() -> SpellingError {
        SpellingError {
            struct_def_stack: vec![],
            in_variant: false,
            doc_hidden_stack: vec![false],
            private_traits: HashSet::new(),
        }
    }

    fn doc_hidden(&self) -> bool {
        *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
    }

    fn prepare_line(input: String) -> String {
        let mut result = input;

        // TODO: only replace if at line beginning
        result = result.replace("//! ", "");
        result = result.replace("//!", "");
        result = result.replace("/// ", "");
        result = result.replace("///", "");
        result = result.replace("// ", "");
        result = result.replace("//", "");

        result
    }

    fn travserse_markdown_block(checker: &mut SpellChecker, cx: &LateContext, sp: Span, block: &Block) {
        match *block {
            Block::Header(ref spans, _) => {
                for span in spans {
                    Self::travserse_markdown_span(checker, cx, sp, span);
                }
            },
            Block::Paragraph(ref spans) => {
                for span in spans {
                    Self::travserse_markdown_span(checker, cx, sp, span);
                }
            }
            Block::Blockquote(_) => {}, // TODO
            Block::CodeBlock(_) => (),
            Block::UnorderedList(_) => {}, // TODO
            Block::Raw(_) => {}, // TODO
            Block::Hr => {},
        }
    }

    fn travserse_markdown_span(checker: &mut SpellChecker, cx: &LateContext, sp: Span, span: &MdSpan) {
        match *span {
            MdSpan::Break => (),
            MdSpan::Text(ref text) => {
                Self::check_text(checker, cx, sp, text.clone());
            },
            MdSpan::Code(_) => (),
            MdSpan::Link(_, _, _) => {}, // TODO
            MdSpan::Image(_, _, _) => {}, // TODO: check alt text?
            MdSpan::Emphasis(ref spans) => {
                for span in spans {
                    Self::travserse_markdown_span(checker, cx, sp, span);
                }
            },
            MdSpan::Strong(ref spans) => {
                for span in spans {
                    Self::travserse_markdown_span(checker, cx, sp, span);
                }
            },
        }
    }

    fn check_text(checker: &mut SpellChecker, cx: &LateContext, sp: Span, test_text: String) {
        if let Ok(errors) = checker.check(&test_text) {
            for e in errors {
                // println!("'{}' (pos: {}) is misspelled!", &e.misspelled, e.position);
                if !e.suggestions.is_empty() {
                    // println!("Maybe you meant '{}'?", &e.suggestions[0]);
                    cx.span_lint(SPELLING_ERROR,
                                 sp,
                                 &format!("'{}' is misspelled. Maybe you meant '{}'",
                                     &e.misspelled,
                                     &e.suggestions[0]
                                 ));
                }
            }
            // println!("{:?}", text.as_str());
        } else {
            println!("FAILED RUNNING CHECK ON LINE:");
            println!("{}", test_text);
        }
    }

    fn check_spelling_errors(&self,
                                cx: &LateContext,
                                id: Option<ast::NodeId>,
                                attrs: &[ast::Attribute],
                                sp: Span,
                                desc: &'static str) {
        // If we're building a test harness, then warning about
        // documentation is probably not really relevant right now.
        if cx.sess().opts.test {
            return;
        }

        // // `#[doc(hidden)]` disables missing_docs check.
        // if self.doc_hidden() {
        //     return;
        // }

        // Only check publicly-visible items, using the result from the privacy pass.
        // It's an option so the crate root can also use this function (it doesn't
        // have a NodeId).
        if let Some(id) = id {
            if !cx.access_levels.is_exported(id) {
                return;
            }
        }

        let mut text_block = "".to_owned();
        println!("=====START BLOCK=====");

        let mut checker = SpellLauncher::new()
            .aspell()
            .dictionary("en")
            .timeout(1000)
            .launch()
            .unwrap();

        let maybe_lines: Vec<Option<String>> = attrs.iter().map(|attr|
            match attr.value.node {
                MetaItemKind::NameValue(ref spanned) => {
                    match spanned.node {
                        LitKind::Str(text, _) => {
                            let mut test_text = text.as_str().to_string();
                            test_text = Self::prepare_line(test_text);

                            return Some(test_text);
                        },
                        _ => None,
                    }
                },
                _ => None,
            }
        ).collect();

        let lines: Vec<_> = maybe_lines.into_iter().filter_map(|l| l).collect();
        let text_block = lines.join("\n");

        println!("{}", text_block);
        let blocks = markdown::tokenize(&text_block);
        for block in &blocks {
            Self::travserse_markdown_block(&mut checker, cx, sp, block);
            // println!("{:?}", block);
        }

        println!("=====END BLOCK=====");

        // let has_doc = attrs.iter().any(|a| a.is_value_str() && a.name() == "doc");
        // if !has_doc {
        //     cx.span_lint(SPELLING_ERROR,
        //                  sp,
        //                  &format!("missing documentation for {}", desc));
        // }
    }
}

impl LintPass for SpellingError {
    fn get_lints(&self) -> LintArray {
        lint_array!(SPELLING_ERROR)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SpellingError {
    fn enter_lint_attrs(&mut self, _: &LateContext, attrs: &[ast::Attribute]) {
        let doc_hidden = self.doc_hidden() ||
                         attrs.iter().any(|attr| {
            attr.check_name("doc") &&
            match attr.meta_item_list() {
                None => false,
                Some(l) => attr::list_contains_name(&l[..], "hidden"),
            }
        });
        self.doc_hidden_stack.push(doc_hidden);
    }

    fn exit_lint_attrs(&mut self, _: &LateContext, _attrs: &[ast::Attribute]) {
        self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
    }

    fn check_struct_def(&mut self,
                        _: &LateContext,
                        _: &hir::VariantData,
                        _: ast::Name,
                        _: &hir::Generics,
                        item_id: ast::NodeId) {
        self.struct_def_stack.push(item_id);
    }

    fn check_struct_def_post(&mut self,
                             _: &LateContext,
                             _: &hir::VariantData,
                             _: ast::Name,
                             _: &hir::Generics,
                             item_id: ast::NodeId) {
        let popped = self.struct_def_stack.pop().expect("empty struct_def_stack");
        assert!(popped == item_id);
    }

    fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
        self.check_spelling_errors(cx, None, &krate.attrs, krate.span, "crate");
    }

    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
        let desc = match it.node {
            hir::ItemFn(..) => "a function",
            hir::ItemMod(..) => "a module",
            hir::ItemEnum(..) => "an enum",
            hir::ItemStruct(..) => "a struct",
            hir::ItemUnion(..) => "a union",
            hir::ItemTrait(.., ref trait_item_refs) => {
                // Issue #11592, traits are always considered exported, even when private.
                // if it.vis == hir::Visibility::Inherited {
                //     self.private_traits.insert(it.id);
                //     for trait_item_ref in trait_item_refs {
                //         self.private_traits.insert(trait_item_ref.id.node_id);
                //     }
                //     return;
                // }
                "a trait"
            }
            hir::ItemTy(..) => "a type alias",
            hir::ItemImpl(.., Some(ref trait_ref), _, ref impl_item_refs) => {
                // If the trait is private, add the impl items to private_traits so they don't get
                // reported for missing docs.
                let real_trait = trait_ref.path.def.def_id();
                if let Some(node_id) = cx.tcx.map.as_local_node_id(real_trait) {
                    match cx.tcx.map.find(node_id) {
                        Some(hir_map::NodeItem(item)) => {
                            if item.vis == hir::Visibility::Inherited {
                                for impl_item_ref in impl_item_refs {
                                    self.private_traits.insert(impl_item_ref.id.node_id);
                                }
                            }
                        }
                        _ => {}
                    }
                }
                return;
            }
            hir::ItemConst(..) => "a constant",
            hir::ItemStatic(..) => "a static",
            _ => return,
        };
        // println!("{:?}", desc);
        // println!("{:?}", it.attrs);

        self.check_spelling_errors(cx, Some(it.id), &it.attrs, it.span, desc);
    }

    // fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
    //     if self.private_traits.contains(&trait_item.id) {
    //         return;
    //     }
    //
    //     let desc = match trait_item.node {
    //         hir::TraitItemKind::Const(..) => "an associated constant",
    //         hir::TraitItemKind::Method(..) => "a trait method",
    //         hir::TraitItemKind::Type(..) => "an associated type",
    //     };
    //
    //     self.check_spelling_errors(cx,
    //                                   Some(trait_item.id),
    //                                   &trait_item.attrs,
    //                                   trait_item.span,
    //                                   desc);
    // }
    //
    // fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
    //     // If the method is an impl for a trait, don't doc.
    //     if method_context(cx, impl_item.id, impl_item.span) == MethodLateContext::TraitImpl {
    //         return;
    //     }
    //
    //     let desc = match impl_item.node {
    //         hir::ImplItemKind::Const(..) => "an associated constant",
    //         hir::ImplItemKind::Method(..) => "a method",
    //         hir::ImplItemKind::Type(_) => "an associated type",
    //     };
    //     self.check_spelling_errors(cx,
    //                                   Some(impl_item.id),
    //                                   &impl_item.attrs,
    //                                   impl_item.span,
    //                                   desc);
    // }
    //
    // fn check_struct_field(&mut self, cx: &LateContext, sf: &hir::StructField) {
    //     if !sf.is_positional() {
    //         if sf.vis == hir::Public || self.in_variant {
    //             let cur_struct_def = *self.struct_def_stack
    //                 .last()
    //                 .expect("empty struct_def_stack");
    //             self.check_spelling_errors(cx,
    //                                           Some(cur_struct_def),
    //                                           &sf.attrs,
    //                                           sf.span,
    //                                           "a struct field")
    //         }
    //     }
    // }
    //
    // fn check_variant(&mut self, cx: &LateContext, v: &hir::Variant, _: &hir::Generics) {
    //     self.check_spelling_errors(cx,
    //                                   Some(v.node.data.id()),
    //                                   &v.node.attrs,
    //                                   v.span,
    //                                   "a variant");
    //     assert!(!self.in_variant);
    //     self.in_variant = true;
    // }
    //
    // fn check_variant_post(&mut self, _: &LateContext, _: &hir::Variant, _: &hir::Generics) {
    //     assert!(self.in_variant);
    //     self.in_variant = false;
    // }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_late_lint_pass(box SpellingError::new() as LateLintPassObject);
}
<commit_msg>refactor(cleanup): clean up copied over comments<commit_after>#![feature(plugin_registrar)]
#![feature(box_syntax, rustc_private)]

extern crate syntax;
extern crate syntax_pos;

// Load rustc as a plugin to get macros
#[macro_use]
extern crate rustc;
extern crate rustc_plugin;

extern crate ispell;
extern crate markdown;

use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass,
                  LateLintPassObject, LintArray};
use rustc::hir;
use rustc_plugin::Registry;
use syntax::ast;
use syntax::ast::MetaItemKind;
use syntax::ast::LitKind;
use syntax::attr;
use syntax_pos::Span;

use ispell::{SpellLauncher, SpellChecker};
use markdown::{Block, Span as MdSpan};

declare_lint!(SPELLING_ERROR, Warn, "Warn about spelling errors.");

pub struct SpellingError {
    /// Stack of IDs of struct definitions.
    struct_def_stack: Vec<ast::NodeId>,

    /// Stack of whether #[doc(hidden)] is set
    /// at each level which has lint attributes.
    doc_hidden_stack: Vec<bool>,
}

impl SpellingError {
    pub fn new() -> SpellingError {
        SpellingError {
            struct_def_stack: vec![],
            doc_hidden_stack: vec![false],
        }
    }

    fn doc_hidden(&self) -> bool {
        *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
    }

    fn prepare_line(input: String) -> String {
        let mut result = input;

        // TODO: only replace if at line beginning
        result = result.replace("//! ", "");
        result = result.replace("//!", "");
        result = result.replace("/// ", "");
        result = result.replace("///", "");
        result = result.replace("// ", "");
        result = result.replace("//", "");

        result
    }

    fn travserse_markdown_block(checker: &mut SpellChecker, cx: &LateContext, sp: Span, block: &Block) {
        match *block {
            Block::Header(ref spans, _) => {
                for span in spans {
                    Self::travserse_markdown_span(checker, cx, sp, span);
                }
            },
            Block::Paragraph(ref spans) => {
                for span in spans {
                    Self::travserse_markdown_span(checker, cx, sp, span);
                }
            }
            Block::Blockquote(_) => {}, // TODO
            Block::CodeBlock(_) => (),
            Block::UnorderedList(_) => {}, // TODO
            Block::Raw(_) => {}, // TODO
            Block::Hr => {},
        }
    }

    fn travserse_markdown_span(checker: &mut SpellChecker, cx: &LateContext, sp: Span, span: &MdSpan) {
        match *span {
            MdSpan::Break => (),
            MdSpan::Text(ref text) => {
                Self::check_text(checker, cx, sp, text.clone());
            },
            MdSpan::Code(_) => (),
            MdSpan::Link(_, _, _) => {}, // TODO
            MdSpan::Image(_, _, _) => {}, // TODO: check alt text?
            MdSpan::Emphasis(ref spans) => {
                for span in spans {
                    Self::travserse_markdown_span(checker, cx, sp, span);
                }
            },
            MdSpan::Strong(ref spans) => {
                for span in spans {
                    Self::travserse_markdown_span(checker, cx, sp, span);
                }
            },
        }
    }

    fn check_text(checker: &mut SpellChecker, cx: &LateContext, sp: Span, test_text: String) {
        if let Ok(errors) = checker.check(&test_text) {
            for e in errors {
                if !e.suggestions.is_empty() {
                    cx.span_lint(SPELLING_ERROR,
                                 sp,
                                 &format!("'{}' is misspelled. Maybe you meant '{}'",
                                     &e.misspelled,
                                     &e.suggestions[0]
                                 ));
                }
            }
            // println!("{:?}", text.as_str());
        } else {
            // DEBUG
            // println!("FAILED RUNNING CHECK ON LINE:");
            // println!("{}", test_text);
        }
    }

    fn check_spelling_errors(&self,
                                cx: &LateContext,
                                id: Option<ast::NodeId>,
                                attrs: &[ast::Attribute],
                                sp: Span) {
        // If we're building a test harness, then warning about
        // documentation is probably not really relevant right now.
        if cx.sess().opts.test {
            return;
        }

        // // `#[doc(hidden)]` disables missing_docs check.
        // if self.doc_hidden() {
        //     return;
        // }

        // Only check publicly-visible items, using the result from the privacy pass.
        // It's an option so the crate root can also use this function (it doesn't
        // have a NodeId).
        if let Some(id) = id {
            if !cx.access_levels.is_exported(id) {
                return;
            }
        }

        // println!("=====START BLOCK====="); // DEBUG

        let mut checker = SpellLauncher::new()
            .aspell()
            .dictionary("en")
            .timeout(1000)
            .launch()
            .unwrap();

        let maybe_lines: Vec<Option<String>> = attrs.iter().map(|attr|
            match attr.value.node {
                MetaItemKind::NameValue(ref spanned) => {
                    match spanned.node {
                        LitKind::Str(text, _) => {
                            let mut test_text = text.as_str().to_string();
                            test_text = Self::prepare_line(test_text);

                            return Some(test_text);
                        },
                        _ => None,
                    }
                },
                _ => None,
            }
        ).collect();

        let lines: Vec<_> = maybe_lines.into_iter().filter_map(|l| l).collect();
        let text_block = lines.join("\n");

        let blocks = markdown::tokenize(&text_block);
        for block in &blocks {
            Self::travserse_markdown_block(&mut checker, cx, sp, block);
        }

        // println!("=====END BLOCK====="); // DEBUG
    }
}

impl LintPass for SpellingError {
    fn get_lints(&self) -> LintArray {
        lint_array!(SPELLING_ERROR)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SpellingError {
    fn enter_lint_attrs(&mut self, _: &LateContext, attrs: &[ast::Attribute]) {
        let doc_hidden = self.doc_hidden() ||
                         attrs.iter().any(|attr| {
            attr.check_name("doc") &&
            match attr.meta_item_list() {
                None => false,
                Some(l) => attr::list_contains_name(&l[..], "hidden"),
            }
        });
        self.doc_hidden_stack.push(doc_hidden);
    }

    fn exit_lint_attrs(&mut self, _: &LateContext, _attrs: &[ast::Attribute]) {
        self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
    }

    fn check_struct_def(&mut self,
                        _: &LateContext,
                        _: &hir::VariantData,
                        _: ast::Name,
                        _: &hir::Generics,
                        item_id: ast::NodeId) {
        self.struct_def_stack.push(item_id);
    }

    fn check_struct_def_post(&mut self,
                             _: &LateContext,
                             _: &hir::VariantData,
                             _: ast::Name,
                             _: &hir::Generics,
                             item_id: ast::NodeId) {
        let popped = self.struct_def_stack.pop().expect("empty struct_def_stack");
        assert!(popped == item_id);
    }

    fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
        self.check_spelling_errors(cx, None, &krate.attrs, krate.span);
    }

    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
        self.check_spelling_errors(cx, Some(it.id), &it.attrs, it.span);
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_late_lint_pass(box SpellingError::new() as LateLintPassObject);
}
<|endoftext|>