<commit_before>use crate::controllers::prelude::*;

use crate::controllers::helpers::*;
use crate::email;
use crate::util::bad_request;
use crate::util::errors::CargoError;

use crate::models::{CrateOwner, Email, Follow, NewEmail, User, Version};
use crate::schema::{crate_owners, crates, emails, follows, users, versions};
use crate::views::{EncodableMe, EncodableVersion, OwnedCrate};

/// Handles the `GET /me` route.
pub fn me(req: &mut dyn Request) -> CargoResult<Response> {
    // Changed to getting User information from database because in
    // src/tests/user.rs, when testing put and get on updating email,
    // request seems to be somehow 'cached'. When we try to get a
    // request from the /me route with the just updated user (call
    // this function) the user is the same as the initial GET request
    // and does not seem to get the updated user information from the
    // database
    // This change is not preferable, we'd rather fix the request,
    // perhaps adding `req.mut_extensions().insert(user)` to the
    // update_user route, however this somehow does not seem to work

    let user_id = req.user()?.id;
    let conn = req.db_conn()?;

    let (user, verified, email, verification_sent) = users::table
        .find(user_id)
        .left_join(emails::table)
        .select((
            users::all_columns,
            emails::verified.nullable(),
            emails::email.nullable(),
            emails::token_generated_at.nullable().is_not_null(),
        ))
        .first::<(User, Option<bool>, Option<String>, bool)>(&*conn)?;

    let owned_crates = crate_owners::table
        .inner_join(crates::table)
        .filter(crate_owners::owner_id.eq(user_id))
        .select((crates::id, crates::name, crate_owners::email_notifications))
        .order(crates::name.asc())
        .load(&*conn)?
        .into_iter()
        .map(|(id, name, email_notifications)| OwnedCrate {
            id,
            name,
            email_notifications,
        })
        .collect();

    let verified = verified.unwrap_or(false);
    let verification_sent = verified || verification_sent;
    let user = User { email, ..user };

    Ok(req.json(&EncodableMe {
        user: user.encodable_private(verified, verification_sent),
        owned_crates,
    }))
}

/// Handles the `GET /me/updates` route.
pub fn updates(req: &mut dyn Request) -> CargoResult<Response> {
    use diesel::dsl::any;

    let user = req.user()?;
    let conn = req.db_conn()?;

    let followed_crates = Follow::belonging_to(user).select(follows::crate_id);
    let data = versions::table
        .inner_join(crates::table)
        .left_outer_join(users::table)
        .filter(crates::id.eq(any(followed_crates)))
        .order(versions::created_at.desc())
        .select((
            versions::all_columns,
            crates::name,
            users::all_columns.nullable(),
        ))
        .paginate(&req.query())?
        .load::<(Version, String, Option<User>)>(&*conn)?;

    let more = data.next_page_params().is_some();

    let versions = data
        .into_iter()
        .map(|(version, crate_name, published_by)| version.encodable(&crate_name, published_by))
        .collect();

    #[derive(Serialize)]
    struct R {
        versions: Vec<EncodableVersion>,
        meta: Meta,
    }
    #[derive(Serialize)]
    struct Meta {
        more: bool,
    }
    Ok(req.json(&R {
        versions,
        meta: Meta { more },
    }))
}

/// Handles the `PUT /user/:user_id` route.
pub fn update_user(req: &mut dyn Request) -> CargoResult<Response> {
    use self::emails::user_id;
    use self::users::dsl::{email, gh_login, users};
    use diesel::{insert_into, update};

    let mut body = String::new();
    req.body().read_to_string(&mut body)?;
    let user = req.user()?;
    let name = &req.params()["user_id"];
    let conn = req.db_conn()?;

    // need to check if current user matches user to be updated
    if &user.id.to_string() != name {
        return Err(human("current user does not match requested user"));
    }

    #[derive(Deserialize)]
    struct UserUpdate {
        user: User,
    }

    #[derive(Deserialize)]
    struct User {
        email: Option<String>,
    }

    let user_update: UserUpdate =
        serde_json::from_str(&body).map_err(|_| human("invalid json request"))?;

    if user_update.user.email.is_none() {
        return Err(human("empty email rejected"));
    }

    let user_email = user_update.user.email.unwrap();
    let user_email = user_email.trim();

    if user_email == "" {
        return Err(human("empty email rejected"));
    }

    conn.transaction::<_, Box<dyn CargoError>, _>(|| {
        update(users.filter(gh_login.eq(&user.gh_login)))
            .set(email.eq(user_email))
            .execute(&*conn)?;

        let new_email = NewEmail {
            user_id: user.id,
            email: user_email,
        };

        let token = insert_into(emails::table)
            .values(&new_email)
            .on_conflict(user_id)
            .do_update()
            .set(&new_email)
            .returning(emails::token)
            .get_result::<String>(&*conn)
            .map_err(|_| human("Error in creating token"))?;

        crate::email::send_user_confirm_email(user_email, &user.gh_login, &token);

        Ok(())
    })?;

    #[derive(Serialize)]
    struct R {
        ok: bool,
    }
    Ok(req.json(&R { ok: true }))
}

/// Handles the `PUT /confirm/:email_token` route
pub fn confirm_user_email(req: &mut dyn Request) -> CargoResult<Response> {
    use diesel::update;

    let conn = req.db_conn()?;
    let req_token = &req.params()["email_token"];

    let updated_rows = update(emails::table.filter(emails::token.eq(req_token)))
        .set(emails::verified.eq(true))
        .execute(&*conn)?;

    if updated_rows == 0 {
        return Err(bad_request("Email belonging to token not found."));
    }

    #[derive(Serialize)]
    struct R {
        ok: bool,
    }
    Ok(req.json(&R { ok: true }))
}

/// Handles `PUT /user/:user_id/resend` route
pub fn regenerate_token_and_send(req: &mut dyn Request) -> CargoResult<Response> {
    use diesel::dsl::sql;
    use diesel::update;

    let user = req.user()?;
    let name = &req.params()["user_id"].parse::<i32>().ok().unwrap();
    let conn = req.db_conn()?;

    // need to check if current user matches user to be updated
    if &user.id != name {
        return Err(human("current user does not match requested user"));
    }

    conn.transaction(|| {
        let email = update(Email::belonging_to(user))
            .set(emails::token.eq(sql("DEFAULT")))
            .get_result::<Email>(&*conn)
            .map_err(|_| bad_request("Email could not be found"))?;

        email::try_send_user_confirm_email(&email.email, &user.gh_login, &email.token)
            .map_err(|_| bad_request("Error in sending email"))
    })?;

    #[derive(Serialize)]
    struct R {
        ok: bool,
    }
    Ok(req.json(&R { ok: true }))
}

/// Handles `PUT /me/email_notifications` route
pub fn update_email_notifications(req: &mut dyn Request) -> CargoResult<Response> {
    use self::crate_owners::dsl::*;
    use diesel::update;

    #[derive(Deserialize)]
    struct CrateEmailNotifications {
        id: i32,
        email_notifications: bool,
    }

    let mut body = String::new();
    req.body().read_to_string(&mut body)?;
    let updates: Vec<CrateEmailNotifications> =
        serde_json::from_str(&body).map_err(|_| human("invalid json request"))?;

    let user = req.user()?;
    let conn = req.db_conn()?;

    for to_update in updates {
        update(CrateOwner::belonging_to(user))
            .set(email_notifications.eq(to_update.email_notifications))
            .filter(crate_id.eq(to_update.id))
            .filter(email_notifications.ne(to_update.email_notifications))
            .execute(&*conn)
            .map_err(|_| human("Error updating crate owner email notifications"))?;
    }

    #[derive(Serialize)]
    struct R {
        ok: bool,
    }
    Ok(req.json(&R { ok: true }))
}
<commit_msg>Unconditionally update crate owners<commit_after>use std::collections::HashMap;

use crate::controllers::prelude::*;

use crate::controllers::helpers::*;
use crate::email;
use crate::util::bad_request;
use crate::util::errors::CargoError;

use crate::models::{CrateOwner, Email, Follow, NewEmail, OwnerKind, User, Version};
use crate::schema::{crate_owners, crates, emails, follows, users, versions};
use crate::views::{EncodableMe, EncodableVersion, OwnedCrate};

/// Handles the `GET /me` route.
pub fn me(req: &mut dyn Request) -> CargoResult<Response> {
    // Changed to getting User information from database because in
    // src/tests/user.rs, when testing put and get on updating email,
    // request seems to be somehow 'cached'. When we try to get a
    // request from the /me route with the just updated user (call
    // this function) the user is the same as the initial GET request
    // and does not seem to get the updated user information from the
    // database
    // This change is not preferable, we'd rather fix the request,
    // perhaps adding `req.mut_extensions().insert(user)` to the
    // update_user route, however this somehow does not seem to work

    let user_id = req.user()?.id;
    let conn = req.db_conn()?;

    let (user, verified, email, verification_sent) = users::table
        .find(user_id)
        .left_join(emails::table)
        .select((
            users::all_columns,
            emails::verified.nullable(),
            emails::email.nullable(),
            emails::token_generated_at.nullable().is_not_null(),
        ))
        .first::<(User, Option<bool>, Option<String>, bool)>(&*conn)?;

    let owned_crates = crate_owners::table
        .inner_join(crates::table)
        .filter(crate_owners::owner_id.eq(user_id))
        .filter(crate_owners::owner_kind.eq(OwnerKind::User as i32))
        .select((crates::id, crates::name, crate_owners::email_notifications))
        .order(crates::name.asc())
        .load(&*conn)?
        .into_iter()
        .map(|(id, name, email_notifications)| OwnedCrate {
            id,
            name,
            email_notifications,
        })
        .collect();

    let verified = verified.unwrap_or(false);
    let verification_sent = verified || verification_sent;
    let user = User { email, ..user };

    Ok(req.json(&EncodableMe {
        user: user.encodable_private(verified, verification_sent),
        owned_crates,
    }))
}

