<commit_before>#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(unused_assignments)]
extern crate json;

use std::cmp::Ordering;

pub struct PhoneticParser<'a> {
    patterns: &'a json::JsonValue,
    vowel: String,
    consonant: String,
    numbers: String,
    case_sensitive: String,
}

impl<'a> PhoneticParser<'a> {
    pub fn new(rule: &json::JsonValue) -> PhoneticParser {
        PhoneticParser {
            patterns: &rule["patterns"],
            vowel: rule["vowel"].as_str().unwrap().to_string(),
            consonant: rule["consonant"].as_str().unwrap().to_string(),
            numbers: rule["number"].as_str().unwrap().to_string(),
            case_sensitive: rule["casesensitive"].as_str().unwrap().to_string(),
        }
    }

    pub fn convert(&self, input: String) -> String {
        let fixed = self.fix_string(input);
        let mut output = String::new();

        let _find = self.patterns[0]["find"].as_str().unwrap();
        let max_pattern_len = _find.len();

        let len = fixed.len();
        let mut cur = 0;
        while cur < len {
            let start = cur as i32;
            let mut end: i32 = 0;
            let mut matched = false;

            for chunk_len in (1..=max_pattern_len).rev() {
                end = start + chunk_len as i32;
                if end <= len as i32 {
                    let chunk = fixed.substring(start as usize, chunk_len as usize);

                    // Binary Search
                    let mut left: i32 = 0;
                    let mut right = self.patterns.len() as i32 - 1;
                    let mut mid: i32 = 0;
                    while right >= left {
                        mid = (right + left) / 2;
                        let pattern = &self.patterns[mid as usize];
                        let find = pattern["find"].as_str().unwrap();
                        if find == chunk {
                            let rules = &pattern["rules"];
                            if !rules.is_empty() {
                                for rule in rules.members() {
                                    let mut replace = true;
                                    let mut chk = 0;
                                    let matches = &rule["matches"];
                                    for _match in matches.members() {
                                        let value = _match["value"].as_str().unwrap_or("");
                                        let _type = _match["type"].as_str().unwrap();
                                        let mut scope = _match["scope"].as_str().unwrap();
                                        let mut is_negative = false;

                                        // Handle Negative
                                        if &scope[0..1] == "!" {
                                            is_negative = true;
                                            scope = &scope[1..];
                                        }

                                        if _find == "suffix" {
                                            chk = end;
                                        } else {
                                            chk = start - 1;
                                        }

                                        // Beginning
                                        match scope {
                                            "punctuation" => if ((chk < 0 && (_type == "prefix"))
                                                || (chk >= len as i32 && (_type == "suffix"))
                                                || self.is_punctuation(fixed.at(chk as usize)))
                                                == is_negative
                                            {
                                                replace = false;
                                                break;
                                            },
                                            "vowel" => if (((chk >= 0 && (_type == "prefix"))
                                                || (chk < len as i32 && (_type == "suffix")))
                                                && self.is_vowel(fixed.at(chk as usize)))
                                                == is_negative
                                            {
                                                replace = false;
                                                break;
                                            },

                                            "consonant" => if (((chk >= 0 && (_type == "prefix"))
                                                || (chk < len as i32 && (_type == "suffix")))
                                                && self.is_consonant(fixed.at(chk as usize)))
                                                == is_negative
                                            {
                                                replace = false;
                                                break;
                                            },

                                            "number" => if (((chk >= 0 && (_type == "prefix"))
                                                || (chk < len as i32 && (_type == "suffix")))
                                                && self.is_number(fixed.at(chk as usize)))
                                                == is_negative
                                            {
                                                replace = false;
                                                break;
                                            },

                                            "exact" => {
                                                let mut s: i32 = 0;
                                                let mut e: i32 = 0;
                                                if _type == "suffix" {
                                                    s = end;
                                                    e = end + value.len() as i32;
                                                } else {
                                                    // Prefix
                                                    s = start - value.len() as i32;
                                                    e = start;
                                                }
                                                if !self.is_exact(value, &fixed, s, e, is_negative)
                                                {
                                                    replace = false;
                                                    break;
                                                }
                                            }
                                            _ => panic!("Unknown scope"),
                                        };
                                    }

                                    if replace {
                                        output += rule["replace"].as_str().unwrap();
                                        cur = (end - 1) as usize;
                                        matched = true;
                                        break;
                                    }
                                }
                            }

                            if matched {
                                break;
                            }

                            // Default
                            output += pattern["replace"].as_str().unwrap();
                            cur = (end - 1) as usize;
                            matched = true;
                            break;
                        } else if find.len() > chunk.len()
                            || (find.len() == chunk.len() && find.cmp(&chunk) == Ordering::Less)
                        {
                            left = mid + 1;
                        } else {
                            right = mid - 1;
                        }
                    }
                    if matched {
                        break;
                    }
                }
            }

            if !matched {
                output += &fixed[cur..cur + 1];
            }
            cur += 1;
        }

        output
    }

    fn fix_string(&self, string: String) -> String {
        string
            .chars()
            .map(|character| {
                if self.is_case_sensitive(character) {
                    character
                } else {
                    character.to_lowercase().next().unwrap()
                }
            })
            .collect()
    }

    fn is_vowel(&self, string: &str) -> bool {
        self.vowel.contains(&string.to_lowercase())
    }

    fn is_consonant(&self, string: &str) -> bool {
        self.consonant.contains(&string.to_lowercase())
    }

    fn is_case_sensitive(&self, character: char) -> bool {
        self.case_sensitive
            .contains(&character.to_lowercase().to_string())
    }

    fn is_number(&self, character: &str) -> bool {
        self.numbers.contains(character)
    }

    fn is_exact(&self, needle: &str, heystack: &str, start: i32, end: i32, not: bool) -> bool {
        let len = end - start;
        (start >= 0 && end < heystack.len() as i32
            && (heystack.substring(start as usize, len as usize) == needle)) != not
    }

    fn is_punctuation(&self, character: &str) -> bool {
        !(self.is_vowel(character) || self.is_consonant(character))
    }
}

trait Substring {
    fn substring(&self, start: usize, length: usize) -> &str;
    fn at(&self, pos: usize) -> &str;
}

impl Substring for std::string::String {
    fn substring(&self, start: usize, length: usize) -> &str {
        &self[start..(start + length)]
    }

    fn at(&self, pos: usize) -> &str {
        &self[pos..pos + 1]
    }
}

impl Substring for str {
    fn substring(&self, start: usize, length: usize) -> &str {
        &self[start..(start + length)]
    }

    fn at(&self, pos: usize) -> &str {
        &self[pos..pos + 1]
    }
}

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

    #[test]
    fn test_helpers() {
        let json = json::parse(include_str!("AvroPhonetic.json")).unwrap();
        let parser = PhoneticParser::new(&json);

        assert!(parser.is_vowel("A"));
        assert_eq!(parser.is_vowel("b"), false);
        assert!(parser.is_consonant("B"));
        assert_eq!(parser.is_consonant("e"), false);
        assert_eq!(parser.fix_string("ODEr AMAr".to_string()), "ODer amar");
        assert!(parser.is_number("1"));
    }
}
<commit_msg>Fix a bug :bug:<commit_after>#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(unused_assignments)]
extern crate json;

use std::cmp::Ordering;

pub struct PhoneticParser<'a> {
    patterns: &'a json::JsonValue,
    vowel: String,
    consonant: String,
    numbers: String,
    case_sensitive: String,
}

impl<'a> PhoneticParser<'a> {
    pub fn new(rule: &json::JsonValue) -> PhoneticParser {
        PhoneticParser {
            patterns: &rule["patterns"],
            vowel: rule["vowel"].as_str().unwrap().to_string(),
            consonant: rule["consonant"].as_str().unwrap().to_string(),
            numbers: rule["number"].as_str().unwrap().to_string(),
            case_sensitive: rule["casesensitive"].as_str().unwrap().to_string(),
        }
    }

    pub fn convert(&self, input: String) -> String {
        let fixed = self.fix_string(input);
        let mut output = String::new();

        let _find = self.patterns[0]["find"].as_str().unwrap();
        let max_pattern_len = _find.len();

        let len = fixed.len();
        let mut cur = 0;
        while cur < len {
            let start = cur as i32;
            let mut end: i32 = 0;
            let mut matched = false;

            for chunk_len in (1..=max_pattern_len).rev() {
                end = start + chunk_len as i32;
                if end <= len as i32 {
                    let chunk = fixed.substring(start as usize, chunk_len as usize);

                    // Binary Search
                    let mut left: i32 = 0;
                    let mut right = self.patterns.len() as i32 - 1;
                    let mut mid: i32 = 0;
                    while right >= left {
                        mid = (right + left) / 2;
                        let pattern = &self.patterns[mid as usize];
                        let find = pattern["find"].as_str().unwrap();
                        if find == chunk {
                            let rules = &pattern["rules"];
                            if !rules.is_empty() {
                                for rule in rules.members() {
                                    let mut replace = true;
                                    let mut chk = 0;
                                    let matches = &rule["matches"];
                                    for _match in matches.members() {
                                        let value = _match["value"].as_str().unwrap_or("");
                                        let _type = _match["type"].as_str().unwrap();
                                        let mut scope = _match["scope"].as_str().unwrap();
                                        let mut is_negative = false;

                                        // Handle Negative
                                        if &scope[0..1] == "!" {
                                            is_negative = true;
                                            scope = &scope[1..];
                                        }

                                        if _type == "suffix" {
                                            chk = end;
                                        } else {
                                            chk = start - 1;
                                        }

                                        // Beginning
                                        match scope {
                                            "punctuation" => if ((chk < 0 && (_type == "prefix"))
                                                || (chk >= len as i32 && (_type == "suffix"))
                                                || self.is_punctuation(fixed.at(chk as usize)))
                                                == is_negative
                                            {
                                                replace = false;
                                                break;
                                            },
                                            "vowel" => if (((chk >= 0 && (_type == "prefix"))
                                                || (chk < len as i32 && (_type == "suffix")))
                                                && self.is_vowel(fixed.at(chk as usize)))
                                                == is_negative
                                            {
                                                replace = false;
                                                break;
                                            },

                                            "consonant" => if (((chk >= 0 && (_type == "prefix"))
                                                || (chk < len as i32 && (_type == "suffix")))
                                                && self.is_consonant(fixed.at(chk as usize)))
                                                == is_negative
                                            {
                                                replace = false;
                                                break;
                                            },

                                            "number" => if (((chk >= 0 && (_type == "prefix"))
                                                || (chk < len as i32 && (_type == "suffix")))
                                                && self.is_number(fixed.at(chk as usize)))
                                                == is_negative
                                            {
                                                replace = false;
                                                break;
                                            },

                                            "exact" => {
                                                let mut s: i32 = 0;
                                                let mut e: i32 = 0;
                                                if _type == "suffix" {
                                                    s = end;
                                                    e = end + value.len() as i32;
                                                } else {
                                                    // Prefix
                                                    s = start - value.len() as i32;
                                                    e = start;
                                                }
                                                if !self.is_exact(value, &fixed, s, e, is_negative)
                                                {
                                                    replace = false;
                                                    break;
                                                }
                                            }
                                            _ => panic!("Unknown scope"),
                                        };
                                    }

                                    if replace {
                                        output += rule["replace"].as_str().unwrap();
                                        cur = (end - 1) as usize;
                                        matched = true;
                                        break;
                                    }
                                }
                            }

                            if matched {
                                break;
                            }

                            // Default
                            output += pattern["replace"].as_str().unwrap();
                            cur = (end - 1) as usize;
                            matched = true;
                            break;
                        } else if find.len() > chunk.len()
                            || (find.len() == chunk.len() && find.cmp(&chunk) == Ordering::Less)
                        {
                            left = mid + 1;
                        } else {
                            right = mid - 1;
                        }
                    }
                    if matched {
                        break;
                    }
                }
            }

            if !matched {
                output += &fixed[cur..cur + 1];
            }
            cur += 1;
        }

        output
    }

