<commit_before>use std::collections::{BTreeMap, HashMap, HashSet};
use std::collections::hash_map::Entry::*;
use std::hash::{Hash, Hasher};
use std::iter;
use std::str::CharIndices;
use std::ops;
use itertools::{GroupBy, Itertools};
use coalesce::Coalesce;

/// A Document contains an id and content.
/// Hashing and equality are based only on the id field.
#[derive(Clone, Debug, Eq, Ord, RustcEncodable, RustcDecodable)]
pub struct Document {
    id: String,
    content: String,
}

impl Document {
    /// Construct a new Document from an id and content.
    /// Both two arguments can be anything that can be turned into a String.
    pub fn new<S, T>(id: S, content: T) -> Document
        where S: Into<String>,
              T: Into<String>
    {
        Document { id: id.into(), content: content.into(), }
    }

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

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

impl Hash for Document {
    // Documents are unique only upon their id
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.id.hash(state);
    }
}

impl PartialEq for Document {
    // Documents are unique only upon their id
    fn eq(&self, other: &Document) -> bool {
        self.id == other.id
    }
}

impl PartialOrd for Document {
    fn partial_cmp(&self, other: &Document) -> Option<::std::cmp::Ordering> {
        self.id.partial_cmp(&other.id)
    }
}

/// A SearchResult is the representation of a Document returned for a specific set of search
/// terms. It is unique upon the document and the vec of highlight indices. It also contains a
/// search score for use in ranking against the other search results
#[derive(Clone, Debug, RustcEncodable)]
pub struct SearchResult<'a> {
    doc: &'a Document,
    highlights: Vec<(usize, usize)>,
    score: f32,
}

impl<'a> SearchResult<'a> {
    fn new(doc: &'a Document, mut highlights: Vec<(usize, usize)>) -> SearchResult<'a> {
        SearchResult {
            score: highlights.iter()
                .map(|&(begin, end)| end - begin)
                .sum::<usize>() as f32 / (doc.content.len() as f32).sqrt(),
            doc: doc,
            highlights: { highlights.sort(); highlights },
        }
    }

    /// Returns the document
    pub fn doc(&self) -> &Document {
        &self.doc
    }

    /// Returns the highlighted indices.
    ///
    /// Each `(usize, usize)` indicates the start and end of a term in the document's content
    /// that should be highlighted.
    pub fn highlights(&self) -> &Vec<(usize, usize)> {
        &self.highlights
    }

    /// Returns the search result's score.
    ///
    /// Score is computed by the product of the summed length of the matching terms and the inverse
    /// square root of the length of the document. Taking the square root of the document's length
    /// helps to combat bias toward short content.
    pub fn score(&self) -> f32 {
        self.score
    }

    pub fn highlight(&self, before: &str, after: &str) -> String {
        let mut begin_idx = 0;
        let mut parts = String::new();
        for &(begin, end) in &self.highlights {
            parts.push_str(&self.doc.content[begin_idx..begin]);
            parts.push_str(before);
            parts.push_str(&self.doc.content[begin..end]);
            parts.push_str(after);
            begin_idx = end;
        }
        parts.push_str(&self.doc.content[begin_idx..]);
        parts
    }
}

/// A basic implementation of an `Index`, the inverted index is a data structure that maps
/// from words to sets of Documents.
#[derive(Debug)]
pub struct InvertedIndex {
    index: BTreeMap<String, BTreeMap<String, Vec<(usize, usize)>>>,
    docs: BTreeMap<String, Document>,
}

impl InvertedIndex {
    pub fn new() -> InvertedIndex {
        InvertedIndex {
            index: BTreeMap::new(),
            docs: BTreeMap::new(),
        }
    }

    /// A basic implementation of index, splits the document's content into whitespace-separated
    /// words, and inserts each word-document pair into the map.
    pub fn index(&mut self, doc: Document) {
        let analyzed  = analyze_doc(doc.content());
        let previous_version = self.docs.insert(doc.id.clone(), doc.clone());
        if let Some(previous_version) = previous_version {
            let previous_analyzed = analyze_doc(previous_version.content());
            for (ngram, _) in previous_analyzed {
                let is_empty = {
                    let docs_for_ngram = self.index.get_mut(&ngram).unwrap();
                    docs_for_ngram.remove(&doc.id);
                    docs_for_ngram.is_empty()
                };
                if is_empty {
                    self.index.remove(&ngram);
                }
            }
        }

        for (ngram, highlighted) in analyzed {
            let mut highlights = self.index.entry(ngram)
                .or_insert_with(BTreeMap::new)
                .entry(doc.id.clone())
                .or_insert_with(Vec::new);
            let coalesce_idx = highlights.binary_search(&highlighted).err().unwrap();
            highlights.coalesce(coalesce_idx, highlighted);
        }
    }

    /// A basic search implementation that splits the query's content into whitespace-separated
    /// words, looks up the set of Documents for each word, and then concatenates the sets.
    pub fn search(&self, query: &str) -> Vec<SearchResult> {
        let unique_terms: HashSet<_> = query.split_whitespace().map(str::to_lowercase).collect();
        let map: HashMap<String, Vec<(usize, usize)>> = unique_terms.into_iter()
            .flat_map(|word| self.index.get(&word))
            .flat_map(BTreeMap::iter)
            .fold(HashMap::new(), |mut map, (doc_id, highlights)| {
                match map.entry(doc_id.clone()) {
                    Vacant(entry) => { entry.insert(highlights.clone()); },
                    Occupied(mut entry) => {
                        let entry: &mut Vec<(usize, usize)> = entry.get_mut();
                        for highlight in highlights {
                            let coalesce_idx = entry.binary_search(highlight).err().unwrap();
                            entry.coalesce(coalesce_idx, highlight.clone());
                        }
                    }
                }
                map
            });
        let mut results: Vec<_> = map.into_iter()
            .map(|(doc_id, index_map)| SearchResult::new(&self.docs[&doc_id], index_map.into_iter().collect()))
            .collect();
        results.sort_by(|result1, result2| result2.score.partial_cmp(&result1.score).unwrap());
        results
    }
}

fn analyze_doc(doc: &str)
-> iter::FlatMap<
    iter::Filter<
        GroupBy<bool, CharIndices, fn(&(usize, char)) -> bool>,
        fn(&(bool, Vec<(usize, char)>)) -> bool>,
    iter::Map<ops::Range<usize>, Ngrams>,
    fn((bool, Vec<(usize, char)>)) -> iter::Map<ops::Range<usize>, Ngrams>>
{
    doc.char_indices()
        .group_by(is_whitespace as fn(&(usize, char)) -> bool)
        .filter(not_whitespace as fn(&(bool, Vec<(usize, char)>)) -> bool)
        .flat_map(ngrams)
}

fn ngrams((_, chars): (bool, Vec<(usize, char)>)) -> iter::Map<ops::Range<usize>, Ngrams> {
    (1..chars.len() + 1).map(Ngrams::new(chars))
}

fn not_whitespace(&(is_whitespace, _): &(bool, Vec<(usize, char)>)) -> bool {
    !is_whitespace
}

fn is_whitespace(&(_, c): &(usize, char)) -> bool {
    c.is_whitespace()
}

struct Ngrams {
    chars: Vec<(usize, char)>
}

impl Ngrams {
    fn new(chars: Vec<(usize, char)>) -> Ngrams {
        Ngrams { chars: chars }
    }
}

impl Fn<(usize,)> for Ngrams {
    extern "rust-call" fn call(&self, (to,): (usize,)) -> (String, (usize, usize)) {
        let word = self.chars[..to].iter().flat_map(|&(_, c)| c.to_lowercase()).collect();
        let start = self.chars[0].0;
        let (last_idx, last_char) = self.chars[to - 1];
        let finish = last_idx + last_char.len_utf8();
        (word, (start, finish))
    }
}

impl FnMut<(usize,)> for Ngrams {
    extern "rust-call" fn call_mut(&mut self, to: (usize,)) -> (String, (usize, usize)) {
        self.call(to)
    }
}

impl FnOnce<(usize,)> for Ngrams {
    type Output = (String, (usize, usize));
    extern "rust-call" fn call_once(self, to: (usize,)) -> (String, (usize, usize)) {
        self.call(to)
    }
}

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

    #[test]
    fn test_ngrams() {
        let mut index = InvertedIndex::new();
        let doc1 = Document::new("1", "learn to program in rust today");
        let doc2 = Document::new("2", "what did you today do");
        index.index(doc1.clone());
        index.index(doc2.clone());
        let search_results = index.search("to");
        let expected: BTreeMap<_, _> = [
            (doc1.clone(), vec![(6, 8), (25, 27)]),
            (doc2, vec![(13, 15)]),
        ].iter().cloned().collect();
        assert_eq!(search_results.len(), expected.len());
        for search_result in &search_results {
            assert_eq!(&search_result.highlights, &expected[search_result.doc])
        }
        assert_eq!("learn to program in rust \
                   today",
                   search_results.iter()
                        .find(|search_result| search_result.doc == &doc1)
                        .unwrap()
                        .highlight("", ""));

    }

    #[test]
    fn test_highlight() {
        let mut index = InvertedIndex::new();
        let doc1 = Document::new("2", "Won\u{2019}t this split the ecosystem? Will everyone use?");
        index.index(doc1.clone());
        let expected =  "Won\u{2019}t this split the *e*cosystem? Will *e*veryone use?";
        let search_results = index.search("e");
        assert_eq!(1, search_results.len());
        assert_eq!(search_results[0].highlight("*", "*"), expected);
    }

    #[test]
    fn test_unicode() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "嗨, 您好");
        index.index(doc.clone());
        let to_search = "您";
        let search_results = index.search(to_search);
        let &SearchResult { ref doc, ref highlights, .. } = search_results.iter().next().unwrap();
        let (begin, end) = highlights[0];
        assert_eq!(&doc.content()[begin..end], to_search);
    }

    #[test]
    fn test_update_doc() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "abc åäö");
        index.index(doc);
        let doc = Document::new("0", "different");
        index.index(doc);
        let search_results = index.search("å");
        assert!(search_results.is_empty());
        assert_eq!(index.docs.len(), 1);
    }

    #[test]
    fn test_ranking() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "beat");
        index.index(doc.clone());
        let doc2 = Document::new("1", "beast");
        index.index(doc2);
        let search_results = index.search("be");
        assert_eq!(index.docs.len(), 2);
        // "beat" should be first, since it's a closer match
        assert_eq!(search_results[0].doc, &doc);
    }

    #[test]
    fn test_duplicate_term() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "beat");
        index.index(doc.clone());
        let search_results = index.search("be be");
        assert_eq!(search_results.len(), 1);
    }

    #[test]
    fn test_duplicate_term2() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "beat");
        index.index(doc.clone());
        let search_results = index.search("be b");
        assert_eq!(search_results.len(), 1);
        assert_eq!(search_results[0].highlights, vec![(0, 2)]);
    }

    #[test]
    fn test_lowercase_search() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "BeAt");
        index.index(doc.clone());
        let search_results = index.search("bE");
        assert_eq!(search_results.len(), 1);
        assert_eq!(search_results[0].highlights, vec![(0, 2)]);
    }

    #[test]
    fn test_lowercase_index() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "BeAt");
        index.index(doc.clone());
        let search_results = index.search("be");
        assert_eq!(search_results.len(), 1);
        assert_eq!(search_results[0].highlights, vec![(0, 2)]);
    }
}
<commit_msg>formatting<commit_after>use std::collections::{BTreeMap, HashMap, HashSet};
use std::collections::hash_map::Entry::*;
use std::hash::{Hash, Hasher};
use std::iter;
use std::str::CharIndices;
use std::ops;
use itertools::{GroupBy, Itertools};
use coalesce::Coalesce;

