<commit_before>// Copyright (C) 2013-2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#![crate_name = "gobject_2_0_sys"]
#![crate_type = "lib"]

#![allow(missing_copy_implementations)]

extern crate glib_2_0_sys as glib;

use glib::types::{gboolean, gchar, gdouble, gfloat, gint, glong};
use glib::types::{gsize, guchar, guint, gulong};
use glib::types::{gpointer, gconstpointer};

pub type GType = gsize;

#[repr(C)]
pub struct GTypeInstance {
    g_class: gpointer
}

#[repr(C)]
pub struct GObject {
    g_type_instance: GTypeInstance,
    ref_count: guint,
    data: gpointer
}

#[repr(C)]
pub struct GValue {
    pub g_type: GType,
    // If the data enum layout turns out to be different on some arch,
    // we'd need arch-specific redefinitions
    data: [u64; 2]
}

pub type GBoxedCopyFunc = extern "C" fn (gpointer) -> gpointer;
pub type GBoxedFreeFunc = extern "C" fn (gpointer);

extern {
    pub fn g_boxed_type_register_static(name: *const gchar, boxed_copy: GBoxedCopyFunc, boxed_free: GBoxedFreeFunc) -> GType;
    pub fn g_error_get_type() -> GType;
    pub fn g_main_context_get_type() -> GType;
    pub fn g_main_loop_get_type() -> GType;
    pub fn g_object_get_type() -> GType;
    pub fn g_object_ref(obj: gpointer) -> gpointer;
    pub fn g_object_unref(obj: gpointer);
    pub fn g_strdup_value_contents(value: *const GValue) -> *mut gchar;
    pub fn g_type_check_instance_is_a(instance: *const GTypeInstance, iface_type: GType) -> gboolean;
    pub fn g_type_from_name(name: *const gchar) -> GType;
    pub fn g_type_name(t: GType) -> *const gchar;
    pub fn g_value_copy(src: *const GValue, dst: *mut GValue);
    pub fn g_value_get_boolean(value: *const GValue) -> gboolean;
    pub fn g_value_get_boxed(value: *const GValue) -> gpointer;
    pub fn g_value_get_char(value: *const GValue) -> gchar;
    pub fn g_value_get_double(value: *const GValue) -> gdouble;
    pub fn g_value_get_enum(value: *const GValue) -> gint;
    pub fn g_value_get_flags(value: *const GValue) -> guint;
    pub fn g_value_get_float(value: *const GValue) -> gfloat;
    pub fn g_value_get_int(value: *const GValue) -> gint;
    pub fn g_value_get_int64(value: *const GValue) -> i64;
    pub fn g_value_get_long(value: *const GValue) -> glong;
    pub fn g_value_get_object(value: *const GValue) -> gpointer;
    pub fn g_value_get_schar(value: *const GValue) -> i8;
    pub fn g_value_get_string(value: *const GValue) -> *const gchar;
    pub fn g_value_get_uchar(value: *const GValue) -> guchar;
    pub fn g_value_get_uint(value: *const GValue) -> guint;
    pub fn g_value_get_uint64(value: *const GValue) -> u64;
    pub fn g_value_get_ulong(value: *const GValue) -> gulong;
    pub fn g_value_dup_boxed(value: *const GValue) -> gpointer;
    pub fn g_value_init(value: *mut GValue, type_id: GType) -> *mut GValue;
    pub fn g_value_reset(value: *mut GValue) -> *mut GValue;
    pub fn g_value_set_boolean(value: *mut GValue, v_boolean: gboolean);
    pub fn g_value_set_char(value: *mut GValue, v_char: gchar);
    pub fn g_value_set_double(value: *mut GValue, v_double: gdouble);
    pub fn g_value_set_enum(value: *mut GValue, v_enum: gint);
    pub fn g_value_set_flags(value: *mut GValue, v_enum: guint);
    pub fn g_value_set_float(value: *mut GValue, v_float: gfloat);
    pub fn g_value_set_int(value: *mut GValue, v_int: gint);
    pub fn g_value_set_int64(value: *mut GValue, v_int: i64);
    pub fn g_value_set_long(value: *mut GValue, v_long: glong);
    pub fn g_value_set_object(value: *mut GValue, v_object: gpointer);
    pub fn g_value_set_schar(value: *mut GValue, v_char: i8);
    pub fn g_value_set_string(value: *mut GValue, v_string: *const gchar);
    pub fn g_value_set_static_string(value: *mut GValue, v_string: *const gchar);
    pub fn g_value_set_uchar(value: *mut GValue, v_char: guchar);
    pub fn g_value_set_uint(value: *mut GValue, v_uint: guint);
    pub fn g_value_set_uint64(value: *mut GValue, v_uint: u64);
    pub fn g_value_set_ulong(value: *mut GValue, v_ulong: gulong);
    pub fn g_value_take_boxed(value: *mut GValue, v_boxed: gconstpointer);
    pub fn g_value_take_string(value: *mut GValue, v_string: *mut gchar);
    pub fn g_value_unset(value: *mut GValue);
}
<commit_msg>Added g_source_get_type()<commit_after>// Copyright (C) 2013-2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#![crate_name = "gobject_2_0_sys"]
#![crate_type = "lib"]

#![allow(missing_copy_implementations)]

extern crate glib_2_0_sys as glib;

use glib::types::{gboolean, gchar, gdouble, gfloat, gint, glong};
use glib::types::{gsize, guchar, guint, gulong};
use glib::types::{gpointer, gconstpointer};

pub type GType = gsize;

#[repr(C)]
pub struct GTypeInstance {
    g_class: gpointer
}

#[repr(C)]
pub struct GObject {
    g_type_instance: GTypeInstance,
    ref_count: guint,
    data: gpointer
}

#[repr(C)]
pub struct GValue {
    pub g_type: GType,
    // If the data enum layout turns out to be different on some arch,
    // we'd need arch-specific redefinitions
    data: [u64; 2]
}

pub type GBoxedCopyFunc = extern "C" fn (gpointer) -> gpointer;
pub type GBoxedFreeFunc = extern "C" fn (gpointer);

extern {
    pub fn g_boxed_type_register_static(name: *const gchar, boxed_copy: GBoxedCopyFunc, boxed_free: GBoxedFreeFunc) -> GType;
    pub fn g_error_get_type() -> GType;
    pub fn g_main_context_get_type() -> GType;
    pub fn g_main_loop_get_type() -> GType;
    pub fn g_object_get_type() -> GType;
    pub fn g_object_ref(obj: gpointer) -> gpointer;
    pub fn g_object_unref(obj: gpointer);
    pub fn g_source_get_type() -> GType;
    pub fn g_strdup_value_contents(value: *const GValue) -> *mut gchar;
    pub fn g_type_check_instance_is_a(instance: *const GTypeInstance, iface_type: GType) -> gboolean;
    pub fn g_type_from_name(name: *const gchar) -> GType;
    pub fn g_type_name(t: GType) -> *const gchar;
    pub fn g_value_copy(src: *const GValue, dst: *mut GValue);
    pub fn g_value_get_boolean(value: *const GValue) -> gboolean;
    pub fn g_value_get_boxed(value: *const GValue) -> gpointer;
    pub fn g_value_get_char(value: *const GValue) -> gchar;
    pub fn g_value_get_double(value: *const GValue) -> gdouble;
    pub fn g_value_get_enum(value: *const GValue) -> gint;
    pub fn g_value_get_flags(value: *const GValue) -> guint;
    pub fn g_value_get_float(value: *const GValue) -> gfloat;
    pub fn g_value_get_int(value: *const GValue) -> gint;
    pub fn g_value_get_int64(value: *const GValue) -> i64;
    pub fn g_value_get_long(value: *const GValue) -> glong;
    pub fn g_value_get_object(value: *const GValue) -> gpointer;
    pub fn g_value_get_schar(value: *const GValue) -> i8;
    pub fn g_value_get_string(value: *const GValue) -> *const gchar;
    pub fn g_value_get_uchar(value: *const GValue) -> guchar;
    pub fn g_value_get_uint(value: *const GValue) -> guint;
    pub fn g_value_get_uint64(value: *const GValue) -> u64;
    pub fn g_value_get_ulong(value: *const GValue) -> gulong;
    pub fn g_value_dup_boxed(value: *const GValue) -> gpointer;
    pub fn g_value_init(value: *mut GValue, type_id: GType) -> *mut GValue;
    pub fn g_value_reset(value: *mut GValue) -> *mut GValue;
    pub fn g_value_set_boolean(value: *mut GValue, v_boolean: gboolean);
    pub fn g_value_set_char(value: *mut GValue, v_char: gchar);
    pub fn g_value_set_double(value: *mut GValue, v_double: gdouble);
    pub fn g_value_set_enum(value: *mut GValue, v_enum: gint);
    pub fn g_value_set_flags(value: *mut GValue, v_enum: guint);
    pub fn g_value_set_float(value: *mut GValue, v_float: gfloat);
    pub fn g_value_set_int(value: *mut GValue, v_int: gint);
    pub fn g_value_set_int64(value: *mut GValue, v_int: i64);
    pub fn g_value_set_long(value: *mut GValue, v_long: glong);
    pub fn g_value_set_object(value: *mut GValue, v_object: gpointer);
    pub fn g_value_set_schar(value: *mut GValue, v_char: i8);
    pub fn g_value_set_string(value: *mut GValue, v_string: *const gchar);
    pub fn g_value_set_static_string(value: *mut GValue, v_string: *const gchar);
    pub fn g_value_set_uchar(value: *mut GValue, v_char: guchar);
    pub fn g_value_set_uint(value: *mut GValue, v_uint: guint);
    pub fn g_value_set_uint64(value: *mut GValue, v_uint: u64);
    pub fn g_value_set_ulong(value: *mut GValue, v_ulong: gulong);
    pub fn g_value_take_boxed(value: *mut GValue, v_boxed: gconstpointer);
    pub fn g_value_take_string(value: *mut GValue, v_string: *mut gchar);
    pub fn g_value_unset(value: *mut GValue);
}
<|endoftext|>


<commit_before>#![feature(box_syntax)]
#![feature(fnbox)]
#![feature(box_raw)]
#![feature(drain)]
#![feature(result_expect)]
#![feature(catch_panic)]

//! Ferrous Threads Crate
//!
//! This crate contains a number of different structs and functions that are of use
//! when attempting to do concurrent/parallel programming.
//!
//! This includes a thread pool, a multi-producer/multi-consumer queue, a task runner, and
//! a publish/subscribe queue.

extern crate canal;

pub mod task_runner;
pub mod thread_pool;
<commit_msg>box_raw is stable on nightly<commit_after>#![feature(box_syntax)]
#![feature(fnbox)]
#![feature(drain)]
#![feature(result_expect)]
#![feature(catch_panic)]

//! Ferrous Threads Crate
//!
//! This crate contains a number of different structs and functions that are of use
//! when attempting to do concurrent/parallel programming.
//!
//! This includes a thread pool, a multi-producer/multi-consumer queue, a task runner, and
//! a publish/subscribe queue.

extern crate canal;

pub mod task_runner;
pub mod thread_pool;
<|endoftext|>


<commit_before>extern crate hyper;
extern crate url;
extern crate rustc_serialize;

use std::io::{Read, Write};
use hyper::client::Request;
use hyper::method::Method;
use hyper::net::Fresh;
use rustc_serialize::{Decodable, json};

#[doc(no_inline)]
pub use hyper::header::*;
#[doc(no_inline)]
pub use url::Url;
#[doc(no_inline)]
pub use hyper::error::Error;

#[derive(Clone)]
pub struct RestClient<'a> {
    url: Url,
    params: Option<Vec<(&'a str, &'a str)>>,
    body: Option<String>,
    headers: Option<Headers>,
}