    fn fix_string(&self, string: String) -> String {
        string
            .chars()
            .map(|character| {
                if self.is_case_sensitive(character) {
                    character
                } else {
                    character.to_lowercase().next().unwrap()
                }
            })
            .collect()
    }

    fn is_vowel(&self, string: &str) -> bool {
        self.vowel.contains(&string.to_lowercase())
    }

    fn is_consonant(&self, string: &str) -> bool {
        self.consonant.contains(&string.to_lowercase())
    }

    fn is_case_sensitive(&self, character: char) -> bool {
        self.case_sensitive
            .contains(&character.to_lowercase().to_string())
    }

    fn is_number(&self, character: &str) -> bool {
        self.numbers.contains(character)
    }

    fn is_exact(&self, needle: &str, heystack: &str, start: i32, end: i32, not: bool) -> bool {
        let len = end - start;
        (start >= 0 && end < heystack.len() as i32
            && (heystack.substring(start as usize, len as usize) == needle)) != not
    }

    fn is_punctuation(&self, character: &str) -> bool {
        !(self.is_vowel(character) || self.is_consonant(character))
    }
}

trait Substring {
    fn substring(&self, start: usize, length: usize) -> &str;
    fn at(&self, pos: usize) -> &str;
}

impl Substring for std::string::String {
    fn substring(&self, start: usize, length: usize) -> &str {
        &self[start..(start + length)]
    }

    fn at(&self, pos: usize) -> &str {
        &self[pos..pos + 1]
    }
}

impl Substring for str {
    fn substring(&self, start: usize, length: usize) -> &str {
        &self[start..(start + length)]
    }

    fn at(&self, pos: usize) -> &str {
        &self[pos..pos + 1]
    }
}

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

    #[test]
    fn test_helpers() {
        let json = json::parse(include_str!("AvroPhonetic.json")).unwrap();
        let parser = PhoneticParser::new(&json);

        assert!(parser.is_vowel("A"));
        assert_eq!(parser.is_vowel("b"), false);
        assert!(parser.is_consonant("B"));
        assert_eq!(parser.is_consonant("e"), false);
        assert_eq!(parser.fix_string("ODEr AMAr".to_string()), "ODer amar");
        assert!(parser.is_number("1"));
    }
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! hado {
    (ret ( $ty:ty ) $expr:expr) => {
        $crate::Monad::< $ty >::ret($expr)
    };
    (ret $expr:expr) => {
        $crate::Monad::ret($expr)
    };
    (ign <- $expr:expr; $($rest:tt)*) => {
        $crate::Monad::bind($expr, |_| hado!($($rest)*))
    };
    (mut $ident:ident <- $expr:expr; $($rest:tt)*) => {
        $crate::Monad::bind($expr, |mut $ident| hado!($($rest)*))
    };
    ($ident:ident <- $expr:expr; $($rest:tt)*) => {
        $crate::Monad::bind($expr, |$ident| hado!($($rest)*))
    };
    ($stmt:stmt; $($rest:tt)*) => {
        { $stmt ; hado!($($rest)*) }
    };
    ($expr:expr) => {
        $expr
    }
}

pub trait Monad<O> {
    type Inner;
    fn bind<F>(t: Self, mut f: F) -> O where F: FnMut(Self::Inner) -> O ;
    fn ret(Self::Inner) -> Self;
}

impl<T, O> Monad<Option<O>> for Option<T> {
    type Inner = T;
    fn bind<F>(t: Option<T>, mut f: F) -> Option<O>
        where F: FnMut(T) -> Option<O> {
        match t {
            Some(t) => f(t),
            None => None,
        }
    }
    fn ret(inner: T) -> Self {
        Some(inner)
    }
}

impl<T, O, E> Monad<Result<O, E>> for Result<T, E> {
    type Inner = T;
    fn bind<F>(t: Result<T, E>, mut f: F) -> Result<O, E>
        where F: FnMut(T) -> Result<O, E> {
        match t {
            Ok(t) => f(t),
            Err(e) => Err(e),
        }
    }
    fn ret(inner: T) -> Self {
        Ok(inner)
    }
}

impl<T, O> Monad<Vec<O>> for Vec<T> {
    type Inner = T;
    fn bind<F>(t: Self, mut f: F) -> Vec<O>
        where F: FnMut(T) -> Vec<O> {
        let mut acc: Vec<O> = Vec::new();
        for v in t {
            let mut _v = f(v);
            acc.append(&mut _v);
        }
        acc
    }
    fn ret(inner: T) -> Vec<T> {
        vec![inner]
    }
}
<commit_msg>Little style fixup<commit_after>#[macro_export]
macro_rules! hado {
    (ret ( $ty:ty ) $expr:expr) => {
        $crate::Monad::< $ty >::ret($expr)
    };
    (ret $expr:expr) => {
        $crate::Monad::ret($expr)
    };
    (ign <- $expr:expr; $($rest:tt)*) => {
        $crate::Monad::bind($expr, |_| hado!($($rest)*))
    };
    (mut $ident:ident <- $expr:expr; $($rest:tt)*) => {
        $crate::Monad::bind($expr, |mut $ident| hado!($($rest)*))
    };
    ($ident:ident <- $expr:expr; $($rest:tt)*) => {
        $crate::Monad::bind($expr, |$ident| hado!($($rest)*))
    };
    ($stmt:stmt; $($rest:tt)*) => {
        { $stmt ; hado!($($rest)*) }
    };
    ($expr:expr) => {
        $expr
    }
}

pub trait Monad<O> {
    type Inner;
    fn bind<F>(t: Self, mut f: F) -> O where F: FnMut(Self::Inner) -> O ;
    fn ret(Self::Inner) -> Self;
}

impl<T, O> Monad<Option<O>> for Option<T> {
    type Inner = T;
    fn bind<F>(t: Option<T>, mut f: F) -> Option<O>
        where F: FnMut(T) -> Option<O> {
        match t {
            Some(t) => f(t),
            None => None,
        }
    }
    fn ret(inner: T) -> Self {
        Some(inner)
    }
}

impl<T, O, E> Monad<Result<O, E>> for Result<T, E> {
    type Inner = T;
    fn bind<F>(t: Result<T, E>, mut f: F) -> Result<O, E>
        where F: FnMut(T) -> Result<O, E> {
        match t {
            Ok(t) => f(t),
            Err(e) => Err(e),
        }
    }
    fn ret(inner: T) -> Self {
        Ok(inner)
    }
}

impl<T, O> Monad<Vec<O>> for Vec<T> {
    type Inner = T;
    fn bind<F>(t: Self, mut f: F) -> Vec<O>
        where F: FnMut(T) -> Vec<O> {
        let mut acc: Vec<O> = Vec::new();
        for v in t {
            acc.append(&mut f(v));
        }
        acc
    }
    fn ret(inner: T) -> Vec<T> {
        vec![inner]
    }
}
<|endoftext|>


<commit_before>//! Redis support for the `r2d2` connection pool.
#![doc(html_root_url = "https://docs.rs/r2d2_redis/0.8.0")]
#![warn(missing_docs)]

pub extern crate r2d2;
pub extern crate redis;

use std::error;
use std::error::Error as _StdError;
use std::fmt;

/// A unified enum of errors returned by redis::Client
#[derive(Debug)]
pub enum Error {
    /// A redis::RedisError
    Other(redis::RedisError),
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.cause() {
            Some(cause) => write!(fmt, "{}: {}", self.description(), cause),
            None => write!(fmt, "{}", self.description()),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Other(ref err) => err.description()
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Other(ref err) => err.cause()
        }
    }
}

/// An `r2d2::ConnectionManager` for `redis::Client`s.
///
/// ## Example
///

/// ```
/// extern crate r2d2_redis;
///
/// use std::ops::Deref;
/// use std::thread;
///
/// use r2d2_redis::{r2d2, redis, RedisConnectionManager};
///
/// fn main() {
///     let manager = RedisConnectionManager::new("redis://localhost").unwrap();
///     let pool = r2d2::Pool::builder()
///         .build(manager)
///         .unwrap();
///
///     let mut handles = vec![];
///
///     for _i in 0..10i32 {
///         let pool = pool.clone();
///         handles.push(thread::spawn(move || {
///             let conn = pool.get().unwrap();
///             let reply = redis::cmd("PING").query::<String>(conn.deref()).unwrap();
///             // Alternatively, without deref():
///             // let reply = redis::cmd("PING").query::<String>(&*conn).unwrap();
///             assert_eq!("PONG", reply);
///         }));
///     }
///
///     for h in handles {
///         h.join().unwrap();
///     }
/// }
/// ```
#[derive(Debug)]
pub struct RedisConnectionManager {
    connection_info: redis::ConnectionInfo
}

