<commit_before>use std::fmt;

use chrono::{DateTime, Local};
use chrono_humanize::HumanTime;
use json::JsonValue;

// #[derive(Debug, Default)]
// pub struct Error {
//     pub detail: String,
// }
//
// #[derive(Debug)]
// pub struct CrateLinks {
//     pub owners: Option<String>,
//     pub reverse_dependencies: String,
//     pub version_downloads: String,
//     pub versions: Option<String>,
// }
//
// pub struct Crate {
//     pub created_at: String,
//     pub description: Option<String>,
//     pub documentation: Option<String>,
//     pub downloads: i32,
//     pub homepage: Option<String>,
//     pub id: String,
//     pub keywords: Option<Vec<String>>,
//     pub license: Option<String>,
//     pub links: CrateLinks,
//     pub max_version: String,
//     pub name: String,
//     pub repository: Option<String>,
//     pub updated_at: String,
//     pub versions: Option<Vec<u64>>,
// }
//
// #[derive(Debug)]
// pub struct Keyword {
//     pub crates_cnt: u64,
//     pub created_at: String,
//     pub id: String,
//     pub keyword: String,
// }
//
// #[derive(Debug)]
// pub struct VersionLinks {
//     pub authors: String,
//     pub dependencies: String,
//     pub version_downloads: String,
// }
//
// #[derive(Debug)]
// pub struct Version {
//     pub krate: String,
//     pub created_at: String,
//     pub dl_path: String,
//     pub downloads: i32,
//     pub features: HashMap<String, Vec<String>>,
//     pub id: i32,
//     pub links: VersionLinks,
//     pub num: String,
//     pub updated_at: String,
//     pub yanked: bool,
// }
//
// pub struct Reply {
//     pub errors: Error,
//     pub krate: Crate,
//     pub keywords: Vec<Keyword>,
//     pub versions: Vec<Version>,
// }

struct TimeStamp(Option<DateTime<Local>>);

impl<'a> From<&'a JsonValue> for TimeStamp {
    fn from(jv: &JsonValue) -> Self {
        let parse = |s: &str| s.parse::<DateTime<Local>>().ok();
        TimeStamp(jv.as_str().and_then(parse))
    }
}

impl fmt::Display for TimeStamp {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(ts) = self.0 {
            if f.alternate() {
                f.pad(&format!("{}", HumanTime::from(ts)))
            } else {
                f.pad(&format!("{}", ts.naive_local()))
            }
        } else {
            f.pad("")
        }
    }
}

pub struct Crate {
    krate: JsonValue,
    versions: JsonValue,
    keywords: JsonValue,
}

const FIELDS: [&'static str; 5] =
    ["description", "documentation", "homepage", "repository", "license"];

impl Crate {
    pub fn new(json: &JsonValue) -> Self {
        let mut krate = json["crate"].clone();
        // Fix up fields that may be absent

        for field in &FIELDS {
            if krate[*field].is_null() {
                krate[*field] = "".into();
            }
        }

        Crate {
            krate: krate,
            versions: json["versions"].clone(),
            keywords: json["keywords"].clone(),
        }
    }

    pub fn print_repository(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Repository:", self.krate["repository"])
        } else {
            format!("{}", self.krate["repository"])
        }
        // if let JsonValue::String(ref repository) = self.krate["repository"] {
        //     if verbose {
        //         format!("{:<16}{}", "Repository:", repository)
        //     } else {
        //         repository.clone()
        //     }
        // }
    }

    pub fn print_documentation(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Documentation:", self.krate["documentation"])
        } else {
            format!("{}", self.krate["documentation"])
        }
        // if let JsonValue::String(ref documentation) = self.krate["documentation"] {
        //     if verbose {
        //         format!("{:<16}{}", "Documentation:", documentation)
        //     } else {
        //         documentation.clone()
        //     }
        // }
    }

    pub fn print_downloads(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Downloads:", self.krate["downloads"])
        } else {
            format!("{}", self.krate["downloads"])
        }
        // if let JsonValue::Number(downloads) = self.krate["downloads"] {
        //     if verbose {
        //         format!("{:<16}{}", "Downloads:", downloads)
        //     } else {
        //         format!("{}", downloads)
        //     }
        // }
    }

    pub fn print_homepage(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Homepage:", self.krate["homepage"])
        } else {
            format!("{}", self.krate["homepage"])
        }
        // if let JsonValue::String(ref homepage) = self.krate["homepage"] {
        //     let fmt = if verbose {
        //         format!("{:<16}{}", "Homepage:", homepage)
        //     } else {
        //         homepage.clone()
        //     };
        //     println!("{}", fmt);
        // }
    }

    fn print_version(v: &JsonValue, verbose: bool) -> String {
        let created_at = TimeStamp::from(&v["created_at"]);
        let mut output = format!("{:<11}{:<#16}{:<11}", v["num"], created_at, v["downloads"]);

        if v["yanked"] == "true" {
            output = output + "(yanked)";
        }

        if verbose {
            // Consider adding some more useful information in verbose mode
            output + "\n"
        } else {
            output + "\n"
        }
    }

    fn print_version_header(verbose: bool) -> String {
        let output = format!("{:<11}{:<#16}{:<11}\n", "VERSION", "RELEASED", "DOWNLOADS");
        if verbose {
            // Consider adding some more useful information in verbose mode
            output + "\n"
        } else {
            output + "\n"
        }
    }

    pub fn print_last_versions(&self, limit: usize, verbose: bool) -> String {
        let mut output = Crate::print_version_header(verbose);
        for version in self.versions.members().take(limit) {
            output = output + &Crate::print_version(version, verbose);
        }
        let length = self.versions.len();
        if limit < length {
            output = output + &format!("\n... use -VV to show all {} versions\n", length);
        }
        output
    }

    pub fn print_keywords(&self, verbose: bool) -> String {
        if verbose {
            format!("{:#}", self.keywords)
        } else {
            format!("{}", self.keywords)
        }
    }
}

impl fmt::Display for Crate {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let created_at = TimeStamp::from(&self.krate["created_at"]);
        let updated_at = TimeStamp::from(&self.krate["updated_at"]);

        let keywords = self.krate["keywords"]
            .members()
            .filter_map(|jv| jv.as_str())
            .collect::<Vec<_>>();

        if f.alternate() {
            write!(f,
                   "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}",
                   format_args!("{:<16}{}", "Crate:", self.krate["name"]),
                   format_args!("{:<16}{}", "Version:", self.krate["max_version"]),
                   format_args!("{:<16}{}", "Description:", self.krate["description"]),
                   format_args!("{:<16}{}", "Downloads:", self.krate["downloads"]),
                   format_args!("{:<16}{}", "Homepage:", self.krate["homepage"]),
                   format_args!("{:<16}{}", "Documentation:", self.krate["documentation"]),
                   format_args!("{:<16}{}", "Repository:", self.krate["repository"]),
                   format_args!("{:<16}{}", "License:", self.krate["license"]),
                   format_args!("{:<16}{:?}", "Keywords:", keywords),
                   format_args!("{:<16}{}  ({:#})", "Created at:", created_at, created_at),
                   format_args!("{:<16}{}  ({:#})", "Updated at:", updated_at, updated_at))
        } else {
            write!(f,
                   "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}",
                   format_args!("{:<16}{}", "Crate:", self.krate["name"]),
                   format_args!("{:<16}{}", "Version:", self.krate["max_version"]),
                   format_args!("{:<16}{}", "Description:", self.krate["description"]),
                   format_args!("{:<16}{}", "Downloads:", self.krate["downloads"]),
                   format_args!("{:<16}{}", "Homepage:", self.krate["homepage"]),
                   format_args!("{:<16}{}", "Documentation:", self.krate["documentation"]),
                   format_args!("{:<16}{}", "Repository:", self.krate["repository"]),
                   format_args!("{:<16}{:#}", "Last updated:", updated_at))
        }
    }
}
<commit_msg>Add brief version history in the default output<commit_after>use std::fmt;

use chrono::{DateTime, Local};
use chrono_humanize::HumanTime;
use json::JsonValue;

// #[derive(Debug, Default)]
// pub struct Error {
//     pub detail: String,
// }
//
// #[derive(Debug)]
// pub struct CrateLinks {
//     pub owners: Option<String>,
//     pub reverse_dependencies: String,
//     pub version_downloads: String,
//     pub versions: Option<String>,
// }
//
// pub struct Crate {
//     pub created_at: String,
//     pub description: Option<String>,
//     pub documentation: Option<String>,
//     pub downloads: i32,
//     pub homepage: Option<String>,
//     pub id: String,
//     pub keywords: Option<Vec<String>>,
//     pub license: Option<String>,
//     pub links: CrateLinks,
//     pub max_version: String,
//     pub name: String,
//     pub repository: Option<String>,
//     pub updated_at: String,
//     pub versions: Option<Vec<u64>>,
// }
//
// #[derive(Debug)]
// pub struct Keyword {
//     pub crates_cnt: u64,
//     pub created_at: String,
//     pub id: String,
//     pub keyword: String,
// }
//
// #[derive(Debug)]
// pub struct VersionLinks {
//     pub authors: String,
//     pub dependencies: String,
//     pub version_downloads: String,
// }
//
// #[derive(Debug)]
// pub struct Version {
//     pub krate: String,
//     pub created_at: String,
//     pub dl_path: String,
//     pub downloads: i32,
//     pub features: HashMap<String, Vec<String>>,
//     pub id: i32,
//     pub links: VersionLinks,
//     pub num: String,
//     pub updated_at: String,
//     pub yanked: bool,
// }
//
// pub struct Reply {
//     pub errors: Error,
//     pub krate: Crate,
//     pub keywords: Vec<Keyword>,
//     pub versions: Vec<Version>,
// }

struct TimeStamp(Option<DateTime<Local>>);

impl<'a> From<&'a JsonValue> for TimeStamp {
    fn from(jv: &JsonValue) -> Self {
        let parse = |s: &str| s.parse::<DateTime<Local>>().ok();
        TimeStamp(jv.as_str().and_then(parse))
    }
}

impl fmt::Display for TimeStamp {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(ts) = self.0 {
            if f.alternate() {
                f.pad(&format!("{}", HumanTime::from(ts)))
            } else {
                f.pad(&format!("{}", ts.naive_local()))
            }
        } else {
            f.pad("")
        }
    }
}

pub struct Crate {
    krate: JsonValue,
    versions: JsonValue,
    keywords: JsonValue,
}