impl<'a> RestClient<'a> {
    /// Constructs a new RestClient.
    pub fn new(url: Url) -> RestClient<'a> {
        RestClient { url: url, params: None, body: None, headers: None }
    }

    /// Sets one parameter. On a GET or DELETE request, this parameter will
    /// be stored in the URL. On a POST or PUT request, it is stored in the
    /// body of the request. Hence, if you call this method on a POST or
    /// PUT request, you cannot also call `body`.
    pub fn param(&'a mut self, key: &'a str, value: &'a str) -> &'a mut RestClient<'a> {
        if let Some(ref mut p) = self.params {
            p.push((key, value));
        }
        else
        {
            let mut v = Vec::new();
            v.push((key, value));
            self.params = Some(v);
        }
        self
    }

    /// Writes a `String` to the body of the request. Don't call this
    /// method if you also call `param` on a PUT or POST request.
    pub fn body(&'a mut self, body: String) -> &'a mut RestClient<'a> {
        self.body = Some(body);
        self
    }

    /// Sets a header for the request.
    pub fn header<H: Header + HeaderFormat>(&'a mut self, header: H) -> &'a mut RestClient<'a> {
        if let Some(ref mut h) = self.headers {
            h.set(header);
        }
        else
        {
            let mut v = Headers::new();
            v.set(header);
            self.headers = Some(v);
        }
        self
    }

    fn send_request(&mut self, mut req: Request<Fresh>) -> Result<String, Error> {
        if let Some(headers) = self.headers.as_ref() {
            req.headers_mut().extend(headers.iter());
        }

        let mut req = try!(req.start());

        if let Some(body) = self.body.as_ref() {
           try!(req.write_all(body.as_bytes()));
        }

        let mut resp = try!(req.send());

        let mut response_string = String::new();
        try!(resp.read_to_string(&mut response_string));
        Ok(response_string)
    }

    /// Sends a GET request and returns either an error
    /// or a `String` of the response.
    pub fn get(&mut self) -> Result<String, hyper::Error> {
        let mut url = self.url.clone();

        if let Some(ref params) = self.params {
            url.set_query_from_pairs(params.into_iter().map(|&x| x));
        }

        let req = try!(Request::new(Method::Get, url));
        self.send_request(req)
    }

    /// Sends a GET request and returns either an error
    /// or a `T` representing the response, deserialised from JSON.
    pub fn get_json_as<T: Decodable>(&mut self) -> Result<T, String> {
        let body = try!(self.get().map_err(|err| err.to_string()));
        json::decode(&*body).map_err(|err| err.to_string())
    }

    /// Sends a DELETE request and returns either an error
    /// or a `String` of the response.
    pub fn delete(&mut self) -> Result<String, Error> {
        let mut url = self.url.clone();

        if let Some(ref params) = self.params {
            url.set_query_from_pairs(params.into_iter().map(|&x| x));
        }

        let req = try!(Request::new(Method::Delete, url));
        self.send_request(req)
    }

    /// Sends a DELETE request and returns either an error
    /// or a `T` representing the response, deserialised from JSON.
    pub fn delete_json_as<T: Decodable>(&mut self) -> Result<T, String> {
        let body = try!(self.delete().map_err(|err| err.to_string()));
        json::decode(&*body).map_err(|err| err.to_string())
    }

    /// Sends a POST request and returns either an error
    /// or a `String` of the response.
    pub fn post(&mut self) -> Result<String, Error> {
        let url = self.url.clone();

        if let Some(ref params) = self.params {
            self.body = Some(url::form_urlencoded::serialize(params.into_iter()));
        }

        let req = try!(Request::new(Method::Post, url));
        self.send_request(req)
    }

    /// Sends a POST request and returns either an error
    /// or a `T` representing the response, deserialised from JSON.
    pub fn post_json_as<T: Decodable>(&mut self) -> Result<T, String> {
        let body = try!(self.post().map_err(|err| err.to_string()));
        json::decode(&*body).map_err(|err| err.to_string())
    }

    /// Sends a PUT request and returns either an error
    /// or a `String` of the response.
    pub fn put(&mut self) -> Result<String, Error> {
        let url = self.url.clone();

        if let Some(ref params) = self.params {
            self.body = Some(url::form_urlencoded::serialize(params.into_iter()));
        }

        let req = try!(Request::new(Method::Put, url));
        self.send_request(req)
    }

    /// Sends a PUT request and returns either an error
    /// or a `T` representing the response, deserialised from JSON.
    pub fn put_json_as<T: Decodable>(&mut self) -> Result<T, String> {
        let body = try!(self.put().map_err(|err| err.to_string()));
        json::decode(&*body).map_err(|err| err.to_string())
    }
}
<commit_msg>Make it possible to add many parameters.<commit_after>extern crate hyper;
extern crate url;
extern crate rustc_serialize;

use std::io::{Read, Write};
use hyper::client::Request;
use hyper::method::Method;
use hyper::net::Fresh;
use rustc_serialize::{Decodable, json};

#[doc(no_inline)]
pub use hyper::header::*;
#[doc(no_inline)]
pub use url::Url;
#[doc(no_inline)]
pub use hyper::error::Error;

#[derive(Clone)]
pub struct RestClient<'a> {
    url: Url,
    params: Option<Vec<(&'a str, &'a str)>>,
    body: Option<String>,
    headers: Option<Headers>,
}

impl<'a> RestClient<'a> {
    /// Constructs a new RestClient.
    pub fn new(url: Url) -> RestClient<'a> {
        RestClient { url: url, params: None, body: None, headers: None }
    }

    /// Sets one parameter. On a GET or DELETE request, this parameter will
    /// be stored in the URL. On a POST or PUT request, it is stored in the
    /// body of the request. Hence, if you call this method on a POST or
    /// PUT request, you cannot also call `body`.
    pub fn param(&'a mut self, key: &'a str, value: &'a str) -> &'a mut RestClient<'a> {
        if let Some(ref mut p) = self.params {
            p.push((key, value));
        }
        else
        {
            let mut v = Vec::new();
            v.push((key, value));
            self.params = Some(v);
        }
        self
    }

    /// Sets many parameters. On a GET or DELETE request, these parameters will
    /// be stored in the URL. On a POST or PUT request, they are stored in the
    /// body of the request. Hence, if you call this method on a POST or
    /// PUT request, you cannot also call `body`.
    pub fn params<T>(&'a mut self, values: T)
        -> &'a mut RestClient<'a>
        where T: IntoIterator<Item=(&'a str, &'a str)> {
        if let Some(ref mut p) = self.params {
            for value in values {
                p.push(value);
            }
        }
        else
        {
            let mut v = Vec::new();
            for value in values {
                v.push(value);
            }
            self.params = Some(v);
        }
        self
    }

    /// Writes a `String` to the body of the request. Don't call this
    /// method if you also call `param` on a PUT or POST request.
    pub fn body(&'a mut self, body: String) -> &'a mut RestClient<'a> {
        self.body = Some(body);
        self
    }

    /// Sets a header for the request.
    pub fn header<H: Header + HeaderFormat>(&'a mut self, header: H) -> &'a mut RestClient<'a> {
        if let Some(ref mut h) = self.headers {
            h.set(header);
        }
        else
        {
            let mut v = Headers::new();
            v.set(header);
            self.headers = Some(v);
        }
        self
    }

    fn send_request(&mut self, mut req: Request<Fresh>) -> Result<String, Error> {
        if let Some(headers) = self.headers.as_ref() {
            req.headers_mut().extend(headers.iter());
        }

        let mut req = try!(req.start());

        if let Some(body) = self.body.as_ref() {
           try!(req.write_all(body.as_bytes()));
        }

        let mut resp = try!(req.send());

        let mut response_string = String::new();
        try!(resp.read_to_string(&mut response_string));
        Ok(response_string)
    }

    /// Sends a GET request and returns either an error
    /// or a `String` of the response.
    pub fn get(&mut self) -> Result<String, hyper::Error> {
        let mut url = self.url.clone();

        if let Some(ref params) = self.params {
            url.set_query_from_pairs(params.into_iter().map(|&x| x));
        }

        let req = try!(Request::new(Method::Get, url));
        self.send_request(req)
    }

    /// Sends a GET request and returns either an error
    /// or a `T` representing the response, deserialised from JSON.
    pub fn get_json_as<T: Decodable>(&mut self) -> Result<T, String> {
        let body = try!(self.get().map_err(|err| err.to_string()));
        json::decode(&*body).map_err(|err| err.to_string())
    }

    /// Sends a DELETE request and returns either an error
    /// or a `String` of the response.
    pub fn delete(&mut self) -> Result<String, Error> {
        let mut url = self.url.clone();

        if let Some(ref params) = self.params {
            url.set_query_from_pairs(params.into_iter().map(|&x| x));
        }

        let req = try!(Request::new(Method::Delete, url));
        self.send_request(req)
    }

    /// Sends a DELETE request and returns either an error
    /// or a `T` representing the response, deserialised from JSON.
    pub fn delete_json_as<T: Decodable>(&mut self) -> Result<T, String> {
        let body = try!(self.delete().map_err(|err| err.to_string()));
        json::decode(&*body).map_err(|err| err.to_string())
    }

    /// Sends a POST request and returns either an error
    /// or a `String` of the response.
    pub fn post(&mut self) -> Result<String, Error> {
        let url = self.url.clone();

        if let Some(ref params) = self.params {
            self.body = Some(url::form_urlencoded::serialize(params.into_iter()));
        }

        let req = try!(Request::new(Method::Post, url));
        self.send_request(req)
    }

    /// Sends a POST request and returns either an error
    /// or a `T` representing the response, deserialised from JSON.
    pub fn post_json_as<T: Decodable>(&mut self) -> Result<T, String> {
        let body = try!(self.post().map_err(|err| err.to_string()));
        json::decode(&*body).map_err(|err| err.to_string())
    }

    /// Sends a PUT request and returns either an error
    /// or a `String` of the response.
    pub fn put(&mut self) -> Result<String, Error> {
        let url = self.url.clone();

        if let Some(ref params) = self.params {
            self.body = Some(url::form_urlencoded::serialize(params.into_iter()));
        }

        let req = try!(Request::new(Method::Put, url));
        self.send_request(req)
    }

    /// Sends a PUT request and returns either an error
    /// or a `T` representing the response, deserialised from JSON.
    pub fn put_json_as<T: Decodable>(&mut self) -> Result<T, String> {
        let body = try!(self.put().map_err(|err| err.to_string()));
        json::decode(&*body).map_err(|err| err.to_string())
    }
}
<|endoftext|>


<commit_before>//! Structured application logging.
//!
//! This module provides:
//!
//!  * The `emit!()` family of macros, for recording application events in an easily machine-readable format
//!  * Collectors for transmitting these events to back-end logging servers
//!
//! The widely-used `log` crate doesn't preserve the structure of the events that are written through it. For example:
//!
//! ```ignore
//! info!("Hello, {}!", env::var("USERNAME").unwrap());
//! ```
//!
//! This writes `"Hello, nblumhardt!"` to the log as an block of text, that can't be broken apart to reveal the username except
//! with regular expressions.
//!
//! The arguments passed to `emit` are named:
//!
//! ```no_run
//! emit!("Hello, {}!", user: env::var("USERNAME").unwrap());
//! ```
//!
//! This event can be rendered into text identically to the `log` example, but structured data collectors also capture the
//! aguments as a key/value property pairs.
//!
//! ```js
//! {
//!   "timestamp": "2016-03-17T00:17:01Z",
//!   "messageTemplate": "Hello, {name}!",
//!   "properties": {
//!     "name": "nblumhardt",
//!     "target": "example_app"
//!   }
//! }
//! ```
//!
//! Back-ends like Elasticsearch, Seq, and Splunk use these in queries like `user == "nblumhardt"` without up-front log parsing.
//!
//! Arguments are captured using `serde`, so there's the potential for complex values to be logged so long as they're `serde::ser::Serialize`.
//!
//! Further, because the template (format) itself is captured, it can be hashed to compute an "event type" for precisely finding
//! all occurrences of the event regardless of the value of the `user` argument.
//!
//! # Examples
//!
//! The example below writes events to stdout.
//!
//! ```
//! #[macro_use]
//! extern crate emit;
//!
//! use std::env;
//! use emit::pipeline;
//! use emit::collectors::stdio;
//!
//! fn main() {
//!     let _flush = pipeline::init(stdio::StdioCollector::new());
//!
//!     emit!("Hello, {}!", name: env::var("USERNAME").unwrap());
//! }
//! ```
//!
//! Output:
//!
//! ```text
//! emit 2016-03-24T05:03:36Z Hello, {name}!
//!   name: "nblumhardt"
//!   target: "example_app"
//!
//! ```