impl RedisConnectionManager {
    /// Creates a new `RedisConnectionManager`.
    ///
    /// See `redis::Client::open` for a description of the parameter
    /// types.
    pub fn new<T: redis::IntoConnectionInfo>(params: T)
            -> Result<RedisConnectionManager, redis::RedisError> {
        Ok(RedisConnectionManager {
            connection_info: try!(params.into_connection_info()),
        })
    }
}

impl r2d2::ManageConnection for RedisConnectionManager {
    type Connection = redis::Connection;
    type Error = Error;

    fn connect(&self) -> Result<redis::Connection, Error> {
        match redis::Client::open(self.connection_info.clone()) {
            Ok(client) => {
                client.get_connection().map_err(Error::Other)
            },
            Err(err) => Err(Error::Other(err))
        }
    }

    fn is_valid(&self, conn: &mut redis::Connection) -> Result<(), Error> {
        redis::cmd("PING").query(conn).map_err(Error::Other)
    }

    fn has_broken(&self, _conn: &mut redis::Connection) -> bool {
        false
    }
}
<commit_msg>update valid/broken logic to avoid PING<commit_after>//! Redis support for the `r2d2` connection pool.
#![doc(html_root_url = "https://docs.rs/r2d2_redis/0.8.0")]
#![warn(missing_docs)]

pub extern crate r2d2;
pub extern crate redis;

use std::error;
use std::error::Error as _StdError;
use std::fmt;

/// A unified enum of errors returned by redis::Client
#[derive(Debug)]
pub enum Error {
    /// A redis::RedisError
    Other(redis::RedisError),

    /// inner redis::Connection reports being closed
    ConnectionClosed,
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.cause() {
            Some(cause) => write!(fmt, "{}: {}", self.description(), cause),
            None => write!(fmt, "{}", self.description()),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Other(ref err) => err.description(),
            Error::ConnectionClosed => "inner redis::Connection reports being closed",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Other(ref err) => err.cause(),
            Error::ConnectionClosed => None,
        }
    }
}

/// An `r2d2::ConnectionManager` for `redis::Client`s.
///
/// ## Example
///

/// ```
/// extern crate r2d2_redis;
///
/// use std::ops::Deref;
/// use std::thread;
///
/// use r2d2_redis::{r2d2, redis, RedisConnectionManager};
///
/// fn main() {
///     let manager = RedisConnectionManager::new("redis://localhost").unwrap();
///     let pool = r2d2::Pool::builder()
///         .build(manager)
///         .unwrap();
///
///     let mut handles = vec![];
///
///     for _i in 0..10i32 {
///         let pool = pool.clone();
///         handles.push(thread::spawn(move || {
///             let conn = pool.get().unwrap();
///             let reply = redis::cmd("PING").query::<String>(conn.deref()).unwrap();
///             // Alternatively, without deref():
///             // let reply = redis::cmd("PING").query::<String>(&*conn).unwrap();
///             assert_eq!("PONG", reply);
///         }));
///     }
///
///     for h in handles {
///         h.join().unwrap();
///     }
/// }
/// ```
#[derive(Debug)]
pub struct RedisConnectionManager {
    connection_info: redis::ConnectionInfo,
}

impl RedisConnectionManager {
    /// Creates a new `RedisConnectionManager`.
    ///
    /// See `redis::Client::open` for a description of the parameter
    /// types.
    pub fn new<T: redis::IntoConnectionInfo>(
        params: T,
    ) -> Result<RedisConnectionManager, redis::RedisError> {
        Ok(RedisConnectionManager {
            connection_info: try!(params.into_connection_info()),
        })
    }
}

impl r2d2::ManageConnection for RedisConnectionManager {
    type Connection = redis::Connection;
    type Error = Error;

    fn connect(&self) -> Result<redis::Connection, Error> {
        match redis::Client::open(self.connection_info.clone()) {
            Ok(client) => client.get_connection().map_err(Error::Other),
            Err(err) => Err(Error::Other(err)),
        }
    }

    fn is_valid(&self, conn: &mut redis::Connection) -> Result<(), Error> {
        if conn.is_open() {
            Ok(())
        } else {
            Err(Error::ConnectionClosed)
        }
    }

    fn has_broken(&self, conn: &mut redis::Connection) -> bool {
        !conn.is_open()
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2018, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

#![allow(deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
#![cfg_attr(feature = "cargo-clippy", allow(transmute_int_to_char))]
#![cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ptr))]
#![cfg_attr(feature = "cargo-clippy", allow(trivially_copy_pass_by_ref))]

extern crate gdk_pixbuf;
extern crate gdk_sys;
extern crate gio;
extern crate gio_sys;
extern crate glib_sys;
#[macro_use]
extern crate glib;
extern crate cairo;
extern crate cairo_sys;
extern crate gobject_sys;
extern crate libc;
extern crate pango;
#[macro_use]
extern crate bitflags;

#[macro_use]
mod rt;
#[macro_use]
mod event;

#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
#[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
#[cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]
mod auto;

pub mod prelude;

pub use self::auto::functions::*;
pub use auto::*;
pub use prelude::*;

pub mod enums;

mod atom;
mod cairo_interaction;
mod change_data;
mod device;
mod device_manager;
mod drag_context;
mod event_button;
mod event_configure;
mod event_crossing;
mod event_dnd;
mod event_expose;
mod event_focus;
mod event_grab_broken;
mod event_key;
mod event_motion;
mod event_owner_change;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod event_pad_axis;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod event_pad_button;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod event_pad_group_mode;
mod event_property;
mod event_proximity;
mod event_scroll;
mod event_selection;
mod event_setting;
mod event_touch;
#[cfg(any(feature = "v3_18", feature = "dox"))]
mod event_touchpad_pinch;
#[cfg(any(feature = "v3_18", feature = "dox"))]
mod event_touchpad_swipe;
mod event_visibility;
mod event_window_state;
mod frame_clock;
mod frame_timings;
mod functions;
mod geometry;
mod keymap;
mod keymap_key;
mod keys;
mod rectangle;
mod rgba;
mod screen;
mod time_coord;
mod visual;
mod window;

pub use gdk_sys::GdkColor as Color;

pub use self::rt::{init, set_initialized};

pub use atom::Atom;
pub use atom::NONE as ATOM_NONE;
pub use atom::SELECTION_CLIPBOARD;
pub use atom::SELECTION_PRIMARY;
pub use atom::SELECTION_SECONDARY;
pub use atom::SELECTION_TYPE_ATOM;
pub use atom::SELECTION_TYPE_BITMAP;
pub use atom::SELECTION_TYPE_COLORMAP;
pub use atom::SELECTION_TYPE_DRAWABLE;
pub use atom::SELECTION_TYPE_INTEGER;
pub use atom::SELECTION_TYPE_PIXMAP;
pub use atom::SELECTION_TYPE_STRING;
pub use atom::SELECTION_TYPE_WINDOW;
pub use atom::TARGET_BITMAP;
pub use atom::TARGET_COLORMAP;
pub use atom::TARGET_DRAWABLE;
pub use atom::TARGET_PIXMAP;
pub use atom::TARGET_STRING;
pub use change_data::ChangeData;
pub use event::Event;
pub use event_button::EventButton;
pub use event_configure::EventConfigure;
pub use event_crossing::EventCrossing;
pub use event_dnd::EventDND;
pub use event_expose::EventExpose;
pub use event_focus::EventFocus;
pub use event_grab_broken::EventGrabBroken;
pub use event_key::EventKey;
pub use event_motion::EventMotion;
pub use event_owner_change::EventOwnerChange;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use event_pad_axis::EventPadAxis;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use event_pad_button::EventPadButton;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use event_pad_group_mode::EventPadGroupMode;
pub use event_property::EventProperty;
pub use event_proximity::EventProximity;
pub use event_scroll::EventScroll;
pub use event_selection::EventSelection;
pub use event_setting::EventSetting;
pub use event_touch::EventTouch;
#[cfg(any(feature = "v3_18", feature = "dox"))]
pub use event_touchpad_pinch::EventTouchpadPinch;
#[cfg(any(feature = "v3_18", feature = "dox"))]
pub use event_touchpad_swipe::EventTouchpadSwipe;
pub use event_visibility::EventVisibility;
pub use event_window_state::EventWindowState;
pub use functions::*;
pub use geometry::Geometry;
pub use keymap_key::KeymapKey;
pub use rectangle::Rectangle;
pub use rgba::{RgbaParseError, RGBA};
pub use time_coord::TimeCoord;
pub use window::WindowAttr;

#[allow(non_camel_case_types)]
pub type key = i32;

pub use self::keys::{keyval_name, keyval_to_unicode};
<commit_msg>Don't reexport prelude content<commit_after>// Copyright 2013-2018, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

#![allow(deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
#![cfg_attr(feature = "cargo-clippy", allow(transmute_int_to_char))]
#![cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ptr))]
#![cfg_attr(feature = "cargo-clippy", allow(trivially_copy_pass_by_ref))]

extern crate gdk_pixbuf;
extern crate gdk_sys;
extern crate gio;
extern crate gio_sys;
extern crate glib_sys;
#[macro_use]
extern crate glib;
extern crate cairo;
extern crate cairo_sys;
extern crate gobject_sys;
extern crate libc;
extern crate pango;
#[macro_use]
extern crate bitflags;

#[macro_use]
mod rt;
#[macro_use]
mod event;

#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
#[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
#[cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]
mod auto;

pub mod prelude;

pub use self::auto::functions::*;
pub use auto::*;

pub mod enums;

mod atom;
mod cairo_interaction;
mod change_data;
mod device;
mod device_manager;
mod drag_context;
mod event_button;
mod event_configure;
mod event_crossing;
mod event_dnd;
mod event_expose;
mod event_focus;
mod event_grab_broken;
mod event_key;
mod event_motion;
mod event_owner_change;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod event_pad_axis;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod event_pad_button;
#[cfg(any(feature = "v3_22", feature = "dox"))]
mod event_pad_group_mode;
mod event_property;
mod event_proximity;
mod event_scroll;
mod event_selection;
mod event_setting;
mod event_touch;
#[cfg(any(feature = "v3_18", feature = "dox"))]
mod event_touchpad_pinch;
#[cfg(any(feature = "v3_18", feature = "dox"))]
mod event_touchpad_swipe;
mod event_visibility;
mod event_window_state;
mod frame_clock;
mod frame_timings;
mod functions;
mod geometry;
mod keymap;
mod keymap_key;
mod keys;
mod rectangle;
mod rgba;
mod screen;
mod time_coord;
mod visual;
mod window;

pub use gdk_sys::GdkColor as Color;

pub use self::rt::{init, set_initialized};

pub use atom::Atom;
pub use atom::NONE as ATOM_NONE;
pub use atom::SELECTION_CLIPBOARD;
pub use atom::SELECTION_PRIMARY;
pub use atom::SELECTION_SECONDARY;
pub use atom::SELECTION_TYPE_ATOM;
pub use atom::SELECTION_TYPE_BITMAP;
pub use atom::SELECTION_TYPE_COLORMAP;
pub use atom::SELECTION_TYPE_DRAWABLE;
pub use atom::SELECTION_TYPE_INTEGER;
pub use atom::SELECTION_TYPE_PIXMAP;
pub use atom::SELECTION_TYPE_STRING;
pub use atom::SELECTION_TYPE_WINDOW;
pub use atom::TARGET_BITMAP;
pub use atom::TARGET_COLORMAP;
pub use atom::TARGET_DRAWABLE;
pub use atom::TARGET_PIXMAP;
pub use atom::TARGET_STRING;
pub use change_data::ChangeData;
pub use event::Event;
pub use event_button::EventButton;
pub use event_configure::EventConfigure;
pub use event_crossing::EventCrossing;
pub use event_dnd::EventDND;
pub use event_expose::EventExpose;
pub use event_focus::EventFocus;
pub use event_grab_broken::EventGrabBroken;
pub use event_key::EventKey;
pub use event_motion::EventMotion;
pub use event_owner_change::EventOwnerChange;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use event_pad_axis::EventPadAxis;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use event_pad_button::EventPadButton;
#[cfg(any(feature = "v3_22", feature = "dox"))]
pub use event_pad_group_mode::EventPadGroupMode;
pub use event_property::EventProperty;
pub use event_proximity::EventProximity;
pub use event_scroll::EventScroll;
pub use event_selection::EventSelection;
pub use event_setting::EventSetting;
pub use event_touch::EventTouch;
#[cfg(any(feature = "v3_18", feature = "dox"))]
pub use event_touchpad_pinch::EventTouchpadPinch;
#[cfg(any(feature = "v3_18", feature = "dox"))]
pub use event_touchpad_swipe::EventTouchpadSwipe;
pub use event_visibility::EventVisibility;
pub use event_window_state::EventWindowState;
pub use functions::*;
pub use geometry::Geometry;
pub use keymap_key::KeymapKey;
pub use rectangle::Rectangle;
pub use rgba::{RgbaParseError, RGBA};
pub use time_coord::TimeCoord;
pub use window::WindowAttr;

#[allow(non_camel_case_types)]
pub type key = i32;

pub use self::keys::{keyval_name, keyval_to_unicode};
<|endoftext|>


<commit_before>#![allow(clippy::type_complexity)]

mod app;
mod extract;
mod handler;
// mod info;
pub mod blocking;
mod config;
pub mod guard;
pub mod middleware;
mod request;
mod resource;
mod responder;
mod route;
mod scope;
mod server;
mod service;
mod state;
pub mod test;

#[allow(unused_imports)]
#[macro_use]
extern crate actix_web_codegen;

#[doc(hidden)]
pub use actix_web_codegen::*;

// re-export for convenience
pub use actix_http::Response as HttpResponse;
pub use actix_http::{body, error, http, Error, HttpMessage, ResponseError, Result};

pub use crate::app::App;
pub use crate::extract::FromRequest;
pub use crate::request::HttpRequest;
pub use crate::resource::Resource;
pub use crate::responder::{Either, Responder};
pub use crate::route::Route;
pub use crate::scope::Scope;
pub use crate::server::HttpServer;
pub use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};

pub mod dev {
    //! The `actix-web` prelude for library developers
    //!
    //! The purpose of this module is to alleviate imports of many common actix
    //! traits by adding a glob import to the top of actix heavy modules:
    //!
    //! ```
    //! # #![allow(unused_imports)]
    //! use actix_web::dev::*;
    //! ```