const FIELDS: [&'static str; 5] =
    ["description", "documentation", "homepage", "repository", "license"];

impl Crate {
    pub fn new(json: &JsonValue) -> Self {
        let mut krate = json["crate"].clone();
        // Fix up fields that may be absent

        for field in &FIELDS {
            if krate[*field].is_null() {
                krate[*field] = "".into();
            }
        }

        Crate {
            krate: krate,
            versions: json["versions"].clone(),
            keywords: json["keywords"].clone(),
        }
    }

    pub fn print_repository(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Repository:", self.krate["repository"])
        } else {
            format!("{}", self.krate["repository"])
        }
        // if let JsonValue::String(ref repository) = self.krate["repository"] {
        //     if verbose {
        //         format!("{:<16}{}", "Repository:", repository)
        //     } else {
        //         repository.clone()
        //     }
        // }
    }

    pub fn print_documentation(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Documentation:", self.krate["documentation"])
        } else {
            format!("{}", self.krate["documentation"])
        }
        // if let JsonValue::String(ref documentation) = self.krate["documentation"] {
        //     if verbose {
        //         format!("{:<16}{}", "Documentation:", documentation)
        //     } else {
        //         documentation.clone()
        //     }
        // }
    }

    pub fn print_downloads(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Downloads:", self.krate["downloads"])
        } else {
            format!("{}", self.krate["downloads"])
        }
        // if let JsonValue::Number(downloads) = self.krate["downloads"] {
        //     if verbose {
        //         format!("{:<16}{}", "Downloads:", downloads)
        //     } else {
        //         format!("{}", downloads)
        //     }
        // }
    }

    pub fn print_homepage(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Homepage:", self.krate["homepage"])
        } else {
            format!("{}", self.krate["homepage"])
        }
        // if let JsonValue::String(ref homepage) = self.krate["homepage"] {
        //     let fmt = if verbose {
        //         format!("{:<16}{}", "Homepage:", homepage)
        //     } else {
        //         homepage.clone()
        //     };
        //     println!("{}", fmt);
        // }
    }

    fn print_version(v: &JsonValue, verbose: bool) -> String {
        let created_at = TimeStamp::from(&v["created_at"]);
        let mut output = format!("{:<11}{:<#16}{:<11}", v["num"], created_at, v["downloads"]);

        if v["yanked"] == "true" {
            output = output + "(yanked)";
        }

        if verbose {
            // Consider adding some more useful information in verbose mode
            output + "\n"
        } else {
            output + "\n"
        }
    }

    fn print_version_header(verbose: bool) -> String {
        let output = format!("{:<11}{:<#16}{:<11}\n", "VERSION", "RELEASED", "DOWNLOADS");
        if verbose {
            // Consider adding some more useful information in verbose mode
            output + "\n"
        } else {
            output + "\n"
        }
    }

    pub fn print_last_versions(&self, limit: usize, verbose: bool) -> String {
        let mut output = Crate::print_version_header(verbose);
        for version in self.versions.members().take(limit) {
            output = output + &Crate::print_version(version, verbose);
        }
        let length = self.versions.len();
        if limit < length {
            output = output + &format!("\n... use -VV to show all {} versions\n", length);
        }
        output
    }

    pub fn print_keywords(&self, verbose: bool) -> String {
        if verbose {
            format!("{:#}", self.keywords)
        } else {
            format!("{}", self.keywords)
        }
    }
}

impl fmt::Display for Crate {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let created_at = TimeStamp::from(&self.krate["created_at"]);
        let updated_at = TimeStamp::from(&self.krate["updated_at"]);

        let keywords = self.krate["keywords"]
            .members()
            .filter_map(|jv| jv.as_str())
            .collect::<Vec<_>>();

        if f.alternate() {
            write!(f,
                   "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}",
                   format_args!("{:<16}{}", "Crate:", self.krate["name"]),
                   format_args!("{:<16}{}", "Version:", self.krate["max_version"]),
                   format_args!("{:<16}{}", "Description:", self.krate["description"]),
                   format_args!("{:<16}{}", "Downloads:", self.krate["downloads"]),
                   format_args!("{:<16}{}", "Homepage:", self.krate["homepage"]),
                   format_args!("{:<16}{}", "Documentation:", self.krate["documentation"]),
                   format_args!("{:<16}{}", "Repository:", self.krate["repository"]),
                   format_args!("{:<16}{}", "License:", self.krate["license"]),
                   format_args!("{:<16}{:?}", "Keywords:", keywords),
                   format_args!("{:<16}{}  ({:#})", "Created at:", created_at, created_at),
                   format_args!("{:<16}{}  ({:#})", "Updated at:", updated_at, updated_at))
        } else {
            let mut versions = String::new();
            for line in self.print_last_versions(5, false).lines() {
                versions = versions + "\n";
                if !line.is_empty() {
                    versions = versions + "  " + line;
                }
            }

            write!(f,
                   "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}",
                   format_args!("{:<16}{}", "Crate:", self.krate["name"]),
                   format_args!("{:<16}{}", "Version:", self.krate["max_version"]),
                   format_args!("{:<16}{}", "Description:", self.krate["description"]),
                   format_args!("{:<16}{}", "Downloads:", self.krate["downloads"]),
                   format_args!("{:<16}{}", "Homepage:", self.krate["homepage"]),
                   format_args!("{:<16}{}", "Documentation:", self.krate["documentation"]),
                   format_args!("{:<16}{}", "Repository:", self.krate["repository"]),
                   format_args!("{:<16}{:#}", "Last updated:", updated_at),
                   format_args!("{:<16}\n{}", "Version history:", versions))
        }
    }
}
<|endoftext|>


<commit_before>use id::{Id, IdIndex, MAXIMUM_CAPACITY};
use flat::{FlatAccess, FlatAccessMut, Flat, FlatGet, FlatGetMut};

pub type IdMapVec<E, T> = IdMap<E, Vec<T>>;

#[derive(Debug)]
pub struct IdMap<E, F: Flat> {
    lookup: Vec<Id<E>>,
    reverse_lookup: Vec<IdIndex>,
    flat: F,
}

impl<E, F: Flat> IdMap<E, F> {
    pub fn new() -> Self {
        IdMap {
            lookup: Vec::new(),
            reverse_lookup: Vec::new(),
            flat: F::new(),
        }
    }

    pub fn with_capacity(capacity: usize) -> Self {
        assert!(capacity <= MAXIMUM_CAPACITY);
        IdMap {
            lookup: Vec::with_capacity(capacity),
            reverse_lookup: Vec::with_capacity(capacity),
            flat: F::with_capacity(capacity),
        }
    }

    #[inline]
    pub fn insert(&mut self, id: Id<E>, mut element: F::Element) -> Option<F::Element> {
        let IdMap { ref mut lookup, ref mut reverse_lookup, ref mut flat } = *self;
        let new_index = {
            let len = reverse_lookup.len();
            assert!(len <= MAXIMUM_CAPACITY);
            len as IdIndex
        };

        let usize_index = id.index as usize;
        let lookup_id = if usize_index < lookup.len() {
            let lookup_id = &mut lookup[usize_index];
            element = match flat.replace(lookup_id.index as usize, element) {
                Ok(value) => {
                    return if id.tag == lookup_id.tag {
                        Some(value)
                    } else {
                        lookup_id.tag = id.tag;
                        None
                    }
                }
                Err(element) => element,
            };
            lookup_id
        } else {
            lookup.resize(usize_index + 1, Id::invalid());
            &mut lookup[usize_index]
        };
        *lookup_id = Id { index: new_index, ..id };
        reverse_lookup.push(id.index);
        flat.push(element);
        None
    }

    #[inline]
    pub fn remove(&mut self, id: Id<E>) -> Option<F::Element> {
        let IdMap { ref mut lookup, ref mut reverse_lookup, ref mut flat } = *self;

        let usize_index = id.index as usize;
        let lookup_index = match lookup.get_mut(usize_index) {
            Some(lookup_id) => {
                if lookup_id.tag != id.tag {
                    return None;
                }
                let index = lookup_id.index;
                *lookup_id = Id::invalid();
                index
            }
            None => return None,
        };
        let usize_lookup_index = lookup_index as usize;
        let old_value = match flat.swap_remove(usize_lookup_index) {
            Some(old_value) => old_value,
            None => return None,
        };
        reverse_lookup.swap_remove(usize_lookup_index);
        reverse_lookup.get(usize_lookup_index)
            .map(|&reverse_index| lookup[reverse_index as usize].index = lookup_index);
        Some(old_value)
    }

    #[inline]
    pub fn get<'a>(&'a self, id: Id<E>) -> Option<<&'a F as FlatGet>::ElementRef>
        where &'a F: FlatGet
    {
        match self.lookup.get(id.index as usize) {
            Some(lookup_id) if lookup_id.tag == id.tag => {
                self.flat.flat_get(lookup_id.index as usize)
            }
            _ => None,
        }
    }

    #[inline]
    pub fn get_mut<'a>(&'a mut self, id: Id<E>) -> Option<<&'a mut F as FlatGetMut>::ElementRefMut>
        where &'a mut F: FlatGetMut
    {
        match self.lookup.get(id.index as usize) {
            Some(lookup_id) if lookup_id.tag == id.tag => {
                self.flat.flat_get_mut(lookup_id.index as usize)
            }
            _ => None,
        }
    }

    #[inline]
    pub fn id_to_index(&self, id: Id<E>) -> Option<usize> {
        match self.lookup.get(id.index as usize) {
            Some(lookup_id) if lookup_id.tag == id.tag => Some(lookup_id.index as usize),
            _ => None,
        }
    }

    #[inline]
    pub fn index_to_id(&self, index: usize) -> Option<Id<E>> {
        match self.reverse_lookup.get(index) {
            Some(&lookup_index) => {
                Some(Id { index: lookup_index, ..self.lookup[lookup_index as usize] })
            }
            _ => None,
        }
    }

    #[inline]
    pub fn access<'a>(&'a self) -> <&'a F as FlatAccess>::Access
        where &'a F: FlatAccess
    {
        self.flat.flat_access()
    }

    #[inline]
    pub fn access_mut<'a>(&'a mut self) -> <&'a mut F as FlatAccessMut>::AccessMut
        where &'a mut F: FlatAccessMut
    {
        self.flat.flat_access_mut()
    }
}

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

    fn setup() -> (IdSlab<()>, IdMapVec<(), u32>) {
        (IdSlab::new(), IdMapVec::new())
    }

    #[test]
    fn insert_twice_returns_first_and_respects_tag() {
        let (mut slab, mut map) = setup();
        let id1 = slab.insert(());
        assert_eq!(map.insert(id1, 1), None);
        assert_eq!(map.insert(id1, 2), Some(1));
        slab.remove(id1);
        let id2 = slab.insert(());
        assert_eq!(map.insert(id2, 3), None);
        assert_eq!(map.insert(id2, 4), Some(3));
        assert_eq!(map.insert(id1, 4), None);
    }

    #[test]
    fn insert_get_returns_correct() {
        let (mut slab, mut map) = setup();
        let id1 = slab.insert(());
        let id2 = slab.insert(());
        assert_eq!(map.get(id1), None);
        assert_eq!(map.get(id2), None);

        assert_eq!(map.insert(id1, 1), None);
        assert_eq!(map.insert(id2, 2), None);

        assert_eq!(map.get(id1), Some(&1));
        assert_eq!(map.get(id2), Some(&2));

        assert_eq!(map.get_mut(id1).map(|x| *x), Some(1));
        assert_eq!(map.get_mut(id2).map(|x| *x), Some(2));

        slab.remove(id1);
        slab.remove(id2);
        let id3 = slab.insert(());
        let id4 = slab.insert(());
        assert_eq!(map.get(id3), None);
        assert_eq!(map.get(id4), None);

        assert_eq!(map.insert(id3, 3), None);
        assert_eq!(map.insert(id4, 4), None);

        assert_eq!(map.get(id1), None);
        assert_eq!(map.get(id2), None);

        assert_eq!(map.get(id3), Some(&3));
        assert_eq!(map.get(id4), Some(&4));
        assert_eq!(map.get_mut(id3).map(|x| *x), Some(3));
        assert_eq!(map.get_mut(id4).map(|x| *x), Some(4));
    }

    #[test]
    fn modify_through_get_mut() {
        let (mut slab, mut map) = setup();
        let id1 = slab.insert(());
        assert_eq!(map.get(id1), None);
        assert_eq!(map.insert(id1, 1), None);
        *map.get_mut(id1).unwrap() = 10;
        assert_eq!(map.get(id1), Some(&10));
        assert_eq!(map.insert(id1, 20), Some(10));
    }

    #[test]
    fn insert_remove_get() {
        let (mut slab, mut map) = setup();
        let id1 = slab.insert(());
        let id2 = slab.insert(());

        assert_eq!(map.insert(id1, 1), None);
        assert_eq!(map.remove(id1), Some(1));
        assert_eq!(map.remove(id1), None);
        assert_eq!(map.get(id1), None);

        assert_eq!(map.insert(id2, 20), None);
        assert_eq!(map.insert(id1, 10), None);
        assert_eq!(map.remove(id1), Some(10));
        assert_eq!(map.get(id2), Some(&20));
        assert_eq!(map.remove(id2), Some(20));
        assert_eq!(map.get(id2), None);
    }
}
<commit_msg>add IdMap::len<commit_after>use id::{Id, IdIndex, MAXIMUM_CAPACITY};
use flat::{FlatAccess, FlatAccessMut, Flat, FlatGet, FlatGetMut};