/// A Document contains an id and content.
/// Hashing and equality are based only on the id field.
#[derive(Clone, Debug, Eq, Ord, RustcEncodable, RustcDecodable)]
pub struct Document {
    id: String,
    content: String,
}

impl Document {
    /// Construct a new Document from an id and content.
    /// Both two arguments can be anything that can be turned into a String.
    pub fn new<S, T>(id: S, content: T) -> Document
        where S: Into<String>,
              T: Into<String>
    {
        Document { id: id.into(), content: content.into(), }
    }

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

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

impl Hash for Document {
    // Documents are unique only upon their id
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.id.hash(state);
    }
}

impl PartialEq for Document {
    // Documents are unique only upon their id
    fn eq(&self, other: &Document) -> bool {
        self.id == other.id
    }
}

impl PartialOrd for Document {
    fn partial_cmp(&self, other: &Document) -> Option<::std::cmp::Ordering> {
        self.id.partial_cmp(&other.id)
    }
}

/// A SearchResult is the representation of a Document returned for a specific set of search
/// terms. It is unique upon the document and the vec of highlight indices. It also contains a
/// search score for use in ranking against the other search results
#[derive(Clone, Debug, RustcEncodable)]
pub struct SearchResult<'a> {
    doc: &'a Document,
    highlights: Vec<(usize, usize)>,
    score: f32,
}

impl<'a> SearchResult<'a> {
    fn new(doc: &'a Document, mut highlights: Vec<(usize, usize)>) -> SearchResult<'a> {
        SearchResult {
            score: highlights.iter()
                .map(|&(begin, end)| end - begin)
                .sum::<usize>() as f32 / (doc.content.len() as f32).sqrt(),
            doc: doc,
            highlights: { highlights.sort(); highlights },
        }
    }

    /// Returns the document
    pub fn doc(&self) -> &Document {
        &self.doc
    }

    /// Returns the highlighted indices.
    ///
    /// Each `(usize, usize)` indicates the start and end of a term in the document's content
    /// that should be highlighted.
    pub fn highlights(&self) -> &Vec<(usize, usize)> {
        &self.highlights
    }

    /// Returns the search result's score.
    ///
    /// Score is computed by the product of the summed length of the matching terms and the inverse
    /// square root of the length of the document. Taking the square root of the document's length
    /// helps to combat bias toward short content.
    pub fn score(&self) -> f32 {
        self.score
    }

    pub fn highlight(&self, before: &str, after: &str) -> String {
        let mut begin_idx = 0;
        let mut parts = String::new();
        for &(begin, end) in &self.highlights {
            parts.push_str(&self.doc.content[begin_idx..begin]);
            parts.push_str(before);
            parts.push_str(&self.doc.content[begin..end]);
            parts.push_str(after);
            begin_idx = end;
        }
        parts.push_str(&self.doc.content[begin_idx..]);
        parts
    }
}

/// A basic implementation of an `Index`, the inverted index is a data structure that maps
/// from words to sets of Documents.
#[derive(Debug)]
pub struct InvertedIndex {
    index: BTreeMap<String, BTreeMap<String, Vec<(usize, usize)>>>,
    docs: BTreeMap<String, Document>,
}

impl InvertedIndex {
    pub fn new() -> InvertedIndex {
        InvertedIndex {
            index: BTreeMap::new(),
            docs: BTreeMap::new(),
        }
    }

    /// A basic implementation of index, splits the document's content into whitespace-separated
    /// words, and inserts each word-document pair into the map.
    pub fn index(&mut self, doc: Document) {
        let analyzed  = analyze_doc(doc.content());
        let previous_version = self.docs.insert(doc.id.clone(), doc.clone());
        if let Some(previous_version) = previous_version {
            let previous_analyzed = analyze_doc(previous_version.content());
            for (ngram, _) in previous_analyzed {
                let is_empty = {
                    let docs_for_ngram = self.index.get_mut(&ngram).unwrap();
                    docs_for_ngram.remove(&doc.id);
                    docs_for_ngram.is_empty()
                };
                if is_empty {
                    self.index.remove(&ngram);
                }
            }
        }

        for (ngram, highlighted) in analyzed {
            let mut highlights = self.index.entry(ngram)
                .or_insert_with(BTreeMap::new)
                .entry(doc.id.clone())
                .or_insert_with(Vec::new);
            let coalesce_idx = highlights.binary_search(&highlighted).err().unwrap();
            highlights.coalesce(coalesce_idx, highlighted);
        }
    }

    /// A basic search implementation that splits the query's content into whitespace-separated
    /// words, looks up the set of Documents for each word, and then concatenates the sets.
    pub fn search(&self, query: &str) -> Vec<SearchResult> {
        let unique_terms: HashSet<_> = query.split_whitespace().map(str::to_lowercase).collect();
        let map: HashMap<String, Vec<(usize, usize)>> = unique_terms.into_iter()
            .flat_map(|word| self.index.get(&word))
            .flat_map(BTreeMap::iter)
            .fold(HashMap::new(), |mut map, (doc_id, highlights)| {
                match map.entry(doc_id.clone()) {
                    Vacant(entry) => { entry.insert(highlights.clone()); },
                    Occupied(mut entry) => {
                        let entry: &mut Vec<(usize, usize)> = entry.get_mut();
                        for highlight in highlights {
                            let coalesce_idx = entry.binary_search(highlight).err().unwrap();
                            entry.coalesce(coalesce_idx, highlight.clone());
                        }
                    }
                }
                map
            });
        let mut results: Vec<_> = map.into_iter()
            .map(|(doc_id, index_map)| SearchResult::new(&self.docs[&doc_id], index_map.into_iter().collect()))
            .collect();
        results.sort_by(|result1, result2| result2.score.partial_cmp(&result1.score).unwrap());
        results
    }
}

fn analyze_doc(doc: &str) ->
    iter::FlatMap<
        iter::Filter<
            GroupBy<bool, CharIndices, fn(&(usize, char)) -> bool>,
            fn(&(bool, Vec<(usize, char)>)) -> bool>,
        iter::Map<ops::Range<usize>, Ngrams>,
        fn((bool, Vec<(usize, char)>)) -> iter::Map<ops::Range<usize>, Ngrams>>
{
    doc.char_indices()
        .group_by(is_whitespace as fn(&(usize, char)) -> bool)
        .filter(not_whitespace as fn(&(bool, Vec<(usize, char)>)) -> bool)
        .flat_map(ngrams)
}

fn ngrams((_, chars): (bool, Vec<(usize, char)>)) -> iter::Map<ops::Range<usize>, Ngrams> {
    (1..chars.len() + 1).map(Ngrams::new(chars))
}

fn not_whitespace(&(is_whitespace, _): &(bool, Vec<(usize, char)>)) -> bool {
    !is_whitespace
}

fn is_whitespace(&(_, c): &(usize, char)) -> bool {
    c.is_whitespace()
}

struct Ngrams {
    chars: Vec<(usize, char)>
}

impl Ngrams {
    fn new(chars: Vec<(usize, char)>) -> Ngrams {
        Ngrams { chars: chars }
    }
}

impl Fn<(usize,)> for Ngrams {
    extern "rust-call" fn call(&self, (to,): (usize,)) -> (String, (usize, usize)) {
        let word = self.chars[..to].iter().flat_map(|&(_, c)| c.to_lowercase()).collect();
        let start = self.chars[0].0;
        let (last_idx, last_char) = self.chars[to - 1];
        let finish = last_idx + last_char.len_utf8();
        (word, (start, finish))
    }
}

impl FnMut<(usize,)> for Ngrams {
    extern "rust-call" fn call_mut(&mut self, to: (usize,)) -> (String, (usize, usize)) {
        self.call(to)
    }
}

impl FnOnce<(usize,)> for Ngrams {
    type Output = (String, (usize, usize));
    extern "rust-call" fn call_once(self, to: (usize,)) -> (String, (usize, usize)) {
        self.call(to)
    }
}

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

    #[test]
    fn test_ngrams() {
        let mut index = InvertedIndex::new();
        let doc1 = Document::new("1", "learn to program in rust today");
        let doc2 = Document::new("2", "what did you today do");
        index.index(doc1.clone());
        index.index(doc2.clone());
        let search_results = index.search("to");
        let expected: BTreeMap<_, _> = [
            (doc1.clone(), vec![(6, 8), (25, 27)]),
            (doc2, vec![(13, 15)]),
        ].iter().cloned().collect();
        assert_eq!(search_results.len(), expected.len());
        for search_result in &search_results {
            assert_eq!(&search_result.highlights, &expected[search_result.doc])
        }
        assert_eq!("learn to program in rust \
                   today",
                   search_results.iter()
                        .find(|search_result| search_result.doc == &doc1)
                        .unwrap()
                        .highlight("", ""));

    }

    #[test]
    fn test_highlight() {
        let mut index = InvertedIndex::new();
        let doc1 = Document::new("2", "Won\u{2019}t this split the ecosystem? Will everyone use?");
        index.index(doc1.clone());
        let expected =  "Won\u{2019}t this split the *e*cosystem? Will *e*veryone use?";
        let search_results = index.search("e");
        assert_eq!(1, search_results.len());
        assert_eq!(search_results[0].highlight("*", "*"), expected);
    }

    #[test]
    fn test_unicode() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "嗨, 您好");
        index.index(doc.clone());
        let to_search = "您";
        let search_results = index.search(to_search);
        let &SearchResult { ref doc, ref highlights, .. } = search_results.iter().next().unwrap();
        let (begin, end) = highlights[0];
        assert_eq!(&doc.content()[begin..end], to_search);
    }

    #[test]
    fn test_update_doc() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "abc åäö");
        index.index(doc);
        let doc = Document::new("0", "different");
        index.index(doc);
        let search_results = index.search("å");
        assert!(search_results.is_empty());
        assert_eq!(index.docs.len(), 1);
    }

    #[test]
    fn test_ranking() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "beat");
        index.index(doc.clone());
        let doc2 = Document::new("1", "beast");
        index.index(doc2);
        let search_results = index.search("be");
        assert_eq!(index.docs.len(), 2);
        // "beat" should be first, since it's a closer match
        assert_eq!(search_results[0].doc, &doc);
    }

    #[test]
    fn test_duplicate_term() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "beat");
        index.index(doc.clone());
        let search_results = index.search("be be");
        assert_eq!(search_results.len(), 1);
    }

    #[test]
    fn test_duplicate_term2() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "beat");
        index.index(doc.clone());
        let search_results = index.search("be b");
        assert_eq!(search_results.len(), 1);
        assert_eq!(search_results[0].highlights, vec![(0, 2)]);
    }

    #[test]
    fn test_lowercase_search() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "BeAt");
        index.index(doc.clone());
        let search_results = index.search("bE");
        assert_eq!(search_results.len(), 1);
        assert_eq!(search_results[0].highlights, vec![(0, 2)]);
    }

    #[test]
    fn test_lowercase_index() {
        let mut index = InvertedIndex::new();
        let doc = Document::new("0", "BeAt");
        index.index(doc.clone());
        let search_results = index.search("be");
        assert_eq!(search_results.len(), 1);
        assert_eq!(search_results[0].highlights, vec![(0, 2)]);
    }
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]

extern crate fftw3_sys as ffi;
extern crate num_traits;
#[macro_use]
extern crate lazy_static;

pub mod plan;
pub mod pair;
pub mod complex;
mod r2r;
mod util;

pub use plan::*;
pub use pair::*;
pub use complex::c64;
pub use r2r::R2R_KIND;