    pub use crate::app::AppRouter;
    pub use crate::config::AppConfig;
    pub use crate::service::HttpServiceFactory;

    pub use actix_http::body::{Body, BodyLength, MessageBody, ResponseBody};
    pub use actix_http::dev::ResponseBuilder as HttpResponseBuilder;
    pub use actix_http::{
        Extensions, Payload, PayloadStream, RequestHead, ResponseHead,
    };
    pub use actix_router::{Path, ResourceDef, Url};

    pub(crate) fn insert_slash(path: &str) -> String {
        let mut path = path.to_owned();
        if !path.is_empty() && !path.starts_with('/') {
            path.insert(0, '/');
        };
        path
    }
}

pub mod web {
    use actix_http::{http::Method, Error, Response};
    use futures::IntoFuture;

    pub use actix_http::Response as HttpResponse;
    pub use bytes::{Bytes, BytesMut};

    use crate::blocking::CpuFuture;
    use crate::extract::FromRequest;
    use crate::handler::{AsyncFactory, Factory};
    use crate::resource::Resource;
    use crate::responder::Responder;
    use crate::route::Route;
    use crate::scope::Scope;

    pub use crate::extract::{Form, Json, Path, Payload, Query};
    pub use crate::extract::{FormConfig, JsonConfig, PayloadConfig};
    pub use crate::request::HttpRequest;
    pub use crate::state::State;

    /// Create resource for a specific path.
    ///
    /// Resources may have variable path segments. For example, a
    /// resource with the path `/a/{name}/c` would match all incoming
    /// requests with paths such as `/a/b/c`, `/a/1/c`, or `/a/etc/c`.
    ///
    /// A variable segment is specified in the form `{identifier}`,
    /// where the identifier can be used later in a request handler to
    /// access the matched value for that segment. This is done by
    /// looking up the identifier in the `Params` object returned by
    /// `HttpRequest.match_info()` method.
    ///
    /// By default, each segment matches the regular expression `[^{}/]+`.
    ///
    /// You can also specify a custom regex in the form `{identifier:regex}`:
    ///
    /// For instance, to route `GET`-requests on any route matching
    /// `/users/{userid}/{friend}` and store `userid` and `friend` in
    /// the exposed `Params` object:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// use actix_web::{web, http, App, HttpResponse};
    ///
    /// fn main() {
    ///     let app = App::new().service(
    ///         web::resource("/users/{userid}/{friend}")
    ///             .route(web::get().to(|| HttpResponse::Ok()))
    ///             .route(web::head().to(|| HttpResponse::MethodNotAllowed()))
    ///     );
    /// }
    /// ```
    pub fn resource
(path: &str) -> Resource
 {
        Resource::new(path)
    }

    /// Configure scope for common root path.
    ///
    /// Scopes collect multiple paths under a common path prefix.
    /// Scope path can contain variable path segments as resources.
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// use actix_web::{web, App, HttpRequest, HttpResponse};
    ///
    /// fn main() {
    ///     let app = App::new().service(
    ///         web::scope("/{project_id}")
    ///             .service(web::resource("/path1").to(|| HttpResponse::Ok()))
    ///             .service(web::resource("/path2").to(|| HttpResponse::Ok()))
    ///             .service(web::resource("/path3").to(|| HttpResponse::MethodNotAllowed()))
    ///     );
    /// }
    /// ```
    ///
    /// In the above example, three routes get added:
    ///  * /{project_id}/path1
    ///  * /{project_id}/path2
    ///  * /{project_id}/path3
    ///
    pub fn scope
(path: &str) -> Scope
 {
        Scope::new(path)
    }

    /// Create **route** without configuration.
    pub fn route
() -> Route
 {
        Route::new()
    }

    /// Create **route** with `GET` method guard.
    pub fn get
() -> Route
 {
        Route::get()
    }

    /// Create **route** with `POST` method guard.
    pub fn post
() -> Route
 {
        Route::post()
    }

    /// Create **route** with `PUT` method guard.
    pub fn put
() -> Route
 {
        Route::put()
    }

    /// Create **route** with `DELETE` method guard.
    pub fn delete
() -> Route
 {
        Route::delete()
    }

    /// Create **route** with `HEAD` method guard.
    pub fn head
() -> Route
 {
        Route::new().method(Method::HEAD)
    }

    /// Create **route** and add method guard.
    pub fn method
(method: Method) -> Route
 {
        Route::new().method(method)
    }

    /// Create a new route and add handler.
    ///
    /// ```rust
    /// use actix_web::{web, App, HttpResponse};
    ///
    /// fn index() -> HttpResponse {
    ///    unimplemented!()
    /// }
    ///
    /// App::new().service(
    ///     web::resource("/").route(
    ///         web::to(index))
    /// );
    /// ```
    pub fn to<F, I, R, P: 'static>(handler: F) -> Route

    where
        F: Factory + 'static,
        I: FromRequest
 + 'static,
        R: Responder + 'static,
    {
        Route::new().to(handler)
    }

    /// Create a new route and add async handler.
    ///
    /// ```rust
    /// use actix_web::{web, App, HttpResponse, Error};
    ///
    /// fn index() -> impl futures::Future<Item=HttpResponse, Error=Error> {
    ///     futures::future::ok(HttpResponse::Ok().finish())
    /// }
    ///
    /// App::new().service(web::resource("/").route(
    ///     web::to_async(index))
    /// );
    /// ```
    pub fn to_async<F, I, R, P: 'static>(handler: F) -> Route

    where
        F: AsyncFactory,
        I: FromRequest
 + 'static,
        R: IntoFuture + 'static,
        R::Item: Into<Response>,
        R::Error: Into<Error>,
    {
        Route::new().to_async(handler)
    }

    /// Execute blocking function on a thread pool, returns future that resolves
    /// to result of the function execution.
    pub fn blocking<F, I, E>(f: F) -> CpuFuture
    where
        F: FnOnce() -> Result + Send + 'static,
        I: Send + 'static,
        E: Send + std::fmt::Debug + 'static,
    {
        crate::blocking::run(f)
    }
}
<commit_msg>rename blocking fn<commit_after>#![allow(clippy::type_complexity)]

mod app;
mod extract;
mod handler;
// mod info;
pub mod blocking;
mod config;
pub mod guard;
pub mod middleware;
mod request;
mod resource;
mod responder;
mod route;
mod scope;
mod server;
mod service;
mod state;
pub mod test;

#[allow(unused_imports)]
#[macro_use]
extern crate actix_web_codegen;

#[doc(hidden)]
pub use actix_web_codegen::*;

// re-export for convenience
pub use actix_http::Response as HttpResponse;
pub use actix_http::{body, error, http, Error, HttpMessage, ResponseError, Result};

pub use crate::app::App;
pub use crate::extract::FromRequest;
pub use crate::request::HttpRequest;
pub use crate::resource::Resource;
pub use crate::responder::{Either, Responder};
pub use crate::route::Route;
pub use crate::scope::Scope;
pub use crate::server::HttpServer;
pub use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};