pub type IdMapVec<E, T> = IdMap<E, Vec<T>>;

#[derive(Debug)]
pub struct IdMap<E, F: Flat> {
    lookup: Vec<Id<E>>,
    reverse_lookup: Vec<IdIndex>,
    flat: F,
}

impl<E, F: Flat> IdMap<E, F> {
    pub fn new() -> Self {
        IdMap {
            lookup: Vec::new(),
            reverse_lookup: Vec::new(),
            flat: F::new(),
        }
    }

    pub fn len(&self) -> usize {
        self.reverse_lookup.len()
    }

    pub fn with_capacity(capacity: usize) -> Self {
        assert!(capacity <= MAXIMUM_CAPACITY);
        IdMap {
            lookup: Vec::with_capacity(capacity),
            reverse_lookup: Vec::with_capacity(capacity),
            flat: F::with_capacity(capacity),
        }
    }

    #[inline]
    pub fn insert(&mut self, id: Id<E>, mut element: F::Element) -> Option<F::Element> {
        let IdMap { ref mut lookup, ref mut reverse_lookup, ref mut flat } = *self;
        let new_index = {
            let len = reverse_lookup.len();
            assert!(len <= MAXIMUM_CAPACITY);
            len as IdIndex
        };

        let usize_index = id.index as usize;
        let lookup_id = if usize_index < lookup.len() {
            let lookup_id = &mut lookup[usize_index];
            element = match flat.replace(lookup_id.index as usize, element) {
                Ok(value) => {
                    return if id.tag == lookup_id.tag {
                        Some(value)
                    } else {
                        lookup_id.tag = id.tag;
                        None
                    }
                }
                Err(element) => element,
            };
            lookup_id
        } else {
            lookup.resize(usize_index + 1, Id::invalid());
            &mut lookup[usize_index]
        };
        *lookup_id = Id { index: new_index, ..id };
        reverse_lookup.push(id.index);
        flat.push(element);
        None
    }

    #[inline]
    pub fn remove(&mut self, id: Id<E>) -> Option<F::Element> {
        let IdMap { ref mut lookup, ref mut reverse_lookup, ref mut flat } = *self;

        let usize_index = id.index as usize;
        let lookup_index = match lookup.get_mut(usize_index) {
            Some(lookup_id) => {
                if lookup_id.tag != id.tag {
                    return None;
                }
                let index = lookup_id.index;
                *lookup_id = Id::invalid();
                index
            }
            None => return None,
        };
        let usize_lookup_index = lookup_index as usize;
        let old_value = match flat.swap_remove(usize_lookup_index) {
            Some(old_value) => old_value,
            None => return None,
        };
        reverse_lookup.swap_remove(usize_lookup_index);
        reverse_lookup.get(usize_lookup_index)
            .map(|&reverse_index| lookup[reverse_index as usize].index = lookup_index);
        Some(old_value)
    }

    #[inline]
    pub fn get<'a>(&'a self, id: Id<E>) -> Option<<&'a F as FlatGet>::ElementRef>
        where &'a F: FlatGet
    {
        match self.lookup.get(id.index as usize) {
            Some(lookup_id) if lookup_id.tag == id.tag => {
                self.flat.flat_get(lookup_id.index as usize)
            }
            _ => None,
        }
    }

    #[inline]
    pub fn get_mut<'a>(&'a mut self, id: Id<E>) -> Option<<&'a mut F as FlatGetMut>::ElementRefMut>
        where &'a mut F: FlatGetMut
    {
        match self.lookup.get(id.index as usize) {
            Some(lookup_id) if lookup_id.tag == id.tag => {
                self.flat.flat_get_mut(lookup_id.index as usize)
            }
            _ => None,
        }
    }

    #[inline]
    pub fn id_to_index(&self, id: Id<E>) -> Option<usize> {
        match self.lookup.get(id.index as usize) {
            Some(lookup_id) if lookup_id.tag == id.tag => Some(lookup_id.index as usize),
            _ => None,
        }
    }

    #[inline]
    pub fn index_to_id(&self, index: usize) -> Option<Id<E>> {
        match self.reverse_lookup.get(index) {
            Some(&lookup_index) => {
                Some(Id { index: lookup_index, ..self.lookup[lookup_index as usize] })
            }
            _ => None,
        }
    }

    #[inline]
    pub fn access<'a>(&'a self) -> <&'a F as FlatAccess>::Access
        where &'a F: FlatAccess
    {
        self.flat.flat_access()
    }

    #[inline]
    pub fn access_mut<'a>(&'a mut self) -> <&'a mut F as FlatAccessMut>::AccessMut
        where &'a mut F: FlatAccessMut
    {
        self.flat.flat_access_mut()
    }
}

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

    fn setup() -> (IdSlab<()>, IdMapVec<(), u32>) {
        (IdSlab::new(), IdMapVec::new())
    }

    #[test]
    fn insert_twice_returns_first_and_respects_tag() {
        let (mut slab, mut map) = setup();
        let id1 = slab.insert(());
        assert_eq!(map.insert(id1, 1), None);
        assert_eq!(map.insert(id1, 2), Some(1));
        slab.remove(id1);
        let id2 = slab.insert(());
        assert_eq!(map.insert(id2, 3), None);
        assert_eq!(map.insert(id2, 4), Some(3));
        assert_eq!(map.insert(id1, 4), None);
    }

    #[test]
    fn insert_get_returns_correct() {
        let (mut slab, mut map) = setup();
        let id1 = slab.insert(());
        let id2 = slab.insert(());
        assert_eq!(map.get(id1), None);
        assert_eq!(map.get(id2), None);

        assert_eq!(map.insert(id1, 1), None);
        assert_eq!(map.insert(id2, 2), None);

        assert_eq!(map.get(id1), Some(&1));
        assert_eq!(map.get(id2), Some(&2));

        assert_eq!(map.get_mut(id1).map(|x| *x), Some(1));
        assert_eq!(map.get_mut(id2).map(|x| *x), Some(2));

        slab.remove(id1);
        slab.remove(id2);
        let id3 = slab.insert(());
        let id4 = slab.insert(());
        assert_eq!(map.get(id3), None);
        assert_eq!(map.get(id4), None);

        assert_eq!(map.insert(id3, 3), None);
        assert_eq!(map.insert(id4, 4), None);

        assert_eq!(map.get(id1), None);
        assert_eq!(map.get(id2), None);

        assert_eq!(map.get(id3), Some(&3));
        assert_eq!(map.get(id4), Some(&4));
        assert_eq!(map.get_mut(id3).map(|x| *x), Some(3));
        assert_eq!(map.get_mut(id4).map(|x| *x), Some(4));
    }

    #[test]
    fn modify_through_get_mut() {
        let (mut slab, mut map) = setup();
        let id1 = slab.insert(());
        assert_eq!(map.get(id1), None);
        assert_eq!(map.insert(id1, 1), None);
        *map.get_mut(id1).unwrap() = 10;
        assert_eq!(map.get(id1), Some(&10));
        assert_eq!(map.insert(id1, 20), Some(10));
    }

    #[test]
    fn insert_remove_get() {
        let (mut slab, mut map) = setup();
        let id1 = slab.insert(());
        let id2 = slab.insert(());

        assert_eq!(map.insert(id1, 1), None);
        assert_eq!(map.remove(id1), Some(1));
        assert_eq!(map.remove(id1), None);
        assert_eq!(map.get(id1), None);

        assert_eq!(map.insert(id2, 20), None);
        assert_eq!(map.insert(id1, 10), None);
        assert_eq!(map.remove(id1), Some(10));
        assert_eq!(map.get(id2), Some(&20));
        assert_eq!(map.remove(id2), Some(20));
        assert_eq!(map.get(id2), None);
    }
}
<|endoftext|>


<commit_before>use collections::string::ToString;
use core::ops::*;

use bounded::Bounded;
use to_primitive::ToPrimitive;
use from_primitive::FromPrimitive;
use round::Round;
use one::One;
use sqrt::Sqrt;
use trig::Trig;
use zero::Zero;

pub trait Num:
    Copy + One + Zero
    + Bounded
    + ToPrimitive
    + FromPrimitive
    + Trig
    + Sqrt
    + Round
    + PartialEq
    + PartialOrd
    + ToString

    + Add<Self, Output = Self>
    + Mul<Self, Output = Self>
    + Sub<Self, Output = Self>
    + Div<Self, Output = Self>
    + Rem<Self, Output = Self>

    + AddAssign<Self>
    + MulAssign<Self>
    + SubAssign<Self>
    + DivAssign<Self>
    + RemAssign<Self>
{
    /// # Examples
    /// ~~~
    /// use num::Num;
    ///
    /// assert_eq!((-50).clamp(&0, &100), 0);
    /// assert_eq!(50.clamp(&0, &100), 50);
    /// assert_eq!(150.clamp(&0, &100), 100);
    /// ~~~
    #[inline(always)]
    fn clamp(&self, min: &Self, max: &Self) -> Self {
        if self < min {
            *min
        } else if self > max {
            *max
        } else {
            *self
        }
    }
    /// # Examples
    /// ~~~
    /// use num::Num;
    ///
    /// assert_eq!((-0.5).clamp01(), 0.0);
    /// assert_eq!(0.5.clamp01(), 0.5);
    /// assert_eq!(1.50.clamp01(), 1.0);
    /// ~~~
    #[inline(always)]
    fn clamp01(&self) -> Self {
        self.clamp(&Zero::zero(), &One::one())
    }
}

impl<T> Num for T where T:
    Copy + One + Zero
    + Bounded
    + ToPrimitive
    + FromPrimitive
    + Trig
    + Sqrt
    + Round
    + PartialEq
    + PartialOrd
    + ToString

    + Add<T, Output = T>
    + Mul<T, Output = T>
    + Sub<T, Output = T>
    + Div<T, Output = T>
    + Rem<T, Output = T>

    + AddAssign<T>
    + MulAssign<T>
    + SubAssign<T>
    + DivAssign<T>
    + RemAssign<T> {}
<commit_msg>clean up<commit_after>use collections::string::ToString;
use core::ops::*;