/// Handles the `GET /me/updates` route.
pub fn updates(req: &mut dyn Request) -> CargoResult<Response> {
    use diesel::dsl::any;

    let user = req.user()?;
    let conn = req.db_conn()?;

    let followed_crates = Follow::belonging_to(user).select(follows::crate_id);
    let data = versions::table
        .inner_join(crates::table)
        .left_outer_join(users::table)
        .filter(crates::id.eq(any(followed_crates)))
        .order(versions::created_at.desc())
        .select((
            versions::all_columns,
            crates::name,
            users::all_columns.nullable(),
        ))
        .paginate(&req.query())?
        .load::<(Version, String, Option<User>)>(&*conn)?;

    let more = data.next_page_params().is_some();

    let versions = data
        .into_iter()
        .map(|(version, crate_name, published_by)| version.encodable(&crate_name, published_by))
        .collect();

    #[derive(Serialize)]
    struct R {
        versions: Vec<EncodableVersion>,
        meta: Meta,
    }
    #[derive(Serialize)]
    struct Meta {
        more: bool,
    }
    Ok(req.json(&R {
        versions,
        meta: Meta { more },
    }))
}

/// Handles the `PUT /user/:user_id` route.
pub fn update_user(req: &mut dyn Request) -> CargoResult<Response> {
    use self::emails::user_id;
    use self::users::dsl::{email, gh_login, users};
    use diesel::{insert_into, update};

    let mut body = String::new();
    req.body().read_to_string(&mut body)?;
    let user = req.user()?;
    let name = &req.params()["user_id"];
    let conn = req.db_conn()?;

    // need to check if current user matches user to be updated
    if &user.id.to_string() != name {
        return Err(human("current user does not match requested user"));
    }

    #[derive(Deserialize)]
    struct UserUpdate {
        user: User,
    }

    #[derive(Deserialize)]
    struct User {
        email: Option<String>,
    }

    let user_update: UserUpdate =
        serde_json::from_str(&body).map_err(|_| human("invalid json request"))?;

    if user_update.user.email.is_none() {
        return Err(human("empty email rejected"));
    }

    let user_email = user_update.user.email.unwrap();
    let user_email = user_email.trim();

    if user_email == "" {
        return Err(human("empty email rejected"));
    }

    conn.transaction::<_, Box<dyn CargoError>, _>(|| {
        update(users.filter(gh_login.eq(&user.gh_login)))
            .set(email.eq(user_email))
            .execute(&*conn)?;

        let new_email = NewEmail {
            user_id: user.id,
            email: user_email,
        };

        let token = insert_into(emails::table)
            .values(&new_email)
            .on_conflict(user_id)
            .do_update()
            .set(&new_email)
            .returning(emails::token)
            .get_result::<String>(&*conn)
            .map_err(|_| human("Error in creating token"))?;

        crate::email::send_user_confirm_email(user_email, &user.gh_login, &token);

        Ok(())
    })?;

    #[derive(Serialize)]
    struct R {
        ok: bool,
    }
    Ok(req.json(&R { ok: true }))
}

/// Handles the `PUT /confirm/:email_token` route
pub fn confirm_user_email(req: &mut dyn Request) -> CargoResult<Response> {
    use diesel::update;

    let conn = req.db_conn()?;
    let req_token = &req.params()["email_token"];

    let updated_rows = update(emails::table.filter(emails::token.eq(req_token)))
        .set(emails::verified.eq(true))
        .execute(&*conn)?;

    if updated_rows == 0 {
        return Err(bad_request("Email belonging to token not found."));
    }

    #[derive(Serialize)]
    struct R {
        ok: bool,
    }
    Ok(req.json(&R { ok: true }))
}

/// Handles `PUT /user/:user_id/resend` route
pub fn regenerate_token_and_send(req: &mut dyn Request) -> CargoResult<Response> {
    use diesel::dsl::sql;
    use diesel::update;

    let user = req.user()?;
    let name = &req.params()["user_id"].parse::<i32>().ok().unwrap();
    let conn = req.db_conn()?;

    // need to check if current user matches user to be updated
    if &user.id != name {
        return Err(human("current user does not match requested user"));
    }

    conn.transaction(|| {
        let email = update(Email::belonging_to(user))
            .set(emails::token.eq(sql("DEFAULT")))
            .get_result::<Email>(&*conn)
            .map_err(|_| bad_request("Email could not be found"))?;

        email::try_send_user_confirm_email(&email.email, &user.gh_login, &email.token)
            .map_err(|_| bad_request("Error in sending email"))
    })?;

    #[derive(Serialize)]
    struct R {
        ok: bool,
    }
    Ok(req.json(&R { ok: true }))
}

/// Handles `PUT /me/email_notifications` route
pub fn update_email_notifications(req: &mut dyn Request) -> CargoResult<Response> {
    use self::crate_owners::dsl::*;
    // use diesel::update;
    use diesel::pg::upsert::excluded;

    #[derive(Deserialize)]
    struct CrateEmailNotifications {
        id: i32,
        email_notifications: bool,
    }

    let mut body = String::new();
    req.body().read_to_string(&mut body)?;
    let updates: HashMap<i32, bool> = serde_json::from_str::<Vec<CrateEmailNotifications>>(&body)
        .map_err(|_| human("invalid json request"))?
        .iter()
        .map(|c| (c.id, c.email_notifications))
        .collect();

    let user = req.user()?;
    let conn = req.db_conn()?;

    // Build inserts from existing crates beloning to the current user
    let to_insert = CrateOwner::belonging_to(user)
        .select((crate_id, owner_id, owner_kind, email_notifications))
        .filter(owner_kind.eq(OwnerKind::User as i32))
        .load(&*conn)?
        .into_iter()
        .map(
            |(c_id, o_id, o_kind, e_notifications): (i32, i32, i32, bool)| {
                (
                    crate_id.eq(c_id),
                    owner_id.eq(o_id),
                    owner_kind.eq(o_kind),
                    email_notifications
                        .eq(updates.get(&c_id).unwrap_or(&e_notifications).to_owned()),
                )
            },
        )
        .collect::<Vec<_>>();

    // Upsert crate owners; this should only actually exectute updates
    diesel::insert_into(crate_owners)
        .values(&to_insert)
        .on_conflict((crate_id, owner_id, owner_kind))
        .do_update()
        .set(email_notifications.eq(excluded(email_notifications)))
        .execute(&*conn)?;

    #[derive(Serialize)]
    struct R {
        ok: bool,
    }
    Ok(req.json(&R { ok: true }))
}
<|endoftext|>


<commit_before>//! TopK implementation.
use countminsketch::CountMinSketch;
use std::cmp::Ordering;
use std::collections::hash_map::Entry;
use std::collections::{BTreeSet, HashMap};
use std::fmt;
use std::hash::Hash;
use std::rc::Rc;

#[derive(Debug)]
struct TreeEntry<T>
where
    T: Eq + Ord,
{
    obj: Rc<T>,
    n: usize,
}

impl<T> Clone for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn clone(&self) -> Self {
        TreeEntry {
            obj: Rc::clone(&self.obj),
            n: self.n,
        }
    }
}

impl<T> PartialEq for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn eq(&self, other: &TreeEntry<T>) -> bool {
        self.obj == other.obj
    }
}

impl<T> Eq for TreeEntry<T> where T: Eq + Ord {}

impl<T> PartialOrd for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn partial_cmp(&self, other: &TreeEntry<T>) -> Option<Ordering> {
        match self.n.cmp(&other.n) {
            Ordering::Greater => Some(Ordering::Greater),
            Ordering::Less => Some(Ordering::Less),
            Ordering::Equal => Some(self.obj.cmp(&other.obj)),
        }
    }
}

impl<T> Ord for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn cmp(&self, other: &TreeEntry<T>) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

/// A TopK is a data structure keeps the `k` most frequent data points of a stream.
///
/// # Examples
/// ```
/// use pdatastructs::countminsketch::CountMinSketch;
/// use pdatastructs::topk::TopK;
///
/// // set up filter
/// let epsilon = 0.1;  // error threshold
/// let delta = 0.2;  // epsilon is hit in (1 - 0.2) * 100% = 80%
/// let mut cms = CountMinSketch::with_point_query_properties(epsilon, delta);
/// let mut tk = TopK::new(2, cms);
///
/// // add some data
/// for i in 0..1000 {
///     let x = i % 10;
///     let y = if x < 4 {
///         0
///     } else if x < 7 {
///         1
///     } else {
///         x
///     };
///     tk.add(x);
/// }
///
/// // later
/// let elements: Vec<u64> = tk.iter().collect();
/// assert_eq!(elements, vec![0, 1]);
/// ```
///
/// # Applications
/// - getting a fixed number of most common example of a large data set
/// - detect hotspots / very common events
///
/// # How It Works
/// The data structure is based on two parts:
///
/// 1. a reservoir for the most common elements that also stores precise (but not exact) counter
///    data
/// 2. a CountMinSketch to guess the count of all other elements
///
/// On insert, it is checked if the element is already in the reservoir. If so, the precise count
/// is updated. If not, the CountMinSketch is queried for a guess. If the guess is higher than the
/// least common element in the reservoir, the new element displaces this reservoir element. The
/// guess is used as an exact count and is stored alongside. In any case, the CountMinSketch is
/// updated.
///
/// # See Also
/// - `std::vec::Vec`: exact solution but needs to store the entire data stream
///
/// # References
/// - ["Top K Frequent Items Algorithm", Zhipeng Jiang, 2017](https://zpjiang.me/2017/11/13/top-k-elementes-system-design/)
#[derive(Clone)]
pub struct TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    cms: CountMinSketch,
    obj2count: HashMap<Rc<T>, usize>,
    tree: BTreeSet<TreeEntry<T>>,
    k: usize,
}