pub mod dev {
    //! The `actix-web` prelude for library developers
    //!
    //! The purpose of this module is to alleviate imports of many common actix
    //! traits by adding a glob import to the top of actix heavy modules:
    //!
    //! ```
    //! # #![allow(unused_imports)]
    //! use actix_web::dev::*;
    //! ```

    pub use crate::app::AppRouter;
    pub use crate::config::AppConfig;
    pub use crate::service::HttpServiceFactory;

    pub use actix_http::body::{Body, BodyLength, MessageBody, ResponseBody};
    pub use actix_http::dev::ResponseBuilder as HttpResponseBuilder;
    pub use actix_http::{
        Extensions, Payload, PayloadStream, RequestHead, ResponseHead,
    };
    pub use actix_router::{Path, ResourceDef, Url};

    pub(crate) fn insert_slash(path: &str) -> String {
        let mut path = path.to_owned();
        if !path.is_empty() && !path.starts_with('/') {
            path.insert(0, '/');
        };
        path
    }
}

pub mod web {
    use actix_http::{http::Method, Error, Response};
    use futures::IntoFuture;

    pub use actix_http::Response as HttpResponse;
    pub use bytes::{Bytes, BytesMut};

    use crate::blocking::CpuFuture;
    use crate::extract::FromRequest;
    use crate::handler::{AsyncFactory, Factory};
    use crate::resource::Resource;
    use crate::responder::Responder;
    use crate::route::Route;
    use crate::scope::Scope;

    pub use crate::extract::{Form, Json, Path, Payload, Query};
    pub use crate::extract::{FormConfig, JsonConfig, PayloadConfig};
    pub use crate::request::HttpRequest;
    pub use crate::state::State;

    /// Create resource for a specific path.
    ///
    /// Resources may have variable path segments. For example, a
    /// resource with the path `/a/{name}/c` would match all incoming
    /// requests with paths such as `/a/b/c`, `/a/1/c`, or `/a/etc/c`.
    ///
    /// A variable segment is specified in the form `{identifier}`,
    /// where the identifier can be used later in a request handler to
    /// access the matched value for that segment. This is done by
    /// looking up the identifier in the `Params` object returned by
    /// `HttpRequest.match_info()` method.
    ///
    /// By default, each segment matches the regular expression `[^{}/]+`.
    ///
    /// You can also specify a custom regex in the form `{identifier:regex}`:
    ///
    /// For instance, to route `GET`-requests on any route matching
    /// `/users/{userid}/{friend}` and store `userid` and `friend` in
    /// the exposed `Params` object:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// use actix_web::{web, http, App, HttpResponse};
    ///
    /// fn main() {
    ///     let app = App::new().service(
    ///         web::resource("/users/{userid}/{friend}")
    ///             .route(web::get().to(|| HttpResponse::Ok()))
    ///             .route(web::head().to(|| HttpResponse::MethodNotAllowed()))
    ///     );
    /// }
    /// ```
    pub fn resource
(path: &str) -> Resource
 {
        Resource::new(path)
    }

    /// Configure scope for common root path.
    ///
    /// Scopes collect multiple paths under a common path prefix.
    /// Scope path can contain variable path segments as resources.
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// use actix_web::{web, App, HttpRequest, HttpResponse};
    ///
    /// fn main() {
    ///     let app = App::new().service(
    ///         web::scope("/{project_id}")
    ///             .service(web::resource("/path1").to(|| HttpResponse::Ok()))
    ///             .service(web::resource("/path2").to(|| HttpResponse::Ok()))
    ///             .service(web::resource("/path3").to(|| HttpResponse::MethodNotAllowed()))
    ///     );
    /// }
    /// ```
    ///
    /// In the above example, three routes get added:
    ///  * /{project_id}/path1
    ///  * /{project_id}/path2
    ///  * /{project_id}/path3
    ///
    pub fn scope
(path: &str) -> Scope
 {
        Scope::new(path)
    }

    /// Create **route** without configuration.
    pub fn route
() -> Route
 {
        Route::new()
    }

    /// Create **route** with `GET` method guard.
    pub fn get
() -> Route
 {
        Route::get()
    }

    /// Create **route** with `POST` method guard.
    pub fn post
() -> Route
 {
        Route::post()
    }

    /// Create **route** with `PUT` method guard.
    pub fn put
() -> Route
 {
        Route::put()
    }

    /// Create **route** with `DELETE` method guard.
    pub fn delete
() -> Route
 {
        Route::delete()
    }

    /// Create **route** with `HEAD` method guard.
    pub fn head
() -> Route
 {
        Route::new().method(Method::HEAD)
    }

    /// Create **route** and add method guard.
    pub fn method
(method: Method) -> Route
 {
        Route::new().method(method)
    }

    /// Create a new route and add handler.
    ///
    /// ```rust
    /// use actix_web::{web, App, HttpResponse};
    ///
    /// fn index() -> HttpResponse {
    ///    unimplemented!()
    /// }
    ///
    /// App::new().service(
    ///     web::resource("/").route(
    ///         web::to(index))
    /// );
    /// ```
    pub fn to<F, I, R, P: 'static>(handler: F) -> Route

    where
        F: Factory + 'static,
        I: FromRequest
 + 'static,
        R: Responder + 'static,
    {
        Route::new().to(handler)
    }

    /// Create a new route and add async handler.
    ///
    /// ```rust
    /// use actix_web::{web, App, HttpResponse, Error};
    ///
    /// fn index() -> impl futures::Future<Item=HttpResponse, Error=Error> {
    ///     futures::future::ok(HttpResponse::Ok().finish())
    /// }
    ///
    /// App::new().service(web::resource("/").route(
    ///     web::to_async(index))
    /// );
    /// ```
    pub fn to_async<F, I, R, P: 'static>(handler: F) -> Route

    where
        F: AsyncFactory,
        I: FromRequest
 + 'static,
        R: IntoFuture + 'static,
        R::Item: Into<Response>,
        R::Error: Into<Error>,
    {
        Route::new().to_async(handler)
    }

    /// Execute blocking function on a thread pool, returns future that resolves
    /// to result of the function execution.
    pub fn block<F, I, E>(f: F) -> CpuFuture
    where
        F: FnOnce() -> Result + Send + 'static,
        I: Send + 'static,
        E: Send + std::fmt::Debug + 'static,
    {
        crate::blocking::run(f)
    }
}
<|endoftext|>


<commit_before>//! The goal of this crate is to provide Rust bindings to the Web APIs and to allow
//! a high degree of interoperability between Rust and JavaScript.
//!
//! ## Examples
//!
//! You can directly embed JavaScript code into Rust:
//!
//! ```rust
//! let message = "Hello, 世界!";
//! let result = js! {
//!     alert( @{message} );
//!     return 2 + 2 * 2;
//! };
//!
//! println!( "2 + 2 * 2 = {:?}", result );
//! ```
//!
//! Even closures are supported:
//!
//! ```rust
//! let print_hello = |name: String| {
//!     println!( "Hello, {}!", name );
//! };
//!
//! js! {
//!     var print_hello = @{print_hello};
//!     print_hello( "Bob" );
//!     print_hello.drop(); // Necessary to clean up the closure on Rust's side.
//! }
//! ```
//!
//! You can also pass arbitrary structures thanks to [serde]:
//!
//! ```rust
//! #[derive(Serialize)]
//! struct Person {
//!     name: String,
//!     age: i32
//! }
//!
//! js_serializable!( Person );
//!
//! js! {
//!     var person = @{person};
//!     console.log( person.name + " is " + person.age + " years old." );
//! };
//! ```
//!
//! [serde]: https://serde.rs/
//!
//! This crate also exposes a number of Web APIs, for example:
//!
//! ```rust
//! let button = document().query_selector( "#hide-button" ).unwrap();
//! button.add_event_listener( move |_: ClickEvent| {
//!     for anchor in document().query_selector_all( "#main a" ) {
//!         js!( @{anchor}.style = "display: none;"; );
//!     }
//! });
//! ```

#![deny(
    missing_docs,
    missing_debug_implementations,
    trivial_numeric_casts,
    unused_import_braces,
    unused_qualifications
)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![cfg_attr(
    all(target_arch = "wasm32", target_os = "unknown"),
    feature(proc_macro)
)]
#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
#![recursion_limit="1500"]

#[cfg(feature = "serde")]
#[macro_use]
extern crate serde as serde_crate;

#[cfg(any(test, feature = "serde_json"))]
extern crate serde_json;

#[cfg(all(test, feature = "serde"))]
#[macro_use]
extern crate serde_derive;

#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
extern crate stdweb_macros;

#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub use stdweb_macros::js_export;

#[macro_use]
mod webcore;
mod webapi;
mod ecosystem;

pub use webcore::initialization::{
    initialize,
    event_loop
};
pub use webcore::value::{
    Undefined,
    Null,
    Value,
    Reference
};
pub use webcore::number::Number;
pub use webcore::object::Object;
pub use webcore::array::Array;

pub use webcore::unsafe_typed_array::UnsafeTypedArray;
pub use webcore::once::Once;

#[cfg(feature = "serde")]
/// A module with serde-related APIs.
pub mod serde {
    pub use ecosystem::serde::{
        ConversionError,
        Serde
    };
}