use bounded::Bounded;
use to_primitive::ToPrimitive;
use from_primitive::FromPrimitive;
use round::Round;
use one::One;
use sqrt::Sqrt;
use trig::Trig;
use zero::Zero;

pub trait Num:
    Copy + One + Zero
    + Bounded
    + ToPrimitive
    + FromPrimitive
    + Trig
    + Sqrt
    + Round
    + PartialEq
    + PartialOrd
    + ToString

    + Add<Self, Output = Self>
    + Mul<Self, Output = Self>
    + Sub<Self, Output = Self>
    + Div<Self, Output = Self>
    + Rem<Self, Output = Self>

    + AddAssign<Self>
    + MulAssign<Self>
    + SubAssign<Self>
    + DivAssign<Self>
    + RemAssign<Self>
{
    /// # Examples
    /// ~~~
    /// use num::Num;
    ///
    /// assert_eq!(50.min(&100), 50);
    /// assert_eq!(100.min(&50), 50);
    /// ~~~
    #[inline]
    fn min(&self, other: &Self) -> Self {
        if self < other {
            *self
        } else {
            *other
        }
    }
    /// # Examples
    /// ~~~
    /// use num::Num;
    ///
    /// assert_eq!(50.max(&100), 100);
    /// assert_eq!(100.max(&50), 100);
    /// ~~~
    #[inline]
    fn max(&self, other: &Self) -> Self {
        if self > other {
            *self
        } else {
            *other
        }
    }
    /// # Examples
    /// ~~~
    /// use num::Num;
    ///
    /// assert_eq!((-50).clamp(&0, &100), 0);
    /// assert_eq!(50.clamp(&0, &100), 50);
    /// assert_eq!(150.clamp(&0, &100), 100);
    /// ~~~
    #[inline]
    fn clamp(&self, min: &Self, max: &Self) -> Self {
        self.min(max).max(min)
    }
    /// # Examples
    /// ~~~
    /// use num::Num;
    ///
    /// assert_eq!((-0.5).clamp01(), 0.0);
    /// assert_eq!(0.5.clamp01(), 0.5);
    /// assert_eq!(1.50.clamp01(), 1.0);
    /// ~~~
    #[inline(always)]
    fn clamp01(&self) -> Self {
        self.clamp(&Zero::zero(), &One::one())
    }
}

impl<T> Num for T where T:
    Copy + One + Zero
    + Bounded
    + ToPrimitive
    + FromPrimitive
    + Trig
    + Sqrt
    + Round
    + PartialEq
    + PartialOrd
    + ToString

    + Add<T, Output = T>
    + Mul<T, Output = T>
    + Sub<T, Output = T>
    + Div<T, Output = T>
    + Rem<T, Output = T>

    + AddAssign<T>
    + MulAssign<T>
    + SubAssign<T>
    + DivAssign<T>
    + RemAssign<T> {}
<|endoftext|>


<commit_before>use libc;

use std::{fmt, io, error, result};
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};

use byteorder::{ByteOrder, BigEndian, LittleEndian};
use crypto::digest::Digest;
use crypto::md5::Md5;

use rand::{Rng, OsRng};
use rustc_serialize::hex::{self, FromHex, ToHex};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};

use time;

const TIMESTAMP_SIZE: usize = 4;
const MACHINE_ID_SIZE: usize = 3;
const PROCESS_ID_SIZE: usize = 2;
const COUNTER_SIZE: usize = 3;

const TIMESTAMP_OFFSET: usize = 0;
const MACHINE_ID_OFFSET: usize = TIMESTAMP_OFFSET + TIMESTAMP_SIZE;
const PROCESS_ID_OFFSET: usize = MACHINE_ID_OFFSET + MACHINE_ID_SIZE;
const COUNTER_OFFSET: usize = PROCESS_ID_OFFSET + PROCESS_ID_SIZE;

const MAX_U24: usize = 0xFFFFFF;

static OID_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
static mut MACHINE_BYTES: Option<[u8; 3]> = None;

extern {
    fn gethostname(name: *mut libc::c_char, size: libc::size_t) -> libc::c_int;
}

/// Errors that can occur during OID construction and generation.
#[derive(Debug)]
pub enum Error {
    ArgumentError(String),
    FromHexError(hex::FromHexError),
    IoError(io::Error),
    HostnameError,
}

impl From<hex::FromHexError> for Error {
    fn from(err: hex::FromHexError) -> Error {
        Error::FromHexError(err)
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::IoError(err)
    }
}

/// Alias for Result<T, oid::Error>.
pub type Result<T> = result::Result<T, Error>;

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::ArgumentError(ref inner) => inner.fmt(fmt),
            &Error::FromHexError(ref inner) => inner.fmt(fmt),
            &Error::IoError(ref inner) => inner.fmt(fmt),
            &Error::HostnameError => write!(fmt, "Failed to retrieve hostname for OID generation."),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::ArgumentError(ref inner) => &inner,
            &Error::FromHexError(ref inner) => inner.description(),
            &Error::IoError(ref inner) => inner.description(),
            &Error::HostnameError => "Failed to retrieve hostname for OID generation.",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Error::ArgumentError(_) => None,
            &Error::FromHexError(ref inner) => Some(inner),
            &Error::IoError(ref inner) => Some(inner),
            &Error::HostnameError => None,
        }
    }
}

/// A wrapper around raw 12-byte ObjectId representations.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct ObjectId {
    id: [u8; 12],
}

impl ObjectId {
    /// Generates a new ObjectID, represented in bytes.
    /// See the [docs](http://docs.mongodb.org/manual/reference/object-id/)
    /// for more information.
    pub fn new() -> Result<ObjectId> {
        let timestamp = ObjectId::gen_timestamp();
        let machine_id = try!(ObjectId::gen_machine_id());
        let process_id = ObjectId::gen_process_id();
        let counter = try!(ObjectId::gen_count());

        let mut buf: [u8; 12] = [0; 12];
        for i in 0..TIMESTAMP_SIZE { buf[TIMESTAMP_OFFSET + i] = timestamp[i]; }
        for i in 0..MACHINE_ID_SIZE { buf[MACHINE_ID_OFFSET + i] = machine_id[i]; }
        for i in 0..PROCESS_ID_SIZE { buf[PROCESS_ID_OFFSET + i] = process_id[i]; }
        for i in 0..COUNTER_SIZE { buf[COUNTER_OFFSET +i] = counter[i]; }

        Ok(ObjectId::with_bytes(buf))
    }

    /// Constructs a new ObjectId wrapper around the raw byte representation.
    pub fn with_bytes(bytes: [u8; 12]) -> ObjectId {
        ObjectId {
            id: bytes,
        }
    }

    /// Creates an ObjectID using a 12-byte (24-char) hexadecimal string.
    pub fn with_string(s: &str) -> Result<ObjectId> {
        let bytes = try!(s.from_hex());
        if bytes.len() != 12 {
            Err(Error::ArgumentError("Provided string must be a 12-byte hexadecimal string.".to_owned()))
        } else {
            let mut byte_array: [u8; 12] = [0; 12];
            for i in 0..12 {
                byte_array[i] = bytes[i];
            }
            Ok(ObjectId::with_bytes(byte_array))
        }
    }

    /// Creates a dummy ObjectId with a specific generation time.
    /// This method should only be used to do range queries on a field
    /// containing ObjectId instances.
    pub fn with_timestamp(time: u32) -> ObjectId {
        let mut buf: [u8; 12] = [0; 12];
        BigEndian::write_u32(&mut buf, time);
        ObjectId::with_bytes(buf)
    }

    /// Returns the raw byte representation of an ObjectId.
    pub fn bytes(&self) -> [u8; 12] {
        self.id
    }

    /// Retrieves the timestamp (seconds since epoch) from an ObjectId.
    pub fn timestamp(&self) -> u32 {
        BigEndian::read_u32(&self.id)
    }

    /// Retrieves the machine id associated with an ObjectId.
    pub fn machine_id(&self) -> u32 {
        let mut buf: [u8; 4] = [0; 4];
        for i in 0..MACHINE_ID_SIZE {
            buf[i] = self.id[MACHINE_ID_OFFSET+i];
        }
        LittleEndian::read_u32(&buf)
    }

    /// Retrieves the process id associated with an ObjectId.
    pub fn process_id(&self) -> u16 {
        LittleEndian::read_u16(&self.id[PROCESS_ID_OFFSET..])
    }

    /// Retrieves the increment counter from an ObjectId.
    pub fn counter(&self) -> u32 {
        let mut buf: [u8; 4] = [0; 4];
        for i in 0..COUNTER_SIZE {
            buf[i+1] = self.id[COUNTER_OFFSET+i];
        }
        BigEndian::read_u32(&buf)
    }

    // Generates a new timestamp representing the current seconds since epoch.
    // Represented in Big Endian.
    fn gen_timestamp() -> [u8; 4] {
        let timespec = time::get_time();
        let timestamp = timespec.sec as u32;

        let mut buf: [u8; 4] = [0; 4];
        BigEndian::write_u32(&mut buf,timestamp);
        buf
    }

    // Generates a new machine id represented as an MD5-hashed 3-byte-encoded hostname string.
    // Represented in Little Endian.
    fn gen_machine_id() -> Result<[u8; 3]> {
        // Short-circuit if machine id has already been calculated.
        // Since the generated machine id is not variable, arising race conditions
        // will have the same MACHINE_BYTES result.
        unsafe {
            if let Some(bytes) = MACHINE_BYTES.as_ref() {
                return Ok(bytes.clone());
            }
        }

        // Retrieve hostname through libc
        let len = 255;
        let mut buf = Vec::<u8>::with_capacity(len);
        let ptr = buf.as_mut_ptr();
        let err = unsafe { gethostname(ptr as *mut libc::c_char, len as libc::size_t) } as i32;

        if err != 0 {
            return Err(Error::HostnameError);
        }

        // Convert bytes into string
        let s = String::from_utf8_lossy(&buf);

        // Hash hostname string
        let mut md5 = Md5::new();
        md5.input_str(&s.into_owned()[..]);
        let hash = md5.result_str();

        // Re-convert string to bytes and grab first three
        let mut bytes = hash.bytes();
        let mut vec: [u8; 3] = [0; 3];
        for i in 0..MACHINE_ID_SIZE {
            match bytes.next() {
                Some(b) => vec[i] = b,
                None => break,
            }
        }

        unsafe { MACHINE_BYTES = Some(vec) };
        Ok(vec)
    }

    // Gets the process ID and returns it as a 2-byte array.
    // Represented in Little Endian.
    fn gen_process_id() -> [u8; 2] {
        let pid = unsafe { libc::getpid() as u16 };
        let mut buf: [u8; 2] = [0; 2];
        LittleEndian::write_u16(&mut buf, pid);
        buf
    }

    // Gets an incremental 3-byte count.
    // Represented in Big Endian.
    fn gen_count() -> Result<[u8; 3]> {
        // Init oid counter
        if OID_COUNTER.load(Ordering::SeqCst) == 0 {
            let mut rng = try!(OsRng::new());
            let start = rng.gen_range(0, MAX_U24 + 1);
            OID_COUNTER.store(start, Ordering::SeqCst);
        }

        let u_counter = OID_COUNTER.fetch_add(1, Ordering::SeqCst);

        // Mod result instead of OID_COUNTER to prevent threading issues.
        // Static mutexes are currently unstable; once they have been
        // stabilized, one should be used to access OID_COUNTER and
        // perform multiple operations atomically.
        let u = u_counter % MAX_U24;

        // Convert usize to writable u64, then extract the first three bytes.
        let u_int = u as u64;

        let mut buf: [u8; 8] = [0; 8];
        BigEndian::write_u64(&mut buf, u_int);
        let buf_u24: [u8; 3] = [buf[5], buf[6], buf[7]];
        Ok(buf_u24)
    }
}