#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum SIGN {
    FFTW_FORWARD = -1,
    FFTW_BACKWARD = 1,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum FLAG {
    /* documented flags */
    FFTW_MEASURE = 0,
    FFTW_DESTROY_INPUT = 1 << 0,
    FFTW_UNALIGNED = 1 << 1,
    FFTW_CONSERVE_MEMORY = 1 << 2,
    FFTW_EXHAUSTIVE = 1 << 3, /* NO_EXHAUSTIVE is default */
    FFTW_PRESERVE_INPUT = 1 << 4, /* cancels FFTW_DESTROY_INPUT */
    FFTW_PATIENT = 1 << 5, /* IMPATIENT is default */
    FFTW_ESTIMATE = 1 << 6,
    FFTW_WISDOM_ONLY = 1 << 21,

    /* undocumented beyond-guru flags */
    FFTW_ESTIMATE_PATIENT = 1 << 7,
    FFTW_BELIEVE_PCOST = 1 << 8,
    FFTW_NO_DFT_R2HC = 1 << 9,
    FFTW_NO_NONTHREADED = 1 << 10,
    FFTW_NO_BUFFERING = 1 << 11,
    FFTW_NO_INDIRECT_OP = 1 << 12,
    FFTW_ALLOW_LARGE_GENERIC = 1 << 13, /* NO_LARGE_GENERIC is default */
    FFTW_NO_RANK_SPLITS = 1 << 14,
    FFTW_NO_VRANK_SPLITS = 1 << 15,
    FFTW_NO_VRECURSE = 1 << 16,
    FFTW_NO_SIMD = 1 << 17,
    FFTW_NO_SLOW = 1 << 18,
    FFTW_NO_FIXED_RADIX_LARGE_N = 1 << 19,
    FFTW_ALLOW_PRUNING = 1 << 20,
}
<commit_msg>Remove plan from fftw3::* scope<commit_after>#![allow(non_camel_case_types)]

extern crate fftw3_sys as ffi;
extern crate num_traits;
#[macro_use]
extern crate lazy_static;

pub mod plan;
pub mod pair;
pub mod complex;
mod r2r;
mod util;

pub use pair::*;
pub use complex::c64;
pub use r2r::R2R_KIND;

#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum SIGN {
    FFTW_FORWARD = -1,
    FFTW_BACKWARD = 1,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum FLAG {
    /* documented flags */
    FFTW_MEASURE = 0,
    FFTW_DESTROY_INPUT = 1 << 0,
    FFTW_UNALIGNED = 1 << 1,
    FFTW_CONSERVE_MEMORY = 1 << 2,
    FFTW_EXHAUSTIVE = 1 << 3, /* NO_EXHAUSTIVE is default */
    FFTW_PRESERVE_INPUT = 1 << 4, /* cancels FFTW_DESTROY_INPUT */
    FFTW_PATIENT = 1 << 5, /* IMPATIENT is default */
    FFTW_ESTIMATE = 1 << 6,
    FFTW_WISDOM_ONLY = 1 << 21,

    /* undocumented beyond-guru flags */
    FFTW_ESTIMATE_PATIENT = 1 << 7,
    FFTW_BELIEVE_PCOST = 1 << 8,
    FFTW_NO_DFT_R2HC = 1 << 9,
    FFTW_NO_NONTHREADED = 1 << 10,
    FFTW_NO_BUFFERING = 1 << 11,
    FFTW_NO_INDIRECT_OP = 1 << 12,
    FFTW_ALLOW_LARGE_GENERIC = 1 << 13, /* NO_LARGE_GENERIC is default */
    FFTW_NO_RANK_SPLITS = 1 << 14,
    FFTW_NO_VRANK_SPLITS = 1 << 15,
    FFTW_NO_VRECURSE = 1 << 16,
    FFTW_NO_SIMD = 1 << 17,
    FFTW_NO_SLOW = 1 << 18,
    FFTW_NO_FIXED_RADIX_LARGE_N = 1 << 19,
    FFTW_ALLOW_PRUNING = 1 << 20,
}
<|endoftext|>


<commit_before>#![cfg_attr(test, feature(test))]

extern crate rustc_serialize;
extern crate encoding;
extern crate time;
extern crate chrono;
extern crate rand;

#[macro_use]
extern crate lazy_static;

pub use header::{
    Header,
    HeaderMap,
    HeaderIter,
    FromHeader,
    ToHeader,
    ToFoldedHeader,
};
pub use address::{Address, Mailbox};
pub use message::{
    MimeMessage,
    MimeMultipartType,
};

pub mod rfc5322;
pub mod rfc2047;
pub mod rfc2045;
pub mod rfc822;
pub mod mimeheaders;
mod header;
mod address;
mod message;
pub mod results;
<commit_msg>reorder modules<commit_after>#![cfg_attr(test, feature(test))]

extern crate rustc_serialize;
extern crate encoding;
extern crate time;
extern crate chrono;
extern crate rand;

#[macro_use]
extern crate lazy_static;

pub use header::{
    Header,
    HeaderMap,
    HeaderIter,
    FromHeader,
    ToHeader,
    ToFoldedHeader,
};
pub use address::{Address, Mailbox};
pub use message::{
    MimeMessage,
    MimeMultipartType,
};

pub mod rfc5322;
pub mod rfc2047;
pub mod rfc2045;
pub mod rfc822;
pub mod mimeheaders;
pub mod results;
mod header;
mod address;
mod message;
<|endoftext|>


<commit_before>extern crate hyper;
extern crate hyper_native_tls;
extern crate pbr;
extern crate regex;

use pbr::ProgressBar;
use std::{process,str};
use std::collections::HashMap;
use hyper::client::response::Response;
use hyper::Client;
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;
use hyper::header::ContentLength;
use std::io::Read;
use std::io::prelude::*;
use std::fs::File;
use regex::Regex;

pub struct Info {
    pub url: String,
    //pub title: String,
    //pub rating: ,
    //pub viewcount: u32,
    //pub author: String,
    //pub length: u32,
    //pub duration: String,
    //pub likes: u32,
    //pub dislikes: u32,
    //pub description: String,
    //pub streams: ,
    //pub audiostreams: ,
    //pub allstreams: ,
}