impl<T> TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    /// Create new Top-K data structure.
    ///
    /// - `k`: number of elements to remember
    /// - `cms`: CountMinSketch that is used for guessing the frequency of elements not currently
    ///   hold. Refer to its documentation about parameter selection.
    ///
    /// Panics if `k == 0`.
    pub fn new(k: usize, cms: CountMinSketch) -> Self {
        assert!(k > 0, "k must be greater than 0");

        Self {
            cms,
            obj2count: HashMap::new(),
            tree: BTreeSet::new(),
            k,
        }
    }

    /// Number of data points to remember.
    pub fn k(&self) -> usize {
        self.k
    }

    /// Observe a data point.
    pub fn add(&mut self, obj: T) {
        // create Rc so we can use obj in multiple data structs
        let rc = Rc::new(obj);

        // always increase CountMinSketch counts
        self.cms.add(&rc);

        // check if entry is in top K
        let size = self.obj2count.len();
        let mut update_obj2count: Option<(usize, Rc<T>)> = None;
        match self.obj2count.entry(Rc::clone(&rc)) {
            Entry::Occupied(mut o) => {
                // it is => increase exact counter
                let mut n = o.get_mut();
                *n += 1;

                // update tree data
                let mut entry = TreeEntry {
                    obj: Rc::clone(&rc),
                    n: *n - 1,
                };
                self.tree.remove(&entry);
                entry.n += 1;
                self.tree.insert(entry);
            }
            Entry::Vacant(v) => {
                // it's not => check capicity
                if size < self.k {
                    // space left => add to top k
                    v.insert(1);
                    self.tree.insert(TreeEntry {
                        obj: Rc::clone(&rc),
                        n: 1,
                    });
                } else {
                    // not enough space => check if it would be a top k element

                    let count = self.cms.query_point(&rc);
                    // count at this point already contains the +1 from the current insertions
                    // because we've updated the CountMinSketch before the query

                    let min: TreeEntry<T> = (*self.tree.iter().next().unwrap()).clone();
                    if count > min.n {
                        // => kick out minimal element of top k
                        self.tree.remove(&min);
                        self.tree.insert(TreeEntry {
                            obj: Rc::clone(&rc),
                            n: count,
                        });

                        // delay obj2count changes, because it is currently borrowed
                        update_obj2count = Some((count, min.obj));
                    }
                }
            }
        }

        // trick the borrow checker
        if let Some((count, obj)) = update_obj2count {
            self.obj2count.insert(rc, count);
            self.obj2count.remove(&obj);
        }
    }

    /// Iterates over collected top-k values.
    ///
    /// The result may contain less than `k` values if less than `k` unique data points where
    /// observed.
    pub fn iter<'a>(&'a self) -> impl 'a + Iterator<Item = T> {
        self.tree.iter().map(|x| (*x.obj).clone())
    }

    /// Check whether the sampler is empty (i.e. no data points observer so far)
    pub fn is_empty(&self) -> bool {
        self.obj2count.is_empty()
    }

    /// Clear sampler, so that it behaves like it never observed any data points.
    pub fn clear(&mut self) {
        self.cms.clear();
        self.tree.clear();
        self.obj2count.clear();
    }
}

impl<T> fmt::Debug for TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "TopK {{ k: {} }}", self.k)
    }
}

impl<T> Extend<T> for TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    fn extend<S: IntoIterator<Item = T>>(&mut self, iter: S) {
        for elem in iter {
            self.add(elem);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::TopK;
    use countminsketch::CountMinSketch;

    #[test]
    #[should_panic(expected = "k must be greater than 0")]
    fn new_panics_k0() {
        let cms = CountMinSketch::with_params(10, 20);
        TopK::<usize>::new(0, cms);
    }

    #[test]
    fn getter() {
        let cms = CountMinSketch::with_params(10, 20);
        let tk: TopK<usize> = TopK::new(2, cms);

        assert_eq!(tk.k(), 2);
    }

    #[test]
    fn add_1() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        tk.add(1);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1]);
    }

    #[test]
    fn add_2_same() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        tk.add(1);
        tk.add(1);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1]);
    }

    #[test]
    fn add_2_different() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        tk.add(1);
        tk.add(2);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1, 2]);
    }

    #[test]
    fn add_n() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        for i in 0..5 {
            tk.add(i);
        }
        for _ in 0..100 {
            tk.add(99);
        }
        for _ in 0..100 {
            tk.add(100);
        }
        for i in 0..5 {
            tk.add(i);
        }
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![99, 100]);
    }

    #[test]
    fn is_empty() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);
        assert_eq!(tk.is_empty(), true);

        tk.add(0);
        assert_eq!(tk.is_empty(), false);
    }

    #[test]
    fn clear() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);
        tk.add(0);

        tk.clear();
        assert_eq!(tk.is_empty(), true);

        tk.add(1);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1]);
    }

    #[test]
    fn clone() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk1 = TopK::new(2, cms);
        tk1.add(0);

        let mut tk2 = tk1.clone();
        tk2.add(1);

        assert_eq!(tk1.iter().collect::<Vec<u32>>(), vec![0]);
        assert_eq!(tk2.iter().collect::<Vec<u32>>(), vec![0, 1]);
    }

    #[test]
    fn debug() {
        let cms = CountMinSketch::with_params(10, 20);
        let tk: TopK<usize> = TopK::new(2, cms);
        assert_eq!(format!("{:?}", tk), "TopK { k: 2 }");
    }

    #[test]
    fn extend() {
        let cms = CountMinSketch::with_params(10, 10);
        let mut tk = TopK::new(2, cms);

        tk.extend(vec![0, 1]);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![0, 1]);
    }
}
<commit_msg>topk: fix example<commit_after>//! TopK implementation.
use countminsketch::CountMinSketch;
use std::cmp::Ordering;
use std::collections::hash_map::Entry;
use std::collections::{BTreeSet, HashMap};
use std::fmt;
use std::hash::Hash;
use std::rc::Rc;

#[derive(Debug)]
struct TreeEntry<T>
where
    T: Eq + Ord,
{
    obj: Rc<T>,
    n: usize,
}

impl<T> Clone for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn clone(&self) -> Self {
        TreeEntry {
            obj: Rc::clone(&self.obj),
            n: self.n,
        }
    }
}

impl<T> PartialEq for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn eq(&self, other: &TreeEntry<T>) -> bool {
        self.obj == other.obj
    }
}

impl<T> Eq for TreeEntry<T> where T: Eq + Ord {}

impl<T> PartialOrd for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn partial_cmp(&self, other: &TreeEntry<T>) -> Option<Ordering> {
        match self.n.cmp(&other.n) {
            Ordering::Greater => Some(Ordering::Greater),
            Ordering::Less => Some(Ordering::Less),
            Ordering::Equal => Some(self.obj.cmp(&other.obj)),
        }
    }
}

impl<T> Ord for TreeEntry<T>
where
    T: Eq + Ord,
{
    fn cmp(&self, other: &TreeEntry<T>) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

/// A TopK is a data structure keeps the `k` most frequent data points of a stream.
///
/// # Examples
/// ```
/// use pdatastructs::countminsketch::CountMinSketch;
/// use pdatastructs::topk::TopK;
///
/// // set up filter
/// let epsilon = 0.1;  // error threshold
/// let delta = 0.2;  // epsilon is hit in (1 - 0.2) * 100% = 80%
/// let mut cms = CountMinSketch::with_point_query_properties(epsilon, delta);
/// let mut tk = TopK::new(2, cms);
///
/// // add some data
/// for i in 0..1000 {
///     let x = i % 10;
///     let y = if x < 4 {
///         0
///     } else if x < 7 {
///         1
///     } else {
///         x
///     };
///     tk.add(y);
/// }
///
/// // later
/// let elements: Vec<u64> = tk.iter().collect();
/// assert_eq!(elements, vec![1, 0]);
/// ```
///
/// # Applications
/// - getting a fixed number of most common example of a large data set
/// - detect hotspots / very common events
///
/// # How It Works
/// The data structure is based on two parts:
///
/// 1. a reservoir for the most common elements that also stores precise (but not exact) counter
///    data
/// 2. a CountMinSketch to guess the count of all other elements
///
/// On insert, it is checked if the element is already in the reservoir. If so, the precise count
/// is updated. If not, the CountMinSketch is queried for a guess. If the guess is higher than the
/// least common element in the reservoir, the new element displaces this reservoir element. The
/// guess is used as an exact count and is stored alongside. In any case, the CountMinSketch is
/// updated.
///
/// # See Also
/// - `std::vec::Vec`: exact solution but needs to store the entire data stream
///
/// # References
/// - ["Top K Frequent Items Algorithm", Zhipeng Jiang, 2017](https://zpjiang.me/2017/11/13/top-k-elementes-system-design/)
#[derive(Clone)]
pub struct TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    cms: CountMinSketch,
    obj2count: HashMap<Rc<T>, usize>,
    tree: BTreeSet<TreeEntry<T>>,
    k: usize,
}