/// A module with bindings to the Web APIs.
pub mod web {
    pub use webapi::window::{
        Window,
        window
    };
    pub use webapi::document::{
        Document,
        document
    };
    pub use webapi::global::{
        set_timeout,
        alert
    };
    pub use webapi::cross_origin_setting::CrossOriginSetting;
    pub use webapi::date::Date;
    pub use webapi::event_target::{IEventTarget, EventTarget, EventListenerHandle};
    pub use webapi::window::RequestAnimationFrameHandle;
    pub use webapi::node::{INode, Node, CloneKind};
    pub use webapi::element::{IElement, Element};
    pub use webapi::text_node::TextNode;
    pub use webapi::html_element::{IHtmlElement, HtmlElement};
    pub use webapi::window_or_worker::IWindowOrWorker;
    pub use webapi::token_list::TokenList;
    pub use webapi::node_list::NodeList;
    pub use webapi::string_map::StringMap;
    pub use webapi::storage::Storage;
    pub use webapi::location::Location;
    pub use webapi::array_buffer::ArrayBuffer;
    pub use webapi::typed_array::TypedArray;
    pub use webapi::file_reader::{FileReader, FileReaderResult};
    pub use webapi::history::History;
    pub use webapi::web_socket::{WebSocket, SocketCloseCode};
    pub use webapi::rendering_context::{RenderingContext, CanvasRenderingContext2d};
    pub use webapi::mutation_observer::{MutationObserver, MutationObserverHandle, MutationObserverInit, MutationRecord};

    /// A module containing XmlHttpRequest and its XhrReadyState
    pub mod xml_http_request {
        pub use webapi::xml_http_request::{ XmlHttpRequest, XhrReadyState };
    }
    /// A module containing error types.
    pub mod error {
        pub use webapi::node::NotFoundError;
    }

    /// A module containing HTML DOM elements.
    pub mod html_element {
        pub use webapi::html_elements::ImageElement;
        pub use webapi::html_elements::InputElement;
        pub use webapi::html_elements::TextAreaElement;
        pub use webapi::html_elements::CanvasElement;
    }

    /// A module containing JavaScript DOM events.
    pub mod event {
        pub use webapi::event::{
            ConcreteEvent,

            IEvent,
            IKeyboardEvent,
            IUiEvent,
            IMouseEvent,
            IFocusEvent,
            IProgressEvent,
            IMessageEvent,

            EventPhase,
            KeyboardLocation,
            ModifierKey,
            MouseButton,

            ChangeEvent,
            KeypressEvent,
            KeyDownEvent,
            KeyUpEvent,
            ClickEvent,
            DoubleClickEvent,
            MouseDownEvent,
            MouseUpEvent,
            MouseMoveEvent,
            FocusEvent,
            BlurEvent,
            HashChangeEvent,
            ResourceLoadEvent,
            ResourceAbortEvent,
            ResourceErrorEvent,
            ResizeEvent,
            ProgressEvent,
            LoadStartEvent,
            LoadEndEvent,
            ProgressLoadEvent,
            ProgressAbortEvent,
            ProgressErrorEvent,
            InputEvent,
            ReadyStateChange,
            PopStateEvent,

            SocketCloseEvent,
            SocketErrorEvent,
            SocketOpenEvent,
            SocketMessageEvent,
        };
    }
}

/// A module containing stable counterparts to currently
/// unstable Rust features.
pub mod unstable {
    pub use webcore::try_from::{
        TryFrom,
        TryInto
    };

    pub use webcore::void::Void;
}

#[doc(hidden)]
pub mod private {
    pub use webcore::ffi::exports::*;
    pub use webcore::serialization::{
        JsSerializable,
        JsSerializableOwned,
        PreallocatedArena,
        SerializedValue
    };

    pub use webcore::newtype::{
        IntoNewtype,
        Newtype
    };

    pub use webcore::value::{
        FromReference,
        FromReferenceUnchecked
    };

    #[cfg(feature = "serde")]
    pub use ecosystem::serde::{
        to_value,
        from_value
    };

    // This is to prevent an unused_mut warnings in macros, because an `allow` doesn't work apparently?
    #[allow(dead_code)]
    #[inline(always)]
    pub fn noop< T >( _: &mut T ) {}
}
<commit_msg>Get rid of the `xml_http_request` namespace in exports<commit_after>//! The goal of this crate is to provide Rust bindings to the Web APIs and to allow
//! a high degree of interoperability between Rust and JavaScript.
//!
//! ## Examples
//!
//! You can directly embed JavaScript code into Rust:
//!
//! ```rust
//! let message = "Hello, 世界!";
//! let result = js! {
//!     alert( @{message} );
//!     return 2 + 2 * 2;
//! };
//!
//! println!( "2 + 2 * 2 = {:?}", result );
//! ```
//!
//! Even closures are supported:
//!
//! ```rust
//! let print_hello = |name: String| {
//!     println!( "Hello, {}!", name );
//! };
//!
//! js! {
//!     var print_hello = @{print_hello};
//!     print_hello( "Bob" );
//!     print_hello.drop(); // Necessary to clean up the closure on Rust's side.
//! }
//! ```
//!
//! You can also pass arbitrary structures thanks to [serde]:
//!
//! ```rust
//! #[derive(Serialize)]
//! struct Person {
//!     name: String,
//!     age: i32
//! }
//!
//! js_serializable!( Person );
//!
//! js! {
//!     var person = @{person};
//!     console.log( person.name + " is " + person.age + " years old." );
//! };
//! ```
//!
//! [serde]: https://serde.rs/
//!
//! This crate also exposes a number of Web APIs, for example:
//!
//! ```rust
//! let button = document().query_selector( "#hide-button" ).unwrap();
//! button.add_event_listener( move |_: ClickEvent| {
//!     for anchor in document().query_selector_all( "#main a" ) {
//!         js!( @{anchor}.style = "display: none;"; );
//!     }
//! });
//! ```

#![deny(
    missing_docs,
    missing_debug_implementations,
    trivial_numeric_casts,
    unused_import_braces,
    unused_qualifications
)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![cfg_attr(
    all(target_arch = "wasm32", target_os = "unknown"),
    feature(proc_macro)
)]
#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
#![recursion_limit="1500"]

#[cfg(feature = "serde")]
#[macro_use]
extern crate serde as serde_crate;

#[cfg(any(test, feature = "serde_json"))]
extern crate serde_json;

#[cfg(all(test, feature = "serde"))]
#[macro_use]
extern crate serde_derive;

#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
extern crate stdweb_macros;

#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub use stdweb_macros::js_export;

#[macro_use]
mod webcore;
mod webapi;
mod ecosystem;

pub use webcore::initialization::{
    initialize,
    event_loop
};
pub use webcore::value::{
    Undefined,
    Null,
    Value,
    Reference
};
pub use webcore::number::Number;
pub use webcore::object::Object;
pub use webcore::array::Array;

pub use webcore::unsafe_typed_array::UnsafeTypedArray;
pub use webcore::once::Once;

#[cfg(feature = "serde")]
/// A module with serde-related APIs.
pub mod serde {
    pub use ecosystem::serde::{
        ConversionError,
        Serde
    };
}

/// A module with bindings to the Web APIs.
pub mod web {
    pub use webapi::window::{
        Window,
        window
    };
    pub use webapi::document::{
        Document,
        document
    };
    pub use webapi::global::{
        set_timeout,
        alert
    };
    pub use webapi::cross_origin_setting::CrossOriginSetting;
    pub use webapi::date::Date;
    pub use webapi::event_target::{IEventTarget, EventTarget, EventListenerHandle};
    pub use webapi::window::RequestAnimationFrameHandle;
    pub use webapi::node::{INode, Node, CloneKind};
    pub use webapi::element::{IElement, Element};
    pub use webapi::text_node::TextNode;
    pub use webapi::html_element::{IHtmlElement, HtmlElement};
    pub use webapi::window_or_worker::IWindowOrWorker;
    pub use webapi::token_list::TokenList;
    pub use webapi::node_list::NodeList;
    pub use webapi::string_map::StringMap;
    pub use webapi::storage::Storage;
    pub use webapi::location::Location;
    pub use webapi::array_buffer::ArrayBuffer;
    pub use webapi::typed_array::TypedArray;
    pub use webapi::file_reader::{FileReader, FileReaderResult};
    pub use webapi::history::History;
    pub use webapi::web_socket::{WebSocket, SocketCloseCode};
    pub use webapi::rendering_context::{RenderingContext, CanvasRenderingContext2d};
    pub use webapi::mutation_observer::{MutationObserver, MutationObserverHandle, MutationObserverInit, MutationRecord};
    pub use webapi::xml_http_request::{XmlHttpRequest, XhrReadyState};

    /// A module containing error types.
    pub mod error {
        pub use webapi::node::NotFoundError;
    }

    /// A module containing HTML DOM elements.
    pub mod html_element {
        pub use webapi::html_elements::ImageElement;
        pub use webapi::html_elements::InputElement;
        pub use webapi::html_elements::TextAreaElement;
        pub use webapi::html_elements::CanvasElement;
    }

    /// A module containing JavaScript DOM events.
    pub mod event {
        pub use webapi::event::{
            ConcreteEvent,

            IEvent,
            IKeyboardEvent,
            IUiEvent,
            IMouseEvent,
            IFocusEvent,
            IProgressEvent,
            IMessageEvent,

            EventPhase,
            KeyboardLocation,
            ModifierKey,
            MouseButton,

            ChangeEvent,
            KeypressEvent,
            KeyDownEvent,
            KeyUpEvent,
            ClickEvent,
            DoubleClickEvent,
            MouseDownEvent,
            MouseUpEvent,
            MouseMoveEvent,
            FocusEvent,
            BlurEvent,
            HashChangeEvent,
            ResourceLoadEvent,
            ResourceAbortEvent,
            ResourceErrorEvent,
            ResizeEvent,
            ProgressEvent,
            LoadStartEvent,
            LoadEndEvent,
            ProgressLoadEvent,
            ProgressAbortEvent,
            ProgressErrorEvent,
            InputEvent,
            ReadyStateChange,
            PopStateEvent,

            SocketCloseEvent,
            SocketErrorEvent,
            SocketOpenEvent,
            SocketMessageEvent,
        };
    }
}

/// A module containing stable counterparts to currently
/// unstable Rust features.
pub mod unstable {
    pub use webcore::try_from::{
        TryFrom,
        TryInto
    };

    pub use webcore::void::Void;
}

#[doc(hidden)]
pub mod private {
    pub use webcore::ffi::exports::*;
    pub use webcore::serialization::{
        JsSerializable,
        JsSerializableOwned,
        PreallocatedArena,
        SerializedValue
    };

    pub use webcore::newtype::{
        IntoNewtype,
        Newtype
    };

    pub use webcore::value::{
        FromReference,
        FromReferenceUnchecked
    };

    #[cfg(feature = "serde")]
    pub use ecosystem::serde::{
        to_value,
        from_value
    };

