<commit_before>//! OAuth 1
//!
//!# Example
//!
//! TODO
extern crate time;

use std::default::Default;
use std::fmt;
use self::time::now_utc;
use std::rand::{thread_rng, Rng};

#[derive(Copy, Show, PartialEq, Eq, Clone)]
#[unstable]
/// Signature Type
pub enum SignatureMethod {
    /// HMAC_SHA1
    HMAC_SHA1,
    /// RSA_SHA1
    RSA_SHA1,
    /// Plaintext
    PLAINTEXT
}

impl Default for SignatureMethod {
    fn default() -> SignatureMethod {
        SignatureMethod::HMAC_SHA1}
}

impl fmt::String for SignatureMethod {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result{
        let out = match *self {
            SignatureMethod::HMAC_SHA1 => {"HMAC-SHA1"},
            SignatureMethod::RSA_SHA1  => {"RSA-SHA1"},
            SignatureMethod::PLAINTEXT => {"PLAINTEXT"}
        };
        write!(f, "{}", out)
    }
}

#[unstable]
pub struct Session<'a> {
    oauth_consumer_key : &'a str,
    oauth_token : &'a str,
    oauth_token_secret : &'a str,
    oauth_signature_method : &'a str,
    oauth_signature : &'a str,
}

// TODO: add to crypto library?
// TODO: Should we have a longer nonce than 10?
fn get_nonce() -> String {
    thread_rng().gen_ascii_chars()
                .take(10)
                .collect()
}

impl<'a> Session<'a> {
    pub fn new (consumer_key: &'a str, token: &'a str, secret: &'a str,
                signature_method: &'a str) -> Session<'a> {
        Session {
            oauth_consumer_key: consumer_key,
            oauth_token: token,
            oauth_token_secret : secret,
            oauth_signature_method: signature_method,
            oauth_signature: "TODO",
        }
    }
    // pub fn set_realm(&mut self, realm : Option<&'a str>)->&Session<'a>{
    //     self.realm = realm;
    //     self
    // }

    pub fn get_temporary_credentials(&self) {
        // TODO
        unimplemented!();
    }
    fn get_header(&self) -> String {
        let header = format!("Authorization: OAuth oauth_consumer_key=\"{}\" \
                oauth_signature=\"{}\", oauth_signature_method=\"{}\", \
                oauth_token=\"{}\", oauth_version=\"1.0\"",
                self.oauth_consumer_key, self.oauth_signature,
                self.oauth_signature_method, self.oauth_token);

        match self.oauth_signature_method {
            "PLAINTEXT" => header,
            _ => format!("{}, oauth_timestamp=\"{}\", oauth_nonce=\"{}\"",
                        header, now_utc().to_timespec().sec, get_nonce())
        }
    }
}

#[cfg(test)]
mod tests {
    use oauth::oauth1::Session;

        // Session initialization and setup test
    #[test]
    fn hw() {
        let s = Session::new("k0azC44q2c0DgF7ua9YZ6Q",
                            "119544186-6YZKqkECA9Z0bxq9bA1vzzG7tfPotCml4oTySkzj",
                            "zvNmU9daj9V00118H9KQBozQQsZt4pyLQcZdc",
                            "HMAC-SHA1");
        println!("{}", s.get_header());
    }
}

#[derive(Clone)]
pub struct Builder {
    request_url         : String,
    consumer_key        : String,
    callback_url        : String,
    signature_method    : SignatureMethod,
    require_nonce       : bool,
    require_timestamp   : bool,
    version             : Option<String>,
    realm               : Option<String>
}

#[derive(Clone)]
pub struct TemporaryCredentials {
    request_url         : String,
    consumer_key        : String,
    callback_url        : String,
    signature_method    : SignatureMethod,
    version             : Option<String>,
    realm               : Option<String>,
    nonce               : Option<String>,
    timestamp           : Option<String>,
}

fn generate_nonce() -> String {
    "".to_string()
}

impl Builder {
    pub fn new(request_url : String, consumer_key : String, callback_url : String, signature_method : SignatureMethod) -> Builder {
        let require = match signature_method {SignatureMethod::PLAINTEXT => false, _ => true};
        Builder {
            request_url         : request_url,
            consumer_key        : consumer_key,
            callback_url        : callback_url,
            signature_method    : signature_method,
            require_nonce       : require,
            require_timestamp   : require,
            version             : None,
            realm               : None
        }
    }

    pub fn set_version(mut self)-> Builder {
        self.version = Some("1.0".to_string());
        self
    }

    pub fn set_realm(mut self, realm : String) -> Builder {
        self.realm = Some(realm);
        self
    }

    pub fn require_nonce(mut self) -> Builder {
        self.require_nonce = true;
        self
    }

    pub fn require_timestamp(mut self) -> Builder {
        self.require_timestamp = true;
        self
    }

    pub fn create(self) -> TemporaryCredentials {
        TemporaryCredentials {
            request_url         : self.request_url,
            consumer_key        : self.consumer_key,
            callback_url        : self.callback_url,
            signature_method    : self.signature_method,
            version             : self.version,
            realm               : self.realm,
            nonce               : if self.require_nonce {Some(generate_nonce())}
            else {None},
            timestamp           : if self.require_timestamp {Some(time::now().to_timespec().sec.to_string())}
            else {None}

        }
    }
}

impl TemporaryCredentials {
    pub fn send_post_request(self)->Result<(),()>{
        Ok(())
    }
}

impl fmt::Show for TemporaryCredentials {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let builder : String;

        write!(f, "output")
    }
}
<commit_msg>Added trait AuthorizationHeader and refactored Session and TemporaryCredentials accordingly<commit_after>//! OAuth 1
//!
//!# Example
//!
//! TODO
extern crate time;

use std::default::Default;
use std::fmt;
use self::time::now_utc;
use std::rand::{thread_rng, Rng};

#[derive(Copy, Show, PartialEq, Eq, Clone)]
#[unstable]
/// Signature Type
pub enum SignatureMethod {
    /// HMAC_SHA1
    HMAC_SHA1,
    /// RSA_SHA1
    RSA_SHA1,
    /// Plaintext
    PLAINTEXT
}

impl Default for SignatureMethod {
    fn default() -> SignatureMethod {
        SignatureMethod::HMAC_SHA1}
}

impl fmt::String for SignatureMethod {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result{
        let out = match *self {
            SignatureMethod::HMAC_SHA1 => {"HMAC-SHA1"},
            SignatureMethod::RSA_SHA1  => {"RSA-SHA1"},
            SignatureMethod::PLAINTEXT => {"PLAINTEXT"}
        };
        write!(f, "{}", out)
    }
}

pub trait AuthorizationHeader {
    fn get_header(&self) -> String;
}

#[unstable]
pub struct Session<'a> {
    oauth_consumer_key : &'a str,
    oauth_token : &'a str,
    oauth_token_secret : &'a str,
    oauth_signature_method : SignatureMethod,
    oauth_signature : &'a str,
}

// TODO: add to crypto library?
// TODO: Should we have a longer nonce than 10?
fn generate_nonce() -> String {
    thread_rng().gen_ascii_chars()
                .take(10)
                .collect()
}

impl<'a> Session<'a> {
    pub fn new (consumer_key: &'a str, token: &'a str, secret: &'a str,
                signature_method: SignatureMethod) -> Session<'a> {
        Session {
            oauth_consumer_key: consumer_key,
            oauth_token: token,
            oauth_token_secret : secret,
            oauth_signature_method: signature_method,
            oauth_signature: "TODO",
        }
    }
    // pub fn set_realm(&mut self, realm : Option<&'a str>)->&Session<'a>{
    //     self.realm = realm;
    //     self
    // }

    pub fn get_temporary_credentials(&self) {
        // TODO
        unimplemented!();
    }
}

impl<'a> AuthorizationHeader for Session<'a>{
    fn get_header(&self) -> String {
        let header = format!("Authorization: OAuth oauth_consumer_key=\"{}\" \
        oauth_signature=\"{}\", oauth_signature_method=\"{}\", \
        oauth_token=\"{}\", oauth_version=\"1.0\"",
        self.oauth_consumer_key, self.oauth_signature,
        self.oauth_signature_method, self.oauth_token);

        match self.oauth_signature_method {
            SignatureMethod::PLAINTEXT => header,
            _ => format!("{}, oauth_timestamp=\"{}\", oauth_nonce=\"{}\"",
            header, now_utc().to_timespec().sec, generate_nonce())
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Session, SignatureMethod, AuthorizationHeader};

        // Session initialization and setup test
    #[test]
    fn hw() {
        let s = Session::new("k0azC44q2c0DgF7ua9YZ6Q",
                            "119544186-6YZKqkECA9Z0bxq9bA1vzzG7tfPotCml4oTySkzj",
                            "zvNmU9daj9V00118H9KQBozQQsZt4pyLQcZdc",
                            SignatureMethod::HMAC_SHA1);
        println!("{}", s.get_header());
    }
}

#[derive(Clone)]
pub struct Builder {
    request_url         : String,
    consumer_key        : String,
    callback_url        : String,
    signature_method    : SignatureMethod,
    require_nonce       : bool,
    require_timestamp   : bool,
    version             : Option<String>,
    realm               : Option<String>
}

#[derive(Clone)]
pub struct TemporaryCredentials {
    request_url         : String,
    consumer_key        : String,
    callback_url        : String,
    signature_method    : SignatureMethod,
    version             : Option<String>,
    realm               : Option<String>,
    nonce               : Option<String>,
    timestamp           : Option<String>,
}

impl Builder {
    pub fn new(request_url : String, consumer_key : String, callback_url : String, signature_method : SignatureMethod) -> Builder {
        let require = match signature_method {SignatureMethod::PLAINTEXT => false, _ => true};
        Builder {
            request_url         : request_url,
            consumer_key        : consumer_key,
            callback_url        : callback_url,
            signature_method    : signature_method,
            require_nonce       : require,
            require_timestamp   : require,
            version             : None,
            realm               : None
        }
    }