impl<T> TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    /// Create new Top-K data structure.
    ///
    /// - `k`: number of elements to remember
    /// - `cms`: CountMinSketch that is used for guessing the frequency of elements not currently
    ///   hold. Refer to its documentation about parameter selection.
    ///
    /// Panics if `k == 0`.
    pub fn new(k: usize, cms: CountMinSketch) -> Self {
        assert!(k > 0, "k must be greater than 0");

        Self {
            cms,
            obj2count: HashMap::new(),
            tree: BTreeSet::new(),
            k,
        }
    }

    /// Number of data points to remember.
    pub fn k(&self) -> usize {
        self.k
    }

    /// Observe a data point.
    pub fn add(&mut self, obj: T) {
        // create Rc so we can use obj in multiple data structs
        let rc = Rc::new(obj);

        // always increase CountMinSketch counts
        self.cms.add(&rc);

        // check if entry is in top K
        let size = self.obj2count.len();
        let mut update_obj2count: Option<(usize, Rc<T>)> = None;
        match self.obj2count.entry(Rc::clone(&rc)) {
            Entry::Occupied(mut o) => {
                // it is => increase exact counter
                let mut n = o.get_mut();
                *n += 1;

                // update tree data
                let mut entry = TreeEntry {
                    obj: Rc::clone(&rc),
                    n: *n - 1,
                };
                self.tree.remove(&entry);
                entry.n += 1;
                self.tree.insert(entry);
            }
            Entry::Vacant(v) => {
                // it's not => check capicity
                if size < self.k {
                    // space left => add to top k
                    v.insert(1);
                    self.tree.insert(TreeEntry {
                        obj: Rc::clone(&rc),
                        n: 1,
                    });
                } else {
                    // not enough space => check if it would be a top k element

                    let count = self.cms.query_point(&rc);
                    // count at this point already contains the +1 from the current insertions
                    // because we've updated the CountMinSketch before the query

                    let min: TreeEntry<T> = (*self.tree.iter().next().unwrap()).clone();
                    if count > min.n {
                        // => kick out minimal element of top k
                        self.tree.remove(&min);
                        self.tree.insert(TreeEntry {
                            obj: Rc::clone(&rc),
                            n: count,
                        });

                        // delay obj2count changes, because it is currently borrowed
                        update_obj2count = Some((count, min.obj));
                    }
                }
            }
        }

        // trick the borrow checker
        if let Some((count, obj)) = update_obj2count {
            self.obj2count.insert(rc, count);
            self.obj2count.remove(&obj);
        }
    }

    /// Iterates over collected top-k values.
    ///
    /// The result may contain less than `k` values if less than `k` unique data points where
    /// observed.
    pub fn iter<'a>(&'a self) -> impl 'a + Iterator<Item = T> {
        self.tree.iter().map(|x| (*x.obj).clone())
    }

    /// Check whether the sampler is empty (i.e. no data points observer so far)
    pub fn is_empty(&self) -> bool {
        self.obj2count.is_empty()
    }

    /// Clear sampler, so that it behaves like it never observed any data points.
    pub fn clear(&mut self) {
        self.cms.clear();
        self.tree.clear();
        self.obj2count.clear();
    }
}

impl<T> fmt::Debug for TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "TopK {{ k: {} }}", self.k)
    }
}

impl<T> Extend<T> for TopK<T>
where
    T: Clone + Eq + Hash + Ord,
{
    fn extend<S: IntoIterator<Item = T>>(&mut self, iter: S) {
        for elem in iter {
            self.add(elem);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::TopK;
    use countminsketch::CountMinSketch;

    #[test]
    #[should_panic(expected = "k must be greater than 0")]
    fn new_panics_k0() {
        let cms = CountMinSketch::with_params(10, 20);
        TopK::<usize>::new(0, cms);
    }

    #[test]
    fn getter() {
        let cms = CountMinSketch::with_params(10, 20);
        let tk: TopK<usize> = TopK::new(2, cms);

        assert_eq!(tk.k(), 2);
    }

    #[test]
    fn add_1() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        tk.add(1);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1]);
    }

    #[test]
    fn add_2_same() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        tk.add(1);
        tk.add(1);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1]);
    }

    #[test]
    fn add_2_different() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        tk.add(1);
        tk.add(2);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1, 2]);
    }

    #[test]
    fn add_n() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);

        for i in 0..5 {
            tk.add(i);
        }
        for _ in 0..100 {
            tk.add(99);
        }
        for _ in 0..100 {
            tk.add(100);
        }
        for i in 0..5 {
            tk.add(i);
        }
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![99, 100]);
    }

    #[test]
    fn is_empty() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);
        assert_eq!(tk.is_empty(), true);

        tk.add(0);
        assert_eq!(tk.is_empty(), false);
    }

    #[test]
    fn clear() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk = TopK::new(2, cms);
        tk.add(0);

        tk.clear();
        assert_eq!(tk.is_empty(), true);

        tk.add(1);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![1]);
    }

    #[test]
    fn clone() {
        let cms = CountMinSketch::with_params(10, 20);
        let mut tk1 = TopK::new(2, cms);
        tk1.add(0);

        let mut tk2 = tk1.clone();
        tk2.add(1);

        assert_eq!(tk1.iter().collect::<Vec<u32>>(), vec![0]);
        assert_eq!(tk2.iter().collect::<Vec<u32>>(), vec![0, 1]);
    }

    #[test]
    fn debug() {
        let cms = CountMinSketch::with_params(10, 20);
        let tk: TopK<usize> = TopK::new(2, cms);
        assert_eq!(format!("{:?}", tk), "TopK { k: 2 }");
    }

    #[test]
    fn extend() {
        let cms = CountMinSketch::with_params(10, 10);
        let mut tk = TopK::new(2, cms);

        tk.extend(vec![0, 1]);
        assert_eq!(tk.iter().collect::<Vec<u32>>(), vec![0, 1]);
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::result::Result as RResult;

use chrono::naive::datetime::NaiveDateTime;
use serde_json::value::Value;
use serde::Serialize;
use serde::Serializer;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Error as SerdeError;
use serde::ser::MapVisitor;
use uuid::Uuid;

use error::TaskError;
use error::TaskErrorKind;
use priority::TaskPriority;
use result::Result;
use status::TaskStatus;
use project::Project;
use tag::Tag;

pub static TASKWARRIOR_DATETIME_TEMPLATE : &'static str = "%Y%m%dT%H%M%SZ";

#[derive(Debug, Clone)]
pub struct Task {
    status      : TaskStatus,
    uuid        : Uuid,
    entry       : NaiveDateTime,
    description : String,

    annotation  : Option<Vec<String>>,
    depends     : Option<String>,
    due         : Option<NaiveDateTime>,
    end         : Option<NaiveDateTime>,
    imask       : Option<i64>,
    mask        : Option<String>,
    modified    : Option<NaiveDateTime>,
    parent      : Option<Uuid>,
    priority    : Option<TaskPriority>,
    project     : Option<Project>,
    recur       : Option<String>,
    scheduled   : Option<NaiveDateTime>,
    start       : Option<NaiveDateTime>,
    tags        : Option<Vec<Tag>>,
    until       : Option<NaiveDateTime>,
    wait        : Option<NaiveDateTime>,
}

/*
 * TODO: We do not fail if the JSON parsing fails. This panics. We rely on taskwarrior to be nice
 * to us. I guess this should be fixed.
 */
impl Task {

    pub fn new(
        status      : TaskStatus,
        uuid        : Uuid,
        entry       : NaiveDateTime,
        description : String,

        annotation  : Option<Vec<String>>,
        depends     : Option<String>,
        due         : Option<NaiveDateTime>,
        end         : Option<NaiveDateTime>,
        imask       : Option<i64>,
        mask        : Option<String>,
        modified    : Option<NaiveDateTime>,
        parent      : Option<Uuid>,
        priority    : Option<TaskPriority>,
        project     : Option<Project>,
        recur       : Option<String>,
        scheduled   : Option<NaiveDateTime>,
        start       : Option<NaiveDateTime>,
        tags        : Option<Vec<Tag>>,
        until       : Option<NaiveDateTime>,
        wait        : Option<NaiveDateTime>,
    ) -> Task
    {
        Task {
            status      : status,
            uuid        : uuid,
            entry       : entry,
            description : description,

            annotation  : annotation,
            depends     : depends,
            due         : due,
            end         : end,
            imask       : imask,
            mask        : mask,
            modified    : modified,
            parent      : parent,
            priority    : priority,
            project     : project,
            recur       : recur,
            scheduled   : scheduled,
            start       : start,
            tags        : tags,
            until       : until,
            wait        : wait,
        }
    }

    pub fn status(&self) -> &TaskStatus {
        &self.status
    }

    pub fn uuid(&self) -> Uuid {
        &self.uuid
    }

    pub fn entry(&self) -> NaiveDateTime {
        &self.entry
    }

    pub fn description(&self) -> String {
        &self.description
    }

    pub fn annotation(&self) -> Option<&Vec<String>> {
        self.annotation.as_ref()
    }

    pub fn depends(&self) -> Option<&String> {
        self.depends.as_ref()
    }

    pub fn due(&self) -> Option<&NaiveDateTime> {
        self.due.as_ref()
    }

    pub fn end(&self) -> Option<&NaiveDateTime> {
        self.end.as_ref()
    }

    pub fn imask(&self) -> Option<&i64> {
        self.imask.as_ref()
    }

    pub fn mask(&self) -> Option<&String> {
        self.mask.as_ref()
    }

    pub fn modified(&self) -> Option<&NaiveDateTime> {
        self.modified.as_ref()
    }

    pub fn parent(&self) -> Option<&Uuid> {
        self.parent.as_ref()
    }

    pub fn priority(&self) -> Option<&TaskPriority> {
        self.priority.as_ref()
    }

    pub fn project(&self) -> Option<&Project> {
        self.project.as_ref()
    }

    pub fn recur(&self) -> Option<&String> {
        self.recur.as_ref()
    }

    pub fn scheduled(&self) -> Option<&NaiveDateTime> {
        self.scheduled.as_ref()
    }

    pub fn start(&self) -> Option<&NaiveDateTime> {
        self.start.as_ref()
    }

    pub fn tags(&self) -> Option<&Vec<Tag>> {
        self.tags.as_ref()
    }

    pub fn until(&self) -> Option<&NaiveDateTime> {
        self.until.as_ref()
    }

    pub fn wait(&self) -> Option<&NaiveDateTime> {
        self.wait.as_ref()
    }

}

impl Serialize for Task {

    fn serialize<S>(&self, serializer: &mut S) -> RResult<(), SerdeError>
        where S: Serializer
    {
        serializer.serialize_struct("Task", TaskVisitor {
            value: self,
            state: 0,
        })
    }

}

struct TaskVisitor<'a> {
    value: &'a Task,
    state: u8,
}