pub fn new(url: &str) -> Info {
    //Regex for youtube URLs.
    let url_regex = Regex::new(r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*").unwrap();
    let mut vid = url;
    if url_regex.is_match(vid) {
        let vid_split = url_regex.captures(vid).unwrap();
        vid = vid_split.get(1).unwrap().as_str();
    }
    let url = format!("https://youtube.com/get_video_info?video_id={}", vid);
    download(&url);
    Info { url: video_url.to_string() }
}

fn download(url: &str) {
    let mut response = send_request(url);
    let mut response_str = String::new();
    response.read_to_string(&mut response_str).unwrap();
    let hq = parse_url(&response_str);

    if hq["status"] != "ok" {
        println!("Video not found!");
        process::exit(1);
    }

    // get video info
    let streams: Vec<&str> = hq["url_encoded_fmt_stream_map"]
        .split(',')
        .collect();

    // list of available qualities
    let mut qualities: HashMap<i32, (String, String)> = HashMap::new();
    for (i, url) in streams.iter().enumerate() {
        let quality = parse_url(url);
        let extension = quality["type"]
            .split('/')
            .nth(1)
            .unwrap()
            .split(';')
            .next()
            .unwrap();
        qualities.insert(i as i32,
                         (quality["url"].to_string(), extension.to_owned()));
        println!("{}- {} {}",
                 i,
                 quality["quality"],
                 quality["type"]);
    }
}

fn send_request(url: &str) -> Response {
    let ssl = NativeTlsClient::new().unwrap();
    let connector = HttpsConnector::new(ssl);
    let client = Client::with_connector(connector);
    client.get(url).send().unwrap_or_else(|e| {
        println!("Network request failed: {}", e);
        process::exit(1);
    })
}

fn parse_url(query: &str) -> HashMap<String, String> {
    let u = format!("{}{}", "http://e.com?", query);
    let parsed_url = hyper::Url::parse(&u).unwrap();
    parsed_url.query_pairs().into_owned().collect()
}
<commit_msg>Add more pub variables<commit_after>extern crate hyper;
extern crate hyper_native_tls;
extern crate pbr;
extern crate regex;

use pbr::ProgressBar;
use std::{process,str};
use std::collections::HashMap;
use hyper::client::response::Response;
use hyper::Client;
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;
use hyper::header::ContentLength;
use std::io::Read;
use std::io::prelude::*;
use std::fs::File;
use regex::Regex;

pub struct Info {
    pub url: String,
    //pub title: String,
    //pub rating: ,
    //pub viewcount: u32,
    //pub author: String,
    //pub length: u32,
    //pub duration: String,
    //pub likes: u32,
    //pub dislikes: u32,
    //pub description: String,
    //pub streams: ,
    //pub audiostreams: ,
    //pub allstreams: ,
}

pub fn new(url: &str) -> Info {
    //Regex for youtube URLs.
    let url_regex = Regex::new(r"^.*(?:(?:youtu\.be/|v/|vi/|u/w/|embed/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*").unwrap();
    let mut vid = url;
    if url_regex.is_match(vid) {
        let vid_split = url_regex.captures(vid).unwrap();
        vid = vid_split.get(1).unwrap().as_str();
    }
    let url = format!("https://youtube.com/get_video_info?video_id={}", vid);
    download(&url);
    Info { url: url.to_string() }
}

fn download(url: &str) {
    let mut response = send_request(url);
    let mut response_str = String::new();
    response.read_to_string(&mut response_str).unwrap();
    let hq = parse_url(&response_str);

    if hq["status"] != "ok" {
        println!("Video not found!");
        process::exit(1);
    }

    // get video info
    let streams: Vec<&str> = hq["url_encoded_fmt_stream_map"]
        .split(',')
        .collect();

    // list of available qualities
    let mut qualities: HashMap<i32, (String, String)> = HashMap::new();
    for (i, url) in streams.iter().enumerate() {
        let quality = parse_url(url);
        let extension = quality["type"]
            .split('/')
            .nth(1)
            .unwrap()
            .split(';')
            .next()
            .unwrap();
        qualities.insert(i as i32,
                         (quality["url"].to_string(), extension.to_owned()));
        println!("{}- {} {}",
                 i,
                 quality["quality"],
                 quality["type"]);
    }
}

fn send_request(url: &str) -> Response {
    let ssl = NativeTlsClient::new().unwrap();
    let connector = HttpsConnector::new(ssl);
    let client = Client::with_connector(connector);
    client.get(url).send().unwrap_or_else(|e| {
        println!("Network request failed: {}", e);
        process::exit(1);
    })
}

fn parse_url(query: &str) -> HashMap<String, String> {
    let u = format!("{}{}", "http://e.com?", query);
    let parsed_url = hyper::Url::parse(&u).unwrap();
    parsed_url.query_pairs().into_owned().collect()
}
<|endoftext|>


<commit_before>extern crate collections;
use std::io::{File, Open, Write, TempDir};
use collections::priority_queue::PriorityQueue;

struct Entry {
	value: u64,
	source: File,
}

impl Ord for Entry {
	fn lt(&self, other: &Entry) -> bool {
		!(self.value < other.value)
	}
}

impl Eq for Entry {
	fn eq(&self, other: &Entry) -> bool {
		self.value == other.value
	}
}

struct PriorityFile {
	queue: ~PriorityQueue<Entry>,
}

impl PriorityFile {
	pub fn new(files: Vec<File>) -> PriorityFile {
		let mut queue: PriorityQueue<Entry> = PriorityQueue::new();
		for mut f in files.move_iter() {
			let number = match f.read_le_u64() {
				Ok(num) => num,
				Err(e) => fail!("failed to read u64 from file: {}", e),
			};
			let entry = Entry {value: number, source: f};
			queue.push(entry);
		}
		PriorityFile {queue: ~queue}
	}

	pub fn next(&mut self) -> Option<u64> {
		match self.queue.maybe_pop() {
			Some(mut res) => {
				let v = res.value;
				match res.source.read_le_u64() {
					Ok(num) => self.queue.push(Entry {value: num, source: res.source}),
					Err(_) => (),
				};
				Some(v)
			},
			None => None,
		}
	}
}

fn externalSort(mut fdInput: File, size: u64, mut fdOutput: File, memSize: u64) {
	let runs = size / memSize;
	let items_per_run = (memSize / 8) as uint;

	println!("There will be {} runs with {} elements each.", runs, items_per_run);

	/* initialize a Vector. Rust Vectors grow but this one will stay fixed */
	let mut run: Vec<u64> = Vec::with_capacity(items_per_run);
	// preallocate it with zeroes
	for _ in range(0, items_per_run) {
		run.push(0_u64);
	}

	// let's create a temporary directory to store the sorted chunks
	let overflow_dir = match TempDir::new("externalsort") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let overflow_path = overflow_dir.path();
	println!("temp dir path {}", overflow_path.display());

	for n in range(0, runs) {
		for element in run.mut_iter() {
			let number = match fdInput.read_le_u64() {
				Ok(num) => num,
				Err(e) => fail!("failed to read u64 from file: {}", e),
			};
			*element = number;
		}
		run.sort();

		let file_path = overflow_path.join(n.to_str());
		let mut file_file = match File::open_mode(&file_path, Open, Write) {
			Ok(f) => f,
			Err(e) => fail!("output file error: {}", e),
		};

		for &element in run.iter() {
			match file_file.write_le_u64(element) {
				Ok (_) => (),
				Err(e) => fail!("writing overflow failed: {}", e),
			};
		};
	};

	let mut files = Vec::with_capacity(runs as uint);
	for n in range(0, runs) {
		let file_path = overflow_path.join(n.to_str());
		let fd = match File::open(&file_path) {
			Ok(f) => f,
			Err(e) => fail!("overflow file open error {}", e),
		};
		files.push(fd);
	}

	let mut pf = PriorityFile::new(files);
	loop {
		match pf.next() {
			Some (number) => match fdOutput.write_le_u64(number) {
				Ok(_) => (),
				Err(e) => fail!("Didn't write to file {}", e),
			},
			None => break,
		};
	};
}

fn main() {
	let input_file_path = &Path::new("input");
	let size = match input_file_path.stat() {
		Ok(stat) => stat.size,
		Err(e) => fail!("Couldn't read {}", e),
	};
	println!("Input file size {}", size);
	let fin = match File::open(input_file_path) {
		Ok(f) => f,
		Err(e) => fail!("input file error: {}", e),
	};
	let fout = match File::open_mode(&Path::new("output"), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};
	externalSort(fin, size, fout, 800);
}
<commit_msg>Some comments<commit_after>extern crate collections;
use std::io::{File, Open, Write, TempDir};
use collections::priority_queue::PriorityQueue;

/*
 * an entry is the number that we read and the file it came from, so after we took
 * out one Entry from the priority queue, we need to know where to take the next number
 * from.
 */
struct Entry {
	value: u64,
	source: File,
}

/* The priority queue depends on the ordering relation and always returns the biggest */
impl Ord for Entry {
	// lesser than implementation
	fn lt(&self, other: &Entry) -> bool {
		// we invert: for us the smallest will have the highest priority
		!(self.value < other.value)
	}
}

/* ordering needs equality for some reason, so there */
impl Eq for Entry {
	fn eq(&self, other: &Entry) -> bool {
		self.value == other.value
	}
}

/* A struct to hold our queue */
struct PriorityFile {
	queue: PriorityQueue<Entry>,
}

/*
 * 'Class' that takes a list of files and does a k-way merge of the smallest values
 * from the files
 */
impl PriorityFile {
	pub fn new(files: Vec<File>) -> PriorityFile {
		let mut queue: PriorityQueue<Entry> = PriorityQueue::new();
		// now that we got the queue, populate it with initial values

		// move_iter is required to get the values themselves, not borrowed pointers to them
		for mut f in files.move_iter() {
			// read from file, append to queue
			let number = match f.read_le_u64() {
				Ok(num) => num,
				Err(e) => fail!("failed to read u64 from file: {}", e),
			};
			queue.push(Entry {value: number, source: f});
		};
		PriorityFile {queue: queue}
	}

	/* Returns the next smallest number from the list of files or None if exhausted */
	pub fn next(&mut self) -> Option<u64> {
		match self.queue.maybe_pop() {
			Some(mut res) => {
				let v = res.value;
				match res.source.read_le_u64() {
					Ok(num) => self.queue.push(Entry {value: num, source: res.source}),
					Err(_) => (),
				};
				Some(v)
			},
			None => None,
		}
	}
}

fn externalSort(mut fdInput: File, size: u64, mut fdOutput: File, memSize: u64) {
	let runs = size / memSize;
	let items_per_run = (memSize / 8) as uint;

	println!("There will be {} runs with {} elements each.", runs, items_per_run);

	/* initialize a Vector. Rust Vectors grow but this one will stay fixed */
	let mut run: Vec<u64> = Vec::with_capacity(items_per_run);
	// preallocate it with zeroes
	for _ in range(0, items_per_run) {
		run.push(0_u64);
	}

	// let's create a temporary directory to store the sorted chunks
	// neat: TempDir deletes the directory and its contents when it goes out of
	// scope
	let overflow_dir = match TempDir::new("externalsort") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let overflow_path = overflow_dir.path();
	println!("temp dir path {}", overflow_path.display());

	// start the sorting runs
	for n in range(0, runs) {
		// iterate over our 'run' buffer and read from the input file
		// I suppose the values are little endian, which considering we are most
		// likely on x86, is a reasonable assumption
		for element in run.mut_iter() {
			let number = match fdInput.read_le_u64() {
				Ok(num) => num,
				Err(e) => fail!("failed to read u64 from file: {}", e),
			};
			*element = number;
		}
		// O(n log n) sort from the stdlib, hopefully more or less equivalent to
		// C++ std::sort
		run.sort();

		// now write out the results into numbered files
		let file_path = overflow_path.join(n.to_str());
		let mut file_file = match File::open_mode(&file_path, Open, Write) {
			Ok(f) => f,
			Err(e) => fail!("overflow file failed opening for write: {}", e),
		};

		for &element in run.iter() {
			match file_file.write_le_u64(element) {
				Ok (_) => (),
				Err(e) => fail!("writing overflow failed: {}", e),
			};
		};
	};

	/* sorting done, now merging */

	// collect all file handles. Hopefully less than 4096
	let mut files = Vec::with_capacity(runs as uint);
	for n in range(0, runs) {
		let file_path = overflow_path.join(n.to_str());
		let fd = match File::open(&file_path) {
			Ok(f) => f,
			Err(e) => fail!("overflow file opening error {}", e),
		};
		files.push(fd);
	}

	// we got a nice class here that spits out sorted numbers until exhausted
	let mut pf = PriorityFile::new(files);
	loop {
		match pf.next() {
			// if we got a number, write it to the output
			Some (number) => match fdOutput.write_le_u64(number) {
				Ok(_) => (),
				Err(e) => fail!("writing output file failed: {}", e),
			},
			None => break,
		};
	};
}

fn main() {
	let input_file_path = &Path::new("input");
	let size = match input_file_path.stat() {
		Ok(stat) => stat.size,
		Err(e) => fail!("Couldn't read {}", e),
	};
	println!("Input file size {}", size);
	let fin = match File::open(input_file_path) {
		Ok(f) => f,
		Err(e) => fail!("input file error: {}", e),
	};
	let fout = match File::open_mode(&Path::new("output"), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};
	externalSort(fin, size, fout, 800);
}
<|endoftext|>


<commit_before>#![crate_name = "shader_version"]
#![deny(missing_doc)]

//! A helper library for detecting and picking compatible shaders.

/// Models knowledge about version range.
pub enum VersionRange<T> {
    /// The version range is working from a version,
    /// up to but not included another version.
    ///
    /// With other words, from first time it works until it breaks.
    VersionFromTo(T, T),
    /// The version range is working from a version,
    /// and possibly for all newer versions unless
    /// the context it is used implies otherwise.
    VersionFrom(T)
}

<commit_msg>Added OpenGL struct<commit_after>#![crate_name = "shader_version"]
#![deny(missing_doc)]

//! A helper library for detecting and picking compatible shaders.

/// Models knowledge about version range.
pub enum VersionRange<T> {
    /// The version range is working from a version,
    /// up to but not included another version.
    ///
    /// With other words, from first time it works until it breaks.
    VersionFromTo(T, T),
    /// The version range is working from a version,
    /// and possibly for all newer versions unless
    /// the context it is used implies otherwise.
    VersionFrom(T)
}

#[allow(non_camel_case_types)]
#[allow(missing_doc)]
pub enum OpenGL {
    OpenGL_2_0,
    OpenGL_2_1,
    OpenGL_3_0,
    OpenGL_3_1,
    OpenGL_3_2,
    OpenGL_3_3,
    OpenGL_4_0,
    OpenGL_4_1,
    OpenGL_4_2,
    OpenGL_4_3,
    OpenGL_4_4
}

<|endoftext|>


<commit_before>//! The mio-based framework for doing I/O in simple and composable way
//!
//! More documentation in [the guide](http://rotor.readthedocs.org)
//!
#![crate_name="rotor"]

pub extern crate void as void_original;
pub extern crate mio as mio_original;
#[macro_use] extern crate log;
#[macro_use] extern crate quick_error;

mod handler;
mod scope;
mod loop_api;
mod response;
mod compose;
mod macros;
mod machine;
mod notify;
mod config;
mod creator;
mod error;
mod loop_time;

pub use machine::Machine;
pub use scope::{Scope, EarlyScope, GenericScope};
pub use scope::{scope as _scope, early_scope as _early_scope};
pub use notify::{Notifier, WakeupError};
pub use config::Config;
pub use creator::{LoopCreator as Loop, LoopInstance};
pub use error::SpawnError;
pub use loop_time::Time;
pub use handler::{Timeo as _Timeo, Notify as _Notify};
pub use loop_api::{LoopApi as _LoopApi};

pub use compose::{Compose2};

// Re-export mio types used in rotor
pub use mio::{EventSet, Evented, PollOpt};
pub use mio::{Timeout, TimerError};
pub use mio_original as mio;
// Re-export void too
pub use void::{Void};
pub use void_original as void;

/// The response of a state machine to the (mio) action
///
/// This value is returned by many methods of the `Machine` trait.
pub struct Response<M, N>(response::ResponseImpl<M, N>);
<commit_msg>doc: intro nits<commit_after>//! The mio-based framework for doing I/O in a simple and composable way.
//!
//! You may want to look at [the guide](http://rotor.readthedocs.org).

#![crate_name="rotor"]

pub extern crate void as void_original;
pub extern crate mio as mio_original;
#[macro_use] extern crate log;
#[macro_use] extern crate quick_error;

mod handler;
mod scope;
mod loop_api;
mod response;
mod compose;
mod macros;
mod machine;
mod notify;
mod config;
mod creator;
mod error;
mod loop_time;

pub use machine::Machine;
pub use scope::{Scope, EarlyScope, GenericScope};
pub use scope::{scope as _scope, early_scope as _early_scope};
pub use notify::{Notifier, WakeupError};
pub use config::Config;
pub use creator::{LoopCreator as Loop, LoopInstance};
pub use error::SpawnError;
pub use loop_time::Time;
pub use handler::{Timeo as _Timeo, Notify as _Notify};
pub use loop_api::{LoopApi as _LoopApi};

pub use compose::{Compose2};

// Re-export mio types used in rotor
pub use mio::{EventSet, Evented, PollOpt};
pub use mio::{Timeout, TimerError};
pub use mio_original as mio;
// Re-export void too
pub use void::{Void};
pub use void_original as void;

/// The response of a state machine to the (mio) action
///
/// This value is returned by many methods of the `Machine` trait.
pub struct Response<M, N>(response::ResponseImpl<M, N>);
<|endoftext|>


<commit_before>/*!
Rust bindings to the [sodium library](https://github.com/jedisct1/libsodium).

Sodium is a portable implementation of Dan Bernsteins [NaCl: Networking and
Cryptography library](http://nacl.cr.yp.to)

For most users, if you want public-key (asymmetric) cryptography you should use
the functions in `crypto::asymmetricbox` for encryption/decryption.

If you want secret-key (symmetric) cryptography you should be using the
functions in `crypto::secretbox` for encryption/decryption.

For public-key signatures you should use the functions in `crypto::sign` for
signature creation and verification.

Unless you know what you're doing you most certainly don't want to use the
functions in `crypto::scalarmult`, `crypto::stream`, `crypto::auth` and
`crypto::onetimeauth`.

## Thread Safety
All functions in this library are thread-safe provided that the `init()`
function has been called during program execution.

If `init()` hasn't been called then all functions except the random-number
generation functions and the key-generation functions are thread-safe.

# Public-key cryptography
 `crypto::asymmetricbox`

 `crypto::sign`

# Secret-key cryptography
 `crypto::secretbox`

 `crypto::stream`

 `crypto::auth`

 `crypto::onetimeauth`

# Low-level functions
 `crypto::hash`

 `crypto::verify`

 `crypto::shorthash`
 */
#![crate_name = "sodiumoxide"]
#![comment = "Fast cryptographic library"]
#![license = "MIT"]
#![crate_type = "lib"]
#![warn(missing_docs)]
#![warn(non_upper_case_globals)]
#![warn(non_camel_case_types)]
#![warn(unused_qualifications)]
#![feature(globs)]
#![feature(macro_rules)]
extern crate libc;
use libc::c_int;

#[link(name = "sodium")]
extern {
    fn sodium_init() -> c_int;
}

/**
 * `init()` initializes the sodium library and chooses faster versions of
 * the primitives if possible. `init()` also makes the random number generation
 * functions (`gen_key`, `gen_keypair`, `gen_nonce`, `randombytes`, `randombytes_into`)
 * thread-safe
 */
pub fn init() -> bool {
    unsafe {
        sodium_init() == 0
    }
}

mod utils;

pub mod randombytes;

/**
 * Cryptographic functions
 */
pub mod crypto {
    pub mod asymmetricbox;
    pub mod sign;
    pub mod scalarmult;
    pub mod auth;
    pub mod hash;
    pub mod secretbox;
    pub mod onetimeauth;
    pub mod stream;
    pub mod shorthash;
    pub mod verify;
}

<commit_msg>Removed unused attributes<commit_after>/*!
Rust bindings to the [sodium library](https://github.com/jedisct1/libsodium).

Sodium is a portable implementation of Dan Bernsteins [NaCl: Networking and
Cryptography library](http://nacl.cr.yp.to)

For most users, if you want public-key (asymmetric) cryptography you should use
the functions in `crypto::asymmetricbox` for encryption/decryption.

If you want secret-key (symmetric) cryptography you should be using the
functions in `crypto::secretbox` for encryption/decryption.

For public-key signatures you should use the functions in `crypto::sign` for
signature creation and verification.

Unless you know what you're doing you most certainly don't want to use the
functions in `crypto::scalarmult`, `crypto::stream`, `crypto::auth` and
`crypto::onetimeauth`.

## Thread Safety
All functions in this library are thread-safe provided that the `init()`
function has been called during program execution.

If `init()` hasn't been called then all functions except the random-number
generation functions and the key-generation functions are thread-safe.

# Public-key cryptography
 `crypto::asymmetricbox`

 `crypto::sign`

# Secret-key cryptography
 `crypto::secretbox`

 `crypto::stream`

 `crypto::auth`

 `crypto::onetimeauth`

# Low-level functions
 `crypto::hash`

 `crypto::verify`

 `crypto::shorthash`
 */
#![crate_name = "sodiumoxide"]
#![crate_type = "lib"]
#![warn(missing_docs)]
#![warn(non_upper_case_globals)]
#![warn(non_camel_case_types)]
#![warn(unused_qualifications)]
#![feature(globs)]
#![feature(macro_rules)]
extern crate libc;
use libc::c_int;

#[link(name = "sodium")]
extern {
    fn sodium_init() -> c_int;
}

/**
 * `init()` initializes the sodium library and chooses faster versions of
 * the primitives if possible. `init()` also makes the random number generation
 * functions (`gen_key`, `gen_keypair`, `gen_nonce`, `randombytes`, `randombytes_into`)
 * thread-safe
 */
pub fn init() -> bool {
    unsafe {
        sodium_init() == 0
    }
}

mod utils;

pub mod randombytes;

/**
 * Cryptographic functions
 */
pub mod crypto {
    pub mod asymmetricbox;
    pub mod sign;
    pub mod scalarmult;
    pub mod auth;
    pub mod hash;
    pub mod secretbox;
    pub mod onetimeauth;
    pub mod stream;
    pub mod shorthash;
    pub mod verify;
}

<|endoftext|>


<commit_before>/*!
Compile-time dimensional analysis for various unit systems using Rust's type system.

Its goal is to provide zero cost unit safety while requiring minimal effort from the programmer.

For a short introduction and some examples, check out the [readme on
GitHub](https://github.com/paholg/dimensioned).

# Use

The recommended way to import this crate is with the rename

```rust
extern crate dimensioned as dim;
```

and then either import the module for the unit system you will be using,

```rust
# extern crate dimensioned as dim;
# fn main() {
use dim::si;
let x = 3.0 * si::M;
# }
```

or import the constants and/or types that you care about,

```rust
# extern crate dimensioned as dim;
# fn main() {
use dim::si::{Meter, M, S};
let x: Meter<f64> = 3.0 * M;
let t = 2.0 * S;
# }
```

For clarity, all the examples contained herein will import unit system modules.

# How it works

When a unit system is created, say the SI system, a struct with two parameters is made; in this
case `SI<V, U>`. The first parameter, `V`, is for the value type -- it can be anything, and is the
value to which we are giving units. The second parameter, `U`, is where the magic happens. It
represents the units, and is a type-level array of type-level numbers. Now, these guys have some
pretty ugly type signatures, so I will express the array as the macro which maps to it, `tarr![]`,
and the type numbers as their aliases; `N1` for -1, `Z0` for 0, `P1` for 1, etc.

The SI system has seven base units, so that's how many elements the type array needs to have. The
order is the order in which the base units were defined, and the values of the type numbers are the
power to which each unit is raised. For example, the first three SI units, in order, are `Meter`,
`Kilogram`, `Second`, so the following aliases exist:

```rust
#[macro_use]
extern crate dimensioned as dim;
use dim::si::SI;
use dim::typenum::{P1, Z0, N1, N2};

type Meter<V>    = SI<V, tarr![P1, Z0, Z0, Z0, Z0, Z0, Z0]>;
type Kilogram<V> = SI<V, tarr![Z0, P1, Z0, Z0, Z0, Z0, Z0]>;
type Second<V>   = SI<V, tarr![Z0, Z0, P1, Z0, Z0, Z0, Z0]>;
type Newton<V>   = SI<V, tarr![P1, P1, N2, Z0, Z0, Z0, Z0]>;
// ...

fn main() {}
```

In addition to creating the unit system struct, `SI`, the type aliases, and constants for each,
various traits are implemented for the unit system. These include arithmetic operations, which work
as follows.

If you try to add a `Meter<f64>` to a `Second<f64>`, then you will get a compiler error because
they have different types and so addition is not defined. Multiplication, on the other hand, is
defined, and results in a normal multiplication of the value types, and the unit powers added.

So, multiplying `Meter<f64>` by `Second<f64>` gives `SI<f64, tarr![P1, Z0, P1, Z0, Z0, Z0,
Z0]>`.

## Example

```rust
extern crate dimensioned as dim;

use dim::si;

fn main() {
    let x = 3.0 * si::M;
    let t = 2.0 * si::S;
    assert_eq!("6 m*s", &format!("{}", x*t));
}
```

That's basically it. All of the dimensional safety comes from whether things typecheck, and from
performing type-level arithmetic, thanks to the [typenum](http://paholg.com/typenum/)
crate. Pretty much everything else is for ergonomics.

*/

#![doc(
    html_logo_url = "https://raw.githubusercontent.com/paholg/dimensioned/master/favicon.png",
    html_favicon_url = "https://raw.githubusercontent.com/paholg/dimensioned/master/favicon.png",
    html_root_url = "http://paholg.com/dimensioned"
)]
#![warn(missing_docs)]
#![allow(unknown_lints)]
#![allow(type_complexity, float_cmp, useless_attribute, doc_markdown)]
#![deny(clippy)]
#![cfg_attr(feature = "ci", deny(warnings))]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(
    all(not(feature = "std"), feature = "nightly"),
    feature(core_intrinsics, extern_prelude)
)]
#![cfg_attr(feature = "oibit", feature(optin_builtin_traits))]
#![cfg_attr(feature = "spec", feature(specialization))]
#![cfg_attr(feature = "cargo-clippy", allow(
    // Don't think we'll ever be able to remove this.
    type_complexity,
    // Not great. See issue #52.
    transmute_ptr_to_ptr,
    // These are output from the build macros; if we could get output integers to include
    // underscores, we could remove it.
    unreadable_literal,
    // This is fine; we have constants defined as f32 and f64, so excessive precition for f32 is
    // good.
    excessive_precision,
))]