    // This is to prevent an unused_mut warnings in macros, because an `allow` doesn't work apparently?
    #[allow(dead_code)]
    #[inline(always)]
    pub fn noop< T >( _: &mut T ) {}
}
<|endoftext|>


<commit_before>#![feature(const_fn)]
#![no_std]

#[cfg(test)]
mod tests;

use core::ops::{Range, Shl, Shr, BitAndAssign, BitOrAssign, Not, BitAnd, BitOr};
use core::mem::size_of;

pub trait BitField: Copy + Eq + Not<Output = Self> +
    Shl<u8, Output = Self> + Shr<u8, Output = Self> +
    BitAnd<Self, Output=Self> + BitOr<Self, Output=Self> + BitAndAssign + BitOrAssign
{
    fn zero() -> Self;
    fn one() -> Self;
    fn length(&self) -> u8;

    fn get_bit(&self, bit: u8) -> bool {
        assert!(bit < self.length());
        self.get_range(bit..(bit + 1)) == Self::one()
    }

    fn get_range(&self, range: Range<u8>) -> Self {
        assert!(range.start < self.length());
        assert!(range.end <= self.length());
        assert!(range.start < range.end);

// shift away high bits
        let bits = *self << (self.length() - range.end) >> (self.length() - range.end);

// shift away low bits
        bits >> range.start
    }

    fn set_bit(&mut self, bit: u8, value: bool) -> &mut Self {
        assert!(bit < self.length());
        if value {
            *self |= Self::one() << bit;
        } else {
            *self &= !(Self::one() << bit);
        }
        self
    }

    fn set_range(&mut self, range: Range<u8>, value: Self) -> &mut Self {
        assert!(range.start < self.length());
        assert!(range.end <= self.length());
        assert!(range.start < range.end);
        assert!(value << (self.length() - (range.end - range.start)) >>
                (self.length() - (range.end - range.start)) == value,
                "value too big");

        let bitmask: Self = !(!Self::zero() << (self.length() - range.end) >>
                              (self.length() - range.end) >>
                              range.start << range.start);

        let bits = *self & bitmask;
// set bits
        *self = bits | (value << range.start);

        self
    }
}

macro_rules! bitfield_impl {
    ($($t:ty)*) => ($(
        impl BitField for $t {
            fn zero() -> Self { 0 }
            fn one() -> Self { 1 }
            fn length(&self) -> u8 {
                size_of::<Self>() as u8 * 8
            }
        }
    )*)
}

bitfield_impl! { u8 u16 u32 u64 usize }
<commit_msg>We no longer need the const_fn feature<commit_after>#![no_std]

#[cfg(test)]
mod tests;

use core::ops::{Range, Shl, Shr, BitAndAssign, BitOrAssign, Not, BitAnd, BitOr};
use core::mem::size_of;

pub trait BitField: Copy + Eq + Not<Output = Self> +
    Shl<u8, Output = Self> + Shr<u8, Output = Self> +
    BitAnd<Self, Output=Self> + BitOr<Self, Output=Self> + BitAndAssign + BitOrAssign
{
    fn zero() -> Self;
    fn one() -> Self;
    fn length(&self) -> u8;

    fn get_bit(&self, bit: u8) -> bool {
        assert!(bit < self.length());
        self.get_range(bit..(bit + 1)) == Self::one()
    }

    fn get_range(&self, range: Range<u8>) -> Self {
        assert!(range.start < self.length());
        assert!(range.end <= self.length());
        assert!(range.start < range.end);

// shift away high bits
        let bits = *self << (self.length() - range.end) >> (self.length() - range.end);

// shift away low bits
        bits >> range.start
    }

    fn set_bit(&mut self, bit: u8, value: bool) -> &mut Self {
        assert!(bit < self.length());
        if value {
            *self |= Self::one() << bit;
        } else {
            *self &= !(Self::one() << bit);
        }
        self
    }

    fn set_range(&mut self, range: Range<u8>, value: Self) -> &mut Self {
        assert!(range.start < self.length());
        assert!(range.end <= self.length());
        assert!(range.start < range.end);
        assert!(value << (self.length() - (range.end - range.start)) >>
                (self.length() - (range.end - range.start)) == value,
                "value too big");

        let bitmask: Self = !(!Self::zero() << (self.length() - range.end) >>
                              (self.length() - range.end) >>
                              range.start << range.start);

        let bits = *self & bitmask;
// set bits
        *self = bits | (value << range.start);

        self
    }
}

macro_rules! bitfield_impl {
    ($($t:ty)*) => ($(
        impl BitField for $t {
            fn zero() -> Self { 0 }
            fn one() -> Self { 1 }
            fn length(&self) -> u8 {
                size_of::<Self>() as u8 * 8
            }
        }
    )*)
}

bitfield_impl! { u8 u16 u32 u64 usize }
<|endoftext|>


<commit_before>#![feature(collections)]
extern crate itertools;

use std::collections::{BTreeMap, HashMap, HashSet};
use std::hash::{Hash, Hasher};
use std::sync::Arc;

use itertools::Itertools;

/// A Document contains an id and content.
/// Hashing and equality are based only on the id field.
#[derive(Clone, Eq, Debug)]
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 {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        state.write(self.id.as_bytes());
    }
}

impl PartialEq<Document> for Document {
    fn eq(&self, other: &Document) -> bool {
        self.id == other.id
    }
}

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
struct IndexedDocument {
    pub doc: Arc<Document>,
    pub highlighted: (usize, usize),
}

/// An Index is anything that can store Documents and return matching Documents for a query.
pub trait Index {
    /// Given a Document, stores it in the index.
    fn index(&mut self, doc: Document);
    /// Given a query, return the set of Documents that match the query.
    /// What constitutes a "match" is implementation-specific; loosely, a Document should
    /// match a query if they are somehow related. A naive implementation might simply
    /// return the set of Documents for which `query` is a substring of their content.
    fn search(&self, query: &str) -> HashSet<SearchResult>;
}

/// A basic implementation of an `Index`, the inverted index is a data structure that maps
/// from words to sets of Documents.
pub type InvertedIndex = BTreeMap<String, HashSet<IndexedDocument>>;

impl Index for InvertedIndex {
    /// A basic implementation of index, splits the document's content into whitespace-separated
    /// words, and inserts each word-document pair into the map.
    fn index(&mut self, doc: Document) {
        let doc = Arc::new(doc);
        let analyzed = doc.content()
            .char_indices()
            .group_by(|&(_, c)| c.is_whitespace())
            .filter(|&(is_whitespace, _)| !is_whitespace)
            .flat_map(|(_, chars)| (1..chars.len() + 1).map(move |to| {
                let word: String = chars[..to].iter().flat_map(|&(_, c)| c.to_lowercase()).collect();
                let start = chars[0].0;
                let (last_idx, last_char) = chars[to - 1];
                let finish = last_idx + last_char.len_utf8();
                (word, (start, finish))
            }));

        for (ngram, highlighted) in analyzed {
            self.entry(ngram).or_insert_with(|| HashSet::new())
                .insert(IndexedDocument { doc: doc.clone(), highlighted: 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.
    fn search(&self, query: &str) -> HashSet<SearchResult> {
        let map = query.split_whitespace()
            .flat_map(|word| self.get(&word.to_lowercase()))
            .flat_map(|docs| docs)
            .cloned()
            .fold(HashMap::new(), |mut map, search_result| {
                map.entry(search_result.doc)
                    .or_insert(Vec::new())
                    .push(search_result.highlighted);
                map
            });
        map.into_iter()
            .map(|(doc, mut highlights)| {
                highlights.sort();
                SearchResult { doc: doc, highlights: highlights }
            })
        .collect()
    }
}

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct SearchResult {
    doc: Arc<Document>,
    highlights: Vec<(usize, usize)>,
}

impl SearchResult {
    #[cfg(test)]
    fn new(doc: Arc<Document>, highlights: Vec<(usize, usize)>) -> SearchResult {
        SearchResult {
            doc: doc,
            highlights: highlights,
        }
    }

    pub fn doc(&self) -> &Arc<Document> {
        &self.doc
    }

    pub fn highlights(&self) -> &Vec<(usize, usize)> {
        &self.highlights
    }

    pub fn highlighted_content(&self) -> String {
        let &SearchResult {ref doc, ref highlights} = self;
        let content = doc.content();
        let mut begin_idx = 0;
        let mut parts = vec![];
        for &(begin, end) in highlights {
            parts.push(&content[begin_idx..begin]);
            parts.push("");
            parts.push(&content[begin..end]);
            parts.push("");
            begin_idx = end;
        }
        parts.push(&content[begin_idx..]);
        parts.into_iter().join("")
    }
}

#[test]
fn test_search1() {
    let mut index = InvertedIndex::new();
    let doc1 = Document::new("1", "learn to program in rust today");
    index.index(doc1.clone());
    let doc2 = Document::new("2", "what did you today do");
    index.index(doc2.clone());
    let search_results = index.search("today");
    let expected = [
        SearchResult::new(Arc::new(doc1), vec![(25, 30)]),
        SearchResult::new(Arc::new(doc2), vec![(13, 18)])
    ];
    assert_eq!(search_results, expected.iter().cloned().collect());
    assert_eq!("learn to program in rust today", expected[0].highlighted_content());
}

#[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 = [
        SearchResult::new(Arc::new(doc1), vec![(6, 8), (25, 27)]),
        SearchResult::new(Arc::new(doc2), vec![(13, 15)]),
    ];
    assert_eq!(search_results, expected.iter().cloned().collect());
    assert_eq!("learn to program in rust today", expected[0].highlighted_content());

}

#[test]
fn test_search2() {
    let mut index = InvertedIndex::new();
    let doc1 = Document::new("2", "what to do today");
    let doc2 = Document::new("3", "hey today");
    index.index(doc1.clone());
    index.index(doc2.clone());
    let search_results = index.search("to");
    let expected = [
        SearchResult::new(Arc::new(doc1), vec![(5, 7), (11, 13)]),
        SearchResult::new(Arc::new(doc2), vec![(4, 6)]),
    ];
    assert_eq!(search_results, expected.iter().cloned().collect());
    assert_eq!(expected[0].highlighted_content(), "what to do today");
}

#[test]
fn test_unicode() {
    let mut index = InvertedIndex::new();
    let doc = Document::new("0", "abc åäö");
    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);
}
<commit_msg>Remove previous version of doc from index when indexing new version<commit_after>#![feature(collections, unboxed_closures, core)]
extern crate itertools;

use std::collections::{BTreeMap, HashMap, HashSet};
use std::hash::{Hash, Hasher};
use std::sync::Arc;
use std::iter;
use std::ops;

use itertools::{GroupBy, Itertools};

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

impl Drop for Document {
    fn drop(&mut self) {
        println!("Dropped doc {}", self.id);
    }
}

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 {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        state.write(self.id.as_bytes());
    }
}