    pub fn set_version(mut self)-> Builder {
        self.version = Some("1.0".to_string());
        self
    }

    pub fn set_realm(mut self, realm : String) -> Builder {
        self.realm = Some(realm);
        self
    }

    pub fn require_nonce(mut self) -> Builder {
        self.require_nonce = true;
        self
    }

    pub fn require_timestamp(mut self) -> Builder {
        self.require_timestamp = true;
        self
    }

    pub fn create(self) -> TemporaryCredentials {
        TemporaryCredentials {
            request_url         : self.request_url,
            consumer_key        : self.consumer_key,
            callback_url        : self.callback_url,
            signature_method    : self.signature_method,
            version             : self.version,
            realm               : self.realm,
            nonce               : if self.require_nonce {Some(generate_nonce())}
                                  else {None},
            timestamp           : if self.require_timestamp {Some(now_utc().to_timespec().sec.to_string())}
                                  else {None}

        }
    }
}

impl TemporaryCredentials {
    pub fn send_post_request(self)->Result<(),()>{
        Ok(())
    }
}

impl AuthorizationHeader for TemporaryCredentials {
    fn get_header(&self) -> String {
        "".to_string()
    }
}

impl fmt::Show for TemporaryCredentials {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let builder : String;

        write!(f, "output")
    }
}
<|endoftext|>


<commit_before>use crate::data::{HETERONYM_TABLE, PINYIN_DATA};
use crate::{get_block_and_index, Pinyin, PinyinData};
use std::convert::TryFrom;
use std::str::Chars;

/// 单个字符的多音字信息
///
/// *仅在启用 `heteronym` 特性时可用*
#[derive(Copy, Clone)]
pub struct PinyinMulti {
    first: &'static PinyinData,
    other_indexes: &'static [u16],
}

impl PinyinMulti {
    /// 对应字符不同发音的数量
    pub fn count(self) -> usize {
        self.other_indexes.len() + 1
    }

    /// 获取指定序号的拼音，如果序号超过总数则panic
    pub fn get(self, idx: usize) -> Pinyin {
        self.get_opt(idx).unwrap()
    }

    /// 获取指定序号的拼音，如果序号超过总数则返回 `None`
    pub fn get_opt(self, idx: usize) -> Option<Pinyin> {
        if idx == 0 {
            Some(Pinyin(self.first))
        } else {
            self.other_indexes
                .get(usize::try_from(idx).unwrap() - 1)
                .map(|i| Pinyin(&PINYIN_DATA[usize::try_from(*i).unwrap()]))
        }
    }
}

impl IntoIterator for PinyinMulti {
    type Item = Pinyin;
    type IntoIter = PinyinMultiIter;

    fn into_iter(self) -> PinyinMultiIter {
        PinyinMultiIter {
            inner: self,
            index: 0,
        }
    }
}

/// *辅助迭代器*，用于迭代一个字的多个拼音
pub struct PinyinMultiIter {
    inner: PinyinMulti,
    index: usize,
}

impl Iterator for PinyinMultiIter {
    type Item = Pinyin;

    fn next(&mut self) -> Option<Pinyin> {
        self.inner.get_opt(self.index).map(|pinyin| {
            self.index += 1;
            pinyin
        })
    }
}

/// 用于获取多音字信息的trait
///
/// *仅在启用 `heteronym` 特性时可用*
pub trait ToPinyinMulti {
    type Output;
    fn to_pinyin_multi(&self) -> Self::Output;
}

/// ```
/// # #[cfg(feature = "with_tone")] {
/// use pinyin::{Pinyin, ToPinyinMulti};
/// let mut iter = '还'.to_pinyin_multi().unwrap().into_iter();
/// let mut next_pinyin = || iter.next().map(Pinyin::with_tone);
/// assert_eq!(next_pinyin(), Some("hái"));
/// assert_eq!(next_pinyin(), Some("fú"));
/// assert_eq!(next_pinyin(), Some("huán"));
/// assert_eq!(next_pinyin(), None);
/// # }
/// ```
impl ToPinyinMulti for char {
    type Output = Option<PinyinMulti>;

    fn to_pinyin_multi(&self) -> Option<PinyinMulti> {
        get_block_and_index(*self).and_then(|(block, index)| {
            let first = match usize::try_from(block.data[index]).unwrap() {
                0 => return None,
                idx => &PINYIN_DATA[idx],
            };
            let idx = usize::try_from(block.heteronym[index]).unwrap();
            let other_indexes = HETERONYM_TABLE[idx];
            Some(PinyinMulti {
                first,
                other_indexes,
            })
        })
    }
}

/// ```
/// # #[cfg(feature = "with_tone")] {
/// use pinyin::{Pinyin, ToPinyinMulti};
/// let mut iter = "还没".to_pinyin_multi();
/// let mut next_heteronym = || {
///     iter.next()
///         .and_then(|m| m)
///         .map(|m| m.into_iter().map(Pinyin::with_tone).collect::<Vec<_>>())
/// };
/// assert_eq!(next_heteronym(), Some(vec!["hái", "fú", "huán"]));
/// assert_eq!(next_heteronym(), Some(vec!["méi", "mò", "me"]));
/// assert_eq!(next_heteronym(), None);
/// # }
/// ```
impl<'a> ToPinyinMulti for &'a str {
    type Output = PinyinMultiStrIter<'a>;

    #[inline]
    fn to_pinyin_multi(&self) -> Self::Output {
        PinyinMultiStrIter(self.chars())
    }
}

/// *辅助迭代器*，用于获取字符串的多音字信息
pub struct PinyinMultiStrIter<'a>(Chars<'a>);

impl<'a> Iterator for PinyinMultiStrIter<'a> {
    type Item = Option<PinyinMulti>;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|c| c.to_pinyin_multi())
    }
}

#[cfg(test)]
mod tests {
    use crate::{Pinyin, PinyinMulti, ToPinyinMulti};

    fn zi() -> PinyinMulti {
        '子'.to_pinyin_multi().expect("no pinyin?")
    }

    #[test]
    fn pinyin_multi_count() {
        assert_eq!(zi().count(), 2);
    }

    #[test]
    #[cfg(feature = "with_tone")]
    fn pinyin_multi_get_opt() {
        assert_eq!(zi().get_opt(0).map(Pinyin::with_tone), Some("zi"));
        assert_eq!(zi().get_opt(1).map(Pinyin::with_tone), Some("zǐ"));
        assert_eq!(zi().get_opt(2).map(Pinyin::with_tone), None);
    }

    #[test]
    #[cfg(feature = "with_tone")]
    fn pinyin_multi_get() {
        assert_eq!(zi().get(0).with_tone(), "zi");
        assert_eq!(zi().get(1).with_tone(), "zǐ");
    }

    #[test]
    #[should_panic]
    fn pinyin_multi_get_panic() {
        zi().get(2);
    }

    #[test]
    #[cfg(feature = "with_tone")]
    fn pinyin_multi_iter() {
        let mut iter = zi().into_iter();
        assert_eq!(iter.next().map(Pinyin::with_tone), Some("zi"));
        assert_eq!(iter.next().map(Pinyin::with_tone), Some("zǐ"));
        assert_eq!(iter.next().map(Pinyin::with_tone), None);
    }

    #[test]
    #[cfg(feature = "with_tone")]
    fn str_to_pinyin_multi() {
        let actual = "还没"
            .to_pinyin_multi()
            .map(|multi| {
                multi
                    .unwrap()
                    .into_iter()
                    .map(Pinyin::with_tone)
                    .collect::<Vec<_>>()
            })
            .collect::<Vec<_>>();
        let expected = vec![vec!["hái", "fú", "huán"], vec!["méi", "mò", "me"]];
        assert_eq!(actual, expected);
    }
}
<commit_msg>消除一个编译警告<commit_after>use crate::data::{HETERONYM_TABLE, PINYIN_DATA};
use crate::{get_block_and_index, Pinyin, PinyinData};
use std::convert::TryFrom;
use std::str::Chars;

/// 单个字符的多音字信息
///
/// *仅在启用 `heteronym` 特性时可用*
#[derive(Copy, Clone)]
pub struct PinyinMulti {
    first: &'static PinyinData,
    other_indexes: &'static [u16],
}