impl ToHex for ObjectId {
    fn to_hex(&self) -> String {
        self.id.to_hex()
    }
}

impl fmt::Display for ObjectId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.to_hex())
    }
}

impl Decodable for ObjectId {
    fn decode<D: Decoder>(d: &mut D) -> result::Result<Self, D::Error> {
        let str = try!(d.read_str());
        Ok(ObjectId::with_string(&str).unwrap())
    }
}

impl Encodable for ObjectId {
    fn encode<S: Encoder>(&self, s: &mut S) -> result::Result<(), S::Error> {
        s.emit_str(&self.to_string())
    }
}

#[test]
fn pid_generation() {
    let pid = unsafe { libc::getpid() as u16 };
    let generated = ObjectId::gen_process_id();
    assert_eq!(pid, LittleEndian::read_u16(&generated));
}

#[test]
fn count_generation() {
    let start = 52222;
    OID_COUNTER.store(start, Ordering::SeqCst);
    let count_res = ObjectId::gen_count();
    assert!(count_res.is_ok());
    let count_bytes = count_res.unwrap();

    let mut buf: [u8; 4] = [0; 4];
    for i in 0..COUNTER_SIZE {
        buf[i+1] = count_bytes[i];
    }

    let count = BigEndian::read_u32(&buf);
    assert_eq!(start as u32, count);
}

#[test]
fn count_is_big_endian() {
    let start = 1122867;
    OID_COUNTER.store(start, Ordering::SeqCst);
    let oid_res = ObjectId::new();
    assert!(oid_res.is_ok());
    let oid = oid_res.unwrap();

    assert_eq!(0x11u8, oid.bytes()[COUNTER_OFFSET]);
    assert_eq!(0x22u8, oid.bytes()[COUNTER_OFFSET + 1]);
    assert_eq!(0x33u8, oid.bytes()[COUNTER_OFFSET + 2]);
}

<commit_msg>Show object id formatted as string in debug trait<commit_after>use libc;

use std::{fmt, io, error, result};
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};

use byteorder::{ByteOrder, BigEndian, LittleEndian};
use crypto::digest::Digest;
use crypto::md5::Md5;

use rand::{Rng, OsRng};
use rustc_serialize::hex::{self, FromHex, ToHex};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};

use time;

const TIMESTAMP_SIZE: usize = 4;
const MACHINE_ID_SIZE: usize = 3;
const PROCESS_ID_SIZE: usize = 2;
const COUNTER_SIZE: usize = 3;

const TIMESTAMP_OFFSET: usize = 0;
const MACHINE_ID_OFFSET: usize = TIMESTAMP_OFFSET + TIMESTAMP_SIZE;
const PROCESS_ID_OFFSET: usize = MACHINE_ID_OFFSET + MACHINE_ID_SIZE;
const COUNTER_OFFSET: usize = PROCESS_ID_OFFSET + PROCESS_ID_SIZE;

const MAX_U24: usize = 0xFFFFFF;

static OID_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
static mut MACHINE_BYTES: Option<[u8; 3]> = None;

extern {
    fn gethostname(name: *mut libc::c_char, size: libc::size_t) -> libc::c_int;
}

/// Errors that can occur during OID construction and generation.
#[derive(Debug)]
pub enum Error {
    ArgumentError(String),
    FromHexError(hex::FromHexError),
    IoError(io::Error),
    HostnameError,
}

impl From<hex::FromHexError> for Error {
    fn from(err: hex::FromHexError) -> Error {
        Error::FromHexError(err)
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::IoError(err)
    }
}

/// Alias for Result<T, oid::Error>.
pub type Result<T> = result::Result<T, Error>;

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::ArgumentError(ref inner) => inner.fmt(fmt),
            &Error::FromHexError(ref inner) => inner.fmt(fmt),
            &Error::IoError(ref inner) => inner.fmt(fmt),
            &Error::HostnameError => write!(fmt, "Failed to retrieve hostname for OID generation."),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::ArgumentError(ref inner) => &inner,
            &Error::FromHexError(ref inner) => inner.description(),
            &Error::IoError(ref inner) => inner.description(),
            &Error::HostnameError => "Failed to retrieve hostname for OID generation.",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Error::ArgumentError(_) => None,
            &Error::FromHexError(ref inner) => Some(inner),
            &Error::IoError(ref inner) => Some(inner),
            &Error::HostnameError => None,
        }
    }
}

/// A wrapper around raw 12-byte ObjectId representations.
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct ObjectId {
    id: [u8; 12],
}

impl ObjectId {
    /// Generates a new ObjectID, represented in bytes.
    /// See the [docs](http://docs.mongodb.org/manual/reference/object-id/)
    /// for more information.
    pub fn new() -> Result<ObjectId> {
        let timestamp = ObjectId::gen_timestamp();
        let machine_id = try!(ObjectId::gen_machine_id());
        let process_id = ObjectId::gen_process_id();
        let counter = try!(ObjectId::gen_count());

        let mut buf: [u8; 12] = [0; 12];
        for i in 0..TIMESTAMP_SIZE { buf[TIMESTAMP_OFFSET + i] = timestamp[i]; }
        for i in 0..MACHINE_ID_SIZE { buf[MACHINE_ID_OFFSET + i] = machine_id[i]; }
        for i in 0..PROCESS_ID_SIZE { buf[PROCESS_ID_OFFSET + i] = process_id[i]; }
        for i in 0..COUNTER_SIZE { buf[COUNTER_OFFSET +i] = counter[i]; }

        Ok(ObjectId::with_bytes(buf))
    }

    /// Constructs a new ObjectId wrapper around the raw byte representation.
    pub fn with_bytes(bytes: [u8; 12]) -> ObjectId {
        ObjectId {
            id: bytes,
        }
    }

    /// Creates an ObjectID using a 12-byte (24-char) hexadecimal string.
    pub fn with_string(s: &str) -> Result<ObjectId> {
        let bytes = try!(s.from_hex());
        if bytes.len() != 12 {
            Err(Error::ArgumentError("Provided string must be a 12-byte hexadecimal string.".to_owned()))
        } else {
            let mut byte_array: [u8; 12] = [0; 12];
            for i in 0..12 {
                byte_array[i] = bytes[i];
            }
            Ok(ObjectId::with_bytes(byte_array))
        }
    }

    /// Creates a dummy ObjectId with a specific generation time.
    /// This method should only be used to do range queries on a field
    /// containing ObjectId instances.
    pub fn with_timestamp(time: u32) -> ObjectId {
        let mut buf: [u8; 12] = [0; 12];
        BigEndian::write_u32(&mut buf, time);
        ObjectId::with_bytes(buf)
    }

    /// Returns the raw byte representation of an ObjectId.
    pub fn bytes(&self) -> [u8; 12] {
        self.id
    }

    /// Retrieves the timestamp (seconds since epoch) from an ObjectId.
    pub fn timestamp(&self) -> u32 {
        BigEndian::read_u32(&self.id)
    }

    /// Retrieves the machine id associated with an ObjectId.
    pub fn machine_id(&self) -> u32 {
        let mut buf: [u8; 4] = [0; 4];
        for i in 0..MACHINE_ID_SIZE {
            buf[i] = self.id[MACHINE_ID_OFFSET+i];
        }
        LittleEndian::read_u32(&buf)
    }

    /// Retrieves the process id associated with an ObjectId.
    pub fn process_id(&self) -> u16 {
        LittleEndian::read_u16(&self.id[PROCESS_ID_OFFSET..])
    }

    /// Retrieves the increment counter from an ObjectId.
    pub fn counter(&self) -> u32 {
        let mut buf: [u8; 4] = [0; 4];
        for i in 0..COUNTER_SIZE {
            buf[i+1] = self.id[COUNTER_OFFSET+i];
        }
        BigEndian::read_u32(&buf)
    }

    // Generates a new timestamp representing the current seconds since epoch.
    // Represented in Big Endian.
    fn gen_timestamp() -> [u8; 4] {
        let timespec = time::get_time();
        let timestamp = timespec.sec as u32;

        let mut buf: [u8; 4] = [0; 4];
        BigEndian::write_u32(&mut buf,timestamp);
        buf
    }

    // Generates a new machine id represented as an MD5-hashed 3-byte-encoded hostname string.
    // Represented in Little Endian.
    fn gen_machine_id() -> Result<[u8; 3]> {
        // Short-circuit if machine id has already been calculated.
        // Since the generated machine id is not variable, arising race conditions
        // will have the same MACHINE_BYTES result.
        unsafe {
            if let Some(bytes) = MACHINE_BYTES.as_ref() {
                return Ok(bytes.clone());
            }
        }

        // Retrieve hostname through libc
        let len = 255;
        let mut buf = Vec::<u8>::with_capacity(len);
        let ptr = buf.as_mut_ptr();
        let err = unsafe { gethostname(ptr as *mut libc::c_char, len as libc::size_t) } as i32;

        if err != 0 {
            return Err(Error::HostnameError);
        }

        // Convert bytes into string
        let s = String::from_utf8_lossy(&buf);

        // Hash hostname string
        let mut md5 = Md5::new();
        md5.input_str(&s.into_owned()[..]);
        let hash = md5.result_str();

        // Re-convert string to bytes and grab first three
        let mut bytes = hash.bytes();
        let mut vec: [u8; 3] = [0; 3];
        for i in 0..MACHINE_ID_SIZE {
            match bytes.next() {
                Some(b) => vec[i] = b,
                None => break,
            }
        }

        unsafe { MACHINE_BYTES = Some(vec) };
        Ok(vec)
    }

    // Gets the process ID and returns it as a 2-byte array.
    // Represented in Little Endian.
    fn gen_process_id() -> [u8; 2] {
        let pid = unsafe { libc::getpid() as u16 };
        let mut buf: [u8; 2] = [0; 2];
        LittleEndian::write_u16(&mut buf, pid);
        buf
    }

    // Gets an incremental 3-byte count.
    // Represented in Big Endian.
    fn gen_count() -> Result<[u8; 3]> {
        // Init oid counter
        if OID_COUNTER.load(Ordering::SeqCst) == 0 {
            let mut rng = try!(OsRng::new());
            let start = rng.gen_range(0, MAX_U24 + 1);
            OID_COUNTER.store(start, Ordering::SeqCst);
        }

        let u_counter = OID_COUNTER.fetch_add(1, Ordering::SeqCst);

        // Mod result instead of OID_COUNTER to prevent threading issues.
        // Static mutexes are currently unstable; once they have been
        // stabilized, one should be used to access OID_COUNTER and
        // perform multiple operations atomically.
        let u = u_counter % MAX_U24;

        // Convert usize to writable u64, then extract the first three bytes.
        let u_int = u as u64;

        let mut buf: [u8; 8] = [0; 8];
        BigEndian::write_u64(&mut buf, u_int);
        let buf_u24: [u8; 3] = [buf[5], buf[6], buf[7]];
        Ok(buf_u24)
    }
}