impl PartialEq<Document> for Document {
    fn eq(&self, other: &Document) -> bool {
        self.id == other.id
    }
}

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
struct IndexedDocument {
    pub doc: Arc<Document>,
    pub highlighted: (usize, usize),
}

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

fn analyze_doc(doc: &str)
-> iter::FlatMap<
    iter::Filter<
        GroupBy<bool, std::str::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)
}

/// A basic implementation of an `Index`, the inverted index is a data structure that maps
/// from words to sets of Documents.
pub struct InvertedIndex {
    index: BTreeMap<String, HashSet<IndexedDocument>>,
    docs: BTreeMap<String, Arc<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 doc = Arc::new(doc);
        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, highlights) in previous_analyzed {
                let is_empty = {
                    let docs_for_ngram = self.index.get_mut(&ngram).unwrap();
                    docs_for_ngram.remove(&IndexedDocument { doc: doc.clone(), highlighted: highlights });
                    docs_for_ngram.is_empty()
                };
                if is_empty {
                    self.index.remove(&ngram);
                }
            }
        }

        for (ngram, highlighted) in analyzed {
            self.index.entry(ngram).or_insert_with(|| HashSet::new())
                .insert(IndexedDocument { doc: doc.clone(), highlighted: 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) -> HashSet<SearchResult> {
        let map = query.split_whitespace()
            .flat_map(|word| self.index.get(&word.to_lowercase()))
            .flat_map(|docs| docs)
            .cloned()
            .fold(HashMap::new(), |mut map, search_result| {
                map.entry(search_result.doc)
                    .or_insert(Vec::new())
                    .push(search_result.highlighted);
                map
            });
        map.into_iter()
            .map(|(doc, mut highlights)| {
                highlights.sort();
                SearchResult { doc: doc, highlights: highlights }
            })
        .collect()
    }
}

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct SearchResult {
    doc: Arc<Document>,
    highlights: Vec<(usize, usize)>,
}

impl SearchResult {
    #[cfg(test)]
    fn new(doc: Arc<Document>, highlights: Vec<(usize, usize)>) -> SearchResult {
        SearchResult {
            doc: doc,
            highlights: highlights,
        }
    }

    pub fn doc(&self) -> &Arc<Document> {
        &self.doc
    }

    pub fn highlights(&self) -> &Vec<(usize, usize)> {
        &self.highlights
    }

    pub fn highlighted_content(&self) -> String {
        let &SearchResult {ref doc, ref highlights} = self;
        let content = doc.content();
        let mut begin_idx = 0;
        let mut parts = vec![];
        for &(begin, end) in highlights {
            parts.push(&content[begin_idx..begin]);
            parts.push("");
            parts.push(&content[begin..end]);
            parts.push("");
            begin_idx = end;
        }
        parts.push(&content[begin_idx..]);
        parts.into_iter().join("")
    }
}

#[test]
fn test_search1() {
    let mut index = InvertedIndex::new();
    let doc1 = Document::new("1", "learn to program in rust today");
    index.index(doc1.clone());
    let doc2 = Document::new("2", "what did you today do");
    index.index(doc2.clone());
    let search_results = index.search("today");
    let expected = [
        SearchResult::new(Arc::new(doc1), vec![(25, 30)]),
        SearchResult::new(Arc::new(doc2), vec![(13, 18)])
    ];
    assert_eq!(search_results, expected.iter().cloned().collect());
    assert_eq!("learn to program in rust today", expected[0].highlighted_content());
}

#[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 = [
        SearchResult::new(Arc::new(doc1), vec![(6, 8), (25, 27)]),
        SearchResult::new(Arc::new(doc2), vec![(13, 15)]),
    ];
    assert_eq!(search_results, expected.iter().cloned().collect());
    assert_eq!("learn to program in rust today", expected[0].highlighted_content());

}

#[test]
fn test_search2() {
    let mut index = InvertedIndex::new();
    let doc1 = Document::new("2", "what to do today");
    let doc2 = Document::new("3", "hey today");
    index.index(doc1.clone());
    index.index(doc2.clone());
    let search_results = index.search("to");
    let expected = [
        SearchResult::new(Arc::new(doc1), vec![(5, 7), (11, 13)]),
        SearchResult::new(Arc::new(doc2), vec![(4, 6)]),
    ];
    assert_eq!(search_results, expected.iter().cloned().collect());
    assert_eq!(expected[0].highlighted_content(), "what to do today");
}

#[test]
fn test_unicode() {
    let mut index = InvertedIndex::new();
    let doc = Document::new("0", "abc åäö");
    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);
}
<|endoftext|>


<commit_before>/*
    This file is a part of cargo-esr.

    Copyright (C) 2017 Mohammad AlSaleh <CE.Mohammad.AlSaleh at gmail.com>
    https://github.com/rust-alt/cargo-esr

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at <http://mozilla.org/MPL/2.0/>.
*/

#![feature(more_struct_aliases)]
#![feature(inclusive_range_syntax)]
#![feature(repeat_str)]
#![feature(field_init_shorthand)]

#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate serde_derive;

extern crate ansi_term;
extern crate serde;
extern crate serde_json;
extern crate hyper;
extern crate native_tls;
extern crate hyper_native_tls;

extern crate time;
extern crate semver;
extern crate pipeliner;
extern crate regex;

#[macro_use]
mod esr_macros;
mod esr_errors;
mod esr_from;
pub mod esr_crate;
pub mod esr_github;
pub mod esr_score;
pub mod esr_printer;
<commit_msg>Remove stabilized features<commit_after>/*
    This file is a part of cargo-esr.

    Copyright (C) 2017 Mohammad AlSaleh <CE.Mohammad.AlSaleh at gmail.com>
    https://github.com/rust-alt/cargo-esr

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at <http://mozilla.org/MPL/2.0/>.
*/

#![feature(inclusive_range_syntax)]
#![feature(field_init_shorthand)]

#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate serde_derive;

extern crate ansi_term;
extern crate serde;
extern crate serde_json;
extern crate hyper;
extern crate native_tls;
extern crate hyper_native_tls;

extern crate time;
extern crate semver;
extern crate pipeliner;
extern crate regex;

#[macro_use]
mod esr_macros;
mod esr_errors;
mod esr_from;
pub mod esr_crate;
pub mod esr_github;
pub mod esr_score;
pub mod esr_printer;
<|endoftext|>


<commit_before>#![cfg(feature = "no_std")]
#![no_std]

#[macro_use]
extern crate cfg_if;

cfg_if! (
    if #[cfg(feature="no_std")] {
        use core::str::FromStr;
    } else {
        use std::str::FromStr;
    }
);
mod char;
mod int;

pub use char::TryFromIntToCharError;
pub use int::TryFromIntError;

pub trait TryFrom<T>: Sized {
    type Err;
    fn try_from(T) -> Result<Self, Self::Err>;
}

pub trait TryInto<T>: Sized {
    type Err;
    fn try_into(self) -> Result<T, Self::Err>;
}

impl<T, U> TryInto<U> for T
where
    U: TryFrom<T>,
{
    type Err = U::Err;
    fn try_into(self) -> Result<U, U::Err> {
        U::try_from(self)
    }
}

impl<'a, T> TryFrom<&'a str> for T
where
    T: FromStr,
{
    type Err = T::Err;
    fn try_from(string: &'a str) -> Result<Self, Self::Err> {
        T::from_str(string)
    }
}

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

    #[test]
    fn should_have_try_from_impl_for_from_str() {
        let result = u32::try_from("3");
        assert_eq!(result.unwrap(), 3)
    }

    #[test]
    fn should_have_try_from_impl_for_from_str_that_handles_err() {
        let result = u32::try_from("hello");
        assert_eq!(
            format!("{}", result.unwrap_err()),
            "invalid digit found in string"
        )
    }

    #[test]
    fn should_have_try_into_impl_for_from_str() {
        let result: Result<u32, _> = "3".try_into();
        assert_eq!(result.unwrap(), 3)
    }
}

/// Error type used when conversion is infallible.
/// The never type (`!`) will replace this when it is available in stable Rust.
#[derive(Debug, Eq, PartialEq)]
pub enum Void {}
<commit_msg>fix compilation<commit_after>#![cfg_attr(feature = "no_std", no_std)]

#[macro_use]
extern crate cfg_if;

cfg_if! (
    if #[cfg(feature="no_std")] {
        use core::str::FromStr;
    } else {
        use std::str::FromStr;
    }
);
mod char;
mod int;

pub use char::TryFromIntToCharError;
pub use int::TryFromIntError;

pub trait TryFrom<T>: Sized {
    type Err;
    fn try_from(T) -> Result<Self, Self::Err>;
}

pub trait TryInto<T>: Sized {
    type Err;
    fn try_into(self) -> Result<T, Self::Err>;
}

impl<T, U> TryInto<U> for T
where
    U: TryFrom<T>,
{
    type Err = U::Err;
    fn try_into(self) -> Result<U, U::Err> {
        U::try_from(self)
    }
}

impl<'a, T> TryFrom<&'a str> for T
where
    T: FromStr,
{
    type Err = T::Err;
    fn try_from(string: &'a str) -> Result<Self, Self::Err> {
        T::from_str(string)
    }
}

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

    #[test]
    fn should_have_try_from_impl_for_from_str() {
        let result = u32::try_from("3");
        assert_eq!(result.unwrap(), 3)
    }

    #[test]
    fn should_have_try_from_impl_for_from_str_that_handles_err() {
        let result = u32::try_from("hello");
        assert_eq!(
            format!("{}", result.unwrap_err()),
            "invalid digit found in string"
        )
    }

    #[test]
    fn should_have_try_into_impl_for_from_str() {
        let result: Result<u32, _> = "3".try_into();
        assert_eq!(result.unwrap(), 3)
    }
}

/// Error type used when conversion is infallible.
/// The never type (`!`) will replace this when it is available in stable Rust.
#[derive(Debug, Eq, PartialEq)]
pub enum Void {}
<|endoftext|>