impl PinyinMulti {
    /// 对应字符不同发音的数量
    pub fn count(self) -> usize {
        self.other_indexes.len() + 1
    }

    /// 获取指定序号的拼音，如果序号超过总数则panic
    pub fn get(self, idx: usize) -> Pinyin {
        self.get_opt(idx).unwrap()
    }

    /// 获取指定序号的拼音，如果序号超过总数则返回 `None`
    pub fn get_opt(self, idx: usize) -> Option<Pinyin> {
        if idx == 0 {
            Some(Pinyin(self.first))
        } else {
            self.other_indexes
                .get(usize::try_from(idx).unwrap() - 1)
                .map(|i| Pinyin(&PINYIN_DATA[usize::try_from(*i).unwrap()]))
        }
    }
}

impl IntoIterator for PinyinMulti {
    type Item = Pinyin;
    type IntoIter = PinyinMultiIter;

    fn into_iter(self) -> PinyinMultiIter {
        PinyinMultiIter {
            inner: self,
            index: 0,
        }
    }
}

/// *辅助迭代器*，用于迭代一个字的多个拼音
pub struct PinyinMultiIter {
    inner: PinyinMulti,
    index: usize,
}

impl Iterator for PinyinMultiIter {
    type Item = Pinyin;

    fn next(&mut self) -> Option<Pinyin> {
        self.inner.get_opt(self.index).map(|pinyin| {
            self.index += 1;
            pinyin
        })
    }
}

/// 用于获取多音字信息的trait
///
/// *仅在启用 `heteronym` 特性时可用*
pub trait ToPinyinMulti {
    type Output;
    fn to_pinyin_multi(&self) -> Self::Output;
}

/// ```
/// # #[cfg(feature = "with_tone")] {
/// use pinyin::{Pinyin, ToPinyinMulti};
/// let mut iter = '还'.to_pinyin_multi().unwrap().into_iter();
/// let mut next_pinyin = || iter.next().map(Pinyin::with_tone);
/// assert_eq!(next_pinyin(), Some("hái"));
/// assert_eq!(next_pinyin(), Some("fú"));
/// assert_eq!(next_pinyin(), Some("huán"));
/// assert_eq!(next_pinyin(), None);
/// # }
/// ```
impl ToPinyinMulti for char {
    type Output = Option<PinyinMulti>;

    fn to_pinyin_multi(&self) -> Option<PinyinMulti> {
        get_block_and_index(*self).and_then(|(block, index)| {
            let first = match usize::try_from(block.data[index]).unwrap() {
                0 => return None,
                idx => &PINYIN_DATA[idx],
            };
            let idx = usize::try_from(block.heteronym[index]).unwrap();
            let other_indexes = HETERONYM_TABLE[idx];
            Some(PinyinMulti {
                first,
                other_indexes,
            })
        })
    }
}

/// ```
/// # #[cfg(feature = "with_tone")] {
/// use pinyin::{Pinyin, ToPinyinMulti};
/// let mut iter = "还没".to_pinyin_multi();
/// let mut next_heteronym = || {
///     iter.next()
///         .and_then(|m| m)
///         .map(|m| m.into_iter().map(Pinyin::with_tone).collect::<Vec<_>>())
/// };
/// assert_eq!(next_heteronym(), Some(vec!["hái", "fú", "huán"]));
/// assert_eq!(next_heteronym(), Some(vec!["méi", "mò", "me"]));
/// assert_eq!(next_heteronym(), None);
/// # }
/// ```
impl<'a> ToPinyinMulti for &'a str {
    type Output = PinyinMultiStrIter<'a>;

    #[inline]
    fn to_pinyin_multi(&self) -> Self::Output {
        PinyinMultiStrIter(self.chars())
    }
}

/// *辅助迭代器*，用于获取字符串的多音字信息
pub struct PinyinMultiStrIter<'a>(Chars<'a>);

impl<'a> Iterator for PinyinMultiStrIter<'a> {
    type Item = Option<PinyinMulti>;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|c| c.to_pinyin_multi())
    }
}

#[cfg(test)]
mod tests {
    #[cfg(feature = "with_tone")]
    use crate::Pinyin;
    use crate::{PinyinMulti, ToPinyinMulti};

    fn zi() -> PinyinMulti {
        '子'.to_pinyin_multi().expect("no pinyin?")
    }

    #[test]
    fn pinyin_multi_count() {
        assert_eq!(zi().count(), 2);
    }

    #[test]
    #[cfg(feature = "with_tone")]
    fn pinyin_multi_get_opt() {
        assert_eq!(zi().get_opt(0).map(Pinyin::with_tone), Some("zi"));
        assert_eq!(zi().get_opt(1).map(Pinyin::with_tone), Some("zǐ"));
        assert_eq!(zi().get_opt(2).map(Pinyin::with_tone), None);
    }

    #[test]
    #[cfg(feature = "with_tone")]
    fn pinyin_multi_get() {
        assert_eq!(zi().get(0).with_tone(), "zi");
        assert_eq!(zi().get(1).with_tone(), "zǐ");
    }

    #[test]
    #[should_panic]
    fn pinyin_multi_get_panic() {
        zi().get(2);
    }

    #[test]
    #[cfg(feature = "with_tone")]
    fn pinyin_multi_iter() {
        let mut iter = zi().into_iter();
        assert_eq!(iter.next().map(Pinyin::with_tone), Some("zi"));
        assert_eq!(iter.next().map(Pinyin::with_tone), Some("zǐ"));
        assert_eq!(iter.next().map(Pinyin::with_tone), None);
    }

    #[test]
    #[cfg(feature = "with_tone")]
    fn str_to_pinyin_multi() {
        let actual = "还没"
            .to_pinyin_multi()
            .map(|multi| {
                multi
                    .unwrap()
                    .into_iter()
                    .map(Pinyin::with_tone)
                    .collect::<Vec<_>>()
            })
            .collect::<Vec<_>>();
        let expected = vec![vec!["hái", "fú", "huán"], vec!["méi", "mò", "me"]];
        assert_eq!(actual, expected);
    }
}
<|endoftext|>


<commit_before>#![cfg(feature = "regex")]
extern crate env_logger;
extern crate gluon;

use gluon::{new_vm, Compiler};

#[test]
fn regex_match() {
    let _ = ::env_logger::try_init();

    let thread = new_vm();
    let text = r#"
        let regex = import! std.regex
        let { (|>) } = import! std.function
        let { not } = import! std.bool
        let { unwrap_ok } = import! std.result
        let { assert }  = import! std.test

        let match_a = regex.new "a" |> unwrap_ok
        assert (regex.is_match match_a "a")
        assert (not (regex.is_match match_a "b"))
        let match_hello = regex.new "hello, .*" |> unwrap_ok
        regex.is_match match_hello "hello, world"
        "#;
    let result = Compiler::new()
        .run_expr_async::<bool>(&thread, "<top>", text)
        .sync_or_error();

    assert!(result.unwrap_or_else(|err| panic!("{}", err)).0);
}

#[test]
fn regex_error() {
    let _ = ::env_logger::try_init();

    let thread = new_vm();
    let text = r#"
        let regex = import! std.regex
        let { (|>) } = import! std.function
        let { unwrap_err } = import! std.result

        regex.new ")" |> unwrap_err |> regex.error_to_string
        "#;
    let result = Compiler::new()
        .run_expr_async::<String>(&thread, "<top>", text)
        .sync_or_error();

    assert_eq!(
        result.unwrap_or_else(|err| panic!("{}", err)).0,
        "Error parsing regex near \')\' at character offset 0: Unopened parenthesis."
    );
}
<commit_msg>Fix regex text after error messages has been changed<commit_after>#![cfg(feature = "regex")]
extern crate env_logger;
extern crate gluon;

use gluon::{new_vm, Compiler};

#[test]
fn regex_match() {
    let _ = ::env_logger::try_init();

    let thread = new_vm();
    let text = r#"
        let regex = import! std.regex
        let { (|>) } = import! std.function
        let { not } = import! std.bool
        let { unwrap_ok } = import! std.result
        let { assert }  = import! std.test

        let match_a = regex.new "a" |> unwrap_ok
        assert (regex.is_match match_a "a")
        assert (not (regex.is_match match_a "b"))
        let match_hello = regex.new "hello, .*" |> unwrap_ok
        regex.is_match match_hello "hello, world"
        "#;
    let result = Compiler::new()
        .run_expr_async::<bool>(&thread, "<top>", text)
        .sync_or_error();

    assert!(result.unwrap_or_else(|err| panic!("{}", err)).0);
}

#[test]
fn regex_error() {
    let _ = ::env_logger::try_init();

    let thread = new_vm();
    let text = r#"
        let regex = import! std.regex
        let { (|>) } = import! std.function
        let { unwrap_err } = import! std.result

        regex.new ")" |> unwrap_err |> regex.error_to_string
        "#;
    let result = Compiler::new()
        .run_expr_async::<String>(&thread, "<top>", text)
        .sync_or_error();

    assert_eq!(
        result.unwrap_or_else(|err| panic!("{}", err)).0,
        "regex parse error:\n    )\n    ^\nerror: unopened group"
    );
}
<|endoftext|>