impl ToHex for ObjectId {
    fn to_hex(&self) -> String {
        self.id.to_hex()
    }
}

impl fmt::Display for ObjectId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.to_hex())
    }
}

impl fmt::Debug for ObjectId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&format!("ObjectId({})", self.to_hex()))
    }
}

impl Decodable for ObjectId {
    fn decode<D: Decoder>(d: &mut D) -> result::Result<Self, D::Error> {
        let str = try!(d.read_str());
        Ok(ObjectId::with_string(&str).unwrap())
    }
}

impl Encodable for ObjectId {
    fn encode<S: Encoder>(&self, s: &mut S) -> result::Result<(), S::Error> {
        s.emit_str(&self.to_string())
    }
}

#[test]
fn pid_generation() {
    let pid = unsafe { libc::getpid() as u16 };
    let generated = ObjectId::gen_process_id();
    assert_eq!(pid, LittleEndian::read_u16(&generated));
}

#[test]
fn count_generation() {
    let start = 52222;
    OID_COUNTER.store(start, Ordering::SeqCst);
    let count_res = ObjectId::gen_count();
    assert!(count_res.is_ok());
    let count_bytes = count_res.unwrap();

    let mut buf: [u8; 4] = [0; 4];
    for i in 0..COUNTER_SIZE {
        buf[i+1] = count_bytes[i];
    }

    let count = BigEndian::read_u32(&buf);
    assert_eq!(start as u32, count);
}

#[test]
fn count_is_big_endian() {
    let start = 1122867;
    OID_COUNTER.store(start, Ordering::SeqCst);
    let oid_res = ObjectId::new();
    assert!(oid_res.is_ok());
    let oid = oid_res.unwrap();

    assert_eq!(0x11u8, oid.bytes()[COUNTER_OFFSET]);
    assert_eq!(0x22u8, oid.bytes()[COUNTER_OFFSET + 1]);
    assert_eq!(0x33u8, oid.bytes()[COUNTER_OFFSET + 2]);
}

#[test]
fn test_display() {
    let id = ObjectId::with_string("53e37d08776f724e42000000").unwrap();

    assert_eq!(
        format!("{}", id),
        "53e37d08776f724e42000000"
    )
}

#[test]
fn test_debug() {
    let id = ObjectId::with_string("53e37d08776f724e42000000").unwrap();

    assert_eq!(
        format!("{:?}", id),
        "ObjectId(53e37d08776f724e42000000)"
    )
}
<|endoftext|>


<commit_before>use ast::{Atom, Expr};
use error::*;

fn eval_args(args: &[Expr]) -> Result<Vec<Expr>> {
    args.iter().map(Expr::eval).collect()
}

pub fn add(args: &[Expr]) -> Result<Expr> {
    // Evaluate all arguments
    match eval_args(args) {
        Ok(ok_args) => {
            // Convert all args to atom
            let atoms: Option<Vec<&Atom>> = ok_args.iter().map(Expr::atom).collect();
            match atoms {
                Some(a) => {
                    if a.iter().all(|x| x.is_flt() || x.is_int()) {
                        // If any are float, promote to float and perform float addition
                        if a.iter().any(|x| x.is_flt()) {
                            Ok(Expr::from(a.iter().map(|x| {
                                if let Some(float) = x.flt() { float } else { x.int().unwrap() as f64 }
                            }).sum::<f64>()))
                        } else {
                            Ok(Expr::from(a.iter()
                                .map(|x| x.int())
                                .map(Option::unwrap)
                                .sum::<i64>()))
                        }
                    } else {
                        Err("could not add non-numeric atom".into())
                    }

                },
                None => Err("could not add non-atom".into()),
            }
        },
        Err(err) => Err(format!("could not eval: {}", err).into()),
    }
}