#[cfg(feature = "clapme")]
extern crate clapme;
#[cfg(feature = "std")]
extern crate core;
extern crate num_traits;
pub extern crate typenum;

// Macro debugging
// #![feature(trace_macros)]
// trace_macros!(true);

// Copied from typenum so that users don't have to import typenum for the make_units macro to work.
// Only change is the paths.
/// Construct a type-level array of type-level integers
///
/// # Example
/// ```rust
/// #[macro_use]
/// extern crate dimensioned as dim;
/// #[macro_use]
/// extern crate generic_array;
///
/// use dim::typenum::consts::*;
/// type TArr = tarr![P3, P2, N5, N8, P2];
///
/// fn main() {
///     use dim::array::ToGA;
///     let x = TArr::to_ga();
///     let y = arr![isize; 3, 2, -5, -8, 2];
///
///     assert_eq!(x, y);
/// }
/// ```
#[macro_export]
macro_rules! tarr {
    () => ( $crate::typenum::ATerm );
    ($n:ty) => ( $crate::typenum::TArr<$n, $crate::typenum::ATerm> );
    ($n:ty,) => ( $crate::typenum::TArr<$n, $crate::typenum::ATerm> );
    ($n:ty, $($tail:ty),+) => ( $crate::typenum::TArr<$n, tarr![$($tail),+]> );
    ($n:ty, $($tail:ty),+,) => ( $crate::typenum::TArr<$n, tarr![$($tail),+]> );
}

// Get a warning without this. If it's fixed, remove `useless_attribute` from clippy allow list
#[allow(unused_imports)]
#[macro_use]
pub extern crate generic_array;

#[cfg(feature = "approx")]
pub extern crate approx;

#[cfg(feature = "serde")]
pub extern crate serde;
#[cfg(feature = "serde_test")]
extern crate serde_test;

#[cfg(feature = "rand")]
pub extern crate rand;

#[macro_use]
mod make_units;
mod fmt;

include!(concat!(env!("OUT_DIR"), "/unit_systems.rs"));
pub mod array;
pub mod conversion;
pub mod dimensions;
pub mod f32prefixes;
pub mod f64prefixes;
pub mod traits;

pub use traits::*;
pub use unit_systems::{cgs, fps, mks, si, ucum};