<commit_before>fn main() {
   // sum up even elements of Fibonacci sequence
   // which not exceed 4.000.000
   let (a, b) = (1, 2);

   println!("The sum of all even Fibonacci elements with value below 4.000.000 equals to: {}", 0);
}
<commit_msg>added rough outline for question 002.<commit_after>fn main() {
   // sum up even elements of Fibonacci sequence
   // which not exceed 4.000.000
   let (a, b) = (1, 2);

   println!("The sum of all even Fibonacci elements with value below 4.000.000 equals to: {}", 0);
}
<|endoftext|>


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

#![allow(dead_code)] // not used on all platforms

use collections::BTreeMap;
use ptr;

pub type Key = usize;

type Dtor = unsafe extern fn(*mut u8);

#[thread_local]
static mut NEXT_KEY: Key = 0;

#[thread_local]
static mut LOCALS: *mut BTreeMap<Key, (*mut u8, Option<Dtor>)> = ptr::null_mut();

unsafe fn locals() -> &'static mut BTreeMap<Key, (*mut u8, Option<Dtor>)> {
    if LOCALS == ptr::null_mut() {
        LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
    }
    &mut *LOCALS
}

#[inline]
pub unsafe fn create(dtor: Option<Dtor>) -> Key {
    let key = NEXT_KEY;
    NEXT_KEY += 1;
    locals().insert(key, (0 as *mut u8, dtor));
    key
}

#[inline]
pub unsafe fn set(key: Key, value: *mut u8) {
    locals().get_mut(&key).unwrap().0 = value;
}

#[inline]
pub unsafe fn get(key: Key) -> *mut u8 {
    locals()[&key].0
}

#[inline]
pub unsafe fn destroy(key: Key) {
    let (value, dtor) = locals().remove(&key).unwrap();
    if let Some(dtor_fn) = dtor {
        dtor_fn(value);
    }
}
<commit_msg>Fix for thread locals<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(dead_code)] // not used on all platforms

use collections::BTreeMap;
use ptr;
use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

pub type Key = usize;

type Dtor = unsafe extern fn(*mut u8);

static NEXT_KEY: AtomicUsize = ATOMIC_USIZE_INIT;

static mut KEYS: *mut BTreeMap<Key, Option<Dtor>> = ptr::null_mut();

#[thread_local]
static mut LOCALS: *mut BTreeMap<Key, *mut u8> = ptr::null_mut();

unsafe fn keys() -> &'static mut BTreeMap<Key, Option<Dtor>> {
    if KEYS == ptr::null_mut() {
        KEYS = Box::into_raw(Box::new(BTreeMap::new()));
    }
    &mut *KEYS
}

unsafe fn locals() -> &'static mut BTreeMap<Key, *mut u8> {
    if LOCALS == ptr::null_mut() {
        LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
    }
    &mut *LOCALS
}

#[inline]
pub unsafe fn create(dtor: Option<Dtor>) -> Key {
    let key = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
    keys().insert(key, dtor);
    key
}

#[inline]
pub unsafe fn get(key: Key) -> *mut u8 {
    if let Some(&entry) = locals().get(&key) {
        entry
    } else {
        ptr::null_mut()
    }
}

#[inline]
pub unsafe fn set(key: Key, value: *mut u8) {
    locals().insert(key, value);
}

#[inline]
pub unsafe fn destroy(key: Key) {
    keys().remove(&key);
}
<|endoftext|>


<commit_before>use indoc::indoc;
use serde_derive::Deserialize;
use serde_yaml::Deserializer;
use std::fmt::Debug;

fn test_error<T>(yaml: &str, expected: &str)
where
    T: serde::de::DeserializeOwned + Debug,
{
    let result = serde_yaml::from_str::<T>(yaml);
    assert_eq!(expected, result.unwrap_err().to_string());
}