pub fn sub(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn mul(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn div(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn equal(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn less(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn less_eq(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn greater(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn greater_eq(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn not(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn and(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn or(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn print(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}
<commit_msg>Stop complaining about unused vars in unimplemented ops<commit_after>#![allow(unused_variables)]

use ast::{Atom, Expr};
use error::*;

fn eval_args(args: &[Expr]) -> Result<Vec<Expr>> {
    args.iter().map(Expr::eval).collect()
}

pub fn add(args: &[Expr]) -> Result<Expr> {
    // Evaluate all arguments
    match eval_args(args) {
        Ok(ok_args) => {
            // Convert all args to atom
            let atoms: Option<Vec<&Atom>> = ok_args.iter().map(Expr::atom).collect();
            match atoms {
                Some(a) => {
                    if a.iter().all(|x| x.is_flt() || x.is_int()) {
                        // If any are float, promote to float and perform float addition
                        if a.iter().any(|x| x.is_flt()) {
                            Ok(Expr::from(a.iter().map(|x| {
                                if let Some(float) = x.flt() { float } else { x.int().unwrap() as f64 }
                            }).sum::<f64>()))
                        } else {
                            Ok(Expr::from(a.iter()
                                .map(|x| x.int())
                                .map(Option::unwrap)
                                .sum::<i64>()))
                        }
                    } else {
                        Err("could not add non-numeric atom".into())
                    }

                },
                None => Err("could not add non-atom".into()),
            }
        },
        Err(err) => Err(format!("could not eval: {}", err).into()),
    }
}

pub fn sub(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn mul(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn div(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn equal(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn less(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn less_eq(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn greater(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn greater_eq(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn not(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn and(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn or(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}

pub fn print(args: &[Expr]) -> Result<Expr> {
    unimplemented!()
}
<|endoftext|>


<commit_before>use crate::server::ServerData;

use actix_http::http::header;
use actix_web::{error::ResponseError, get, http::StatusCode, web, HttpRequest, HttpResponse};
use mongodb::oid::ObjectId;
use serde::Deserialize;
use serde_qs::actix::QsQuery;

#[get("thumbnail/{course_id}")]
pub fn get_thumbnail(
    data: web::Data<ServerData>,
    path: web::Path<String>,
    query: QsQuery<GetThumbnail2>,
    req: HttpRequest,
) -> Result<HttpResponse, GetCourse2ThumbnailError> {
    let course_id = path.into_inner();
    let course_id = ObjectId::with_string(&course_id)?;
    let thumb = data.get_course2_thumbnail(course_id, query.into_inner())?;
    Ok(HttpResponse::Ok()
        .set_header(header::CONTENT_TYPE, "image/jpeg")
        .body(thumb))
}

#[derive(Debug, Deserialize)]
pub struct GetThumbnail2 {
    #[serde(default)]
    pub size: Size2,
}

#[derive(Clone, Debug, Deserialize, PartialEq)]
pub enum Size2 {
    S,
    M,
    L,
    ORIGINAL,
}

impl Size2 {
    pub fn get_dimensions(&self) -> (u32, u32) {
        match *self {
            Size2::S => (160, 90),
            Size2::M => (320, 180),
            Size2::L => (480, 270),
            Size2::ORIGINAL => (640, 360),
        }
    }
}

impl Default for Size2 {
    fn default() -> Self {
        Size2::ORIGINAL
    }
}

impl Into<String> for Size2 {
    fn into(self) -> String {
        match self {
            Size2::S => "thumb_s".to_string(),
            Size2::M => "thumb_m".to_string(),
            Size2::L => "thumb_l".to_string(),
            Size2::ORIGINAL => "thumb".to_string(),
        }
    }
}

#[derive(Debug, Fail)]
pub enum GetCourse2ThumbnailError {
    #[fail(display = "")]
    CourseNotFound(ObjectId),
    #[fail(display = "Object id invalid.\nReason: {}", _0)]
    MongoOid(mongodb::oid::Error),
    #[fail(display = "[GetCourse2ThumbnailError::Mongo]: {}", _0)]
    Mongo(mongodb::Error),
    #[fail(display = "[GetCourse2ThumbnailError::Image]: {}", _0)]
    Image(image::ImageError),
}

impl From<mongodb::oid::Error> for GetCourse2ThumbnailError {
    fn from(err: mongodb::oid::Error) -> Self {
        GetCourse2ThumbnailError::MongoOid(err)
    }
}

impl From<mongodb::Error> for GetCourse2ThumbnailError {
    fn from(err: mongodb::Error) -> Self {
        GetCourse2ThumbnailError::Mongo(err)
    }
}

impl From<image::ImageError> for GetCourse2ThumbnailError {
    fn from(err: image::ImageError) -> Self {
        GetCourse2ThumbnailError::Image(err)
    }
}

impl ResponseError for GetCourse2ThumbnailError {
    fn error_response(&self) -> HttpResponse {
        match *self {
            GetCourse2ThumbnailError::CourseNotFound(_) => HttpResponse::new(StatusCode::NOT_FOUND),
            GetCourse2ThumbnailError::MongoOid(mongodb::oid::Error::FromHexError(_)) => {
                HttpResponse::new(StatusCode::BAD_REQUEST)
            }
            GetCourse2ThumbnailError::MongoOid(_) => {
                HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
            }
            GetCourse2ThumbnailError::Mongo(_) => {
                HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
            }
            GetCourse2ThumbnailError::Image(_) => {
                HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
            }
        }
    }
}
<commit_msg>fix thumbnail2 oid error status code<commit_after>use crate::server::ServerData;

use actix_http::http::header;
use actix_web::{error::ResponseError, get, http::StatusCode, web, HttpRequest, HttpResponse};
use mongodb::oid::ObjectId;
use serde::Deserialize;
use serde_qs::actix::QsQuery;

#[get("thumbnail/{course_id}")]
pub fn get_thumbnail(
    data: web::Data<ServerData>,
    path: web::Path<String>,
    query: QsQuery<GetThumbnail2>,
    req: HttpRequest,
) -> Result<HttpResponse, GetCourse2ThumbnailError> {
    let course_id = path.into_inner();
    let course_id = ObjectId::with_string(&course_id)?;
    let thumb = data.get_course2_thumbnail(course_id, query.into_inner())?;
    Ok(HttpResponse::Ok()
        .set_header(header::CONTENT_TYPE, "image/jpeg")
        .body(thumb))
}

#[derive(Debug, Deserialize)]
pub struct GetThumbnail2 {
    #[serde(default)]
    pub size: Size2,
}

#[derive(Clone, Debug, Deserialize, PartialEq)]
pub enum Size2 {
    S,
    M,
    L,
    ORIGINAL,
}

impl Size2 {
    pub fn get_dimensions(&self) -> (u32, u32) {
        match *self {
            Size2::S => (160, 90),
            Size2::M => (320, 180),
            Size2::L => (480, 270),
            Size2::ORIGINAL => (640, 360),
        }
    }
}

impl Default for Size2 {
    fn default() -> Self {
        Size2::ORIGINAL
    }
}

impl Into<String> for Size2 {
    fn into(self) -> String {
        match self {
            Size2::S => "thumb_s".to_string(),
            Size2::M => "thumb_m".to_string(),
            Size2::L => "thumb_l".to_string(),
            Size2::ORIGINAL => "thumb".to_string(),
        }
    }
}

#[derive(Debug, Fail)]
pub enum GetCourse2ThumbnailError {
    #[fail(display = "")]
    CourseNotFound(ObjectId),
    #[fail(display = "Object id invalid.\nReason: {}", _0)]
    MongoOid(mongodb::oid::Error),
    #[fail(display = "[GetCourse2ThumbnailError::Mongo]: {}", _0)]
    Mongo(mongodb::Error),
    #[fail(display = "[GetCourse2ThumbnailError::Image]: {}", _0)]
    Image(image::ImageError),
}

impl From<mongodb::oid::Error> for GetCourse2ThumbnailError {
    fn from(err: mongodb::oid::Error) -> Self {
        GetCourse2ThumbnailError::MongoOid(err)
    }
}

impl From<mongodb::Error> for GetCourse2ThumbnailError {
    fn from(err: mongodb::Error) -> Self {
        GetCourse2ThumbnailError::Mongo(err)
    }
}

impl From<image::ImageError> for GetCourse2ThumbnailError {
    fn from(err: image::ImageError) -> Self {
        GetCourse2ThumbnailError::Image(err)
    }
}

impl ResponseError for GetCourse2ThumbnailError {
    fn error_response(&self) -> HttpResponse {
        match *self {
            GetCourse2ThumbnailError::CourseNotFound(_) => HttpResponse::new(StatusCode::NOT_FOUND),
            GetCourse2ThumbnailError::MongoOid(mongodb::oid::Error::FromHexError(_)) => {
                HttpResponse::new(StatusCode::BAD_REQUEST)
            }
            GetCourse2ThumbnailError::MongoOid(_) => HttpResponse::new(StatusCode::BAD_REQUEST),
            GetCourse2ThumbnailError::Mongo(_) => {
                HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
            }
            GetCourse2ThumbnailError::Image(_) => {
                HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::iter;
use byteorder::{BigEndian, ByteOrder};

pub struct SHA512 {}

impl SHA512 {
    /// Only supports messages with at most 2^64 - 1 bits for now
    pub fn pad(bytes: &mut Vec<u8>) {
        let len = len(bytes);
        bytes.push(0x80);
        let padding = (128 + 112 - bytes.len() % 128) % 128;
        bytes.extend(iter::repeat(0).take(padding));
        bytes.extend_from_slice(&[0; 8]);
        bytes.extend_from_slice(&len);
    }
}

fn len(bytes: &[u8]) -> [u8; 8] {
    let mut len = [0; 8];
    BigEndian::write_u64(&mut len, 8 * bytes.len() as u64);
    len
}

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

    #[test]
    fn test_pad() {
        let mut message = vec![0b01100001, 0b01100010, 0b01100011, 0b01100100, 0b01100101];
        let expected = h2b(
            "6162636465800000000000000000000000000000000000000000000000000000\
             0000000000000000000000000000000000000000000000000000000000000000\
             0000000000000000000000000000000000000000000000000000000000000000\
             0000000000000000000000000000000000000000000000000000000000000028",
        );
        SHA512::pad(&mut message);
        assert_eq!(expected, message);
    }
}
<commit_msg>sha: add sha-512<commit_after>use std::iter;
use byteorder::{BigEndian, ByteOrder};

pub const K: [u64; 80] = [
    0x428a2f98d728ae22,
    0x7137449123ef65cd,
    0xb5c0fbcfec4d3b2f,
    0xe9b5dba58189dbbc,
    0x3956c25bf348b538,
    0x59f111f1b605d019,
    0x923f82a4af194f9b,
    0xab1c5ed5da6d8118,
    0xd807aa98a3030242,
    0x12835b0145706fbe,
    0x243185be4ee4b28c,
    0x550c7dc3d5ffb4e2,
    0x72be5d74f27b896f,
    0x80deb1fe3b1696b1,
    0x9bdc06a725c71235,
    0xc19bf174cf692694,
    0xe49b69c19ef14ad2,
    0xefbe4786384f25e3,
    0x0fc19dc68b8cd5b5,
    0x240ca1cc77ac9c65,
    0x2de92c6f592b0275,
    0x4a7484aa6ea6e483,
    0x5cb0a9dcbd41fbd4,
    0x76f988da831153b5,
    0x983e5152ee66dfab,
    0xa831c66d2db43210,
    0xb00327c898fb213f,
    0xbf597fc7beef0ee4,
    0xc6e00bf33da88fc2,
    0xd5a79147930aa725,
    0x06ca6351e003826f,
    0x142929670a0e6e70,
    0x27b70a8546d22ffc,
    0x2e1b21385c26c926,
    0x4d2c6dfc5ac42aed,
    0x53380d139d95b3df,
    0x650a73548baf63de,
    0x766a0abb3c77b2a8,
    0x81c2c92e47edaee6,
    0x92722c851482353b,
    0xa2bfe8a14cf10364,
    0xa81a664bbc423001,
    0xc24b8b70d0f89791,
    0xc76c51a30654be30,
    0xd192e819d6ef5218,
    0xd69906245565a910,
    0xf40e35855771202a,
    0x106aa07032bbd1b8,
    0x19a4c116b8d2d0c8,
    0x1e376c085141ab53,
    0x2748774cdf8eeb99,
    0x34b0bcb5e19b48a8,
    0x391c0cb3c5c95a63,
    0x4ed8aa4ae3418acb,
    0x5b9cca4f7763e373,
    0x682e6ff3d6b2b8a3,
    0x748f82ee5defb2fc,
    0x78a5636f43172f60,
    0x84c87814a1f0ab72,
    0x8cc702081a6439ec,
    0x90befffa23631e28,
    0xa4506cebde82bde9,
    0xbef9a3f7b2c67915,
    0xc67178f2e372532b,
    0xca273eceea26619c,
    0xd186b8c721c0c207,
    0xeada7dd6cde0eb1e,
    0xf57d4f7fee6ed178,
    0x06f067aa72176fba,
    0x0a637dc5a2c898a6,
    0x113f9804bef90dae,
    0x1b710b35131c471b,
    0x28db77f523047d84,
    0x32caab7b40c72493,
    0x3c9ebe0a15c9bebc,
    0x431d67c49c100d4c,
    0x4cc5d4becb3e42b6,
    0x597f299cfc657e2a,
    0x5fcb6fab3ad6faec,
    0x6c44198c4a475817,
];

pub struct SHA512 {}

impl SHA512 {
    pub fn digest(message: &[u8]) -> [u8; 64] {
        let mut message = message.to_vec();
        Self::pad(&mut message);
        let mut hash: [u64; 8] = [
            0x6a09e667f3bcc908,
            0xbb67ae8584caa73b,
            0x3c6ef372fe94f82b,
            0xa54ff53a5f1d36f1,
            0x510e527fade682d1,
            0x9b05688c2b3e6c1f,
            0x1f83d9abfb41bd6b,
            0x5be0cd19137e2179,
        ];
        let mut w = [0; 80];
        for chunk in message.chunks(128) {
            for (wt, long) in w.iter_mut().zip(chunk.chunks(8)) {
                *wt = BigEndian::read_u64(long);
            }
            for t in 16..80 {
                w[t] = Self::ssig1(w[t - 2])
                    .wrapping_add(w[t - 7])
                    .wrapping_add(Self::ssig0(w[t - 15]))
                    .wrapping_add(w[t - 16]);
            }
            let mut a = hash[0];
            let mut b = hash[1];
            let mut c = hash[2];
            let mut d = hash[3];
            let mut e = hash[4];
            let mut f = hash[5];
            let mut g = hash[6];
            let mut h = hash[7];
            for (&kt, &wt) in K.iter().zip(w.iter()) {
                let t1 = h.wrapping_add(Self::bsig1(e))
                    .wrapping_add(Self::ch(e, f, g))
                    .wrapping_add(kt)
                    .wrapping_add(wt);
                let t2 = Self::bsig0(a).wrapping_add(Self::maj(a, b, c));
                h = g;
                g = f;
                f = e;
                e = d.wrapping_add(t1);
                d = c;
                c = b;
                b = a;
                a = t1.wrapping_add(t2);
            }
            hash[0] = hash[0].wrapping_add(a);
            hash[1] = hash[1].wrapping_add(b);
            hash[2] = hash[2].wrapping_add(c);
            hash[3] = hash[3].wrapping_add(d);
            hash[4] = hash[4].wrapping_add(e);
            hash[5] = hash[5].wrapping_add(f);
            hash[6] = hash[6].wrapping_add(g);
            hash[7] = hash[7].wrapping_add(h);
        }
        let mut digest = [0; 64];
        for (chunk, &long) in digest.chunks_mut(8).zip(&hash) {
            BigEndian::write_u64(chunk, long);
        }
        digest
    }
    pub fn ch(x: u64, y: u64, z: u64) -> u64 {
        (x & y) ^ (!x & z)
    }

    pub fn maj(x: u64, y: u64, z: u64) -> u64 {
        (x & y) ^ (x & z) ^ (y & z)
    }

    pub fn bsig0(x: u64) -> u64 {
        x.rotate_right(28) ^ x.rotate_right(34) ^ x.rotate_right(39)
    }

    pub fn bsig1(x: u64) -> u64 {
        x.rotate_right(14) ^ x.rotate_right(18) ^ x.rotate_right(41)
    }

    pub fn ssig0(x: u64) -> u64 {
        x.rotate_right(1) ^ x.rotate_right(8) ^ (x >> 7)
    }

    pub fn ssig1(x: u64) -> u64 {
        x.rotate_right(19) ^ x.rotate_right(61) ^ (x >> 6)
    }

    /// Only supports messages with at most 2^64 - 1 bits for now
    pub fn pad(bytes: &mut Vec<u8>) {
        let len = len(bytes);
        bytes.push(0x80);
        let padding = (128 + 112 - bytes.len() % 128) % 128;
        bytes.extend(iter::repeat(0).take(padding));
        bytes.extend_from_slice(&[0; 8]);
        bytes.extend_from_slice(&len);
    }
}

fn len(bytes: &[u8]) -> [u8; 8] {
    let mut len = [0; 8];
    BigEndian::write_u64(&mut len, 8 * bytes.len() as u64);
    len
}

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

    #[test]
    fn test_pad() {
        let mut message = vec![0b01100001, 0b01100010, 0b01100011, 0b01100100, 0b01100101];
        let expected = h2b(
            "6162636465800000000000000000000000000000000000000000000000000000\
             0000000000000000000000000000000000000000000000000000000000000000\
             0000000000000000000000000000000000000000000000000000000000000000\
             0000000000000000000000000000000000000000000000000000000000000028",
        );
        SHA512::pad(&mut message);
        assert_eq!(expected, message);
    }

    #[test]
    fn test_digest() {
        let expected = h2b(
            "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce\
             47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
        );
        let actual = SHA512::digest(&[]);
        assert_eq!(64, actual.len());
        for (lhs, rhs) in expected.iter().zip(actual.iter()) {
            assert_eq!(lhs, rhs);
        }
    }
}
<|endoftext|>


<commit_before>//! The AWS SQS API.

#![cfg_attr(feature = "nightly-testing", allow(while_let_loop))]

include!(concat!(env!("OUT_DIR"), "/sqs.rs"));

#[cfg(test)]
mod test {
    use std::collections::HashMap;
    use sqs::{SqsClient, SendMessageRequest, ReceiveMessageRequest, MessageAttributeValue};

    use super::super::{Region, SignedRequest};
    use super::super::mock::*;

    extern crate env_logger;

    #[test]
    fn should_serialize_map_parameters_in_query_string() {
        let mock = MockRequestDispatcher::with_status(200)
            .with_body(r#"<?xml version="1.0" encoding="UTF-8"?>
            <SendMessageResponse>
              <SendMessageResult>
                  <MD5OfMessageBody>
                      fafb00f5732ab283681e124bf8747ed1
                  </MD5OfMessageBody>
                  <MD5OfMessageAttributes>
                3ae8f24a165a8cedc005670c81a27295
                  </MD5OfMessageAttributes>
                  <MessageId>
                      5fea7756-0ea4-451a-a703-a558b933e274
                  </MessageId>
              </SendMessageResult>
              <ResponseMetadata>
                  <RequestId>
                      27daac76-34dd-47df-bd01-1f6e873584a0
                  </RequestId>
              </ResponseMetadata>
            </SendMessageResponse>"#)
            .with_request_checker(|request: &SignedRequest| {
                assert_eq!("POST", request.method);
                assert_eq!("/", request.path);
                assert_eq!(None, request.payload);
                assert_eq!(Some(&Some("test_attribute_name".to_owned())),
                           request.params.get("MessageAttribute.1.Name"));
                assert_eq!(Some(&Some("test_attribute_value".to_owned())),
                           request.params.get("MessageAttribute.1.Value.StringValue"));
                assert_eq!(Some(&Some("String".to_owned())),
                           request.params.get("MessageAttribute.1.Value.DataType"));
            });

        let mut message_attributes = HashMap::new();

        message_attributes.insert("test_attribute_name".to_owned(),
                                  MessageAttributeValue {
                                      string_value: Some("test_attribute_value".to_owned()),
                                      data_type: "String".to_owned(),
                                      ..Default::default()
                                  });
        let request = SendMessageRequest {
            message_body: "foo".to_owned(),
            queue_url: "bar".to_owned(),
            message_attributes: Some(message_attributes),
            ..Default::default()
        };

        let client =
            SqsClient::with_request_dispatcher(mock, MockCredentialsProvider, Region::UsEast1);
        let _result = client.send_message(&request).unwrap();
    }

    #[test]
    fn should_fix_issue_323() {
        let mock = MockRequestDispatcher::with_status(200)
            .with_body(r#"<?xml version="1.0" encoding="UTF-8"?>
            <ReceiveMessageResponse>
              <ReceiveMessageResult>
                <Message>
                  <MessageId>
                    5fea7756-0ea4-451a-a703-a558b933e274
                  </MessageId>
                  <ReceiptHandle>
                    MbZj6wDWli+JvwwJaBV+3dcjk2YW2vA3+STFFljTM8tJJg6HRG6PYSasuWXPJB+Cw
                    Lj1FjgXUv1uSj1gUPAWV66FU/WeR4mq2OKpEGYWbnLmpRCJVAyeMjeU5ZBdtcQ+QE
                    auMZc8ZRv37sIW2iJKq3M9MFx1YvV11A2x/KSbkJ0=
                  </ReceiptHandle>
                  <MD5OfBody>
                    fafb00f5732ab283681e124bf8747ed1
                  </MD5OfBody>
                  This is a test message
                  <Attribute>
                    <Name>SenderId</Name>
                    <Value>195004372649</Value>
                  </Attribute>
                </Message>
              </ReceiveMessageResult>
              <ResponseMetadata>
                <RequestId>
                  b6633655-283d-45b4-aee4-4e84e0ae6afa
                </RequestId>
              </ResponseMetadata>
          </ReceiveMessageResponse>"#)
            .with_request_checker(|request: &SignedRequest| {
                assert_eq!("POST", request.method);
                assert_eq!("/", request.path);
                // assert_eq!(None, request.payload);
                assert_eq!(request.params.get("Action"), Some(&Some("ReceiveMessage".to_owned())));
                assert_eq!(request.params.get("MaxNumberOfMessages"), Some(&Some("1".to_owned())));
                assert_eq!(request.params.get("VisibilityTimeout"), Some(&Some("2".to_owned())));
                assert_eq!(request.params.get("WaitTimeSeconds"), Some(&Some("3".to_owned())));
                assert_eq!(request.params.get("Integer"), None);
            });

        let request = ReceiveMessageRequest {
          max_number_of_messages: Some(1),
          queue_url: "foo".to_owned(),
          visibility_timeout: Some(2),
          wait_time_seconds: Some(3),
            ..Default::default()
        };

        let client = SqsClient::with_request_dispatcher(mock, MockCredentialsProvider, Region::UsEast1);
        let _result = client.receive_message(&request).unwrap();
    }
}
<commit_msg>remove commented-out line<commit_after>//! The AWS SQS API.

#![cfg_attr(feature = "nightly-testing", allow(while_let_loop))]

include!(concat!(env!("OUT_DIR"), "/sqs.rs"));

#[cfg(test)]
mod test {
    use std::collections::HashMap;
    use sqs::{SqsClient, SendMessageRequest, ReceiveMessageRequest, MessageAttributeValue};

    use super::super::{Region, SignedRequest};
    use super::super::mock::*;

    extern crate env_logger;

    #[test]
    fn should_serialize_map_parameters_in_query_string() {
        let mock = MockRequestDispatcher::with_status(200)
            .with_body(r#"<?xml version="1.0" encoding="UTF-8"?>
            <SendMessageResponse>
              <SendMessageResult>
                  <MD5OfMessageBody>
                      fafb00f5732ab283681e124bf8747ed1
                  </MD5OfMessageBody>
                  <MD5OfMessageAttributes>
                3ae8f24a165a8cedc005670c81a27295
                  </MD5OfMessageAttributes>
                  <MessageId>
                      5fea7756-0ea4-451a-a703-a558b933e274
                  </MessageId>
              </SendMessageResult>
              <ResponseMetadata>
                  <RequestId>
                      27daac76-34dd-47df-bd01-1f6e873584a0
                  </RequestId>
              </ResponseMetadata>
            </SendMessageResponse>"#)
            .with_request_checker(|request: &SignedRequest| {
                assert_eq!("POST", request.method);
                assert_eq!("/", request.path);
                assert_eq!(None, request.payload);
                assert_eq!(Some(&Some("test_attribute_name".to_owned())),
                           request.params.get("MessageAttribute.1.Name"));
                assert_eq!(Some(&Some("test_attribute_value".to_owned())),
                           request.params.get("MessageAttribute.1.Value.StringValue"));
                assert_eq!(Some(&Some("String".to_owned())),
                           request.params.get("MessageAttribute.1.Value.DataType"));
            });

        let mut message_attributes = HashMap::new();

        message_attributes.insert("test_attribute_name".to_owned(),
                                  MessageAttributeValue {
                                      string_value: Some("test_attribute_value".to_owned()),
                                      data_type: "String".to_owned(),
                                      ..Default::default()
                                  });
        let request = SendMessageRequest {
            message_body: "foo".to_owned(),
            queue_url: "bar".to_owned(),
            message_attributes: Some(message_attributes),
            ..Default::default()
        };

        let client =
            SqsClient::with_request_dispatcher(mock, MockCredentialsProvider, Region::UsEast1);
        let _result = client.send_message(&request).unwrap();
    }

    #[test]
    fn should_fix_issue_323() {
        let mock = MockRequestDispatcher::with_status(200)
            .with_body(r#"<?xml version="1.0" encoding="UTF-8"?>
            <ReceiveMessageResponse>
              <ReceiveMessageResult>
                <Message>
                  <MessageId>
                    5fea7756-0ea4-451a-a703-a558b933e274
                  </MessageId>
                  <ReceiptHandle>
                    MbZj6wDWli+JvwwJaBV+3dcjk2YW2vA3+STFFljTM8tJJg6HRG6PYSasuWXPJB+Cw
                    Lj1FjgXUv1uSj1gUPAWV66FU/WeR4mq2OKpEGYWbnLmpRCJVAyeMjeU5ZBdtcQ+QE
                    auMZc8ZRv37sIW2iJKq3M9MFx1YvV11A2x/KSbkJ0=
                  </ReceiptHandle>
                  <MD5OfBody>
                    fafb00f5732ab283681e124bf8747ed1
                  </MD5OfBody>
                  This is a test message
                  <Attribute>
                    <Name>SenderId</Name>
                    <Value>195004372649</Value>
                  </Attribute>
                </Message>
              </ReceiveMessageResult>
              <ResponseMetadata>
                <RequestId>
                  b6633655-283d-45b4-aee4-4e84e0ae6afa
                </RequestId>
              </ResponseMetadata>
          </ReceiveMessageResponse>"#)
            .with_request_checker(|request: &SignedRequest| {
                assert_eq!("POST", request.method);
                assert_eq!("/", request.path);
                assert_eq!(request.params.get("Action"), Some(&Some("ReceiveMessage".to_owned())));
                assert_eq!(request.params.get("MaxNumberOfMessages"), Some(&Some("1".to_owned())));
                assert_eq!(request.params.get("VisibilityTimeout"), Some(&Some("2".to_owned())));
                assert_eq!(request.params.get("WaitTimeSeconds"), Some(&Some("3".to_owned())));
                assert_eq!(request.params.get("Integer"), None);
            });

        let request = ReceiveMessageRequest {
          max_number_of_messages: Some(1),
          queue_url: "foo".to_owned(),
          visibility_timeout: Some(2),
          wait_time_seconds: Some(3),
            ..Default::default()
        };

        let client = SqsClient::with_request_dispatcher(mock, MockCredentialsProvider, Region::UsEast1);
        let _result = client.receive_message(&request).unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate getopts;
use std::os;
use std::io;
use std::collections::HashMap;

use getopts::getopts;
use getopts::optflag;
use getopts::usage;

fn main() {
    let args: Vec<String> = os::args()
        .iter()
        .map(|x| x.to_string())
        .collect();

    let opts = [
        optflag("h", "help", "Show help.")
    ];

    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_str()) }
    };

    if matches.opt_present("h") {
        println!("{}", usage("Produce a sorted-by-frequency list of lines from input.", opts));
        return;
    }

    let mut lines: HashMap<String,int> = HashMap::new();

    for line in io::stdin().lines() {
        lines.insert_or_update_with(line.unwrap(), 1, |_k, v| *v = *v + 1);
    }

    let mut sorted_lines: Vec<(int, String)> = Vec::new();

    for (line, count) in lines.iter() {
        sorted_lines.push((*count, line.clone()));
    }

    sorted_lines.sort_by(|a, b| b.cmp(a));

    for &(ref count, ref line) in sorted_lines.iter() {
        print!("{}: {}", count, line);
    }
}
<commit_msg>Remove colon in suc output.<commit_after>extern crate getopts;
use std::os;
use std::io;
use std::collections::HashMap;

use getopts::getopts;
use getopts::optflag;
use getopts::usage;

fn main() {
    let args: Vec<String> = os::args()
        .iter()
        .map(|x| x.to_string())
        .collect();

    let opts = [
        optflag("h", "help", "Show help.")
    ];

    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_str()) }
    };

    if matches.opt_present("h") {
        println!("{}", usage("Produce a sorted-by-frequency list of lines from input.", opts));
        return;
    }

    let mut lines: HashMap<String,int> = HashMap::new();

    for line in io::stdin().lines() {
        lines.insert_or_update_with(line.unwrap(), 1, |_k, v| *v = *v + 1);
    }

    let mut sorted_lines: Vec<(int, String)> = Vec::new();

    for (line, count) in lines.iter() {
        sorted_lines.push((*count, line.clone()));
    }

    sorted_lines.sort_by(|a, b| b.cmp(a));

    for &(ref count, ref line) in sorted_lines.iter() {
        print!("{} {}", count, line);
    }
}
<|endoftext|>