// Used for the make_units macro
#[doc(hidden)]
pub mod dimcore {
    pub use core::{f32, f64, fmt, marker, mem, ops};
}
<commit_msg>Moved `feature(extern_prelude)` behind `not(feature = "nightly")` check to avoid warning<commit_after>/*!
Compile-time dimensional analysis for various unit systems using Rust's type system.

Its goal is to provide zero cost unit safety while requiring minimal effort from the programmer.

For a short introduction and some examples, check out the [readme on
GitHub](https://github.com/paholg/dimensioned).

# Use

The recommended way to import this crate is with the rename

```rust
extern crate dimensioned as dim;
```

and then either import the module for the unit system you will be using,

```rust
# extern crate dimensioned as dim;
# fn main() {
use dim::si;
let x = 3.0 * si::M;
# }
```

or import the constants and/or types that you care about,

```rust
# extern crate dimensioned as dim;
# fn main() {
use dim::si::{Meter, M, S};
let x: Meter<f64> = 3.0 * M;
let t = 2.0 * S;
# }
```

For clarity, all the examples contained herein will import unit system modules.

# How it works

When a unit system is created, say the SI system, a struct with two parameters is made; in this
case `SI<V, U>`. The first parameter, `V`, is for the value type -- it can be anything, and is the
value to which we are giving units. The second parameter, `U`, is where the magic happens. It
represents the units, and is a type-level array of type-level numbers. Now, these guys have some
pretty ugly type signatures, so I will express the array as the macro which maps to it, `tarr![]`,
and the type numbers as their aliases; `N1` for -1, `Z0` for 0, `P1` for 1, etc.

The SI system has seven base units, so that's how many elements the type array needs to have. The
order is the order in which the base units were defined, and the values of the type numbers are the
power to which each unit is raised. For example, the first three SI units, in order, are `Meter`,
`Kilogram`, `Second`, so the following aliases exist:

```rust
#[macro_use]
extern crate dimensioned as dim;
use dim::si::SI;
use dim::typenum::{P1, Z0, N1, N2};

type Meter<V>    = SI<V, tarr![P1, Z0, Z0, Z0, Z0, Z0, Z0]>;
type Kilogram<V> = SI<V, tarr![Z0, P1, Z0, Z0, Z0, Z0, Z0]>;
type Second<V>   = SI<V, tarr![Z0, Z0, P1, Z0, Z0, Z0, Z0]>;
type Newton<V>   = SI<V, tarr![P1, P1, N2, Z0, Z0, Z0, Z0]>;
// ...

fn main() {}
```

In addition to creating the unit system struct, `SI`, the type aliases, and constants for each,
various traits are implemented for the unit system. These include arithmetic operations, which work
as follows.

If you try to add a `Meter<f64>` to a `Second<f64>`, then you will get a compiler error because
they have different types and so addition is not defined. Multiplication, on the other hand, is
defined, and results in a normal multiplication of the value types, and the unit powers added.

So, multiplying `Meter<f64>` by `Second<f64>` gives `SI<f64, tarr![P1, Z0, P1, Z0, Z0, Z0,
Z0]>`.

## Example

```rust
extern crate dimensioned as dim;

use dim::si;

fn main() {
    let x = 3.0 * si::M;
    let t = 2.0 * si::S;
    assert_eq!("6 m*s", &format!("{}", x*t));
}
```

That's basically it. All of the dimensional safety comes from whether things typecheck, and from
performing type-level arithmetic, thanks to the [typenum](http://paholg.com/typenum/)
crate. Pretty much everything else is for ergonomics.

*/

#![doc(
    html_logo_url = "https://raw.githubusercontent.com/paholg/dimensioned/master/favicon.png",
    html_favicon_url = "https://raw.githubusercontent.com/paholg/dimensioned/master/favicon.png",
    html_root_url = "http://paholg.com/dimensioned"
)]
#![warn(missing_docs)]
#![allow(unknown_lints)]
#![allow(type_complexity, float_cmp, useless_attribute, doc_markdown)]
#![deny(clippy)]
#![cfg_attr(feature = "ci", deny(warnings))]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(
    all(not(feature = "std"), feature = "nightly"),
    feature(core_intrinsics)
)]
#![cfg_attr(
    all(not(feature = "std"), not(feature = "nightly")),
    feature(extern_prelude)
)]
#![cfg_attr(feature = "oibit", feature(optin_builtin_traits))]
#![cfg_attr(feature = "spec", feature(specialization))]
#![cfg_attr(feature = "cargo-clippy", allow(
    // Don't think we'll ever be able to remove this.
    type_complexity,
    // Not great. See issue #52.
    transmute_ptr_to_ptr,
    // These are output from the build macros; if we could get output integers to include
    // underscores, we could remove it.
    unreadable_literal,
    // This is fine; we have constants defined as f32 and f64, so excessive precition for f32 is
    // good.
    excessive_precision,
))]

#[cfg(feature = "clapme")]
extern crate clapme;
#[cfg(feature = "std")]
extern crate core;
extern crate num_traits;
pub extern crate typenum;

// Macro debugging
// #![feature(trace_macros)]
// trace_macros!(true);

// Copied from typenum so that users don't have to import typenum for the make_units macro to work.
// Only change is the paths.
/// Construct a type-level array of type-level integers
///
/// # Example
/// ```rust
/// #[macro_use]
/// extern crate dimensioned as dim;
/// #[macro_use]
/// extern crate generic_array;
///
/// use dim::typenum::consts::*;
/// type TArr = tarr![P3, P2, N5, N8, P2];
///
/// fn main() {
///     use dim::array::ToGA;
///     let x = TArr::to_ga();
///     let y = arr![isize; 3, 2, -5, -8, 2];
///
///     assert_eq!(x, y);
/// }
/// ```
#[macro_export]
macro_rules! tarr {
    () => ( $crate::typenum::ATerm );
    ($n:ty) => ( $crate::typenum::TArr<$n, $crate::typenum::ATerm> );
    ($n:ty,) => ( $crate::typenum::TArr<$n, $crate::typenum::ATerm> );
    ($n:ty, $($tail:ty),+) => ( $crate::typenum::TArr<$n, tarr![$($tail),+]> );
    ($n:ty, $($tail:ty),+,) => ( $crate::typenum::TArr<$n, tarr![$($tail),+]> );
}

// Get a warning without this. If it's fixed, remove `useless_attribute` from clippy allow list
#[allow(unused_imports)]
#[macro_use]
pub extern crate generic_array;

#[cfg(feature = "approx")]
pub extern crate approx;

#[cfg(feature = "serde")]
pub extern crate serde;
#[cfg(feature = "serde_test")]
extern crate serde_test;

#[cfg(feature = "rand")]
pub extern crate rand;

#[macro_use]
mod make_units;
mod fmt;

include!(concat!(env!("OUT_DIR"), "/unit_systems.rs"));
pub mod array;
pub mod conversion;
pub mod dimensions;
pub mod f32prefixes;
pub mod f64prefixes;
pub mod traits;

pub use traits::*;
pub use unit_systems::{cgs, fps, mks, si, ucum};

// Used for the make_units macro
#[doc(hidden)]
pub mod dimcore {
    pub use core::{f32, f64, fmt, marker, mem, ops};
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::mem::size_of;

struct t {a: u8, b: i8}
struct u {a: u8, b: i8, c: u8}
struct v {a: u8, b: i8, c: v2, d: u32}
struct v2 {u: char, v: u8}
struct w {a: int, b: ()}
struct x {a: int, b: (), c: ()}
struct y {x: int}

enum e1 {
    a(u8, u32), b(u32), c
}
enum e2 {
    a(u32), b
}
enum e3 {
    a([u64, ..0], u32), b
}

pub fn main() {
    assert_eq!(size_of::<u8>(), 1 as uint);
    assert_eq!(size_of::<u32>(), 4 as uint);
    assert_eq!(size_of::<char>(), 4 as uint);
    assert_eq!(size_of::<i8>(), 1 as uint);
    assert_eq!(size_of::<i32>(), 4 as uint);
    assert_eq!(size_of::<t>(), 2 as uint);
    assert_eq!(size_of::<u>(), 3 as uint);
    // Alignment causes padding before the char and the u32.

    assert!(size_of::<v>() ==
                16 as uint);
    assert_eq!(size_of::<int>(), size_of::<uint>());
    assert_eq!(size_of::<w>(), size_of::<int>());
    assert_eq!(size_of::<x>(), size_of::<int>());
    assert_eq!(size_of::<int>(), size_of::<y>());

    // Make sure enum types are the appropriate size, mostly
    // around ensuring alignment is handled properly
    assert_eq!(size_of::<e1>(), 8 as uint);
    assert_eq!(size_of::<e2>(), 8 as uint);
    assert_eq!(size_of::<e3>(), 16 as uint);
}
<commit_msg>Add enum size cases to type-sizes test<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::mem::size_of;

struct t {a: u8, b: i8}
struct u {a: u8, b: i8, c: u8}
struct v {a: u8, b: i8, c: v2, d: u32}
struct v2 {u: char, v: u8}
struct w {a: int, b: ()}
struct x {a: int, b: (), c: ()}
struct y {x: int}

enum e1 {
    a(u8, u32), b(u32), c
}
enum e2 {
    a(u32), b
}

enum e3 {
    a([u64, ..0], u32), b
}

pub fn main() {
    assert_eq!(size_of::<u8>(), 1 as uint);
    assert_eq!(size_of::<u32>(), 4 as uint);
    assert_eq!(size_of::<char>(), 4 as uint);
    assert_eq!(size_of::<i8>(), 1 as uint);
    assert_eq!(size_of::<i32>(), 4 as uint);
    assert_eq!(size_of::<t>(), 2 as uint);
    assert_eq!(size_of::<u>(), 3 as uint);
    // Alignment causes padding before the char and the u32.

    assert!(size_of::<v>() ==
                16 as uint);
    assert_eq!(size_of::<int>(), size_of::<uint>());
    assert_eq!(size_of::<w>(), size_of::<int>());
    assert_eq!(size_of::<x>(), size_of::<int>());
    assert_eq!(size_of::<int>(), size_of::<y>());

    // Make sure enum types are the appropriate size, mostly
    // around ensuring alignment is handled properly

    assert_eq!(size_of::<e1>(), 8 as uint);
    assert_eq!(size_of::<e2>(), 8 as uint);
    assert_eq!(size_of::<e3>(), 16 as uint);
}
<|endoftext|>


<commit_before>use std::{ net, marker, io, collections,  };
use std::str::FromStr;
use std::io::Read;

use mio::*;

const SERVER: Token = Token(0);

pub struct WebSocketServer<T, C> where T: WebSocketHandler<C> {
    handler: T,                                         // User handler which implements callbacks
    phantom: marker::PhantomData<C>,                    // I need to use this to calm down the compiler
    listener: tcp::TcpListener,                         // Listens all incoming connections

    clients: collections::HashMap<Token, (C, tcp::TcpStream)>, // List af all clients
    client_tokens: usize                                       // Counter to assign tokens to clients
}

impl<T, C> Handler for WebSocketServer<T, C> where T: WebSocketHandler<C> {
    type Timeout = ();
    type Message = ();

    fn ready(&mut self, main_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
        match token {
            // Got new connection. Let's add it to the list of clients and notify a user
            SERVER => {
                match self.listener.accept() {
                    Ok(client) => {
                        self.register_client(client, main_loop);
                    },
                    Err(e) => { println!("Error accepting a client: {}", e) }
                }
            }
            ref t => {
                // Client have disconnected
                // TODO: Handle error
                if events.is_error() || events.is_hup() {
                    self.disconnect_client(token, main_loop);
                    return;
                }

                // Client sent a message
                match self.clients.get_mut(t) {
                    Some(&mut (ref mut client, ref mut stream)) => {
                        let ref mut buffer = [0; 1024];

                        if let Ok(_) = stream.read(buffer) {
                            self.handler.on_message(String::from_utf8_lossy(buffer).into_owned(), client)
                        }
                    },
                    None => { println!("Failed to find a client, which sends a message {:?}", token); }
                }
            }
        }
    }
}

impl<T, C> WebSocketServer<T, C> where T: WebSocketHandler<C> + Sync {
    fn new(handler: T, addr: &'static str) -> io::Result<WebSocketServer<T, C>> {
        let formated_addr = net::SocketAddr::from_str(addr).unwrap();
        let listener = try!(tcp::TcpListener::bind(&formated_addr));

        let mut result = WebSocketServer {
            handler: handler,
            phantom: marker::PhantomData,
            listener:listener,
            clients: collections::HashMap::new(),
            client_tokens: 2
        };

        let mut main_loop = try!(EventLoop::<Self>::new());
        try!(main_loop.register(&result.listener, SERVER));
        try!(main_loop.run(&mut result));

        return Ok(result)
    }