extern crate serde;
extern crate serde_json;
extern crate chrono;
extern crate hyper;

#[macro_use]
extern crate log;

pub mod message_templates;
pub mod events;
pub mod pipeline;
pub mod collectors;

#[macro_export]
#[doc(hidden)]
macro_rules! __emit_get_event_data {
    ($target:expr, $s:expr, $( $n:ident: $v:expr ),* ) => {{
        #[allow(unused_imports)]
        use std::fmt::Write;
        use std::collections;

        // Underscores avoid the unused_mut warning
        let mut _names: Vec<&str> = vec![];
        let mut properties: collections::BTreeMap<&'static str, String> = collections::BTreeMap::new();

        $(
            _names.push(stringify!($n));
            properties.insert(stringify!($n), $crate::message_templates::capture(&$v));
        )*

        properties.insert("target", $crate::message_templates::capture(&$target));

        let template = $crate::message_templates::build_template($s, &_names);

        (template, properties)
    }};
}

#[macro_export]
macro_rules! emit {
    ( target: $target:expr, $s:expr, $( $n:ident: $v:expr ),* ) => {{
        #[allow(unused_imports)]
        use log;
        log!(target: $target, log::LogLevel::Info, $s, $($v),*);
        let (template, properties) = __emit_get_event_data!($target, $s, $($n: $v),*);
        let event = $crate::events::Event::new_now(template, properties);
        $crate::pipeline::emit(event);
    }};

    ( target: $target:expr, $s:expr ) => {{
        emit!(target: $target, $s,);
    }};

    ( $s:expr, $( $n:ident: $v:expr ),* ) => {{
        emit!(target: module_path!(), $s, $($n: $v),*);
    }};

    ( $s:expr ) => {{
        emit!(target: module_path!(), $s,);
    }};
}

#[cfg(test)]
mod tests {
    use collectors::seq;
    use pipeline;
    use std::env;

    #[test]
    fn unparameterized_templates_are_captured() {
        let (template, properties) = __emit_get_event_data!("t", "Starting...",);
        assert!(template == "Starting...");
        assert!(properties.len() == 1);
    }

    #[test]
    fn template_and_properties_are_captured() {
        let u = "nblumhardt";
        let q = 42;

        let (template, properties) = __emit_get_event_data!("t", "User {} exceeded quota of {}!", user: u, quota: q);
        assert!(template == "User {user} exceeded quota of {quota}!");
        assert!(properties.get("user") == Some(&"\"nblumhardt\"".to_owned()));
        assert!(properties.get("quota") == Some(&"42".to_owned()));
        assert!(properties.len() == 3);
    }

    #[test]
    pub fn emitted_events_are_flushed() {
        let _flush = pipeline::init(seq::SeqCollector::new_local());
        emit!("Hello, {}!", name: env::var("USERNAME").unwrap());
    }
}
<commit_msg>Get rid of the callsite integration with log; going to add a collector to integrate for now (#7)<commit_after>//! Structured application logging.
//!
//! This module provides:
//!
//!  * The `emit!()` family of macros, for recording application events in an easily machine-readable format
//!  * Collectors for transmitting these events to back-end logging servers
//!
//! The widely-used `log` crate doesn't preserve the structure of the events that are written through it. For example:
//!
//! ```ignore
//! info!("Hello, {}!", env::var("USERNAME").unwrap());
//! ```
//!
//! This writes `"Hello, nblumhardt!"` to the log as an block of text, that can't be broken apart to reveal the username except
//! with regular expressions.
//!
//! The arguments passed to `emit` are named:
//!
//! ```ignore
//! emit!("Hello, {}!", user: env::var("USERNAME").unwrap());
//! ```
//!
//! This event can be rendered into text identically to the `log` example, but structured data collectors also capture the
//! aguments as a key/value property pairs.
//!
//! ```js
//! {
//!   "timestamp": "2016-03-17T00:17:01Z",
//!   "messageTemplate": "Hello, {name}!",
//!   "properties": {
//!     "name": "nblumhardt",
//!     "target": "example_app"
//!   }
//! }
//! ```
//!
//! Back-ends like Elasticsearch, Seq, and Splunk use these in queries like `user == "nblumhardt"` without up-front log parsing.
//!
//! Arguments are captured using `serde`, so there's the potential for complex values to be logged so long as they're `serde::ser::Serialize`.
//!
//! Further, because the template (format) itself is captured, it can be hashed to compute an "event type" for precisely finding
//! all occurrences of the event regardless of the value of the `user` argument.
//!
//! # Examples
//!
//! The example below writes events to stdout.
//!
//! ```
//! #[macro_use]
//! extern crate emit;
//!
//! use std::env;
//! use emit::pipeline;
//! use emit::collectors::stdio;
//!
//! fn main() {
//!     let _flush = pipeline::init(stdio::StdioCollector::new());
//!
//!     emit!("Hello, {}!", name: env::var("USERNAME").unwrap());
//! }
//! ```
//!
//! Output:
//!
//! ```text
//! emit 2016-03-24T05:03:36Z Hello, {name}!
//!   name: "nblumhardt"
//!   target: "example_app"
//!
//! ```

extern crate serde;
extern crate serde_json;
extern crate chrono;
extern crate hyper;

#[macro_use]
extern crate log;

pub mod message_templates;
pub mod events;
pub mod pipeline;
pub mod collectors;

#[macro_export]
#[doc(hidden)]
macro_rules! __emit_get_event_data {
    ($target:expr, $s:expr, $( $n:ident: $v:expr ),* ) => {{
        #[allow(unused_imports)]
        use std::fmt::Write;
        use std::collections;

        // Underscores avoid the unused_mut warning
        let mut _names: Vec<&str> = vec![];
        let mut properties: collections::BTreeMap<&'static str, String> = collections::BTreeMap::new();

        $(
            _names.push(stringify!($n));
            properties.insert(stringify!($n), $crate::message_templates::capture(&$v));
        )*

        properties.insert("target", $crate::message_templates::capture(&$target));

        let template = $crate::message_templates::build_template($s, &_names);

        (template, properties)
    }};
}

#[macro_export]
macro_rules! emit {
    (target: $target:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        let (template, properties) = __emit_get_event_data!($target, $s, $($n: $v),*);
        let event = $crate::events::Event::new_now(template, properties);
        $crate::pipeline::emit(event);
    }};

    ($s:expr, $($n:ident: $v:expr),*) => {{
        emit!(target: module_path!(), $s, $($n: $v),*);
    }};
}

#[cfg(test)]
mod tests {
    use collectors::stdio;
    use pipeline;
    use std::env;

    #[test]
    fn unparameterized_templates_are_captured() {
        let (template, properties) = __emit_get_event_data!("t", "Starting...",);
        assert!(template == "Starting...");
        assert!(properties.len() == 1);
    }

    #[test]
    fn template_and_properties_are_captured() {
        let u = "nblumhardt";
        let q = 42;

        let (template, properties) = __emit_get_event_data!("t", "User {} exceeded quota of {}!", user: u, quota: q);
        assert!(template == "User {user} exceeded quota of {quota}!");
        assert!(properties.get("user") == Some(&"\"nblumhardt\"".to_owned()));
        assert!(properties.get("quota") == Some(&"42".to_owned()));
        assert!(properties.len() == 3);
    }

    #[test]
    pub fn emitted_events_are_flushed() {
        let _flush = pipeline::init(stdio::StdioCollector::new());
        emit!("Hello, {}!", name: env::var("USERNAME").unwrap());
    }
}
<|endoftext|>


<commit_before>
mod abort_on_panic;

use abort_on_panic::abort_on_panic;

/// Allows use of a value inside a `&mut T` as though it was owned by the closure
///
/// The closure must return a valid T
/// # Aborts
/// Will abort the program (exiting with status code -1) if the closure panics.
///
/// # Example
/// ```
/// struct Foo;
/// let mut foo = Foo;
/// take_mut::take(&mut foo, |foo| {
///     // Can now consume from the reference, and provide a new value later
///     drop(foo);
///     // Do more stuff
///     Foo // Return new Foo from closure
/// });
pub fn take<T, F>(mut_ref: &mut T, closure: F)
  where F: FnOnce(T) -> T {
    use std::ptr;
    abort_on_panic(|| {
        unsafe {
            let old_t = ptr::read(mut_ref);
            let new_t = closure(old_t);
            ptr::write(mut_ref, new_t);
        }
    });
}

#[test]
fn it_works() {
    #[derive(PartialEq, Eq, Debug)]
    enum Foo {A, B};
    impl Drop for Foo {
        fn drop(&mut self) {
            match *self {
                Foo::A => println!("Foo::A dropped"),
                Foo::B => println!("Foo::B dropped")
            }
        }
    }
    let mut foo = Foo::A;
    take(&mut foo, |mut f| {
       drop(f);
       Foo::B
    });
    assert_eq!(&foo, &Foo::B);
}<commit_msg>Add crate-level documentation, and improve take() documentation.<commit_after>//! This crate provides (at this time) a single function, `take()`.
//!
//! `take()` allows for taking `T` out of a `&mut T`, doing anything with it including consuming it, and producing another `T` to put back in the `&mut T`.
//!
//! Contrast with `std::mem::replace()`, which allows for putting a different `T` into a `&mut T`, but requiring the new `T` to be available before being able to consume the old `T`.

mod abort_on_panic;

use abort_on_panic::abort_on_panic;

/// Allows use of a value pointed to by `&mut T` as though it was owned, as long as a `T` is made available afterwards.
///
/// The closure must return a valid T.
/// # Aborts
/// Will abort the program (exiting with status code -1) if the closure panics.
///
/// # Example
/// ```
/// struct Foo;
/// let mut foo = Foo;
/// take_mut::take(&mut foo, |foo| {
///     // Can now consume the Foo, and provide a new value later
///     drop(foo);
///     // Do more stuff
///     Foo // Return new Foo from closure, which goes back into the &mut Foo
/// });
/// ```
pub fn take<T, F>(mut_ref: &mut T, closure: F)
  where F: FnOnce(T) -> T {
    use std::ptr;
    abort_on_panic(|| {
        unsafe {
            let old_t = ptr::read(mut_ref);
            let new_t = closure(old_t);
            ptr::write(mut_ref, new_t);
        }
    });
}

#[test]
fn it_works() {
    #[derive(PartialEq, Eq, Debug)]
    enum Foo {A, B};
    impl Drop for Foo {
        fn drop(&mut self) {
            match *self {
                Foo::A => println!("Foo::A dropped"),
                Foo::B => println!("Foo::B dropped")
            }
        }
    }
    let mut foo = Foo::A;
    take(&mut foo, |mut f| {
       drop(f);
       Foo::B
    });
    assert_eq!(&foo, &Foo::B);
}<|endoftext|>


<commit_before>/* 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/. */

/*!
# Autogard
*/

// TODO Using expression template will give better performance.
//      e.g., http://www.met.reading.ac.uk/clouds/adept/

// TODO Multi-threading support.

// TODO Add Valgrind, ASAN, and TSAN tests.

#![crate_name = "autograd"]
#![crate_type = "rlib"]

#![feature(thread_local)]

extern crate num;

mod context;
mod float;

pub use context::Context;
// TODO ideally Private traits shouldn't be exported.
pub use context::ContextCratePrivate;
pub use context::ContextModulePrivate;

pub use float::Float;
<commit_msg>Add column wrapping TODO.<commit_after>/* 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/. */

/*!
# Autogard
*/

// TODO Using expression template will give better performance.
//      e.g., http://www.met.reading.ac.uk/clouds/adept/

// TODO Multi-threading support.

// TODO Add Valgrind, ASAN, and TSAN tests.

// TODO Repect Rust column wrapping guide.
//      https://github.com/rust-lang/rust-guidelines/blob/master/style/whitespace.md