impl<'a> MapVisitor for TaskVisitor<'a> {

    fn visit<S>(&mut self, serializer: &mut S) -> RResult<Option<()>, SerdeError>
        where S: Serializer
    {
        match self.state {
            0 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("status", &self.value.status))))
            },
            1 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("uuid", &self.value.uuid))))
            },
            2 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("entry", &self.value.entry))))
            },
            3 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("description", &self.value.description))))
            },
            4 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("annotation", &self.value.annotation))))
            },
            5 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("depends", &self.value.depends))))
            },
            6 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("due", &self.value.due))))
            },
            7 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("end", &self.value.end))))
            },
            8 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("imask", &self.value.imask))))
            },
            9 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("mask", &self.value.mask))))
            },
            10 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("modified", &self.value.modified))))
            },
            11 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("parent", &self.value.parent))))
            },
            12 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("priority", &self.value.priority))))
            },
            13 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("project", &self.value.project))))
            },
            14 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("recur", &self.value.recur))))
            },
            15 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("scheduled", &self.value.scheduled))))
            },
            16 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("start", &self.value.start))))
            },
            17 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("tags", &self.value.tags))))
            },
            18 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("until", &self.value.until))))
            },
            19 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("wait", &self.value.wait))))
            },
            _ => {
                Ok(None)
            }
        }
    }

}
<commit_msg>Fixup task<commit_after>use std::collections::BTreeMap;
use std::result::Result as RResult;

use chrono::naive::datetime::NaiveDateTime;
use serde_json::value::Value;
use serde::Serialize;
use serde::Serializer;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Error as SerdeError;
use serde::ser::MapVisitor;
use uuid::Uuid;

use error::TaskError;
use error::TaskErrorKind;
use priority::TaskPriority;
use result::Result;
use status::TaskStatus;
use project::Project;
use tag::Tag;

pub static TASKWARRIOR_DATETIME_TEMPLATE : &'static str = "%Y%m%dT%H%M%SZ";

#[derive(Debug, Clone)]
pub struct Task {
    status      : TaskStatus,
    uuid        : Uuid,
    entry       : NaiveDateTime,
    description : String,

    annotation  : Option<Vec<String>>,
    depends     : Option<String>,
    due         : Option<NaiveDateTime>,
    end         : Option<NaiveDateTime>,
    imask       : Option<i64>,
    mask        : Option<String>,
    modified    : Option<NaiveDateTime>,
    parent      : Option<Uuid>,
    priority    : Option<TaskPriority>,
    project     : Option<Project>,
    recur       : Option<String>,
    scheduled   : Option<NaiveDateTime>,
    start       : Option<NaiveDateTime>,
    tags        : Option<Vec<Tag>>,
    until       : Option<NaiveDateTime>,
    wait        : Option<NaiveDateTime>,
}

/*
 * TODO: We do not fail if the JSON parsing fails. This panics. We rely on taskwarrior to be nice
 * to us. I guess this should be fixed.
 */
impl Task {

    pub fn new(
        status      : TaskStatus,
        uuid        : Uuid,
        entry       : NaiveDateTime,
        description : String,

        annotation  : Option<Vec<String>>,
        depends     : Option<String>,
        due         : Option<NaiveDateTime>,
        end         : Option<NaiveDateTime>,
        imask       : Option<i64>,
        mask        : Option<String>,
        modified    : Option<NaiveDateTime>,
        parent      : Option<Uuid>,
        priority    : Option<TaskPriority>,
        project     : Option<Project>,
        recur       : Option<String>,
        scheduled   : Option<NaiveDateTime>,
        start       : Option<NaiveDateTime>,
        tags        : Option<Vec<Tag>>,
        until       : Option<NaiveDateTime>,
        wait        : Option<NaiveDateTime>,
    ) -> Task
    {
        Task {
            status      : status,
            uuid        : uuid,
            entry       : entry,
            description : description,

            annotation  : annotation,
            depends     : depends,
            due         : due,
            end         : end,
            imask       : imask,
            mask        : mask,
            modified    : modified,
            parent      : parent,
            priority    : priority,
            project     : project,
            recur       : recur,
            scheduled   : scheduled,
            start       : start,
            tags        : tags,
            until       : until,
            wait        : wait,
        }
    }

    pub fn status(&self) -> &TaskStatus {
        &self.status
    }

    pub fn uuid(&self) -> Uuid {
        &self.uuid
    }

    pub fn entry(&self) -> NaiveDateTime {
        &self.entry
    }

    pub fn description(&self) -> String {
        &self.description
    }

    pub fn annotation(&self) -> Option<&Vec<String>> {
        self.annotation.as_ref()
    }

    pub fn depends(&self) -> Option<&String> {
        self.depends.as_ref()
    }

    pub fn due(&self) -> Option<&NaiveDateTime> {
        self.due.as_ref()
    }

    pub fn end(&self) -> Option<&NaiveDateTime> {
        self.end.as_ref()
    }

    pub fn imask(&self) -> Option<&i64> {
        self.imask.as_ref()
    }

    pub fn mask(&self) -> Option<&String> {
        self.mask.as_ref()
    }

    pub fn modified(&self) -> Option<&NaiveDateTime> {
        self.modified.as_ref()
    }

    pub fn parent(&self) -> Option<&Uuid> {
        self.parent.as_ref()
    }

    pub fn priority(&self) -> Option<&TaskPriority> {
        self.priority.as_ref()
    }

    pub fn project(&self) -> Option<&Project> {
        self.project.as_ref()
    }

    pub fn recur(&self) -> Option<&String> {
        self.recur.as_ref()
    }

    pub fn scheduled(&self) -> Option<&NaiveDateTime> {
        self.scheduled.as_ref()
    }

    pub fn start(&self) -> Option<&NaiveDateTime> {
        self.start.as_ref()
    }

    pub fn tags(&self) -> Option<&Vec<Tag>> {
        self.tags.as_ref()
    }

    pub fn until(&self) -> Option<&NaiveDateTime> {
        self.until.as_ref()
    }

    pub fn wait(&self) -> Option<&NaiveDateTime> {
        self.wait.as_ref()
    }

}

impl Serialize for Task {

    fn serialize<S>(&self, serializer: &mut S) -> RResult<(), S::Error>
        where S: Serializer
    {
        serializer.serialize_struct("Task", TaskVisitor {
            value: self,
            state: 0,
        })
    }

}

struct TaskVisitor<'a> {
    value: &'a Task,
    state: u8,
}

impl<'a> MapVisitor for TaskVisitor<'a> {

    fn visit<S>(&mut self, serializer: &mut S) -> RResult<Option<()>, S::Error>
        where S: Serializer
    {
        match self.state {
            0 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("status", &self.value.status))))
            },
            1 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("uuid", &self.value.uuid))))
            },
            2 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("entry", &self.value.entry))))
            },
            3 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("description", &self.value.description))))
            },
            4 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("annotation", &self.value.annotation))))
            },
            5 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("depends", &self.value.depends))))
            },
            6 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("due", &self.value.due))))
            },
            7 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("end", &self.value.end))))
            },
            8 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("imask", &self.value.imask))))
            },
            9 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("mask", &self.value.mask))))
            },
            10 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("modified", &self.value.modified))))
            },
            11 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("parent", &self.value.parent))))
            },
            12 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("priority", &self.value.priority))))
            },
            13 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("project", &self.value.project))))
            },
            14 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("recur", &self.value.recur))))
            },
            15 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("scheduled", &self.value.scheduled))))
            },
            16 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("start", &self.value.start))))
            },
            17 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("tags", &self.value.tags))))
            },
            18 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("until", &self.value.until))))
            },
            19 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("wait", &self.value.wait))))
            },
            _ => {
                Ok(None)
            }
        }
    }

}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2015 Y. T. Chung

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! Cipher defined with Rust binding for libsodium

extern crate libc;

use std::iter::repeat;

use crypto::cipher::{Cipher, CipherType, CipherResult};

const BLOCK_SIZE: usize = 64; // Just for Salsa20 and Chacha20

mod ffi {
    pub use libsodium_ffi::crypto_stream_chacha20_xor_ic;
    pub use libsodium_ffi::crypto_stream_salsa20_xor_ic;
}

pub struct SodiumCipher {
    cipher_type: CipherType,
    key: Vec<u8>,
    iv: Vec<u8>,
    counter: usize,
    buf: Vec<u8>,
}