    fn register_client(&mut self, client: Option<tcp::TcpStream>, main_loop: &mut EventLoop<Self>) {
        if let Some(client) = client {
            self.client_tokens += 1;

            match main_loop.register(&client, Token(self.client_tokens)) {
                Err(e) => { println!("Error registering a client: {}", e) },
                _ => {
                    let addr = format!("{}", client.peer_addr().unwrap());

                    let _ = self.clients.insert(Token(self.client_tokens),
                                                (self.handler.on_connect(addr), client));
                }
            }
        }
    }

    fn disconnect_client(&mut self, token: Token, main_loop: &mut EventLoop<Self>) {
        match self.clients.remove(&token) {
            Some((client, stream)) => {
                match main_loop.deregister(&stream) {
                    Ok(_) => { self.handler.on_disconnect(client) },
                    Err(e) => { println!("Failed do unregister a client {}", e) }
                }
            },
            None => { println!("Failed to disconnect a client"); }
        }
    }
}

pub trait WebSocketHandler<C>: Sized + marker::Sync {
    fn listen(self, addr: &'static str) -> io::Result<WebSocketServer<Self, C>> {
        return WebSocketServer::new(self, addr)
    }

    fn on_connect(&self, addr: String) -> C;
    fn on_message(&self, message: String, client: &mut C);
    fn on_disconnect(&self, client: C);
}
<commit_msg>Minor code cleanup<commit_after>use std::{ net, marker, io, collections,  };
use std::str::FromStr;
use std::io::Read;

use mio::*;

const SERVER: Token = Token(0);

struct TokenFactory(usize);
impl TokenFactory {
    fn next_token(&mut self) -> Token { self.0 += 1; Token(self.0) }
}

pub struct WebSocketServer<T, C> where T: WebSocketHandler<C> {
    handler: T,                                         // User handler which implements callbacks
    phantom: marker::PhantomData<C>,                    // I need to use this to calm down the compiler
    listener: tcp::TcpListener,                         // Listens all incoming connections

    clients: collections::HashMap<Token, (C, tcp::TcpStream)>, // List af all clients
    tokens: TokenFactory                                       // Counter to assign tokens to clients
}

impl<T, C> Handler for WebSocketServer<T, C> where T: WebSocketHandler<C> {
    type Timeout = ();
    type Message = ();

    fn ready(&mut self, main_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
        match token {
            // Got new connection. Lets add it to the list of clients and notify a user
            SERVER => {
                match self.listener.accept() {
                    Ok(client) => { self.register_client(client, main_loop); },
                    Err(e) => { println!("Error accepting a client: {}", e) }
                }
            }
            ref token => {
                // Client has been disconnected
                // TODO: Handle error
                if events.is_error() || events.is_hup() {
                    self.disconnect_client(*token, main_loop);
                    return;
                }

                // Got a message from a client
                match self.clients.get_mut(token) {
                    Some(&mut (ref mut client, ref mut stream)) => {
                        let ref mut buffer = [0; 1024];

                        if let Ok(_) = stream.read(buffer) {
                            self.handler.on_message(String::from_utf8_lossy(buffer).into_owned(), client)
                        }
                    },
                    None => { println!("Failed to find a client, which sends a message {:?}", token); }
                }
            }
        }
    }
}

impl<T, C> WebSocketServer<T, C> where T: WebSocketHandler<C> + Sync {
    fn new(handler: T, addr: &'static str) -> io::Result<()> {
        let formated_addr = net::SocketAddr::from_str(addr).unwrap();
        let listener = try!(tcp::TcpListener::bind(&formated_addr));

        let mut result = WebSocketServer {
            handler: handler,
            phantom: marker::PhantomData,
            listener:listener,
            clients: collections::HashMap::new(),
            tokens: TokenFactory(1)
        };

        let mut main_loop = try!(EventLoop::<Self>::new());
        try!(main_loop.register(&result.listener, SERVER));
        try!(main_loop.run(&mut result));

        return Ok(())
    }

    fn register_client(&mut self, client: Option<tcp::TcpStream>, main_loop: &mut EventLoop<Self>) {
        if let Some(client) = client {
            let token = self.tokens.next_token();

            match main_loop.register(&client, token) {
                Err(e) => { println!("Error registering a client: {}", e) },
                _ => {
                    let addr = format!("{}", client.peer_addr().unwrap());

                    let _ = self.clients.insert(token,
                                                (self.handler.on_connect(addr), client));
                }
            }
        }
    }

    fn disconnect_client(&mut self, token: Token, main_loop: &mut EventLoop<Self>) {
        match self.clients.remove(&token) {
            Some((client, stream)) => {
                match main_loop.deregister(&stream) {
                    Ok(_) => { self.handler.on_disconnect(client) },
                    Err(e) => { println!("Failed do unregister a client {}", e) }
                }
            },
            None => { println!("Failed to disconnect a client"); }
        }
    }
}

pub trait WebSocketHandler<C>: Sized + marker::Sync {
    fn listen(self, addr: &'static str) -> io::Result<()> {
        return WebSocketServer::new(self, addr)
    }