#![crate_name = "autograd"]
#![crate_type = "rlib"]

#![feature(thread_local)]

extern crate num;

mod context;
mod float;

pub use context::Context;
// TODO ideally Private traits shouldn't be exported.
pub use context::ContextCratePrivate;
pub use context::ContextModulePrivate;

pub use float::Float;
<|endoftext|>


<commit_before>extern crate pulldown_cmark;
extern crate svgbob;

use pulldown_cmark::Parser;
use pulldown_cmark::Event;
use pulldown_cmark::Tag;
use pulldown_cmark::Options;

pub fn parse(arg: &str) -> String {
    let parser = Parser::new_ext(arg, Options::all());
    let bob_fence = "bob";
    let mut start_bob = false;
    let mut bob_text = String::new();
    let parser = parser.map(|event| match event {
        Event::Text(text) => {
            if start_bob {
                bob_text.push_str(&text);
                Event::Text("".into())
            } else {
                Event::Text(text)
            }
        }
        Event::Start(tag) => {
            match tag {
                Tag::CodeBlock(ref lang) => {
                    if lang == bob_fence {
                        start_bob = true;
                        bob_text.clear();
                        Event::Text("".into())
                    } else {
                        Event::Start(tag.clone())
                    }
                }
                _ => Event::Start(tag),
            }
        }
        Event::End(ref tag) => {
            match *tag {
                Tag::CodeBlock(ref lang) => {
                    if lang == bob_fence {
                        start_bob = false;
                        let svg = svgbob::to_svg(&bob_text).to_string();
                        bob_text.clear();
                        Event::Html(svg.into())
                    } else {
                        Event::End(tag.clone())
                    }
                }
                _ => Event::End(tag.clone()),
            }
        }
        _ => event,
    });
    let mut html = String::new();
    pulldown_cmark::html::push_html(&mut html, parser);
    html
}
<commit_msg>Added an idiomatic-y plugin system<commit_after>extern crate pulldown_cmark;
extern crate svgbob;
extern crate comic;

use pulldown_cmark::Parser;
use pulldown_cmark::Event;
use pulldown_cmark::Tag;
use pulldown_cmark::Options;
use std::collections::HashMap;
use std::borrow::Cow;

fn bob_handler(s: &str) -> String {
    svgbob::to_svg(s).to_string()
}

fn comic_handler(s: &str) -> String {
    comic::to_svg(s).to_string()
}

pub fn parse(arg: &str) -> String{
    let mut plugins:HashMap<String, Box<Fn(&str)->String>>  = HashMap::new();
    plugins.insert("bob".into(), Box::new(bob_handler));
    plugins.insert("comic".into(), Box::new(comic_handler));
    parse_with_plugins(arg, plugins)
}

pub fn parse_with_plugins(arg: &str, plugins: HashMap<String, Box<Fn(&str) -> String>>) -> String {
    let parser = Parser::new_ext(arg, Options::all());
    let mut fence_start = false;
    let mut text_buffer = String::new();
    let mut active_handler: Option<&Box<Fn(&str)->String>> = None;
    let mut active_fence: Option<String> = None;

    let parser = parser.map(|event| match event {
        Event::Text(text) => {
            if fence_start {
                text_buffer.push_str(&text);
                Event::Text("".into())
            } else {
                Event::Text(text)
            }
        }
        Event::Start(tag) => {
            match tag {
                Tag::CodeBlock(ref lang) => {
                    match plugins.get(&lang.to_string()) {
                        Some(handler) => {
                            fence_start = true;
                            text_buffer.clear();
                            active_handler = Some(handler);
                            active_fence = Some(lang.to_string());
                            Event::Text("".into())
                        }
                        None => {
                            Event::Start(tag.clone())
                        }
                    }
                }
                _ => Event::Start(tag),
            }
        }
        Event::End(ref tag) => {
            match *tag {
                Tag::CodeBlock(ref lang) => {
                    if active_fence == Some(lang.to_string()) {
                        fence_start = false;
                        match active_handler{
                            Some(handler) => {
                                let out = handler(&text_buffer);
                                text_buffer.clear();
                                active_handler = None; //reset handler to none
                                Event::Html(out.into())
                            },
                            None => {
                                println!("Warning: no handler for this end tag");
                                Event::Text("".into())
                            }
                        }
                    } else {
                        Event::End(tag.clone())
                    }
                }
                _ => Event::End(tag.clone()),
            }
        }
        _ => event,
    });
    let mut html = String::new();
    pulldown_cmark::html::push_html(&mut html, parser);
    html
}
<|endoftext|>


<commit_before>//! SplitMut - a crate for retreiving multiple mutable values within the same collection
//!
//! # Example
//! ```
//! use std::collections::HashMap;
//! use splitmut::SplitMut;
//!
//! // Create a hashmap
//! let mut h = HashMap::new();
//! h.insert(1, "Hello");
//! h.insert(2, "world");
//!
//! // Swap two values easily
//! {
//!     let (m1, m2) = h.get2_mut(&1, &2);
//!     std::mem::swap(m1.unwrap(), m2.unwrap());
//! }
//! assert_eq!(h.get(&1), Some(&"world"));
//! assert_eq!(h.get(&2), Some(&"Hello"));
//! ```

use std::ptr::null_mut;
use std::collections::{HashMap, BTreeMap, VecDeque};

#[inline]
fn to_ptr<V>(s: Option<&mut V>) -> *mut V { s.map(|q| q as *mut V).unwrap_or(null_mut()) }

fn check_ptr<V>(a: *mut V, b: *mut V) {
    if a == b && a != null_mut() { panic!("SplitMut called with identical keys!"); }
}

#[inline]
unsafe fn from_ptr<'q, V>(a: *mut V) -> Option<&'q mut V> {
    if a == null_mut() { None } else { Some(std::mem::transmute(a)) }
}

/// Just add `use splitmut::SplitMut;` to have these methods working on
/// mutable slices, Vec, VecDeque, HashMap and BTreeMap.
pub trait SplitMut<K, V> {
    /// Wrapper for get_mut, used internally.
    fn get1_mut(&mut self, k1: K) -> Option<&mut V>;
    /// Wrapper for get_unchecked_mut, used internally.
    ///
    /// # Undefined behaviour
    /// It is undefined behaviour to call this with a key that does not correspond to a value.
    /// You have been warned.
    unsafe fn get1_unchecked_mut(&mut self, k1: K) -> &mut V;

    /// Returns two mutable references to two distinct values within
    /// the same collection.
    ///
    /// # Panic
    /// This function will panic if the two keys point to the same value.
    fn get2_mut(&mut self, k1: K, k2: K) -> (Option<&mut V>, Option<&mut V>) {
        let p1 = to_ptr(self.get1_mut(k1));
        let p2 = to_ptr(self.get1_mut(k2));
        check_ptr(p1, p2);
        unsafe { (from_ptr(p1), from_ptr(p2)) }
    }

    /// Returns three mutable references to three distinct values within
    /// the same collection.
    ///
    /// # Panic
    /// This function will panic if any two keys point to the same value.
    fn get3_mut(&mut self, k1: K, k2: K, k3: K) -> (Option<&mut V>, Option<&mut V>, Option<&mut V>) {
        let p1 = to_ptr(self.get1_mut(k1));
        let p2 = to_ptr(self.get1_mut(k2));
        let p3 = to_ptr(self.get1_mut(k3));
        check_ptr(p1, p2);
        check_ptr(p1, p3);
        check_ptr(p2, p3);
        unsafe { (from_ptr(p1), from_ptr(p2), from_ptr(p3)) }
    }

    /// Returns four mutable references to four distinct values within
    /// the same collection.
    ///
    /// # Panic
    /// This function will panic if any two keys point to the same value.
    fn get4_mut(&mut self, k1: K, k2: K, k3: K, k4: K) -> (Option<&mut V>, Option<&mut V>, Option<&mut V>, Option<&mut V>) {
        let p1 = to_ptr(self.get1_mut(k1));
        let p2 = to_ptr(self.get1_mut(k2));
        let p3 = to_ptr(self.get1_mut(k3));
        let p4 = to_ptr(self.get1_mut(k4));
        check_ptr(p1, p2);
        check_ptr(p1, p3);
        check_ptr(p2, p3);
        check_ptr(p1, p4);
        check_ptr(p2, p4);
        check_ptr(p3, p4);
        unsafe { (from_ptr(p1), from_ptr(p2), from_ptr(p3), from_ptr(p4)) }
    }

    /// Returns two mutable references to two distinct values within
    /// the same collection.
    ///
    /// # Undefined behaviour
    /// It is undefined behaviour to call this with a key that does not
    /// correspond to a value, or with keys pointing to the same value.
    /// You have been warned.
    unsafe fn get2_unchecked_mut(&mut self, k1: K, k2: K) -> (&mut V, &mut V) {
        let p2 = self.get1_unchecked_mut(k2) as *mut V;
        (self.get1_unchecked_mut(k1), std::mem::transmute(p2))
    }

    /// Returns three mutable references to three distinct values within
    /// the same collection.
    ///
    /// # Undefined behaviour
    /// It is undefined behaviour to call this with a key that does not
    /// correspond to a value, or with any two keys pointing to the same value.
    /// You have been warned.
    unsafe fn get3_unchecked_mut(&mut self, k1: K, k2: K, k3: K) -> (&mut V, &mut V, &mut V) {
        let p2 = self.get1_unchecked_mut(k2) as *mut V;
        let p3 = self.get1_unchecked_mut(k3) as *mut V;
        (self.get1_unchecked_mut(k1), std::mem::transmute(p2), std::mem::transmute(p3))
    }

    /// Returns four mutable references to four distinct values within
    /// the same collection.
    ///
    /// # Undefined behaviour
    /// It is undefined behaviour to call this with a key that does not
    /// correspond to a value, or with any two keys pointing to the same value.
    /// You have been warned.
    unsafe fn get4_unchecked_mut(&mut self, k1: K, k2: K, k3: K, k4: K) -> (&mut V, &mut V, &mut V, &mut V) {
        let p2 = self.get1_unchecked_mut(k2) as *mut V;
        let p3 = self.get1_unchecked_mut(k3) as *mut V;
        let p4 = self.get1_unchecked_mut(k4) as *mut V;
        (self.get1_unchecked_mut(k1), std::mem::transmute(p2), std::mem::transmute(p3), std::mem::transmute(p4))
    }
}

impl<'a, V> SplitMut<usize, V> for &'a mut [V] {
    #[inline]
    fn get1_mut(&mut self, k: usize) -> Option<&mut V> { self.get_mut(k) }
    #[inline]
    unsafe fn get1_unchecked_mut(&mut self, k: usize) -> &mut V { self.get_unchecked_mut(k) }
}

impl<'a, V> SplitMut<usize, V> for Vec<V> {
    #[inline]
    fn get1_mut(&mut self, k: usize) -> Option<&mut V> { self.get_mut(k) }
    #[inline]
    unsafe fn get1_unchecked_mut(&mut self, k: usize) -> &mut V { self.get_unchecked_mut(k) }
}

impl<'a, V> SplitMut<usize, V> for VecDeque<V> {
    #[inline]
    fn get1_mut(&mut self, k: usize) -> Option<&mut V> { self.get_mut(k) }
    #[inline]
    unsafe fn get1_unchecked_mut(&mut self, k: usize) -> &mut V { std::mem::transmute(self.get_mut(k)) }
}