impl SodiumCipher {
    pub fn new(t: CipherType, key: &[u8], iv: &[u8]) -> SodiumCipher {
        match t {
            CipherType::Salsa20 | CipherType::ChaCha20 => (),
            _ => panic!("Sodium does not support {:?} cipher", t),
        }

        SodiumCipher {
            cipher_type: t,
            key: key.to_vec(),
            iv: iv.to_vec(),
            counter: 0,
            buf: Vec::new(),
        }
    }
}

impl Cipher for SodiumCipher {
    fn update(&mut self, data: &[u8], out: &mut Vec<u8>) -> CipherResult<()> {
        let padding_len = self.counter % BLOCK_SIZE;
        let mut pad;
        let padded_data =
            if padding_len == 0 {
                data
            } else {
                pad = Some(repeat(0u8).take(padding_len).chain(data.iter().map(|&x| x)).collect::<Vec<u8>>());
                &pad.as_ref().unwrap()[..]
            };

        if self.buf.len() < padding_len + data.len() {
            self.buf.resize(padding_len + data.len(), 0u8);
        }

        match self.cipher_type {
            CipherType::ChaCha20 => unsafe {
                ffi::crypto_stream_chacha20_xor_ic(self.buf.as_mut_ptr() as *mut libc::c_char, padded_data.as_ptr(),
                                                  (padding_len + data.len()) as libc::c_ulonglong,
                                                  self.iv.as_ptr(),
                                                  (self.counter / BLOCK_SIZE) as libc::uint64_t,
                                                  self.key.as_ptr());
            },
            CipherType::Salsa20 => unsafe {
                ffi::crypto_stream_salsa20_xor_ic(self.buf.as_mut_ptr() as *mut libc::c_char, padded_data.as_ptr(),
                                                (padding_len + data.len()) as libc::c_ulonglong,
                                                self.iv.as_ptr(),
                                                (self.counter / BLOCK_SIZE) as libc::uint64_t,
                                                self.key.as_ptr());
            },
            _ => unreachable!(),
        }

        self.counter += data.len();

        out.push_all(&self.buf[padding_len..padding_len + data.len()]);

        Ok(())
    }

    fn finalize(&mut self, _: &mut Vec<u8>) -> CipherResult<()> {
        Ok(())
    }
}

#[cfg(test)]
mod test_sodium {
    use crypto::cipher::{Cipher, CipherType};
    use crypto::sodium::SodiumCipher;

    #[test]
    fn test_sodium_cipher() {
        let ct = CipherType::ChaCha20;

        let key = ct.bytes_to_key(b"PassWORD");
        let message = b"message";

        let iv = ct.gen_init_vec();

        let mut enc = SodiumCipher::new(ct, &key[..], &iv[..]);
        let mut encrypted_msg = Vec::new();
        enc.update(message, &mut encrypted_msg).unwrap();

        let mut dec = SodiumCipher::new(ct, &key[..], &iv[..]);
        let mut decrypted_msg = Vec::new();
        dec.update(&encrypted_msg[0..], &mut decrypted_msg).unwrap();

        assert_eq!(message, &decrypted_msg[..]);
    }
}
<commit_msg>build with nightly<commit_after>// The MIT License (MIT)

// Copyright (c) 2015 Y. T. Chung

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! Cipher defined with Rust binding for libsodium

extern crate libc;

use std::iter::repeat;

use crypto::cipher::{Cipher, CipherType, CipherResult};

const BLOCK_SIZE: usize = 64; // Just for Salsa20 and Chacha20

mod ffi {
    pub use libsodium_ffi::crypto_stream_chacha20_xor_ic;
    pub use libsodium_ffi::crypto_stream_salsa20_xor_ic;
}

pub struct SodiumCipher {
    cipher_type: CipherType,
    key: Vec<u8>,
    iv: Vec<u8>,
    counter: usize,
    buf: Vec<u8>,
}

impl SodiumCipher {
    pub fn new(t: CipherType, key: &[u8], iv: &[u8]) -> SodiumCipher {
        match t {
            CipherType::Salsa20 | CipherType::ChaCha20 => (),
            _ => panic!("Sodium does not support {:?} cipher", t),
        }

        SodiumCipher {
            cipher_type: t,
            key: key.to_vec(),
            iv: iv.to_vec(),
            counter: 0,
            buf: Vec::new(),
        }
    }
}

impl Cipher for SodiumCipher {
    fn update(&mut self, data: &[u8], out: &mut Vec<u8>) -> CipherResult<()> {
        let padding_len = self.counter % BLOCK_SIZE;
        let pad =
            if padding_len == 0 {
                None
            } else {
                let pad = repeat(0u8).take(padding_len).chain(data.iter().map(|&x| x)).collect::<Vec<u8>>();
                Some(pad)
            };

        let padded_data = match &pad {
            &Some(ref p) => &p[..],
            &None => data,
        };

        if self.buf.len() < padding_len + data.len() {
            self.buf.resize(padding_len + data.len(), 0u8);
        }

        match self.cipher_type {
            CipherType::ChaCha20 => unsafe {
                ffi::crypto_stream_chacha20_xor_ic(self.buf.as_mut_ptr() as *mut libc::c_char, padded_data.as_ptr(),
                                                  (padding_len + data.len()) as libc::c_ulonglong,
                                                  self.iv.as_ptr(),
                                                  (self.counter / BLOCK_SIZE) as libc::uint64_t,
                                                  self.key.as_ptr());
            },
            CipherType::Salsa20 => unsafe {
                ffi::crypto_stream_salsa20_xor_ic(self.buf.as_mut_ptr() as *mut libc::c_char, padded_data.as_ptr(),
                                                (padding_len + data.len()) as libc::c_ulonglong,
                                                self.iv.as_ptr(),
                                                (self.counter / BLOCK_SIZE) as libc::uint64_t,
                                                self.key.as_ptr());
            },
            _ => unreachable!(),
        }

        self.counter += data.len();

        out.push_all(&self.buf[padding_len..padding_len + data.len()]);

        Ok(())
    }

    fn finalize(&mut self, _: &mut Vec<u8>) -> CipherResult<()> {
        Ok(())
    }
}

#[cfg(test)]
mod test_sodium {
    use crypto::cipher::{Cipher, CipherType};
    use crypto::sodium::SodiumCipher;

    #[test]
    fn test_sodium_cipher() {
        let ct = CipherType::ChaCha20;

        let key = ct.bytes_to_key(b"PassWORD");
        let message = b"message";

        let iv = ct.gen_init_vec();

        let mut enc = SodiumCipher::new(ct, &key[..], &iv[..]);
        let mut encrypted_msg = Vec::new();
        enc.update(message, &mut encrypted_msg).unwrap();

        let mut dec = SodiumCipher::new(ct, &key[..], &iv[..]);
        let mut decrypted_msg = Vec::new();
        dec.update(&encrypted_msg[0..], &mut decrypted_msg).unwrap();

        assert_eq!(message, &decrypted_msg[..]);
    }
}
<|endoftext|>


<commit_before>#![cfg(test)]

use super::{execute, Section};

#[test]
fn use_it() {
    let mut left: int = 0;
    let mut right: int = 0;
    execute(&mut [
        || left = 22,
        || right = 44
    ]);
    assert_eq!(left, 22);
    assert_eq!(right, 44);
}

// #[test]
// fn use_it_bad() {
//     let mut left: int = 0;
//     let mut right: int = 0;
//     execute(&mut [
//         || left = 22,
//         || left = 44  //~ ERROR cannot borrow `left` as mutable more than once
//     ]);
//     assert_eq!(left, 22);
//     assert_eq!(right, 44);
// }
<commit_msg>Code up quicksort example<commit_after>#![cfg(test)]

use super::{execute, Section};

#[test]
fn use_it() {
    let mut left: int = 0;
    let mut right: int = 0;
    execute(&mut [
        || left = 22,
        || right = 44
    ]);
    assert_eq!(left, 22);
    assert_eq!(right, 44);
}

#[cfg(test)]
fn quicksort(v: &mut [int]) {
    if v.len() <= 1 {
        return;
    }

    let pivot_value = v[0]; // simplest possible thing...
    let mid = partition(pivot_value, v);
    let (left, right) = v.mut_split_at(mid);
    execute(&mut [
        || quicksort(left),
        || quicksort(right)
    ]);

    fn partition(pivot_value: int,
                 v: &mut [int])
                 -> uint
    {
        // Invariant:
        //     .. l ==> less than or equal to pivot
        //     r .. ==> greater than pivot
        let mut l = 0;
        let mut r = v.len() - 1;
        while l <= r {
            if v[l] > pivot_value {
                v.swap(l, r);
                r -= 1;
            } else if v[r] <= pivot_value {
                v.swap(l, r);
                l += 1;
            } else {
                l += 1;
                r -= 1;
            }
        }
        return l;
    }
}

#[test]
fn call_quicksort() {
    let mut v = [55, 12, 86, 8, 3, 5];
    quicksort(v.as_mut_slice());
    let mut bound = 0;
    for &elem in v.iter() {
        assert!(elem >= bound);
        bound = elem;
    }
}

// #[test]
// fn use_it_bad() {
//     let mut left: int = 0;
//     let mut right: int = 0;
//     execute(&mut [
//         || left = 22,
//         || left = 44  //~ ERROR cannot borrow `left` as mutable more than once
//     ]);
//     assert_eq!(left, 22);
//     assert_eq!(right, 44);
// }
<|endoftext|>


<commit_before>use std::convert::From;

use serde::Deserialize;
use serde_json;
use serde_json::value::Value;