#[test]
fn test_incorrect_type() {
    let yaml = indoc! {"
        ---
        str
    "};
    let expected = "invalid type: string \"str\", expected i16 at line 2 column 1";
    test_error::<i16>(yaml, expected);
}

#[test]
fn test_incorrect_nested_type() {
    #[derive(Deserialize, Debug)]
    struct A {
        #[allow(dead_code)]
        b: Vec<B>,
    }
    #[derive(Deserialize, Debug)]
    enum B {
        C(C),
    }
    #[derive(Deserialize, Debug)]
    struct C {
        #[allow(dead_code)]
        d: bool,
    }
    let yaml = indoc! {"
        b:
          - !C
            d: fase
    "};
    let expected = "b[0].d: invalid type: string \"fase\", expected a boolean at line 3 column 8";
    test_error::<A>(yaml, expected);
}

#[test]
fn test_empty() {
    let expected = "EOF while parsing a value";
    test_error::<String>("", expected);
}

#[test]
fn test_missing_field() {
    #[derive(Deserialize, Debug)]
    struct Basic {
        #[allow(dead_code)]
        v: bool,
        #[allow(dead_code)]
        w: bool,
    }
    let yaml = indoc! {"
        ---
        v: true
    "};
    let expected = "missing field `w` at line 2 column 1";
    test_error::<Basic>(yaml, expected);
}

#[test]
fn test_unknown_anchor() {
    let yaml = indoc! {"
        ---
        *some
    "};
    let expected = "unknown anchor at line 2 column 1";
    test_error::<String>(yaml, expected);
}

#[test]
fn test_ignored_unknown_anchor() {
    #[derive(Deserialize, Debug)]
    struct Wrapper {
        #[allow(dead_code)]
        c: (),
    }
    let yaml = indoc! {"
        b: [*a]
        c: ~
    "};
    let expected = "unknown anchor at line 1 column 5";
    test_error::<Wrapper>(yaml, expected);
}

#[test]
fn test_two_documents() {
    let yaml = indoc! {"
        ---
        0
        ---
        1
    "};
    let expected = "deserializing from YAML containing more than one document is not supported";
    test_error::<usize>(yaml, expected);
}

#[test]
fn test_second_document_syntax_error() {
    let yaml = indoc! {"
        ---
        0
        ---
        ]
    "};

    let mut de = Deserializer::from_str(yaml);
    let first_doc = de.next().unwrap();
    let result = <usize as serde::Deserialize>::deserialize(first_doc);
    assert_eq!(0, result.unwrap());

    let second_doc = de.next().unwrap();
    let result = <usize as serde::Deserialize>::deserialize(second_doc);
    let expected = "did not find expected node content at line 4 column 1, while parsing a block node at line 4 column 1";
    assert_eq!(expected, result.unwrap_err().to_string());
}

#[test]
fn test_missing_enum_tag() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(usize),
    }
    let yaml = indoc! {r#"
        "V": 16
        "other": 32
    "#};
    let expected = "invalid type: map, expected a YAML tag starting with '!' at position 0";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_variant_not_a_seq() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(usize),
    }
    let yaml = indoc! {r#"
        ---
        !V
        value: 0
    "#};
    let expected = "invalid type: map, expected usize at line 2 column 1";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_bad_bool() {
    let yaml = indoc! {"
        ---
        !!bool str
    "};
    let expected = "invalid value: string \"str\", expected a boolean at line 2 column 1";
    test_error::<bool>(yaml, expected);
}

#[test]
fn test_bad_int() {
    let yaml = indoc! {"
        ---
        !!int str
    "};
    let expected = "invalid value: string \"str\", expected an integer at line 2 column 1";
    test_error::<i64>(yaml, expected);
}

#[test]
fn test_bad_float() {
    let yaml = indoc! {"
        ---
        !!float str
    "};
    let expected = "invalid value: string \"str\", expected a float at line 2 column 1";
    test_error::<f64>(yaml, expected);
}

#[test]
fn test_bad_null() {
    let yaml = indoc! {"
        ---
        !!null str
    "};
    let expected = "invalid value: string \"str\", expected null at line 2 column 1";
    test_error::<()>(yaml, expected);
}

#[test]
fn test_short_tuple() {
    let yaml = indoc! {"
        ---
        [0, 0]
    "};
    let expected = "invalid length 2, expected a tuple of size 3 at line 2 column 1";
    test_error::<(u8, u8, u8)>(yaml, expected);
}

#[test]
fn test_long_tuple() {
    let yaml = indoc! {"
        ---
        [0, 0, 0]
    "};
    let expected = "invalid length 3, expected sequence of 2 elements at line 2 column 1";
    test_error::<(u8, u8)>(yaml, expected);
}

#[test]
fn test_invalid_scalar_type() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: [(); 1],
    }

    let yaml = "x:\n";
    let expected = "x: invalid type: unit value, expected an array of length 1 at line 1 column 3";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_infinite_recursion_objects() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "&a {'x': *a}";
    let expected = "recursion limit exceeded at position 0";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_infinite_recursion_arrays() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "&a [*a]";
    let expected = "recursion limit exceeded at position 0";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_finite_recursion_objects() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "{'x':".repeat(1_000) + &"}".repeat(1_000);
    let expected = "recursion limit exceeded at line 1 column 641";
    test_error::<S>(&yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_finite_recursion_arrays() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "[".repeat(1_000) + &"]".repeat(1_000);
    let expected = "recursion limit exceeded at line 1 column 129";
    test_error::<S>(&yaml, expected);
}
<commit_msg>Add a test of billion laughs input<commit_after>use indoc::indoc;
use serde::de::{Deserialize, SeqAccess, Visitor};
use serde_derive::Deserialize;
use serde_yaml::Deserializer;
use std::collections::BTreeMap;
use std::fmt::{self, Debug};

fn test_error<T>(yaml: &str, expected: &str)
where
    T: serde::de::DeserializeOwned + Debug,
{
    let result = serde_yaml::from_str::<T>(yaml);
    assert_eq!(expected, result.unwrap_err().to_string());
}

#[test]
fn test_incorrect_type() {
    let yaml = indoc! {"
        ---
        str
    "};
    let expected = "invalid type: string \"str\", expected i16 at line 2 column 1";
    test_error::<i16>(yaml, expected);
}

#[test]
fn test_incorrect_nested_type() {
    #[derive(Deserialize, Debug)]
    struct A {
        #[allow(dead_code)]
        b: Vec<B>,
    }
    #[derive(Deserialize, Debug)]
    enum B {
        C(C),
    }
    #[derive(Deserialize, Debug)]
    struct C {
        #[allow(dead_code)]
        d: bool,
    }
    let yaml = indoc! {"
        b:
          - !C
            d: fase
    "};
    let expected = "b[0].d: invalid type: string \"fase\", expected a boolean at line 3 column 8";
    test_error::<A>(yaml, expected);
}

#[test]
fn test_empty() {
    let expected = "EOF while parsing a value";
    test_error::<String>("", expected);
}

#[test]
fn test_missing_field() {
    #[derive(Deserialize, Debug)]
    struct Basic {
        #[allow(dead_code)]
        v: bool,
        #[allow(dead_code)]
        w: bool,
    }
    let yaml = indoc! {"
        ---
        v: true
    "};
    let expected = "missing field `w` at line 2 column 1";
    test_error::<Basic>(yaml, expected);
}

#[test]
fn test_unknown_anchor() {
    let yaml = indoc! {"
        ---
        *some
    "};
    let expected = "unknown anchor at line 2 column 1";
    test_error::<String>(yaml, expected);
}

#[test]
fn test_ignored_unknown_anchor() {
    #[derive(Deserialize, Debug)]
    struct Wrapper {
        #[allow(dead_code)]
        c: (),
    }
    let yaml = indoc! {"
        b: [*a]
        c: ~
    "};
    let expected = "unknown anchor at line 1 column 5";
    test_error::<Wrapper>(yaml, expected);
}

#[test]
fn test_two_documents() {
    let yaml = indoc! {"
        ---
        0
        ---
        1
    "};
    let expected = "deserializing from YAML containing more than one document is not supported";
    test_error::<usize>(yaml, expected);
}

#[test]
fn test_second_document_syntax_error() {
    let yaml = indoc! {"
        ---
        0
        ---
        ]
    "};

    let mut de = Deserializer::from_str(yaml);
    let first_doc = de.next().unwrap();
    let result = <usize as serde::Deserialize>::deserialize(first_doc);
    assert_eq!(0, result.unwrap());

    let second_doc = de.next().unwrap();
    let result = <usize as serde::Deserialize>::deserialize(second_doc);
    let expected = "did not find expected node content at line 4 column 1, while parsing a block node at line 4 column 1";
    assert_eq!(expected, result.unwrap_err().to_string());
}

#[test]
fn test_missing_enum_tag() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(usize),
    }
    let yaml = indoc! {r#"
        "V": 16
        "other": 32
    "#};
    let expected = "invalid type: map, expected a YAML tag starting with '!' at position 0";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_variant_not_a_seq() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(usize),
    }
    let yaml = indoc! {r#"
        ---
        !V
        value: 0
    "#};
    let expected = "invalid type: map, expected usize at line 2 column 1";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_bad_bool() {
    let yaml = indoc! {"
        ---
        !!bool str
    "};
    let expected = "invalid value: string \"str\", expected a boolean at line 2 column 1";
    test_error::<bool>(yaml, expected);
}

#[test]
fn test_bad_int() {
    let yaml = indoc! {"
        ---
        !!int str
    "};
    let expected = "invalid value: string \"str\", expected an integer at line 2 column 1";
    test_error::<i64>(yaml, expected);
}

#[test]
fn test_bad_float() {
    let yaml = indoc! {"
        ---
        !!float str
    "};
    let expected = "invalid value: string \"str\", expected a float at line 2 column 1";
    test_error::<f64>(yaml, expected);
}

#[test]
fn test_bad_null() {
    let yaml = indoc! {"
        ---
        !!null str
    "};
    let expected = "invalid value: string \"str\", expected null at line 2 column 1";
    test_error::<()>(yaml, expected);
}

#[test]
fn test_short_tuple() {
    let yaml = indoc! {"
        ---
        [0, 0]
    "};
    let expected = "invalid length 2, expected a tuple of size 3 at line 2 column 1";
    test_error::<(u8, u8, u8)>(yaml, expected);
}

#[test]
fn test_long_tuple() {
    let yaml = indoc! {"
        ---
        [0, 0, 0]
    "};
    let expected = "invalid length 3, expected sequence of 2 elements at line 2 column 1";
    test_error::<(u8, u8)>(yaml, expected);
}

#[test]
fn test_invalid_scalar_type() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: [(); 1],
    }

    let yaml = "x:\n";
    let expected = "x: invalid type: unit value, expected an array of length 1 at line 1 column 3";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_infinite_recursion_objects() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "&a {'x': *a}";
    let expected = "recursion limit exceeded at position 0";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_infinite_recursion_arrays() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "&a [*a]";
    let expected = "recursion limit exceeded at position 0";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_finite_recursion_objects() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "{'x':".repeat(1_000) + &"}".repeat(1_000);
    let expected = "recursion limit exceeded at line 1 column 641";
    test_error::<S>(&yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_finite_recursion_arrays() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "[".repeat(1_000) + &"]".repeat(1_000);
    let expected = "recursion limit exceeded at line 1 column 129";
    test_error::<S>(&yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_billion_laughs() {
    #[derive(Debug)]
    struct X;

    impl<'de> Deserialize<'de> for X {
        fn deserialize<D>(deserializer: D) -> Result<X, D::Error>
        where
            D: serde::Deserializer<'de>,
        {
            impl<'de> Visitor<'de> for X {
                type Value = X;

                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                    formatter.write_str("exponential blowup")
                }

                fn visit_unit<E>(self) -> Result<X, E> {
                    Ok(X)
                }

                fn visit_seq<S>(self, mut seq: S) -> Result<X, S::Error>
                where
                    S: SeqAccess<'de>,
                {
                    while let Some(X) = seq.next_element()? {}
                    Ok(X)
                }
            }

            deserializer.deserialize_any(X)
        }
    }

    let yaml = indoc! {"
        a: &a ~
        b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
        c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
        d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
        e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
        f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
        g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
        h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
        i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
    "};
    let expected = "repetition limit exceeded";
    test_error::<BTreeMap<String, X>>(yaml, expected);
}
<|endoftext|>


<commit_before>//! way-cooler registry.

use std::ops::Deref;
use std::cmp::Eq;
use std::fmt::Display;
use std::hash::Hash;
use std::borrow::Borrow;
use std::collections::hash_map::{HashMap, Entry};
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};

use rustc_serialize::Decodable;
use rustc_serialize::json::{Json, ToJson, Decoder, DecoderError};

mod types;
mod commands;
pub use self::types::*; // Export constants too

#[cfg(test)]
mod tests;

pub type RegMap = HashMap<String, RegistryField>;

lazy_static! {
    /// Registry variable for the registry
    static ref REGISTRY: RwLock<RegMap> = RwLock::new(HashMap::new());
}

/// Error types that can happen
#[derive(Debug, PartialEq)]
pub enum RegistryError {
    /// The registry key was not found
    KeyNotFound,
    /// The registry key was of the wrong type
    WrongKeyType,
    /// Attempting to set a readonly value
    InvalidOperation,
}

/// Result type of gets/sets to the registry
pub type RegistryResult<T> = Result<T, RegistryError>;

/// Initialize the registry (register default commands)
pub fn init() {
    commands::register_defaults();
}

/// Acquires a read lock on the registry.
pub fn read_lock<'a>() -> RwLockReadGuard<'a, RegMap> {
    REGISTRY.read().expect("Unable to read from registry!")
}

/// Acquires a write lock on the registry.
pub fn write_lock<'a>() -> RwLockWriteGuard<'a, RegMap> {
    REGISTRY.write().expect("Unable to write to registry!")
}

/// Gets a RegistryField enum with the specified name
pub fn get_field<K>(name: &K) -> Option<RegistryField>
    where String: Borrow<K>, K: Hash + Eq + Display {
    // clone() will either clone an Arc or an Arc+AccessFlags
    let result = read_lock().get(name).map(|v| v.clone());
    trace!("get: {} => {:?}", name, &result);
    return result;
}

/// Attempts to get a command from the registry.
pub fn get_command<K>(name: &K) -> RegistryResult<CommandFn>
    where String: Borrow<K>, K: Hash + Eq + Display {
    get_field(name).ok_or(RegistryError::KeyNotFound)
        .and_then(|val| match val {
        RegistryField::Command(com) => Ok(com),
        _ => Err(RegistryError::WrongKeyType)
    })
}

/// Gets a data type from the registry, returning a reference to the property
/// method if the field is a property.
pub fn get_data<K>(name: &K) -> RegistryResult<RegistryGetData>
where String: Borrow<K>, K: Hash + Eq + Display {
    get_field(name).ok_or(RegistryError::KeyNotFound)
        .and_then(|val| match val {
            RegistryField::Object { flags, data } =>
                Ok(RegistryGetData::Object(flags, data)),
            RegistryField::Property { get: maybe_get, .. } =>
                match maybe_get {
                    Some(get) => Ok(RegistryGetData::Property(get)),
                    None => Err(RegistryError::InvalidOperation)
                },
            _ => Err(RegistryError::WrongKeyType)
        })
}

/// Get a Rust structure from the registry
#[allow(dead_code)]
    pub fn get_struct<K, T>(name: &K)
                        -> RegistryResult<(AccessFlags, Result<T, DecoderError>)>
where String: Borrow <K>, K: Hash + Eq + Display, T: Decodable {
    get_json(name).map(|(flags, json)|
        (flags, T::decode(&mut Decoder::new(json.deref().clone()))))
}

/// Get Json data from the registry, evaluating if a property was found.
pub fn get_json<K>(name: &K) -> RegistryResult<(AccessFlags, Arc<Json>)>
where String: Borrow<K>, K: Hash + Eq + Display {
    get_data(name).map(|val| val.resolve())
}

/// Set a value to the given registry field.
pub fn set_field(key: String, value: RegistryField)
                 -> RegistryResult<Option<RegistryField>> {
    let mut reg = write_lock();
    match reg.entry(key) {
        Entry::Occupied(mut entry) => {
            let first_type = entry.get().get_type();
            if first_type.can_set_from(value.get_type()) {
                Ok(Some(entry.insert(value)))
            }
            else {
                Err(RegistryError::WrongKeyType)
            }
        },
        Entry::Vacant(vacancy) => {
            vacancy.insert(value);
            Ok(None)
        }
    }
}

/// Set a command to the given Command
#[allow(dead_code)]
pub fn set_command(key: String, command: CommandFn)
                   -> RegistryResult<Option<CommandFn>> {
    set_field(key, RegistryField::Command(command))
        .map(|maybe_field|
              maybe_field.and_then(|field|
                                    field.get_command()))
}

/// Set a value to the given JSON value.
#[allow(dead_code)]
pub fn set_json(key: String, flags: AccessFlags, json: Json)
                -> RegistryResult<Option<(AccessFlags, Arc<Json>)>> {
    let mut reg = write_lock();
    match reg.entry(key) {
        Entry::Vacant(vacancy) => {
            vacancy.insert(RegistryField::Object {
                flags: flags, data: Arc::new(json)
            });
            return Ok(None);
        },
        Entry::Occupied(mut entry) => {
            let first_type = entry.get().get_type();
            if first_type == FieldType::Object {
                return Ok(entry.insert(RegistryField::Object {
                    flags: flags, data: Arc::new(json)
                }).as_object());
            }
            else if first_type == FieldType::Property {
                match entry.get().clone().as_property_set() {
                    Some(func) => {
                        func(json);
                        return Ok(None);
                    }
                    None => return Err(RegistryError::InvalidOperation)
                }
            }
            else {
                return Err(RegistryError::WrongKeyType);
            }
        }
    }
    return Ok(None);
}

/// Set an object/property in the registry to a value using a ToJson.
#[allow(dead_code)]
pub fn set_struct<T: ToJson>(key: String, flags: AccessFlags, value: T)
                             -> RegistryResult<Option<(AccessFlags, Arc<Json>)>> {
    set_json(key, flags, value.to_json())
}

/// Sets a value for a given Json value, optionally returning the associated property.
#[allow(dead_code)]
pub fn set_with_property(key: String, flags: AccessFlags, json: Json)
                         -> RegistryResult<Option<(Json, SetFn)>> {
    let mut reg = write_lock();
    match reg.entry(key) {
        Entry::Vacant(vacancy) => {
            vacancy.insert(RegistryField::Object {
                flags: flags, data: Arc::new(json)
            });
            Ok(None)
        },
        Entry::Occupied(mut entry) => {
            let first_type = entry.get().get_type();
            if first_type == FieldType::Object {
                entry.insert(RegistryField::Object {
                    flags: flags, data: Arc::new(json)
                });
                Ok(None)
            }
            else if first_type == FieldType::Property {
                Ok(Some((json, entry.get().clone().as_property_set()
                   .expect("set_json_property: checked value of field type"))))
            }
            else {
                Err(RegistryError::WrongKeyType)
            }
        }
    }
}

/// Binds properties to a field of the registry
#[allow(dead_code)]
pub fn set_property_field(key: String, get_fn: Option<GetFn>, set_fn: Option<SetFn>)
                          -> RegistryResult<Option<RegistryField>> {
    set_field(key, RegistryField::Property { get: get_fn, set: set_fn })
}

/// Whether this map contains a key of any type
#[allow(dead_code)]
pub fn contains_key<K>(key: &K) -> bool
where String: Borrow<K>, K: Hash + Eq + Display {
    trace!("contains_key: {}", *key);
    let read_reg = read_lock();
    read_reg.contains_key(key)
}

/// Whether the registry contains a key of some type:
/// None: no key
/// true: same type key
/// false: different type key
#[allow(dead_code)]
pub fn contains_key_of<K>(key: &K, field_type: FieldType) -> Option<bool>
where String: Borrow<K>, K: Hash + Eq + Display {
    let read_reg = read_lock();
    read_reg.get(key).map(|field| field.get_type() == field_type)
}
<commit_msg>Registry methods take an &str for key<commit_after>//! way-cooler registry.

use std::ops::Deref;
use std::cmp::Eq;
use std::fmt::Display;
use std::hash::Hash;
use std::borrow::Borrow;
use std::collections::hash_map::{HashMap, Entry};
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};

use rustc_serialize::Decodable;
use rustc_serialize::json::{Json, ToJson, Decoder, DecoderError};

mod types;
mod commands;
pub use self::types::*; // Export constants too

#[cfg(test)]
mod tests;

pub type RegMap = HashMap<String, RegistryField>;

lazy_static! {
    /// Registry variable for the registry
    static ref REGISTRY: RwLock<RegMap> = RwLock::new(HashMap::new());
}

/// Error types that can happen
#[derive(Debug, PartialEq)]
pub enum RegistryError {
    /// The registry key was not found
    KeyNotFound,
    /// The registry key was of the wrong type
    WrongKeyType,
    /// Attempting to set a readonly value
    InvalidOperation,
}

/// Result type of gets/sets to the registry
pub type RegistryResult<T> = Result<T, RegistryError>;

/// Initialize the registry (register default commands)
pub fn init() {
    commands::register_defaults();
}

/// Acquires a read lock on the registry.
pub fn read_lock<'a>() -> RwLockReadGuard<'a, RegMap> {
    REGISTRY.read().expect("Unable to read from registry!")
}

/// Acquires a write lock on the registry.
pub fn write_lock<'a>() -> RwLockWriteGuard<'a, RegMap> {
    REGISTRY.write().expect("Unable to write to registry!")
}

/// Gets a RegistryField enum with the specified name
pub fn get_field(name: &str) -> Option<RegistryField> {
    // clone() will either clone an Arc or an Arc+AccessFlags
    let result = read_lock().get(name).map(|v| v.clone());
    trace!("get: {} => {:?}", name, &result);
    return result;
}

/// Attempts to get a command from the registry.
pub fn get_command(name: &str) -> RegistryResult<CommandFn> {
    get_field(name).ok_or(RegistryError::KeyNotFound)
        .and_then(|val| match val {
        RegistryField::Command(com) => Ok(com),
        _ => Err(RegistryError::WrongKeyType)
    })
}

/// Gets a data type from the registry, returning a reference to the property
/// method if the field is a property.
pub fn get_data(name: &str) -> RegistryResult<RegistryGetData> {
    get_field(name).ok_or(RegistryError::KeyNotFound)
        .and_then(|val| match val {
            RegistryField::Object { flags, data } =>
                Ok(RegistryGetData::Object(flags, data)),
            RegistryField::Property { get: maybe_get, .. } =>
                match maybe_get {
                    Some(get) => Ok(RegistryGetData::Property(get)),
                    None => Err(RegistryError::InvalidOperation)
                },
            _ => Err(RegistryError::WrongKeyType)
        })
}

/// Get a Rust structure from the registry
#[allow(dead_code)]
pub fn get_struct<T>(name: &str)
                     -> RegistryResult<(AccessFlags, Result<T, DecoderError>)>
where T: Decodable {
    get_json(name).map(|(flags, json)|
        (flags, T::decode(&mut Decoder::new(json.deref().clone()))))
}

/// Get Json data from the registry, evaluating if a property was found.
pub fn get_json(name: &str) -> RegistryResult<(AccessFlags, Arc<Json>)> {
    get_data(name).map(|val| val.resolve())
}

/// Set a value to the given registry field.
pub fn set_field(key: String, value: RegistryField)
                 -> RegistryResult<Option<RegistryField>> {
    let mut reg = write_lock();
    match reg.entry(key) {
        Entry::Occupied(mut entry) => {
            let first_type = entry.get().get_type();
            if first_type.can_set_from(value.get_type()) {
                Ok(Some(entry.insert(value)))
            }
            else {
                Err(RegistryError::WrongKeyType)
            }
        },
        Entry::Vacant(vacancy) => {
            vacancy.insert(value);
            Ok(None)
        }
    }
}

/// Set a command to the given Command
#[allow(dead_code)]
pub fn set_command(key: String, command: CommandFn)
                   -> RegistryResult<Option<CommandFn>> {
    set_field(key, RegistryField::Command(command))
        .map(|maybe_field|
              maybe_field.and_then(|field|
                                    field.get_command()))
}

/// Set a value to the given JSON value.
#[allow(dead_code)]
pub fn set_json(key: String, flags: AccessFlags, json: Json)
                -> RegistryResult<Option<(AccessFlags, Arc<Json>)>> {
    let mut reg = write_lock();
    match reg.entry(key) {
        Entry::Vacant(vacancy) => {
            vacancy.insert(RegistryField::Object {
                flags: flags, data: Arc::new(json)
            });
            return Ok(None);
        },
        Entry::Occupied(mut entry) => {
            let first_type = entry.get().get_type();
            if first_type == FieldType::Object {
                return Ok(entry.insert(RegistryField::Object {
                    flags: flags, data: Arc::new(json)
                }).as_object());
            }
            else if first_type == FieldType::Property {
                match entry.get().clone().as_property_set() {
                    Some(func) => {
                        func(json);
                        return Ok(None);
                    }
                    None => return Err(RegistryError::InvalidOperation)
                }
            }
            else {
                return Err(RegistryError::WrongKeyType);
            }
        }
    }
    return Ok(None);
}

/// Set an object/property in the registry to a value using a ToJson.
#[allow(dead_code)]
pub fn set_struct<T: ToJson>(key: String, flags: AccessFlags, value: T)
                             -> RegistryResult<Option<(AccessFlags, Arc<Json>)>> {
    set_json(key, flags, value.to_json())
}

/// Sets a value for a given Json value, optionally returning the associated property.
#[allow(dead_code)]
pub fn set_with_property(key: String, flags: AccessFlags, json: Json)
                         -> RegistryResult<Option<(Json, SetFn)>> {
    let mut reg = write_lock();
    match reg.entry(key) {
        Entry::Vacant(vacancy) => {
            vacancy.insert(RegistryField::Object {
                flags: flags, data: Arc::new(json)
            });
            Ok(None)
        },
        Entry::Occupied(mut entry) => {
            let first_type = entry.get().get_type();
            if first_type == FieldType::Object {
                entry.insert(RegistryField::Object {
                    flags: flags, data: Arc::new(json)
                });
                Ok(None)
            }
            else if first_type == FieldType::Property {
                Ok(Some((json, entry.get().clone().as_property_set()
                   .expect("set_json_property: checked value of field type"))))
            }
            else {
                Err(RegistryError::WrongKeyType)
            }
        }
    }
}

/// Binds properties to a field of the registry
#[allow(dead_code)]
pub fn set_property_field(key: String, get_fn: Option<GetFn>, set_fn: Option<SetFn>)
                          -> RegistryResult<Option<RegistryField>> {
    set_field(key, RegistryField::Property { get: get_fn, set: set_fn })
}

/// Whether this map contains a key of any type
#[allow(dead_code)]
pub fn contains_key<K>(key: &K) -> bool
where String: Borrow<K>, K: Hash + Eq + Display {
    trace!("contains_key: {}", *key);
    let read_reg = read_lock();
    read_reg.contains_key(key)
}

/// Whether the registry contains a key of some type:
/// None: no key
/// true: same type key
/// false: different type key
#[allow(dead_code)]
pub fn contains_key_of<K>(key: &K, field_type: FieldType) -> Option<bool>
where String: Borrow<K>, K: Hash + Eq + Display {
    let read_reg = read_lock();
    read_reg.get(key).map(|field| field.get_type() == field_type)
}
<|endoftext|>


<commit_before><commit_msg>Add test for another file<commit_after><|endoftext|>


<commit_before>use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use parking_lot::{RwLock};
use bifrost_hasher::{hash_str, hash_bytes};
use raft::{RaftService, IS_LEADER};
use rpc;
use utils::bincode;
use serde;
use super::super::{OpType};
use super::super::super::RaftMsg;
use super::*;

pub struct Subscriber {
    pub session_id: u64,
    pub client: Arc<AsyncServiceClient>
}

pub struct Subscriptions {
    next_id: u64,
    subscribers: HashMap<u64, Subscriber>,
    suber_subs: HashMap<u64, HashSet<u64>>, //suber_id -> sub_id
    subscriptions: HashMap<SubKey, HashSet<u64>>, // key -> sub_id
    sub_suber: HashMap<u64, u64>,
    sub_to_key: HashMap<u64, SubKey>, //sub_id -> sub_key
}

impl Subscriptions {

    pub fn new() -> Subscriptions {
        Subscriptions {
            next_id: 0,
            subscribers: HashMap::new(),
            suber_subs: HashMap::new(),
            subscriptions: HashMap::new(),
            sub_suber: HashMap::new(),
            sub_to_key: HashMap::new(),
        }
    }

    pub fn subscribe(&mut self, key: SubKey, address: &String, session_id: u64) -> Result<u64, ()> {
        let sub_service_id = DEFAULT_SERVICE_ID;
        let suber_id = hash_str(address);
        let suber_exists = self.subscribers.contains_key(&suber_id);
        let sub_id = self.next_id;
        let require_reload_suber = if suber_exists {
            let session_match = self.subscribers.get(&suber_id).unwrap().session_id == session_id;
            if !session_match {
                self.remove_subscriber(suber_id);
                true
            } else {false}
        } else {true};
        if !self.subscribers.contains_key(&suber_id) {
            self.subscribers.insert(suber_id, Subscriber {
                session_id: session_id,
                client: {
                    if let Ok(client) = rpc::DEFAULT_CLIENT_POOL.get(address) {
                        AsyncServiceClient::new(sub_service_id, &client)
                    } else {
                        return Err(());
                    }
                }
            });
        }
        self.suber_subs.entry(suber_id).or_insert_with(|| HashSet::new()).insert(sub_id);
        self.subscriptions.entry(key).or_insert_with(|| HashSet::new()).insert(sub_id);
        self.sub_to_key.insert(sub_id, key);
        self.sub_suber.insert(sub_id, suber_id);

        self.next_id += 1;
        Ok(sub_id)
    }

    pub fn remove_subscriber(&mut self, suber_id: u64) {
        let suber_subs = if let Some(sub_ids) = self.suber_subs.get(&suber_id) {
            sub_ids.iter().cloned().collect()
        } else {Vec::<u64>::new()};
        for subs_id in suber_subs {
            self.remove_subscription(subs_id)
        }
        self.subscribers.remove(&suber_id);
        self.suber_subs.remove(&suber_id);
    }

    pub fn remove_subscription(&mut self, id: u64) {
        let sub_key = self.sub_to_key.remove(&id);
        if let Some(sub_key) = sub_key {
            if let Some(ref mut sub_subers) = self.subscriptions.get_mut(&sub_key) {
                sub_subers.remove(&id);
                self.sub_suber.remove(&id);
            }
        }
    }
}

pub struct SMCallback {
    pub subscriptions: Arc<RwLock<Subscriptions>>,
    pub raft_service: Arc<RaftService>,
    pub sm_id: u64,
}

#[derive(Debug, Clone, Copy)]
pub enum NotifyFailure {
    IsNotLeader,
    OpTypeNotSubscribe,
    CannotFindSubscription,
    CannotFindSubscribers,
    CannotFindSubscriber
}

impl SMCallback {
    pub fn new(state_machine_id: u64, raft_service: Arc<RaftService>) -> SMCallback {
        let meta = raft_service.meta.read();
        let sm = meta.state_machine.read();
        let subs = sm.configs.subscriptions.clone();
        SMCallback {
            subscriptions: subs,
            raft_service: raft_service.clone(),
            sm_id: state_machine_id,
        }
    }

    pub fn notify<R>(&self, func: &RaftMsg<R>, data: R)
        -> Result<(usize, Vec<NotifyFailure>, Vec<Result<Result<(), ()>, rpc::RPCError>>), NotifyFailure>
        where R: serde::Serialize + Send + Sync {
        if !IS_LEADER.get() {return Err(NotifyFailure::IsNotLeader);}
        let (fn_id, op_type, pattern_data) = func.encode();
        match op_type {
            OpType::SUBSCRIBE => {
                let pattern_id = hash_bytes(&pattern_data.as_slice());
                let raft_sid = self.raft_service.options.service_id;
                let sm_id = self.sm_id;
                let key = (raft_sid, sm_id, fn_id, pattern_id);
                let svr_subs = self.subscriptions.read();
                debug!("Subs key: {:?}", svr_subs.subscriptions.keys());
                debug!("Looking for: {:?}", &key);
                if let Some(sub_ids) = svr_subs.subscriptions.get(&key) {
                    let data = bincode::serialize(&data);
                    let sub_result: Vec<_> = sub_ids.iter().map(|sub_id| {
                        if let Some(subscriber_id) = svr_subs.sub_suber.get(&sub_id) {
                            if let Some(subscriber) = svr_subs.subscribers.get(&subscriber_id) {
                                let data = data.clone();
                                let client = subscriber.client.clone();
                                Ok(client.notify(&key, &data))
                            } else {
                                Err(NotifyFailure::CannotFindSubscriber)
                            }
                        } else {
                            Err(NotifyFailure::CannotFindSubscribers)
                        }
                    }).collect();
                    let errors = sub_result.iter()
                        .filter(|r| r.is_err())
                        .map(|r| {if let &Err(e) = r { Some(e) } else { None }})
                        .map(|o| o.clone().unwrap())
                        .collect::<Vec<NotifyFailure>>();
                    let response = sub_result.into_iter()
                        .filter(|r| r.is_ok())
                        .map(|r| r.unwrap())
                        .map(|req| req.wait())
                        .collect::<Vec<_>>();
                    return Ok((sub_ids.len(), errors, response));
                } else {
                    return Err(NotifyFailure::CannotFindSubscription)
                }
            },
            _ => {
                return Err(NotifyFailure::OpTypeNotSubscribe)
            }
        }
    }
}

pub fn notify<R, F>(callback: &Option<SMCallback>, func: &RaftMsg<R>, data: F)
    where F: Fn() -> R,
          R: serde::Serialize + Send + Sync {
    if let Some(ref callback) = *callback {
        callback.notify(func, data());
    }
}<commit_msg>still catching<commit_after>use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use parking_lot::{RwLock};
use bifrost_hasher::{hash_str, hash_bytes};
use raft::{RaftService, IS_LEADER};
use rpc;
use utils::bincode;
use serde;
use super::super::{OpType};
use super::super::super::RaftMsg;
use super::*;

pub struct Subscriber {
    pub session_id: u64,
    pub client: Arc<AsyncServiceClient>
}

pub struct Subscriptions {
    next_id: u64,
    subscribers: HashMap<u64, Subscriber>,
    suber_subs: HashMap<u64, HashSet<u64>>, //suber_id -> sub_id
    subscriptions: HashMap<SubKey, HashSet<u64>>, // key -> sub_id
    sub_suber: HashMap<u64, u64>,
    sub_to_key: HashMap<u64, SubKey>, //sub_id -> sub_key
}

impl Subscriptions {

    pub fn new() -> Subscriptions {
        Subscriptions {
            next_id: 0,
            subscribers: HashMap::new(),
            suber_subs: HashMap::new(),
            subscriptions: HashMap::new(),
            sub_suber: HashMap::new(),
            sub_to_key: HashMap::new(),
        }
    }

    pub fn subscribe(&mut self, key: SubKey, address: &String, session_id: u64) -> Result<u64, ()> {
        let sub_service_id = DEFAULT_SERVICE_ID;
        let suber_id = hash_str(address);
        let suber_exists = self.subscribers.contains_key(&suber_id);
        let sub_id = self.next_id;
        let require_reload_suber = if suber_exists {
            let session_match = self.subscribers.get(&suber_id).unwrap().session_id == session_id;
            if !session_match {
                self.remove_subscriber(suber_id);
                true
            } else {false}
        } else {true};
        if !self.subscribers.contains_key(&suber_id) {
            self.subscribers.insert(suber_id, Subscriber {
                session_id: session_id,
                client: {
                    if let Ok(client) = rpc::DEFAULT_CLIENT_POOL.get(address) {
                        AsyncServiceClient::new(sub_service_id, &client)
                    } else {
                        return Err(());
                    }
                }
            });
        }
        self.suber_subs.entry(suber_id).or_insert_with(|| HashSet::new()).insert(sub_id);
        self.subscriptions.entry(key).or_insert_with(|| HashSet::new()).insert(sub_id);
        self.sub_to_key.insert(sub_id, key);
        self.sub_suber.insert(sub_id, suber_id);

        self.next_id += 1;
        Ok(sub_id)
    }

    pub fn remove_subscriber(&mut self, suber_id: u64) {
        let suber_subs = if let Some(sub_ids) = self.suber_subs.get(&suber_id) {
            sub_ids.iter().cloned().collect()
        } else {Vec::<u64>::new()};
        for subs_id in suber_subs {
            self.remove_subscription(subs_id)
        }
        self.subscribers.remove(&suber_id);
        self.suber_subs.remove(&suber_id);
    }

    pub fn remove_subscription(&mut self, id: u64) {
        let sub_key = self.sub_to_key.remove(&id);
        if let Some(sub_key) = sub_key {
            if let Some(ref mut sub_subers) = self.subscriptions.get_mut(&sub_key) {
                sub_subers.remove(&id);
                self.sub_suber.remove(&id);
            }
        }
    }
}

pub struct SMCallback {
    pub subscriptions: Arc<RwLock<Subscriptions>>,
    pub raft_service: Arc<RaftService>,
    pub sm_id: u64,
}

#[derive(Debug, Clone, Copy)]
pub enum NotifyFailure {
    IsNotLeader,
    OpTypeNotSubscribe,
    CannotFindSubscription,
    CannotFindSubscribers,
    CannotFindSubscriber
}

impl SMCallback {
    pub fn new(state_machine_id: u64, raft_service: Arc<RaftService>) -> SMCallback {
        let meta = raft_service.meta.read();
        let sm = meta.state_machine.read();
        let subs = sm.configs.subscriptions.clone();
        SMCallback {
            subscriptions: subs,
            raft_service: raft_service.clone(),
            sm_id: state_machine_id,
        }
    }

    pub fn notify<R>(&self, func: &RaftMsg<R>, data: R)
        -> Result<(usize, Vec<NotifyFailure>, Vec<Result<Result<(), ()>, rpc::RPCError>>), NotifyFailure>
        where R: serde::Serialize + Send + Sync {
        if !IS_LEADER.get() {return Err(NotifyFailure::IsNotLeader);}
        let (fn_id, op_type, pattern_data) = func.encode();
        match op_type {
            OpType::SUBSCRIBE => {
                let pattern_id = hash_bytes(&pattern_data.as_slice());
                let raft_sid = self.raft_service.options.service_id;
                let sm_id = self.sm_id;
                let key = (raft_sid, sm_id, fn_id, pattern_id);
                let svr_subs = self.subscriptions.read();
                println!("Subs key: {:?}", svr_subs.subscriptions.keys());
                println!("Looking for: {:?}", &key);
                if let Some(sub_ids) = svr_subs.subscriptions.get(&key) {
                    let data = bincode::serialize(&data);
                    let sub_result: Vec<_> = sub_ids.iter().map(|sub_id| {
                        if let Some(subscriber_id) = svr_subs.sub_suber.get(&sub_id) {
                            if let Some(subscriber) = svr_subs.subscribers.get(&subscriber_id) {
                                let data = data.clone();
                                let client = subscriber.client.clone();
                                Ok(client.notify(&key, &data))
                            } else {
                                Err(NotifyFailure::CannotFindSubscriber)
                            }
                        } else {
                            Err(NotifyFailure::CannotFindSubscribers)
                        }
                    }).collect();
                    let errors = sub_result.iter()
                        .filter(|r| r.is_err())
                        .map(|r| {if let &Err(e) = r { Some(e) } else { None }})
                        .map(|o| o.clone().unwrap())
                        .collect::<Vec<NotifyFailure>>();
                    let response = sub_result.into_iter()
                        .filter(|r| r.is_ok())
                        .map(|r| r.unwrap())
                        .map(|req| req.wait())
                        .collect::<Vec<_>>();
                    return Ok((sub_ids.len(), errors, response));
                } else {
                    return Err(NotifyFailure::CannotFindSubscription)
                }
            },
            _ => {
                return Err(NotifyFailure::OpTypeNotSubscribe)
            }
        }
    }
}

pub fn notify<R, F>(callback: &Option<SMCallback>, func: &RaftMsg<R>, data: F)
    where F: Fn() -> R,
          R: serde::Serialize + Send + Sync {
    if let Some(ref callback) = *callback {
        callback.notify(func, data());
    }
}<|endoftext|>