impl<'a, K: std::hash::Hash + Eq, V> SplitMut<&'a K, V> for HashMap<K, V> {
    #[inline]
    fn get1_mut(&mut self, k: &'a K) -> Option<&mut V> { self.get_mut(k) }
    #[inline]
    unsafe fn get1_unchecked_mut(&mut self, k: &'a K) -> &mut V { std::mem::transmute(self.get_mut(k)) }
}

impl<'a, K: Ord, V> SplitMut<&'a K, V> for BTreeMap<K, V> {
    #[inline]
    fn get1_mut(&mut self, k: &'a K) -> Option<&mut V> { self.get_mut(k) }
    #[inline]
    unsafe fn get1_unchecked_mut(&mut self, k: &'a K) -> &mut V { std::mem::transmute(self.get_mut(k)) }
}

#[test]
#[should_panic]
fn hash_same() {
    let mut h = HashMap::new();
    h.insert(3u8, 5u16);
    h.get2_mut(&3, &3);
}

#[test]
fn hash_reg() {
    let mut h = HashMap::new();
    h.insert(3u8, 5u16);
    h.insert(4u8, 9u16);
    { let (a, b) = h.get2_mut(&3, &4);
      std::mem::swap(a.unwrap(), b.unwrap());
    }
    assert_eq!(h.get2_mut(&2, &2), (None, None));
    assert_eq!(unsafe { h.get2_unchecked_mut(&3, &4) }, (&mut 9u16, &mut 5u16));
    assert_eq!(h.get2_mut(&2, &3), (None, Some(&mut 9u16)));
}

#[test]
#[should_panic]
fn deque_same() {
    let mut h = VecDeque::new();
    h.push_front(5u16);
    h.get2_mut(0, 0);
}

#[test]
fn deque_reg() {
    let mut h = VecDeque::new();
    h.push_back(5u16);
    h.push_back(9u16);
    { let (a, b) = h.get2_mut(0, 1);
      std::mem::swap(a.unwrap(), b.unwrap());
    }
    assert_eq!(h.get2_mut(2, 2), (None, None));
    assert_eq!(unsafe { h.get2_unchecked_mut(0, 1) }, (&mut 9u16, &mut 5u16));
    assert_eq!(h.get2_mut(2, 0), (None, Some(&mut 9u16)));
}

#[test]
fn vec() {
    let mut h = vec!["Hello", "world", "!"];
    { let (a, b, c) = h.get3_mut(0, 1, 2);
      *c.unwrap() = "universe";
      std::mem::swap(a.unwrap(), b.unwrap());
    }
    assert_eq!(&*h, &["world", "Hello", "universe"]);

}
<commit_msg>Change a few transmutes to "&mut *"<commit_after>//! SplitMut - a crate for retreiving multiple mutable values within the same collection
//!
//! # Example
//! ```
//! use std::collections::HashMap;
//! use splitmut::SplitMut;
//!
//! // Create a hashmap
//! let mut h = HashMap::new();
//! h.insert(1, "Hello");
//! h.insert(2, "world");
//!
//! // Swap two values easily
//! {
//!     let (m1, m2) = h.get2_mut(&1, &2);
//!     std::mem::swap(m1.unwrap(), m2.unwrap());
//! }
//! assert_eq!(h.get(&1), Some(&"world"));
//! assert_eq!(h.get(&2), Some(&"Hello"));
//! ```

use std::ptr::null_mut;
use std::collections::{HashMap, BTreeMap, VecDeque};

#[inline]
fn to_ptr<V>(s: Option<&mut V>) -> *mut V { s.map(|q| q as *mut V).unwrap_or(null_mut()) }

fn check_ptr<V>(a: *mut V, b: *mut V) {
    if a == b && a != null_mut() { panic!("SplitMut called with identical keys!"); }
}

#[inline]
unsafe fn from_ptr<'q, V>(a: *mut V) -> Option<&'q mut V> {
    if a == null_mut() { None } else { Some(&mut *a) }
}

/// Just add `use splitmut::SplitMut;` to have these methods working on
/// mutable slices, Vec, VecDeque, HashMap and BTreeMap.
pub trait SplitMut<K, V> {
    /// Wrapper for get_mut, used internally.
    fn get1_mut(&mut self, k1: K) -> Option<&mut V>;
    /// Wrapper for get_unchecked_mut, used internally.
    ///
    /// # Undefined behaviour
    /// It is undefined behaviour to call this with a key that does not correspond to a value.
    /// You have been warned.
    unsafe fn get1_unchecked_mut(&mut self, k1: K) -> &mut V;

    /// Returns two mutable references to two distinct values within
    /// the same collection.
    ///
    /// # Panic
    /// This function will panic if the two keys point to the same value.
    fn get2_mut(&mut self, k1: K, k2: K) -> (Option<&mut V>, Option<&mut V>) {
        let p1 = to_ptr(self.get1_mut(k1));
        let p2 = to_ptr(self.get1_mut(k2));
        check_ptr(p1, p2);
        unsafe { (from_ptr(p1), from_ptr(p2)) }
    }

    /// Returns three mutable references to three distinct values within
    /// the same collection.
    ///
    /// # Panic
    /// This function will panic if any two keys point to the same value.
    fn get3_mut(&mut self, k1: K, k2: K, k3: K) -> (Option<&mut V>, Option<&mut V>, Option<&mut V>) {
        let p1 = to_ptr(self.get1_mut(k1));
        let p2 = to_ptr(self.get1_mut(k2));
        let p3 = to_ptr(self.get1_mut(k3));
        check_ptr(p1, p2);
        check_ptr(p1, p3);
        check_ptr(p2, p3);
        unsafe { (from_ptr(p1), from_ptr(p2), from_ptr(p3)) }
    }

    /// Returns four mutable references to four distinct values within
    /// the same collection.
    ///
    /// # Panic
    /// This function will panic if any two keys point to the same value.
    fn get4_mut(&mut self, k1: K, k2: K, k3: K, k4: K) -> (Option<&mut V>, Option<&mut V>, Option<&mut V>, Option<&mut V>) {
        let p1 = to_ptr(self.get1_mut(k1));
        let p2 = to_ptr(self.get1_mut(k2));
        let p3 = to_ptr(self.get1_mut(k3));
        let p4 = to_ptr(self.get1_mut(k4));
        check_ptr(p1, p2);
        check_ptr(p1, p3);
        check_ptr(p2, p3);
        check_ptr(p1, p4);
        check_ptr(p2, p4);
        check_ptr(p3, p4);
        unsafe { (from_ptr(p1), from_ptr(p2), from_ptr(p3), from_ptr(p4)) }
    }

    /// Returns two mutable references to two distinct values within
    /// the same collection.
    ///
    /// # Undefined behaviour
    /// It is undefined behaviour to call this with a key that does not
    /// correspond to a value, or with keys pointing to the same value.
    /// You have been warned.
    unsafe fn get2_unchecked_mut(&mut self, k1: K, k2: K) -> (&mut V, &mut V) {
        let p2 = self.get1_unchecked_mut(k2) as *mut V;
        (self.get1_unchecked_mut(k1), &mut *p2)
    }

    /// Returns three mutable references to three distinct values within
    /// the same collection.
    ///
    /// # Undefined behaviour
    /// It is undefined behaviour to call this with a key that does not
    /// correspond to a value, or with any two keys pointing to the same value.
    /// You have been warned.
    unsafe fn get3_unchecked_mut(&mut self, k1: K, k2: K, k3: K) -> (&mut V, &mut V, &mut V) {
        let p2 = self.get1_unchecked_mut(k2) as *mut V;
        let p3 = self.get1_unchecked_mut(k3) as *mut V;
        (self.get1_unchecked_mut(k1), &mut *p2, &mut *p3)
    }

    /// Returns four mutable references to four distinct values within
    /// the same collection.
    ///
    /// # Undefined behaviour
    /// It is undefined behaviour to call this with a key that does not
    /// correspond to a value, or with any two keys pointing to the same value.
    /// You have been warned.
    unsafe fn get4_unchecked_mut(&mut self, k1: K, k2: K, k3: K, k4: K) -> (&mut V, &mut V, &mut V, &mut V) {
        let p2 = self.get1_unchecked_mut(k2) as *mut V;
        let p3 = self.get1_unchecked_mut(k3) as *mut V;
        let p4 = self.get1_unchecked_mut(k4) as *mut V;
        (self.get1_unchecked_mut(k1), &mut *p2, &mut *p3, &mut *p4)
    }
}

impl<'a, V> SplitMut<usize, V> for &'a mut [V] {
    #[inline]
    fn get1_mut(&mut self, k: usize) -> Option<&mut V> { self.get_mut(k) }
    #[inline]
    unsafe fn get1_unchecked_mut(&mut self, k: usize) -> &mut V { self.get_unchecked_mut(k) }
}

impl<'a, V> SplitMut<usize, V> for Vec<V> {
    #[inline]
    fn get1_mut(&mut self, k: usize) -> Option<&mut V> { self.get_mut(k) }
    #[inline]
    unsafe fn get1_unchecked_mut(&mut self, k: usize) -> &mut V { self.get_unchecked_mut(k) }
}

impl<'a, V> SplitMut<usize, V> for VecDeque<V> {
    #[inline]
    fn get1_mut(&mut self, k: usize) -> Option<&mut V> { self.get_mut(k) }
    #[inline]
    unsafe fn get1_unchecked_mut(&mut self, k: usize) -> &mut V { std::mem::transmute(self.get_mut(k)) }
}

impl<'a, K: std::hash::Hash + Eq, V> SplitMut<&'a K, V> for HashMap<K, V> {
    #[inline]
    fn get1_mut(&mut self, k: &'a K) -> Option<&mut V> { self.get_mut(k) }
    #[inline]
    unsafe fn get1_unchecked_mut(&mut self, k: &'a K) -> &mut V { std::mem::transmute(self.get_mut(k)) }
}

impl<'a, K: Ord, V> SplitMut<&'a K, V> for BTreeMap<K, V> {
    #[inline]
    fn get1_mut(&mut self, k: &'a K) -> Option<&mut V> { self.get_mut(k) }
    #[inline]
    unsafe fn get1_unchecked_mut(&mut self, k: &'a K) -> &mut V { std::mem::transmute(self.get_mut(k)) }
}

#[test]
#[should_panic]
fn hash_same() {
    let mut h = HashMap::new();
    h.insert(3u8, 5u16);
    h.get2_mut(&3, &3);
}

#[test]
fn hash_reg() {
    let mut h = HashMap::new();
    h.insert(3u8, 5u16);
    h.insert(4u8, 9u16);
    { let (a, b) = h.get2_mut(&3, &4);
      std::mem::swap(a.unwrap(), b.unwrap());
    }
    assert_eq!(h.get2_mut(&2, &2), (None, None));
    assert_eq!(unsafe { h.get2_unchecked_mut(&3, &4) }, (&mut 9u16, &mut 5u16));
    assert_eq!(h.get2_mut(&2, &3), (None, Some(&mut 9u16)));
}

#[test]
#[should_panic]
fn deque_same() {
    let mut h = VecDeque::new();
    h.push_front(5u16);
    h.get2_mut(0, 0);
}

#[test]
fn deque_reg() {
    let mut h = VecDeque::new();
    h.push_back(5u16);
    h.push_back(9u16);
    { let (a, b) = h.get2_mut(0, 1);
      std::mem::swap(a.unwrap(), b.unwrap());
    }
    assert_eq!(h.get2_mut(2, 2), (None, None));
    assert_eq!(unsafe { h.get2_unchecked_mut(0, 1) }, (&mut 9u16, &mut 5u16));
    assert_eq!(h.get2_mut(2, 0), (None, Some(&mut 9u16)));
}

#[test]
fn vec() {
    let mut h = vec!["Hello", "world", "!"];
    { let (a, b, c) = h.get3_mut(0, 1, 2);
      *c.unwrap() = "universe";
      std::mem::swap(a.unwrap(), b.unwrap());
    }
    assert_eq!(&*h, &["world", "Hello", "universe"]);

}
<|endoftext|>


<commit_before>extern crate random_choice;

use std::collections::{HashSet, HashMap};
use std::iter::FromIterator;
use std::cmp::max;
use self::random_choice::random_choice;

pub struct GSDMM {
    alpha: f64,
    beta: f64,
    K:usize,
    V:f64,
    D:usize,
    maxit:isize,
    clusters: Vec<usize>,
    pub docs: Vec<Vec<String>>,
    pub labels: Vec<usize>,
    pub cluster_counts: Vec<u32>,
    pub cluster_word_counts:Vec<u32>,
    pub cluster_word_distributions: Vec<HashMap<String,u32>>
}

impl GSDMM {
    pub fn new(alpha:f64, beta:f64, K: usize, maxit:isize, vocab:HashSet<String>, docs:Vec<Vec<String>>) -> GSDMM {
        let D = docs.len();

        // compute utilized vocabulary size.
        let mut utilized_vocab = HashSet::with_capacity(vocab.len());
        for doc in &docs {
            for word in doc {
                utilized_vocab.insert(word.clone());
            }
        }
        let V = utilized_vocab.len() as f64;
        println!("Fitting with alpha={}, beta={}, K={}, maxit={}, vocab size={}", alpha, beta, K, maxit, V as u32);

        let clusters = (0_usize..K).collect::<Vec<usize>>();
        let mut d_z: Vec<usize> = (0_usize..D).map(|_| 0_usize).collect::<Vec<usize>>(); // doc labels
        let mut m_z: Vec<u32> = GSDMM::zero_vector(K);  // cluster sizes
        let mut n_z: Vec<u32> = GSDMM::zero_vector(K);  // cluster word counts
        let mut n_z_w = Vec::<HashMap<String, u32>>::with_capacity(K);  // container for cluster word distributions
        for _ in 0_usize..K {
            let mut m = HashMap::<String, u32>::with_capacity(max(vocab.len() / 10, 100));
            &n_z_w.push(m);
        }

        // randomly initialize cluster assignment
        let p = (0..K).map(|_| 1_f64 / (K as f64)).collect::<Vec<f64>>();

        let choices = random_choice().random_choice_f64(&clusters, &p, D) ;
        for i in 0..D {
            let z = choices[i].clone();
            let ref doc = docs[i];
            d_z[i] = z;
            m_z[z] += 1;
            n_z[z] += doc.len() as u32;
            let ref mut clust_words: HashMap<String, u32> = n_z_w[z];
            for word in doc {
                if !clust_words.contains_key(word) {
                    clust_words.insert(word.clone(), 0_u32);
                }
                    * clust_words.get_mut(word).unwrap() += 1_u32;
            }
        }

        GSDMM {
            alpha: alpha,
            beta: beta,
            K: K,
            V: V,
            D: D,
            maxit:maxit,
            docs:docs,
            clusters: clusters.clone(),     // Don't totally get why we need the clone here!
            labels: d_z,
            cluster_counts: m_z,
            cluster_word_counts: n_z,
            cluster_word_distributions: n_z_w
        }
    }

    pub fn fit(&mut self) {
        let mut number_clusters = self.K;
        for it in 0..self.maxit {
            let mut total_transfers = 0;
            for i in 0..self.D {
                let ref doc = self.docs[i];
                let doc_size = doc.len() as u32;

                // remove the doc from its current cluster
                let z_old = self.labels[i];
                self.cluster_counts[z_old] -= 1;
                self.cluster_word_counts[z_old] -= doc_size;

                // modify the map: enclose it in a block so we can borrow views again.
                {
                    let ref mut old_clust_words: HashMap<String, u32> = self.cluster_word_distributions[z_old];
                    for word in doc {
                        *old_clust_words.get_mut(word).unwrap() -= 1_u32;

                        // compact dictionary once a key is exausted.
                        if old_clust_words[word] == 0_u32 {
                            old_clust_words.remove(word);
                        }
                    }
                }

                // update the probability vector
                let p = self.score(&doc);

                // choose the next cluster randomly according to the computed probability
                let z_new: usize = random_choice().random_choice_f64(&self.clusters, &p, 1)[0].clone();

                // transfer document to the new cluster
                if z_new != z_old {
                    total_transfers += 1;
                }
                self.labels[i] = z_new;
                self.cluster_counts[z_new] += 1_u32;
                self.cluster_word_counts[z_new] += doc_size;

                {
                    let ref mut new_clust_words: HashMap<String, u32> = self.cluster_word_distributions[z_new];
                    for word in doc {
                        if !new_clust_words.contains_key(word) {
                            new_clust_words.insert(word.clone(), 0_u32);
                        }
                            *new_clust_words.get_mut(word).unwrap() += 1_u32;
                    }
                }
            }
            let new_number_clusters = self.cluster_word_distributions.iter().map(|c| if c.len()>0 {1} else {0} ).sum();
            println!("Iteration {}: {} docs transferred with {} clusters populated.", it, total_transfers, new_number_clusters);

            // apply ad-hoc convergence test
            if total_transfers==0 && new_number_clusters==number_clusters {
                println!("Converged after {} iterations. Solution has {} clusters.", it, new_number_clusters);
                break
            }
            number_clusters = new_number_clusters;
        }
    }

    pub fn score(&self, doc:&Vec<String>) -> Vec<f64> {
        /// Score an input document using the formula of Yin and Wang 2014 (equation 3)
        /// http://dbgroup.cs.tsinghua.edu.cn/wangjy/papers/KDD14-GSDMM.pdf
        ///
        /// # Arguments
        ///
        /// * `doc` - A vector of unique string tokens characterizing the document
        ///
        /// # Value
        ///
        /// Vec<f64> - A length K probability vector where each component represents the probability
        /// of the doc belonging to a particular cluster.
        ///

        // We break the formula into the following pieces
        // p = N1*N2/(D1*D2) = exp(lN1 - lD1 + lN2 - lD2)
        // lN1 = log(m_z[z] + alpha)
        // lN2 = log(D - 1 + K*alpha)
        // lN2 = log(product(n_z_w[w] + beta)) = sum(log(n_z_w[w] + beta))
        // lD2 = log(product(n_z[d] + V*beta + i -1)) = sum(log(n_z[d] + V*beta + i -1))
        let mut p = (0..self.K).map(|_| 0_f64).collect::<Vec<f64>>();
        let lD1 = ((self.D - 1) as f64 + (self.K as f64) * self.alpha).ln();
        let doc_size = doc.len() as u32;
        for label in 0_usize..self.K {
            let lN1 = (self.cluster_counts[label] as f64 + self.alpha).ln();
            let mut lN2 = 0_f64;
            let mut lD2 = 0_f64;

            let ref cluster: HashMap<String, u32> = self.cluster_word_distributions[label];

            for word in doc {
                lN2 += (*cluster.get(word).unwrap_or(&0_u32) as f64 + self.beta).ln();
            }
            for j in 1_u32..(doc_size+1) {
                lD2 += ((self.cluster_word_counts[label] + j) as f64 - 1_f64 + self.V * self.beta).ln();
            }
            p[label] = (lN1 - lD1 + lN2 - lD2).exp();
        }

        // normalize the probability
        let pnorm: f64 = p.iter().sum();
        for label in 0_usize..self.K {
            p[label] = p[label] / pnorm;
        }
        p
    }

    fn zero_vector(size:usize) -> Vec<u32>
    {
        let mut v = Vec::<u32>::with_capacity(size);
        for _ in 0_usize..size {
            v.push(0_u32)
        }
        v
    }

}

#[test]
fn simple_run() {
    let mut vocab = HashSet::<String>::new();
    vocab.insert("A".to_string());
    vocab.insert("B".to_string());
    vocab.insert("C".to_string());

    let mut docs = Vec::<Vec<String>>::new();
    docs.push(vec!("A".to_string()));
    docs.push(vec!("A".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));

    let mut model = GSDMM::new(0.1, 0.00001, 10, 30, vocab, docs);
    model.fit();

    // check the total number across all partitions is equal to the number of docs
    assert_eq!(18, model.cluster_counts.iter().sum::<u32>());

    // check that we get three clusters
    assert_eq!(3, model.cluster_counts.into_iter().filter(|x| x>&0_u32 ).collect::<Vec<u32>>().len());

    // check that the clusters are pure
    println!("{:?}", model.cluster_word_distributions);
    let mut check_map = HashMap::<usize,String>::new();
    for (i,label) in vec!("A","A","B","B","B","B","B","B","B","B","C","C","C","C","C","C","C","C").into_iter().enumerate() {
        if check_map.contains_key(&model.labels[i]) {
            assert_eq!(check_map[&model.labels[i]], label);
        } else {
            check_map.insert(model.labels[i], label.to_string());
        }

    }
}
<commit_msg>Check non-zero probability vector before normalize<commit_after>extern crate random_choice;

use std::collections::{HashSet, HashMap};
use std::iter::FromIterator;
use std::cmp::max;
use self::random_choice::random_choice;

pub struct GSDMM {
    alpha: f64,
    beta: f64,
    K:usize,
    V:f64,
    D:usize,
    maxit:isize,
    clusters: Vec<usize>,
    pub docs: Vec<Vec<String>>,
    pub labels: Vec<usize>,
    pub cluster_counts: Vec<u32>,
    pub cluster_word_counts:Vec<u32>,
    pub cluster_word_distributions: Vec<HashMap<String,u32>>
}

impl GSDMM {
    pub fn new(alpha:f64, beta:f64, K: usize, maxit:isize, vocab:HashSet<String>, docs:Vec<Vec<String>>) -> GSDMM {
        let D = docs.len();

        // compute utilized vocabulary size.
        let mut utilized_vocab = HashSet::with_capacity(vocab.len());
        for doc in &docs {
            for word in doc {
                utilized_vocab.insert(word.clone());
            }
        }
        let V = utilized_vocab.len() as f64;
        println!("Fitting with alpha={}, beta={}, K={}, maxit={}, vocab size={}", alpha, beta, K, maxit, V as u32);

        let clusters = (0_usize..K).collect::<Vec<usize>>();
        let mut d_z: Vec<usize> = (0_usize..D).map(|_| 0_usize).collect::<Vec<usize>>(); // doc labels
        let mut m_z: Vec<u32> = GSDMM::zero_vector(K);  // cluster sizes
        let mut n_z: Vec<u32> = GSDMM::zero_vector(K);  // cluster word counts
        let mut n_z_w = Vec::<HashMap<String, u32>>::with_capacity(K);  // container for cluster word distributions
        for _ in 0_usize..K {
            let mut m = HashMap::<String, u32>::with_capacity(max(vocab.len() / 10, 100));
            &n_z_w.push(m);
        }

        // randomly initialize cluster assignment
        let p = (0..K).map(|_| 1_f64 / (K as f64)).collect::<Vec<f64>>();

        let choices = random_choice().random_choice_f64(&clusters, &p, D) ;
        for i in 0..D {
            let z = choices[i].clone();
            let ref doc = docs[i];
            d_z[i] = z;
            m_z[z] += 1;
            n_z[z] += doc.len() as u32;
            let ref mut clust_words: HashMap<String, u32> = n_z_w[z];
            for word in doc {
                if !clust_words.contains_key(word) {
                    clust_words.insert(word.clone(), 0_u32);
                }
                    * clust_words.get_mut(word).unwrap() += 1_u32;
            }
        }

        GSDMM {
            alpha: alpha,
            beta: beta,
            K: K,
            V: V,
            D: D,
            maxit:maxit,
            docs:docs,
            clusters: clusters.clone(),     // Don't totally get why we need the clone here!
            labels: d_z,
            cluster_counts: m_z,
            cluster_word_counts: n_z,
            cluster_word_distributions: n_z_w
        }
    }

    pub fn fit(&mut self) {
        let mut number_clusters = self.K;
        for it in 0..self.maxit {
            let mut total_transfers = 0;
            for i in 0..self.D {
                let ref doc = self.docs[i];
                let doc_size = doc.len() as u32;

                // remove the doc from its current cluster
                let z_old = self.labels[i];
                self.cluster_counts[z_old] -= 1;
                self.cluster_word_counts[z_old] -= doc_size;

                // modify the map: enclose it in a block so we can borrow views again.
                {
                    let ref mut old_clust_words: HashMap<String, u32> = self.cluster_word_distributions[z_old];
                    for word in doc {
                        *old_clust_words.get_mut(word).unwrap() -= 1_u32;

                        // compact dictionary once a key is exausted.
                        if old_clust_words[word] == 0_u32 {
                            old_clust_words.remove(word);
                        }
                    }
                }

                // update the probability vector
                let p = self.score(&doc);

                // choose the next cluster randomly according to the computed probability
                let z_new: usize = random_choice().random_choice_f64(&self.clusters, &p, 1)[0].clone();

                // transfer document to the new cluster
                if z_new != z_old {
                    total_transfers += 1;
                }
                self.labels[i] = z_new;
                self.cluster_counts[z_new] += 1_u32;
                self.cluster_word_counts[z_new] += doc_size;

                {
                    let ref mut new_clust_words: HashMap<String, u32> = self.cluster_word_distributions[z_new];
                    for word in doc {
                        if !new_clust_words.contains_key(word) {
                            new_clust_words.insert(word.clone(), 0_u32);
                        }
                            *new_clust_words.get_mut(word).unwrap() += 1_u32;
                    }
                }
            }
            let new_number_clusters = self.cluster_word_distributions.iter().map(|c| if c.len()>0 {1} else {0} ).sum();
            println!("Iteration {}: {} docs transferred with {} clusters populated.", it, total_transfers, new_number_clusters);

            // apply ad-hoc convergence test
            if total_transfers==0 && new_number_clusters==number_clusters {
                println!("Converged after {} iterations. Solution has {} clusters.", it, new_number_clusters);
                break
            }
            number_clusters = new_number_clusters;
        }
    }

    pub fn score(&self, doc:&Vec<String>) -> Vec<f64> {
        /// Score an input document using the formula of Yin and Wang 2014 (equation 3)
        /// http://dbgroup.cs.tsinghua.edu.cn/wangjy/papers/KDD14-GSDMM.pdf
        ///
        /// # Arguments
        ///
        /// * `doc` - A vector of unique string tokens characterizing the document
        ///
        /// # Value
        ///
        /// Vec<f64> - A length K probability vector where each component represents the probability
        /// of the doc belonging to a particular cluster.
        ///

        // We break the formula into the following pieces
        // p = N1*N2/(D1*D2) = exp(lN1 - lD1 + lN2 - lD2)
        // lN1 = log(m_z[z] + alpha)
        // lN2 = log(D - 1 + K*alpha)
        // lN2 = log(product(n_z_w[w] + beta)) = sum(log(n_z_w[w] + beta))
        // lD2 = log(product(n_z[d] + V*beta + i -1)) = sum(log(n_z[d] + V*beta + i -1))
        let mut p = (0..self.K).map(|_| 0_f64).collect::<Vec<f64>>();
        let lD1 = ((self.D - 1) as f64 + (self.K as f64) * self.alpha).ln();
        let doc_size = doc.len() as u32;
        for label in 0_usize..self.K {
            let lN1 = (self.cluster_counts[label] as f64 + self.alpha).ln();
            let mut lN2 = 0_f64;
            let mut lD2 = 0_f64;

            let ref cluster: HashMap<String, u32> = self.cluster_word_distributions[label];

            for word in doc {
                lN2 += (*cluster.get(word).unwrap_or(&0_u32) as f64 + self.beta).ln();
            }
            for j in 1_u32..(doc_size+1) {
                lD2 += ((self.cluster_word_counts[label] + j) as f64 - 1_f64 + self.V * self.beta).ln();
            }
            p[label] = (lN1 - lD1 + lN2 - lD2).exp();
        }

        // normalize the probability
        let pnorm: f64 = p.iter().sum();
        if pnorm>0_f64 {
            for label in 0_usize..self.K {
                p[label] = p[label] / pnorm;
            }
        }
        p
    }

    fn zero_vector(size:usize) -> Vec<u32>
    {
        let mut v = Vec::<u32>::with_capacity(size);
        for _ in 0_usize..size {
            v.push(0_u32)
        }
        v
    }

}

#[test]
fn simple_run() {
    let mut vocab = HashSet::<String>::new();
    vocab.insert("A".to_string());
    vocab.insert("B".to_string());
    vocab.insert("C".to_string());

    let mut docs = Vec::<Vec<String>>::new();
    docs.push(vec!("A".to_string()));
    docs.push(vec!("A".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("B".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));
    docs.push(vec!("C".to_string()));

    let mut model = GSDMM::new(0.1, 0.00001, 10, 30, vocab, docs);
    model.fit();

    // check the total number across all partitions is equal to the number of docs
    assert_eq!(18, model.cluster_counts.iter().sum::<u32>());

    // check that we get three clusters
    assert_eq!(3, model.cluster_counts.into_iter().filter(|x| x>&0_u32 ).collect::<Vec<u32>>().len());

    // check that the clusters are pure
    println!("{:?}", model.cluster_word_distributions);
    let mut check_map = HashMap::<usize,String>::new();
    for (i,label) in vec!("A","A","B","B","B","B","B","B","B","B","C","C","C","C","C","C","C","C").into_iter().enumerate() {
        if check_map.contains_key(&model.labels[i]) {
            assert_eq!(check_map[&model.labels[i]], label);
        } else {
            check_map.insert(model.labels[i], label.to_string());
        }

    }
}
<|endoftext|>


<commit_before>//
// Copyright 2014-2016 the slack-rs authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Slack realtime messaging client: https://api.slack.com/bot-users
//!
//! See [CHANGELOG.md](https://github.com/slack-rs/slack-rs/blob/master/CHANGELOG.md) for latest
//! release notes.

extern crate reqwest;
pub extern crate slack_api as api;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tungstenite;
#[macro_use]
extern crate log;

pub mod error;
pub use error::Error;

pub use api::{Channel, Group, Im, Team, User, Message};

mod events;
pub use events::Event;

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{self, channel};
use events::{MessageSent, MessageError};

/// Implement this trait in your code to handle message events
pub trait EventHandler {
    /// When a message is received this will be called with self, the slack client,
    /// and the `Event` received.
    fn on_event(&mut self, cli: &RtmClient, event: Event);

    /// Called when the connection is closed for any reason.
    fn on_close(&mut self, cli: &RtmClient);

    /// Called when the connection is opened.
    fn on_connect(&mut self, cli: &RtmClient);
}

/// Used for passing websocket messages in channels
#[derive(Debug)]
enum WsMessage {
    Close,
    Text(String),
}

/// The actual messaging client.
pub struct RtmClient {
    start_response: api::rtm::StartResponse,
    sender: Sender,
    rx: mpsc::Receiver<WsMessage>,
}

/// Thread-safe API for sending messages asynchronously
#[derive(Clone)]
pub struct Sender {
    tx: mpsc::Sender<WsMessage>,
    msg_num: Arc<AtomicUsize>,
}

impl Sender {
    /// Get the next message id
    ///
    /// A value returned from this method *must* be included in the JSON payload
    /// (the `id` field) when constructing your own message.
    pub fn get_msg_uid(&self) -> usize {
        self.msg_num.fetch_add(1, Ordering::SeqCst)
    }

    /// Send a raw message
    ///
    /// Must set `message.id` using result of `get_msg_id()`.
    ///
    /// Success from this API does not guarantee the message is delivered
    /// successfully since that runs on a separate task.
    pub fn send(&self, raw: &str) -> Result<(), Error> {
        self.tx
            .send(WsMessage::Text(raw.to_string()))
            .map_err(|err| Error::Internal(format!("{}", err)))?;
        Ok(())
    }

    /// Send a message to the specified channel id
    ///
    /// Success from this API does not guarantee the message is delivered
    /// successfully since that runs on a separate task.
    ///
    /// `channel_id` is the slack channel id, e.g. `UXYZ1234`, *not* `#general`.
    ///
    /// Only valid after `RtmClient::run`.
    pub fn send_message(&self, channel_id: &str, msg: &str) -> Result<usize, Error> {
        let n = self.get_msg_uid();
        let msg_json = serde_json::to_string(&msg)?;
        let mstr = format!(r#"{{"id": {},"type": "message", "channel": "{}","text": "{}"}}"#,
                           n,
                           channel_id,
                           &msg_json[1..msg_json.len() - 1]);

        self.send(&mstr[..])
            .map_err(|err| Error::Internal(format!("{}", err)))?;

        Ok(n)
    }

    /// Marks connected client as being typing to a channel
    /// This is mostly used to signal to other peers that a message
    /// is being typed. Will have the server send a "user_typing" message to all the
    /// peers.
    /// Slack doc can be found at https://api.slack.com/rtm under "Typing Indicators"
    ///
    /// `channel_id` is the slack channel id, e.g. `UXYZ1234`, not `#general`.
    pub fn send_typing(&self, channel_id: &str) -> Result<usize, Error> {
        let n = self.get_msg_uid();
        let mstr = format!(r#"{{"id": {}, "type": "typing", "channel": "{}"}}"#,
                           n,
                           channel_id);

        self.send(&mstr)
            .map_err(|err| Error::Internal(format!("{:?}", err)))?;
        Ok(n)
    }

    /// Subscribes to presence updates for the given users
    /// This is due to the update in presence events detailed here:
    /// https://api.slack.com/changelog/2017-10-making-rtm-presence-subscription-only
    ///
    /// `user_list` is a slice of the list of users to subscrib, e.g. `W839208`, not @xyz.
    /// The full list of users to subscribe to must be sent each time the subscription should
    /// change
    /// Slack doc can be found at https://api.slack.com/docs/presence-and-status under "Determining
    /// user presence"
    pub fn subscribe_presence(&self, user_list: &[&str]) -> Result<usize, Error> {
        let n = self.get_msg_uid();
        let mstr = format!(r#"{{"type": "presence_sub", "ids": "{:?}"}}"#,
                           user_list);

        self.send(&mstr)
            .map_err(|err| Error::Internal(format!("{:?}", err)))?;
        Ok(n)
    }

    /// Shutdown `RtmClient`
    pub fn shutdown(&self) -> Result<(), Error> {
        self.tx
            .send(WsMessage::Close)
            .map_err(|_| Error::Internal("Error sending shutdown message".into()))
    }
}

impl RtmClient {
    /// Logs in to slack. Call this before calling `run`.
    /// Alternatively use `login_and_run`.
    pub fn login(token: &str) -> Result<RtmClient, Error> {
        let client = reqwest::Client::new();
        let start_response = api::rtm::start(&client, token, &Default::default())?;

        // setup channels for passing messages
        let (tx, rx) = channel::<WsMessage>();
        let sender = Sender {
            tx: tx,
            msg_num: Arc::new(AtomicUsize::new(0)),
        };

        Ok(RtmClient {
               start_response: start_response,
               sender: sender,
               rx: rx,
           })
    }

    /// Runs the message receive loop
    pub fn run<T: EventHandler>(&self, handler: &mut T) -> Result<(), Error> {
        let start_url = self.start_response
            .url
            .as_ref()
            .ok_or(Error::Api("Slack did not provide a URL".into()))?;
        let mut start_url_qp = start_url.clone();
        start_url_qp.push_str(&("?batch_presence_aware=1".to_string()));
        println!("start_url returned is \"{:?}\"", start_url_qp);
        let wss_url = reqwest::Url::parse(&start_url_qp)?;
        let (mut websocket, _resp) = tungstenite::client::connect(wss_url)?;

        // Slack can leave us hanging
        {
            let socket = match *websocket.get_mut() {
                tungstenite::stream::Stream::Plain(ref s) => s,
                tungstenite::stream::Stream::Tls(ref mut t) => t.get_mut()
            };
            socket.set_read_timeout(Some(std::time::Duration::from_secs(30)))?;
            socket.set_write_timeout(Some(std::time::Duration::from_secs(25)))?;
        }

        handler.on_connect(self);

        let mut prev_ = ::std::time::Instant::now();

        // receive loop
        loop {
            // try to write out pending messages (if any)
            loop {
                match self.rx.try_recv() {
                    Ok(msg) => {
                        match msg {
                            WsMessage::Text(text) => {
                                websocket
                                    .write_message(tungstenite::Message::Text(text))?
                            }
                            WsMessage::Close => {
                                handler.on_close(self);
                                return websocket.close(None).map_err(|e| e.into());
                            }
                        }
                    }
                    Err(mpsc::TryRecvError::Disconnected) => {
                        handler.on_close(self);
                        return Err(Error::Internal("rx disconnected".into()));
                    }
                    Err(mpsc::TryRecvError::Empty) => break,
                }
            }

            // blocks until a message is received or websocket errors
            let message = match websocket.read_message() {
                Err(e) => {
                    debug!("{:?}", e);
                    // read failed, try send ping to check still alive
                    websocket.write_message(tungstenite::Message::Ping(vec![]))?;
                    continue;
                }
                Ok(m) => m
            };

            let received = ::std::time::Instant::now(); {
                let print_recieved = |var: &str| {
                    debug!("RTM WS {} recieved {:?} since last msg", var, received - prev_);
                };
                // handle the message
                match message {
                    tungstenite::Message::Text(text) => {
                        match Event::from_json(&text[..]) {
                            Ok(event) => handler.on_event(self, event),
                            Err(err) => {
                                info!("Unable to deserialize slack message, error: {}: json: {}",
                                      err,
                                      text);
                            }
                        }
                    }
                    tungstenite::Message::Binary(_) => print_recieved("Binary"),
                    tungstenite::Message::Ping(_) => print_recieved("Ping"),
                    tungstenite::Message::Pong(_) => print_recieved("Pong"),
                }
            }
            prev_ = received;
        }
    }

    /// Runs the main loop for the client after logging in to slack.
    ///
    /// Returns an error if the process fails at any point, or an Ok(()) on successful
    /// close.
    ///
    /// Takes an `EventHandler` implemented by the user which will be called when `Event`s are
    /// received.
    pub fn login_and_run<T: EventHandler>(token: &str, handler: &mut T) -> Result<(), Error> {
        let client = RtmClient::login(token)?;
        client.run(handler)
    }

    /// Get a reference thread-safe cloneable message `Sender`
    pub fn sender(&self) -> &Sender {
        &self.sender
    }

    /// Returns a reference to the `StartResponse`.
    pub fn start_response(&self) -> &api::rtm::StartResponse {
        &self.start_response
    }
}

impl Event {
    /// Try to deserialize an `Event` from a json-encoded `&str`
    fn from_json(s: &str) -> Result<Event, Error> {
        match serde_json::from_str::<Event>(s) {
            Ok(ev) => Ok(ev),
            Err(e) => {
                // try for the MessageSent / MessageError variants that don't expose type
                if let Ok(ev) = serde_json::from_str::<MessageSent>(s) {
                    Ok(Event::MessageSent(ev))
                } else if let Ok(ev) = serde_json::from_str::<MessageError>(s) {
                    Ok(Event::MessageError(ev))
                } else {
                    Err(e.into())
                }
            }
        }
    }
}
<commit_msg>fix json bug<commit_after>//
// Copyright 2014-2016 the slack-rs authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Slack realtime messaging client: https://api.slack.com/bot-users
//!
//! See [CHANGELOG.md](https://github.com/slack-rs/slack-rs/blob/master/CHANGELOG.md) for latest
//! release notes.

extern crate reqwest;
pub extern crate slack_api as api;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tungstenite;
#[macro_use]
extern crate log;

pub mod error;
pub use error::Error;

pub use api::{Channel, Group, Im, Team, User, Message};

mod events;
pub use events::Event;

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{self, channel};
use events::{MessageSent, MessageError};

/// Implement this trait in your code to handle message events
pub trait EventHandler {
    /// When a message is received this will be called with self, the slack client,
    /// and the `Event` received.
    fn on_event(&mut self, cli: &RtmClient, event: Event);

    /// Called when the connection is closed for any reason.
    fn on_close(&mut self, cli: &RtmClient);

    /// Called when the connection is opened.
    fn on_connect(&mut self, cli: &RtmClient);
}

/// Used for passing websocket messages in channels
#[derive(Debug)]
enum WsMessage {
    Close,
    Text(String),
}

/// The actual messaging client.
pub struct RtmClient {
    start_response: api::rtm::StartResponse,
    sender: Sender,
    rx: mpsc::Receiver<WsMessage>,
}

/// Thread-safe API for sending messages asynchronously
#[derive(Clone)]
pub struct Sender {
    tx: mpsc::Sender<WsMessage>,
    msg_num: Arc<AtomicUsize>,
}

impl Sender {
    /// Get the next message id
    ///
    /// A value returned from this method *must* be included in the JSON payload
    /// (the `id` field) when constructing your own message.
    pub fn get_msg_uid(&self) -> usize {
        self.msg_num.fetch_add(1, Ordering::SeqCst)
    }

    /// Send a raw message
    ///
    /// Must set `message.id` using result of `get_msg_id()`.
    ///
    /// Success from this API does not guarantee the message is delivered
    /// successfully since that runs on a separate task.
    pub fn send(&self, raw: &str) -> Result<(), Error> {
        self.tx
            .send(WsMessage::Text(raw.to_string()))
            .map_err(|err| Error::Internal(format!("{}", err)))?;
        Ok(())
    }

    /// Send a message to the specified channel id
    ///
    /// Success from this API does not guarantee the message is delivered
    /// successfully since that runs on a separate task.
    ///
    /// `channel_id` is the slack channel id, e.g. `UXYZ1234`, *not* `#general`.
    ///
    /// Only valid after `RtmClient::run`.
    pub fn send_message(&self, channel_id: &str, msg: &str) -> Result<usize, Error> {
        let n = self.get_msg_uid();
        let msg_json = serde_json::to_string(&msg)?;
        let mstr = format!(r#"{{"id": {},"type": "message", "channel": "{}","text": "{}"}}"#,
                           n,
                           channel_id,
                           &msg_json[1..msg_json.len() - 1]);

        self.send(&mstr[..])
            .map_err(|err| Error::Internal(format!("{}", err)))?;

        Ok(n)
    }

    /// Marks connected client as being typing to a channel
    /// This is mostly used to signal to other peers that a message
    /// is being typed. Will have the server send a "user_typing" message to all the
    /// peers.
    /// Slack doc can be found at https://api.slack.com/rtm under "Typing Indicators"
    ///
    /// `channel_id` is the slack channel id, e.g. `UXYZ1234`, not `#general`.
    pub fn send_typing(&self, channel_id: &str) -> Result<usize, Error> {
        let n = self.get_msg_uid();
        let mstr = format!(r#"{{"id": {}, "type": "typing", "channel": "{}"}}"#,
                           n,
                           channel_id);

        self.send(&mstr)
            .map_err(|err| Error::Internal(format!("{:?}", err)))?;
        Ok(n)
    }

    /// Subscribes to presence updates for the given users
    /// This is due to the update in presence events detailed here:
    /// https://api.slack.com/changelog/2017-10-making-rtm-presence-subscription-only
    ///
    /// `user_list` is a slice of the list of users to subscrib, e.g. `W839208`, not @xyz.
    /// The full list of users to subscribe to must be sent each time the subscription should
    /// change
    /// Slack doc can be found at https://api.slack.com/docs/presence-and-status under "Determining
    /// user presence"
    pub fn subscribe_presence(&self, user_list: &[&str]) -> Result<usize, Error> {
        let n = self.get_msg_uid();
        let mstr = format!(r#"{{"type": "presence_sub", "ids": {:?}}}"#,
                           user_list);

        self.send(&mstr)
            .map_err(|err| Error::Internal(format!("{:?}", err)))?;
        Ok(n)
    }

    /// Shutdown `RtmClient`
    pub fn shutdown(&self) -> Result<(), Error> {
        self.tx
            .send(WsMessage::Close)
            .map_err(|_| Error::Internal("Error sending shutdown message".into()))
    }
}

impl RtmClient {
    /// Logs in to slack. Call this before calling `run`.
    /// Alternatively use `login_and_run`.
    pub fn login(token: &str) -> Result<RtmClient, Error> {
        let client = reqwest::Client::new();
        let start_response = api::rtm::start(&client, token, &Default::default())?;

        // setup channels for passing messages
        let (tx, rx) = channel::<WsMessage>();
        let sender = Sender {
            tx: tx,
            msg_num: Arc::new(AtomicUsize::new(0)),
        };

        Ok(RtmClient {
               start_response: start_response,
               sender: sender,
               rx: rx,
           })
    }

    /// Runs the message receive loop
    pub fn run<T: EventHandler>(&self, handler: &mut T) -> Result<(), Error> {
        let start_url = self.start_response
            .url
            .as_ref()
            .ok_or(Error::Api("Slack did not provide a URL".into()))?;
        let mut start_url_qp = start_url.clone();
        start_url_qp.push_str(&("?batch_presence_aware=1".to_string()));
        println!("start_url returned is \"{:?}\"", start_url_qp);
        let wss_url = reqwest::Url::parse(&start_url_qp)?;
        let (mut websocket, _resp) = tungstenite::client::connect(wss_url)?;

        // Slack can leave us hanging
        {
            let socket = match *websocket.get_mut() {
                tungstenite::stream::Stream::Plain(ref s) => s,
                tungstenite::stream::Stream::Tls(ref mut t) => t.get_mut()
            };
            socket.set_read_timeout(Some(std::time::Duration::from_secs(30)))?;
            socket.set_write_timeout(Some(std::time::Duration::from_secs(25)))?;
        }

        handler.on_connect(self);

        let mut prev_ = ::std::time::Instant::now();

        // receive loop
        loop {
            // try to write out pending messages (if any)
            loop {
                match self.rx.try_recv() {
                    Ok(msg) => {
                        match msg {
                            WsMessage::Text(text) => {
                                websocket
                                    .write_message(tungstenite::Message::Text(text))?
                            }
                            WsMessage::Close => {
                                handler.on_close(self);
                                return websocket.close(None).map_err(|e| e.into());
                            }
                        }
                    }
                    Err(mpsc::TryRecvError::Disconnected) => {
                        handler.on_close(self);
                        return Err(Error::Internal("rx disconnected".into()));
                    }
                    Err(mpsc::TryRecvError::Empty) => break,
                }
            }

            // blocks until a message is received or websocket errors
            let message = match websocket.read_message() {
                Err(e) => {
                    debug!("{:?}", e);
                    // read failed, try send ping to check still alive
                    websocket.write_message(tungstenite::Message::Ping(vec![]))?;
                    continue;
                }
                Ok(m) => m
            };

            let received = ::std::time::Instant::now(); {
                let print_recieved = |var: &str| {
                    debug!("RTM WS {} recieved {:?} since last msg", var, received - prev_);
                };
                // handle the message
                match message {
                    tungstenite::Message::Text(text) => {
                        match Event::from_json(&text[..]) {
                            Ok(event) => handler.on_event(self, event),
                            Err(err) => {
                                info!("Unable to deserialize slack message, error: {}: json: {}",
                                      err,
                                      text);
                            }
                        }
                    }
                    tungstenite::Message::Binary(_) => print_recieved("Binary"),
                    tungstenite::Message::Ping(_) => print_recieved("Ping"),
                    tungstenite::Message::Pong(_) => print_recieved("Pong"),
                }
            }
            prev_ = received;
        }
    }

    /// Runs the main loop for the client after logging in to slack.
    ///
    /// Returns an error if the process fails at any point, or an Ok(()) on successful
    /// close.
    ///
    /// Takes an `EventHandler` implemented by the user which will be called when `Event`s are
    /// received.
    pub fn login_and_run<T: EventHandler>(token: &str, handler: &mut T) -> Result<(), Error> {
        let client = RtmClient::login(token)?;
        client.run(handler)
    }

    /// Get a reference thread-safe cloneable message `Sender`
    pub fn sender(&self) -> &Sender {
        &self.sender
    }

    /// Returns a reference to the `StartResponse`.
    pub fn start_response(&self) -> &api::rtm::StartResponse {
        &self.start_response
    }
}

impl Event {
    /// Try to deserialize an `Event` from a json-encoded `&str`
    fn from_json(s: &str) -> Result<Event, Error> {
        match serde_json::from_str::<Event>(s) {
            Ok(ev) => Ok(ev),
            Err(e) => {
                // try for the MessageSent / MessageError variants that don't expose type
                if let Ok(ev) = serde_json::from_str::<MessageSent>(s) {
                    Ok(Event::MessageSent(ev))
                } else if let Ok(ev) = serde_json::from_str::<MessageError>(s) {
                    Ok(Event::MessageError(ev))
                } else {
                    Err(e.into())
                }
            }
        }
    }
}
<|endoftext|>