    fn on_connect(&self, addr: String) -> C;
    fn on_message(&self, message: String, client: &mut C);
    fn on_disconnect(&self, client: C);
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::{Arc, RwLock};
use std::sync::mpsc::{channel, Receiver};
use std::time::Duration;

use cli;
use env_logger;
use gitignore;
use log;
use notification_filter::NotificationFilter;
use process::{self, Process};
use signal::{self, Signal};
use watcher::{Event, Watcher};
use pathop::PathOp;

fn init_logger(debug: bool) {
    let mut log_builder = env_logger::LogBuilder::new();
    let level = if debug {
        log::LogLevelFilter::Debug
    } else {
        log::LogLevelFilter::Warn
    };

    log_builder
        .format(|r| format!("*** {}", r.args()))
        .filter(None, level);
    log_builder.init().expect("unable to initialize logger");
}

pub fn run(args: cli::Args) {
    let child_process: Arc<RwLock<Option<Process>>> = Arc::new(RwLock::new(None));
    let weak_child = Arc::downgrade(&child_process);

    // Convert signal string to the corresponding integer
    let signal = signal::new(args.signal);

    signal::install_handler(move |sig: Signal| {
        if let Some(lock) = weak_child.upgrade() {
            let strong = lock.read().unwrap();
            if let Some(ref child) = *strong {
                match sig {
                    Signal::SIGCHLD => child.reap(), // SIGCHLD is special, initiate reap()
                    _ => child.signal(sig),
                }
            }
        }
    });

    init_logger(args.debug);

    let paths: Vec<PathBuf> = args.paths
        .iter()
        .map(|p| {
                 Path::new(&p)
                     .canonicalize()
                     .expect(&format!("unable to canonicalize \"{}\"", &p))
                     .to_owned()
             })
        .collect();

    let gitignore = if !args.no_vcs_ignore {
        gitignore::load(&paths)
    } else {
        gitignore::load(&[])
    };

    let filter = NotificationFilter::new(args.filters, args.ignores, gitignore)
        .expect("unable to create notification filter");

    let (tx, rx) = channel();
    let watcher =
        Watcher::new(tx, &paths, args.poll, args.poll_interval).expect("unable to create watcher");

    if watcher.is_polling() {
        warn!("Polling for changes every {} ms", args.poll_interval);
    }

    // Start child process initially, if necessary
    if args.run_initially && !args.once {
        if args.clear_screen {
            cli::clear_screen();
        }

        let mut guard = child_process.write().unwrap();
        *guard = Some(process::spawn(&args.cmd, vec![], args.no_shell));
    }

    loop {
        debug!("Waiting for filesystem activity");
        let paths = wait_fs(&rx, &filter, args.debounce);
        if let Some(path) = paths.get(0) {
            debug!("Path updated: {:?}", path);
        }

        // We have three scenarios here:
        //
        // 1. Make sure the previous run was ended, then run the command again
        // 2. Just send a specified signal to the child, do nothing more
        // 3. Send SIGTERM to the child, wait for it to exit, then run the command again
        // 4. Send a specified signal to the child, wait for it to exit, then run the command again
        //
        let scenario = (args.restart, signal.is_some());

        match scenario {
            // Custom restart behaviour (--restart was given, and --signal specified):
            // Send specified signal to the child, wait for it to exit, then run the command again
            (true, true) => {
                signal_process(&child_process, signal, true);

                // Launch child process
                if args.clear_screen {
                    cli::clear_screen();
                }

                debug!("Launching child process");
                {
                    let mut guard = child_process.write().unwrap();
                    *guard = Some(process::spawn(&args.cmd, paths, args.no_shell));
                }
            }

            // Default restart behaviour (--restart was given, but --signal wasn't specified):
            // Send SIGTERM to the child, wait for it to exit, then run the command again
            (true, false) => {
                let sigterm = signal::new(Some("SIGTERM".to_owned()));
                signal_process(&child_process, sigterm, true);

                // Launch child process
                if args.clear_screen {
                    cli::clear_screen();
                }

                debug!("Launching child process");
                {
                    let mut guard = child_process.write().unwrap();
                    *guard = Some(process::spawn(&args.cmd, paths, args.no_shell));
                }
            }

            // SIGHUP scenario: --signal was given, but --restart was not
            // Just send a signal (e.g. SIGHUP) to the child, do nothing more
            (false, true) => signal_process(&child_process, signal, false),

            // Default behaviour (neither --signal nor --restart specified):
            // Make sure the previous run was ended, then run the command again
            (false, false) => {
                signal_process(&child_process, None, true);

                // Launch child process
                if args.clear_screen {
                    cli::clear_screen();
                }

                debug!("Launching child process");
                {
                    let mut guard = child_process.write().unwrap();
                    *guard = Some(process::spawn(&args.cmd, paths, args.no_shell));
                }
            }
        }

        // Handle once option for integration testing
        if args.once {
            signal_process(&child_process, signal, false);
            break;
        }
    }
}

fn wait_fs(rx: &Receiver<Event>, filter: &NotificationFilter, debounce: u64) -> Vec<PathOp> {
    let mut paths = vec![];
    let mut cache = HashMap::new();

    loop {
        let e = rx.recv().expect("error when reading event");

        if let Some(ref path) = e.path {
            let pathop = PathOp::new(path, e.op.ok(), e.cookie);
            // Ignore cache for the initial file. Otherwise, in
            // debug mode it's hard to track what's going on
            let excluded = filter.is_excluded(path);
            if !cache.contains_key(&pathop) {
                cache.insert(pathop.clone(), excluded);
            }

            if !excluded {
                paths.push(pathop);
                break;
            }
        }
    }

    // Wait for filesystem activity to cool off
    let timeout = Duration::from_millis(debounce);
    while let Ok(e) = rx.recv_timeout(timeout) {
        if let Some(ref path) = e.path {
            let pathop = PathOp::new(path, e.op.ok(), e.cookie);
            if cache.contains_key(&pathop) {
                continue;
            }

            let excluded = filter.is_excluded(path);

            cache.insert(pathop.clone(), excluded);

            if !excluded {
                paths.push(pathop);
            }
        }
    }

    paths
}

// signal_process sends signal to process. It waits for the process to exit if wait is true
fn signal_process(process: &RwLock<Option<Process>>, signal: Option<Signal>, wait: bool) {
    let guard = process.read().unwrap();

    if let Some(ref child) = *guard {
        if let Some(s) = signal {
            child.signal(s);
        }

        if wait {
            debug!("Waiting for process to exit...");
            child.wait();
        }
    }
}
<commit_msg>Add a warning and fallback on polling mode if limit exceeded<commit_after>use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::{Arc, RwLock};
use std::sync::mpsc::{channel, Receiver};
use std::time::Duration;

use cli;
use env_logger;
use gitignore;
use log;
use notify::Error;
use notification_filter::NotificationFilter;
use process::{self, Process};
use signal::{self, Signal};
use watcher::{Event, Watcher};
use pathop::PathOp;

fn init_logger(debug: bool) {
    let mut log_builder = env_logger::LogBuilder::new();
    let level = if debug {
        log::LogLevelFilter::Debug
    } else {
        log::LogLevelFilter::Warn
    };

    log_builder
        .format(|r| format!("*** {}", r.args()))
        .filter(None, level);
    log_builder.init().expect("unable to initialize logger");
}

#[cfg(target_os="linux")]
fn should_switch_to_poll(e: &Error) -> bool {
    use nix::libc;

    match e {
        &Error::Io(ref e) if e.raw_os_error() == Some(libc::ENOSPC) => true,
        _ => false,
    }
}

#[cfg(not(target_os="linux"))]
fn should_switch_to_poll(_: &Error) -> bool {
    // not known conditions to switch
    false
}

pub fn run(args: cli::Args) {
    let child_process: Arc<RwLock<Option<Process>>> = Arc::new(RwLock::new(None));
    let weak_child = Arc::downgrade(&child_process);

    // Convert signal string to the corresponding integer
    let signal = signal::new(args.signal);

    signal::install_handler(move |sig: Signal| {
        if let Some(lock) = weak_child.upgrade() {
            let strong = lock.read().unwrap();
            if let Some(ref child) = *strong {
                match sig {
                    Signal::SIGCHLD => child.reap(), // SIGCHLD is special, initiate reap()
                    _ => child.signal(sig),
                }
            }
        }
    });

    init_logger(args.debug);

    let paths: Vec<PathBuf> = args.paths
        .iter()
        .map(|p| {
                 Path::new(&p)
                     .canonicalize()
                     .expect(&format!("unable to canonicalize \"{}\"", &p))
                     .to_owned()
             })
        .collect();

    let gitignore = if !args.no_vcs_ignore {
        gitignore::load(&paths)
    } else {
        gitignore::load(&[])
    };

    let filter = NotificationFilter::new(args.filters, args.ignores, gitignore)
        .expect("unable to create notification filter");

    let (tx, rx) = channel();
    let watcher = match Watcher::new(tx.clone(), &paths, args.poll, args.poll_interval) {
        Ok(watcher) => watcher,
        Err(ref e) if !args.poll && should_switch_to_poll(e) => {
            warn!("System notification limit is too small, \
                falling back to polling mode.");
            if cfg!(target_os="linux") {
                warn!("For better performance increase system limit: \n   \
                       sysctl fs.inotify.max_user_watches=524288");
            }
            Watcher::new(tx, &paths, true, args.poll_interval)
                .expect("polling watcher should always work")
        }
        Err(e) => {
            panic!("Error setting up watcher: {}", e);
        }
    };

    if watcher.is_polling() {
        warn!("Polling for changes every {} ms", args.poll_interval);
    }

    // Start child process initially, if necessary
    if args.run_initially && !args.once {
        if args.clear_screen {
            cli::clear_screen();
        }

        let mut guard = child_process.write().unwrap();
        *guard = Some(process::spawn(&args.cmd, vec![], args.no_shell));
    }

    loop {
        debug!("Waiting for filesystem activity");
        let paths = wait_fs(&rx, &filter, args.debounce);
        if let Some(path) = paths.get(0) {
            debug!("Path updated: {:?}", path);
        }

        // We have three scenarios here:
        //
        // 1. Make sure the previous run was ended, then run the command again
        // 2. Just send a specified signal to the child, do nothing more
        // 3. Send SIGTERM to the child, wait for it to exit, then run the command again
        // 4. Send a specified signal to the child, wait for it to exit, then run the command again
        //
        let scenario = (args.restart, signal.is_some());

        match scenario {
            // Custom restart behaviour (--restart was given, and --signal specified):
            // Send specified signal to the child, wait for it to exit, then run the command again
            (true, true) => {
                signal_process(&child_process, signal, true);

                // Launch child process
                if args.clear_screen {
                    cli::clear_screen();
                }

                debug!("Launching child process");
                {
                    let mut guard = child_process.write().unwrap();
                    *guard = Some(process::spawn(&args.cmd, paths, args.no_shell));
                }
            }

            // Default restart behaviour (--restart was given, but --signal wasn't specified):
            // Send SIGTERM to the child, wait for it to exit, then run the command again
            (true, false) => {
                let sigterm = signal::new(Some("SIGTERM".to_owned()));
                signal_process(&child_process, sigterm, true);

                // Launch child process
                if args.clear_screen {
                    cli::clear_screen();
                }

                debug!("Launching child process");
                {
                    let mut guard = child_process.write().unwrap();
                    *guard = Some(process::spawn(&args.cmd, paths, args.no_shell));
                }
            }

            // SIGHUP scenario: --signal was given, but --restart was not
            // Just send a signal (e.g. SIGHUP) to the child, do nothing more
            (false, true) => signal_process(&child_process, signal, false),

            // Default behaviour (neither --signal nor --restart specified):
            // Make sure the previous run was ended, then run the command again
            (false, false) => {
                signal_process(&child_process, None, true);

                // Launch child process
                if args.clear_screen {
                    cli::clear_screen();
                }

                debug!("Launching child process");
                {
                    let mut guard = child_process.write().unwrap();
                    *guard = Some(process::spawn(&args.cmd, paths, args.no_shell));
                }
            }
        }

        // Handle once option for integration testing
        if args.once {
            signal_process(&child_process, signal, false);
            break;
        }
    }
}

fn wait_fs(rx: &Receiver<Event>, filter: &NotificationFilter, debounce: u64) -> Vec<PathOp> {
    let mut paths = vec![];
    let mut cache = HashMap::new();

    loop {
        let e = rx.recv().expect("error when reading event");

        if let Some(ref path) = e.path {
            let pathop = PathOp::new(path, e.op.ok(), e.cookie);
            // Ignore cache for the initial file. Otherwise, in
            // debug mode it's hard to track what's going on
            let excluded = filter.is_excluded(path);
            if !cache.contains_key(&pathop) {
                cache.insert(pathop.clone(), excluded);
            }

            if !excluded {
                paths.push(pathop);
                break;
            }
        }
    }

    // Wait for filesystem activity to cool off
    let timeout = Duration::from_millis(debounce);
    while let Ok(e) = rx.recv_timeout(timeout) {
        if let Some(ref path) = e.path {
            let pathop = PathOp::new(path, e.op.ok(), e.cookie);
            if cache.contains_key(&pathop) {
                continue;
            }

            let excluded = filter.is_excluded(path);

            cache.insert(pathop.clone(), excluded);

            if !excluded {
                paths.push(pathop);
            }
        }
    }

    paths
}

// signal_process sends signal to process. It waits for the process to exit if wait is true
fn signal_process(process: &RwLock<Option<Process>>, signal: Option<Signal>, wait: bool) {
    let guard = process.read().unwrap();

    if let Some(ref child) = *guard {
        if let Some(s) = signal {
            child.signal(s);
        }

        if wait {
            debug!("Waiting for process to exit...");
            child.wait();
        }
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use super::gl;
use super::gl_lib::types::*;
use super::types::GLError;

pub struct Shader {
    gl_id: GLuint
}

impl Shader {
    pub unsafe fn from_id(id: GLuint) -> Shader {
        Shader { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }

    pub fn source(&mut self, shader_source: &str) {
        unsafe {
            let source = shader_source.as_ptr() as *const GLchar;
            let length = shader_source.len() as GLint;

            gl::ShaderSource(self.gl_id, 1,
                             &source as *const *const GLchar,
                             &length as *const GLint);
        }
    }

    pub fn compile(&mut self) -> Result<(), GLError> {
        let success = unsafe {
            gl::CompileShader(self.gl_id);
            let mut compile_status : GLint = mem::uninitialized();
            gl::GetShaderiv(self.gl_id,
                            gl::COMPILE_STATUS,
                            &mut compile_status as *mut GLint);

            compile_status == gl::TRUE as GLint
        };

        if success {
            Ok(())
        }
        else {
            unsafe {
                let mut info_length : GLint = mem::uninitialized();
                gl::GetShaderiv(self.gl_id,
                                gl::INFO_LOG_LENGTH,
                                &mut info_length as *mut GLint);

                let mut bytes = Vec::<u8>::with_capacity(info_length as usize);

                gl::GetShaderInfoLog(self.gl_id,
                                     info_length,
                                     ptr::null_mut(),
                                     bytes.as_mut_ptr() as *mut GLchar);

                let msg = String::from_utf8(bytes)
                                 .unwrap_or(String::from("<Unknown error>"));

                Err(GLError { message: msg })
            }
        }
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteShader(self.gl_id);
        }
    }
}

#[derive(Debug, Clone, Copy)]
#[allow(non_camel_case_types)]
pub enum ShaderType {
    VERTEX_SHADER = gl::VERTEX_SHADER as isize,
    FRAGMENT_SHADER = gl::FRAGMENT_SHADER as isize
}
pub use self::ShaderType::*;
<commit_msg>Fix `Shader.compile` returning an empty `GLError` on failure<commit_after>use std::mem;
use std::ptr;
use super::gl;
use super::gl_lib::types::*;
use super::types::GLError;

pub struct Shader {
    gl_id: GLuint
}

impl Shader {
    pub unsafe fn from_id(id: GLuint) -> Shader {
        Shader { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }

    pub fn source(&mut self, shader_source: &str) {
        unsafe {
            let source = shader_source.as_ptr() as *const GLchar;
            let length = shader_source.len() as GLint;

            gl::ShaderSource(self.gl_id, 1,
                             &source as *const *const GLchar,
                             &length as *const GLint);
        }
    }

    pub fn compile(&mut self) -> Result<(), GLError> {
        let success = unsafe {
            gl::CompileShader(self.gl_id);
            let mut compile_status : GLint = mem::uninitialized();
            gl::GetShaderiv(self.gl_id,
                            gl::COMPILE_STATUS,
                            &mut compile_status as *mut GLint);

            compile_status == gl::TRUE as GLint
        };

        if success {
            Ok(())
        }
        else {
            unsafe {
                let mut info_length : GLint = mem::uninitialized();
                gl::GetShaderiv(self.gl_id,
                                gl::INFO_LOG_LENGTH,
                                &mut info_length as *mut GLint);

                let mut bytes = Vec::<u8>::with_capacity(info_length as usize);

                gl::GetShaderInfoLog(self.gl_id,
                                     info_length,
                                     ptr::null_mut(),
                                     bytes.as_mut_ptr() as *mut GLchar);
                bytes.set_len((info_length - 1) as usize);

                let msg = String::from_utf8(bytes)
                                 .unwrap_or(String::from("<Unknown error>"));

                Err(GLError { message: msg })
            }
        }
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteShader(self.gl_id);
        }
    }
}

#[derive(Debug, Clone, Copy)]
#[allow(non_camel_case_types)]
pub enum ShaderType {
    VERTEX_SHADER = gl::VERTEX_SHADER as isize,
    FRAGMENT_SHADER = gl::FRAGMENT_SHADER as isize
}
pub use self::ShaderType::*;
<|endoftext|>