use ::error::{GraphError, Neo4jError};

pub trait ResultTrait {
    fn results(&self) -> &Vec<CypherResult>;
    fn errors(&self) -> &Vec<Neo4jError>;
}

#[derive(Debug, Deserialize)]
pub struct QueryResult {
    pub results: Vec<CypherResult>,
    pub errors: Vec<Neo4jError>,
}

impl ResultTrait for QueryResult {
    fn results(&self) -> &Vec<CypherResult> {
        &self.results
    }

    fn errors(&self) -> &Vec<Neo4jError> {
        &self.errors
    }
}

/// Holds a single row of the result of a cypher query
#[derive(Clone, Debug, Deserialize)]
pub struct RowResult {
    row: Vec<Value>,
}

/// Holds the result of a cypher query
#[derive(Clone, Debug, Deserialize)]
pub struct CypherResult {
    pub columns: Vec<String>,
    pub data: Vec<RowResult>,
}

impl CypherResult {
    /// Returns an iterator over the rows of the result
    pub fn rows(&self) -> Rows {
        Rows::new(&self.columns, &self.data)
    }
}

pub struct Rows<'a> {
    current_index: usize,
    columns: &'a Vec<String>,
    data: &'a Vec<RowResult>,
}

impl<'a> Rows<'a> {
    pub fn new(columns: &'a Vec<String>, data: &'a Vec<RowResult>) -> Self {
        Rows {
            current_index: 0,
            columns: columns,
            data: data,
        }
    }
}

pub struct Row<'a> {
    columns: &'a Vec<String>,
    data: &'a Vec<Value>,
}

impl<'a> Row<'a> {
    pub fn new(columns: &'a Vec<String>, data: &'a Vec<Value>) -> Self {
        Row {
            columns: columns,
            data: data,
        }
    }

    /// Gets the value of a column by its name
    ///
    /// The column name must be exactly as it was named in the query. For example, if your query
    /// was `"MATCH (n:PERSON) RETURN n.name, n.gender"`, then you should use `row.get("n.name")`
    /// and `row.get("n.gender")` since this is what the neo4j api produces.
    ///
    /// If the column does not exist in the row, an `Err` is returned with the message
    /// `"No such column: {column_name}"`.
    pub fn get<T: Deserialize>(&self, column: &str) -> Result<T, GraphError> {
        match self.columns.iter().position(|c| c == column) {
            Some(index) => self.get_n(index),
            None => Err(GraphError::new(&format!("No such column: {}", &column))),
        }
    }

    /// Gets the value of a column by order
    ///
    /// Column number is 0 based, so the first column is 0, the second is 1 and so on.
    ///
    /// If the column number is not within the columns length, and `Err` is returned with the
    /// message `"No such column at index {column_number}"`.
    pub fn get_n<T:Deserialize>(&self, column: usize) -> Result<T, GraphError> {
        let column_data = match self.data.get(column) {
            Some(c) => c.clone(),
            None => return Err(GraphError::new(&format!("No column at index {}", column))),
        };

        serde_json::value::from_value::<T>(column_data).map_err(From::from)
    }
}

impl<'a> Iterator for Rows<'a> {
    type Item = Row<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.data.get(self.current_index).map(|data| {
            self.current_index += 1;
            Row::new(self.columns.as_ref(), data.row.as_ref())
        })
    }
}

#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;
    use serde_json::value as json_value;
    use super::*;

    #[derive(Clone, Serialize)]
    struct Person {
        name: String,
        lastname: String,
    }

    fn make_result() -> CypherResult {
        let node = Person {
            name: "Test".to_owned(),
            lastname: "Result".to_owned(),
        };

        let node = json_value::to_value(&node);
        let row_data = vec![node];

        let row1 = RowResult { row: row_data.clone() };
        let row2 = RowResult { row: row_data.clone() };

        let data = vec![row1, row2];
        let columns = vec!["node".to_owned()];

        CypherResult {
            columns: columns,
            data: data,
        }
    }

    #[test]
    fn rows() {
        let result = make_result();
        for row in result.rows() {
            let row = row.get::<BTreeMap<String, String>>("node");
            assert!(row.is_ok());

            let row = row.unwrap();
            assert_eq!(row.get("name").unwrap(), "Test");
            assert_eq!(row.get("lastname").unwrap(), "Result");
        }
    }
}
<commit_msg>Add test for `Row::{get, get_n}`<commit_after>use std::convert::From;

use serde::Deserialize;
use serde_json;
use serde_json::value::Value;

use ::error::{GraphError, Neo4jError};

pub trait ResultTrait {
    fn results(&self) -> &Vec<CypherResult>;
    fn errors(&self) -> &Vec<Neo4jError>;
}

#[derive(Debug, Deserialize)]
pub struct QueryResult {
    pub results: Vec<CypherResult>,
    pub errors: Vec<Neo4jError>,
}

impl ResultTrait for QueryResult {
    fn results(&self) -> &Vec<CypherResult> {
        &self.results
    }

    fn errors(&self) -> &Vec<Neo4jError> {
        &self.errors
    }
}

/// Holds a single row of the result of a cypher query
#[derive(Clone, Debug, Deserialize)]
pub struct RowResult {
    row: Vec<Value>,
}

/// Holds the result of a cypher query
#[derive(Clone, Debug, Deserialize)]
pub struct CypherResult {
    pub columns: Vec<String>,
    pub data: Vec<RowResult>,
}

impl CypherResult {
    /// Returns an iterator over the rows of the result
    pub fn rows(&self) -> Rows {
        Rows::new(&self.columns, &self.data)
    }
}

pub struct Rows<'a> {
    current_index: usize,
    columns: &'a Vec<String>,
    data: &'a Vec<RowResult>,
}

impl<'a> Rows<'a> {
    pub fn new(columns: &'a Vec<String>, data: &'a Vec<RowResult>) -> Self {
        Rows {
            current_index: 0,
            columns: columns,
            data: data,
        }
    }
}

pub struct Row<'a> {
    columns: &'a Vec<String>,
    data: &'a Vec<Value>,
}

impl<'a> Row<'a> {
    pub fn new(columns: &'a Vec<String>, data: &'a Vec<Value>) -> Self {
        Row {
            columns: columns,
            data: data,
        }
    }

    /// Gets the value of a column by its name
    ///
    /// The column name must be exactly as it was named in the query. For example, if your query
    /// was `"MATCH (n:PERSON) RETURN n.name, n.gender"`, then you should use `row.get("n.name")`
    /// and `row.get("n.gender")` since this is what the neo4j api produces.
    ///
    /// If the column does not exist in the row, an `Err` is returned with the message
    /// `"No such column: {column_name}"`.
    pub fn get<T: Deserialize>(&self, column: &str) -> Result<T, GraphError> {
        match self.columns.iter().position(|c| c == column) {
            Some(index) => self.get_n(index),
            None => Err(GraphError::new(&format!("No such column: {}", &column))),
        }
    }

    /// Gets the value of a column by order
    ///
    /// Column number is 0 based, so the first column is 0, the second is 1 and so on.
    ///
    /// If the column number is not within the columns length, and `Err` is returned with the
    /// message `"No such column at index {column_number}"`.
    pub fn get_n<T:Deserialize>(&self, column: usize) -> Result<T, GraphError> {
        let column_data = match self.data.get(column) {
            Some(c) => c.clone(),
            None => return Err(GraphError::new(&format!("No column at index {}", column))),
        };

        serde_json::value::from_value::<T>(column_data).map_err(From::from)
    }
}

impl<'a> Iterator for Rows<'a> {
    type Item = Row<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.data.get(self.current_index).map(|data| {
            self.current_index += 1;
            Row::new(self.columns.as_ref(), data.row.as_ref())
        })
    }
}

#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;
    use serde_json::value as json_value;
    use super::*;

    #[derive(Clone, Serialize)]
    struct Person {
        name: String,
        lastname: String,
    }

    fn make_result() -> CypherResult {
        let node = Person {
            name: "Test".to_owned(),
            lastname: "Result".to_owned(),
        };

        let node = json_value::to_value(&node);
        let row_data = vec![node];

        let row1 = RowResult { row: row_data.clone() };
        let row2 = RowResult { row: row_data.clone() };

        let data = vec![row1, row2];
        let columns = vec!["node".to_owned()];

        CypherResult {
            columns: columns,
            data: data,
        }
    }

    #[test]
    fn rows() {
        let result = make_result();
        for row in result.rows() {
            let row = row.get::<BTreeMap<String, String>>("node");
            assert!(row.is_ok());

            let row = row.unwrap();
            assert_eq!(row.get("name").unwrap(), "Test");
            assert_eq!(row.get("lastname").unwrap(), "Result");
        }
    }

    #[test]
    #[should_panic(expected = "No such column")]
    fn no_column_name_in_row() {
        let result = make_result();
        let rows: Vec<Row> = result.rows().collect();
        let ref row = rows[0];
        row.get::<String>("nonexistent").unwrap();
    }

    #[test]
    #[should_panic(expected = "No column at index")]
    fn no_column_index_in_row() {
        let result = make_result();
        let rows: Vec<Row> = result.rows().collect();
        let ref row = rows[0];
        row.get_n::<String>(99).unwrap();
    }
}
<|endoftext|>


<commit_before>

pub struct User {
	pub id: u64,
	pub display_name: String,
}
<commit_msg>God damned newlines!<commit_after>
pub struct User {
	pub id: u64,
	pub display_name: String
}
<|endoftext|>


<commit_before>//! Various convenience functions for `built` at runtime.

/// Parses version-strings with `semver::Version::parse()`.
///
/// This function is only available if `built` was compiled with the
/// `semver` feature.
///
/// The function takes a reference to an array of names and version numbers as
/// serialized by `built` and returns an iterator over the unchanged names
/// and parsed version numbers.
///
/// ```
/// pub mod build_info {
///     pub const DEPENDENCIES: [(&'static str, &'static str); 1] = [("built", "0.1.0")];
/// }
///
/// let deps = build_info::DEPENDENCIES;
/// assert!(built::util::parse_versions(&deps)
///                      .any(|(name, ver)| name == "built" &&
///                                         ver >= semver::Version::parse("0.1.0").unwrap()));
/// ```
///
/// # Panics
/// If a version can't be parsed by `semver::Version::parse()`. This should never
/// happen with version strings provided by Cargo and `built`.
#[cfg(feature = "semver")]
pub fn parse_versions<'a, T>(
    name_and_versions: T,
) -> impl Iterator<Item = (&'a str, semver::Version)>
where
    T: IntoIterator<Item = &'a (&'a str, &'a str)>,
{
    fn parse_version<'a>(t: &'a (&'a str, &'a str)) -> (&'a str, semver::Version) {
        (t.0, t.1.parse().unwrap())
    }
    name_and_versions.into_iter().map(parse_version)
}

/// Parse a time-string as formatted by `built`.
///
/// ```
/// use chrono::Datelike;
///
/// pub mod build_info {
///     pub const BUILT_TIME_UTC: &'static str = "Tue, 14 Feb 2017 05:21:41 GMT";
/// }
///
/// assert_eq!(built::util::strptime(&build_info::BUILT_TIME_UTC).year(), 2017);
/// ```
///
/// # Panics
/// If the string can't be parsed. This should never happen with input provided
/// by `built`.
#[cfg(feature = "chrono")]
pub fn strptime(s: &str) -> chrono::DateTime<chrono::offset::Utc> {
    chrono::DateTime::parse_from_rfc2822(s)
        .unwrap()
        .with_timezone(&chrono::offset::Utc)
}

/// Retrieves the git-tag or hash describing the exact version.
///
/// If a valid git-repo can't be discovered at or above the given path,
/// `Ok(None)` is returned instead of an `Err`-value.
///
/// # Errors
/// Errors from `git2` are returned if the repository does exists at all.
#[cfg(feature = "git2")]
pub fn get_repo_description(root: &std::path::Path) -> Result<Option<String>, git2::Error> {
    match git2::Repository::discover(root) {
        Ok(repo) => {
            let mut desc_opt = git2::DescribeOptions::new();
            desc_opt.describe_tags().show_commit_oid_as_fallback(true);
            Ok(Some(
                repo.describe(&desc_opt)
                    .and_then(|desc| desc.format(None))?,
            ))
        }
        Err(ref e)
            if e.class() == git2::ErrorClass::Repository
                && e.code() == git2::ErrorCode::NotFound =>
        {
            Ok(None)
        }
        Err(e) => Err(e),
    }
}

/// Retrieves the branch name and hash of HEAD.
///
/// The returned value is a tuple of head's reference name and long hash. The
/// branch name will be `None` if the head is detached, or it's not valid UTF-8.
///
/// If a valid git-repo can't be discovered at or above the given path,
/// `Ok(None)` is returned instead of an `Err`-value.
///
/// # Errors
/// Errors from `git2` are returned if the repository does exists at all.
#[cfg(feature = "git2")]
pub fn get_repo_head(
    root: &std::path::Path,
) -> Result<Option<(Option<String>, String)>, git2::Error> {
    match git2::Repository::discover(root) {
        Ok(repo) => {
            let head = repo.head()?;
            let branch = head.name();
            let commit = head.peel_to_commit()?.id();
            Ok(Some((
                branch.map(ToString::to_string),
                format!("{}", commit),
            )))
        }
        Err(ref e)
            if e.class() == git2::ErrorClass::Repository
                && e.code() == git2::ErrorCode::NotFound =>
        {
            Ok(None)
        }
        Err(e) => Err(e),
    }
}

/// Detect execution on various Continiuous Integration platforms.
///
/// CI-platforms are detected by the presence of known environment variables.
/// This allows to detect specific CI-platform (like `GitLab`); various
/// generic environment variables are also checked, which may result in
/// `CIPlatform::Generic`.
///
/// Since some platforms have fairly generic environment variables to begin with
/// (e.g. `TASK_ID`), this function may have false positives.
pub fn detect_ci() -> Option<super::CIPlatform> {
    super::CIPlatform::detect_from_envmap(&super::get_environment())
}
<commit_msg>Fix `GIT_HEAD_REF` not being `None` if detached.<commit_after>//! Various convenience functions for `built` at runtime.

/// Parses version-strings with `semver::Version::parse()`.
///
/// This function is only available if `built` was compiled with the
/// `semver` feature.
///
/// The function takes a reference to an array of names and version numbers as
/// serialized by `built` and returns an iterator over the unchanged names
/// and parsed version numbers.
///
/// ```
/// pub mod build_info {
///     pub const DEPENDENCIES: [(&'static str, &'static str); 1] = [("built", "0.1.0")];
/// }
///
/// let deps = build_info::DEPENDENCIES;
/// assert!(built::util::parse_versions(&deps)
///                      .any(|(name, ver)| name == "built" &&
///                                         ver >= semver::Version::parse("0.1.0").unwrap()));
/// ```
///
/// # Panics
/// If a version can't be parsed by `semver::Version::parse()`. This should never
/// happen with version strings provided by Cargo and `built`.
#[cfg(feature = "semver")]
pub fn parse_versions<'a, T>(
    name_and_versions: T,
) -> impl Iterator<Item = (&'a str, semver::Version)>
where
    T: IntoIterator<Item = &'a (&'a str, &'a str)>,
{
    fn parse_version<'a>(t: &'a (&'a str, &'a str)) -> (&'a str, semver::Version) {
        (t.0, t.1.parse().unwrap())
    }
    name_and_versions.into_iter().map(parse_version)
}

/// Parse a time-string as formatted by `built`.
///
/// ```
/// use chrono::Datelike;
///
/// pub mod build_info {
///     pub const BUILT_TIME_UTC: &'static str = "Tue, 14 Feb 2017 05:21:41 GMT";
/// }
///
/// assert_eq!(built::util::strptime(&build_info::BUILT_TIME_UTC).year(), 2017);
/// ```
///
/// # Panics
/// If the string can't be parsed. This should never happen with input provided
/// by `built`.
#[cfg(feature = "chrono")]
pub fn strptime(s: &str) -> chrono::DateTime<chrono::offset::Utc> {
    chrono::DateTime::parse_from_rfc2822(s)
        .unwrap()
        .with_timezone(&chrono::offset::Utc)
}

/// Retrieves the git-tag or hash describing the exact version.
///
/// If a valid git-repo can't be discovered at or above the given path,
/// `Ok(None)` is returned instead of an `Err`-value.
///
/// # Errors
/// Errors from `git2` are returned if the repository does exists at all.
#[cfg(feature = "git2")]
pub fn get_repo_description(root: &std::path::Path) -> Result<Option<String>, git2::Error> {
    match git2::Repository::discover(root) {
        Ok(repo) => {
            let mut desc_opt = git2::DescribeOptions::new();
            desc_opt.describe_tags().show_commit_oid_as_fallback(true);
            Ok(Some(
                repo.describe(&desc_opt)
                    .and_then(|desc| desc.format(None))?,
            ))
        }
        Err(ref e)
            if e.class() == git2::ErrorClass::Repository
                && e.code() == git2::ErrorCode::NotFound =>
        {
            Ok(None)
        }
        Err(e) => Err(e),
    }
}

/// Retrieves the branch name and hash of HEAD.
///
/// The returned value is a tuple of head's reference name and long hash. The
/// branch name will be `None` if the head is detached, or it's not valid UTF-8.
///
/// If a valid git-repo can't be discovered at or above the given path,
/// `Ok(None)` is returned instead of an `Err`-value.
///
/// # Errors
/// Errors from `git2` are returned if the repository does exists at all.
#[cfg(feature = "git2")]
pub fn get_repo_head(
    root: &std::path::Path,
) -> Result<Option<(Option<String>, String)>, git2::Error> {
    match git2::Repository::discover(root) {
        Ok(repo) => {
            // Supposed to be the reference pointed to by HEAD, but it's HEAD
            // itself, if detached
            let head_ref = repo.head()?;
            let branch = {
                // Check whether `head` is realy the pointed to reference and
                // not HEAD itself.
                if !repo.head_detached()? {
                    head_ref.name()
                } else {
                    None
                }
            };
            let commit = head_ref.peel_to_commit()?.id();
            Ok(Some((
                branch.map(ToString::to_string),
                format!("{}", commit),
            )))
        }
        Err(ref e)
            if e.class() == git2::ErrorClass::Repository
                && e.code() == git2::ErrorCode::NotFound =>
        {
            Ok(None)
        }
        Err(e) => Err(e),
    }
}

/// Detect execution on various Continiuous Integration platforms.
///
/// CI-platforms are detected by the presence of known environment variables.
/// This allows to detect specific CI-platform (like `GitLab`); various
/// generic environment variables are also checked, which may result in
/// `CIPlatform::Generic`.
///
/// Since some platforms have fairly generic environment variables to begin with
/// (e.g. `TASK_ID`), this function may have false positives.
pub fn detect_ci() -> Option<super::CIPlatform> {
    super::CIPlatform::detect_from_envmap(&super::get_environment())
}
<|endoftext|>