<commit_before>use hdr_histogram::simple_hdr_histogram::*;

#[test]
fn count_at_value_on_empty() {
    let mut the_hist = init_histo(1, 100000, 3);

    assert_eq!(the_hist.get_count_at_value(1).unwrap(), 0);
    assert_eq!(the_hist.get_count_at_value(5000).unwrap(), 0);
    assert_eq!(the_hist.get_count_at_value(100000).unwrap(), 0);
}

#[test]
fn count_at_value_after_record() {
    let mut the_hist = init_histo(1, 100000, 3);

    let result = the_hist.record_single_value(5000);
    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not add single record to histogram because error: {}", err))
    }

    assert_eq!(the_hist.get_count_at_value(1).unwrap(), 0);
    assert_eq!(the_hist.get_count_at_value(5000).unwrap(), 1);
    assert_eq!(the_hist.get_count_at_value(100000).unwrap(), 0);
}

#[test]
fn can_get_count_after_record() {
    let mut the_hist = init_histo(1, 100000, 3);
    let result = the_hist.record_single_value(5000);
    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not add single record to histogram because error: {}", err))
    }

    let count = the_hist.get_count();
    assert_eq!(count, 1);
}

#[test]
fn can_get_max_after_record() {
    let mut the_hist = init_histo(1, 100000, 3);
    let result = the_hist.record_single_value(5000);
    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not add single record to histogram because error: {}", err))
    }

    let max = the_hist.get_max();
    assert_eq!(max, 5000);
}

#[test]
fn can_record_single_value() {
    let mut the_hist = init_histo(1, 100000, 3);
    let result = the_hist.record_single_value(5000);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not add single record to histogram because error: {}", err))
    }
}

#[test]
fn can_compute_indexes_for_smallest_value() {
    let the_hist = init_histo(1, 100000, 3);
    let value = 1;
    assert_eq!(the_hist.get_bucket_index(value), 0);
    assert_eq!(the_hist.get_sub_bucket_index(value, 0), 1);
    assert_eq!(the_hist.counts_array_index(value), 1);
}

#[test]
fn can_compute_counts_array_index() {
    let the_hist = init_histo(1, 100000, 3);
    let result = the_hist.counts_array_index(5000);

    assert_eq!(result, 3298);
}

#[test]
fn can_get_bucket_index() {
    let the_hist = init_histo(1, 100000, 3);
    let result = the_hist.get_bucket_index(5000);
    assert_eq!(result, 2)
}

#[test]
fn can_get_sub_bucket_index() {
    let the_hist = init_histo(1, 100000, 3);
    let result = the_hist.get_sub_bucket_index(5000, 2);
    assert_eq!(result, 1250)
}

/// lowest_discernible_value: must be >= 1
/// highest_trackable_value: must be >= 2 * lowest_discernible_value
/// num_significant_digits: must be <= 5
fn init_histo(lowest_discernible_value: u64, highest_trackable_value: u64, num_significant_digits: u32) -> SimpleHdrHistogram<u64> {

    assert!(lowest_discernible_value >= 1);
    assert!(highest_trackable_value >= 2 * lowest_discernible_value);
    assert!(num_significant_digits <= 5);

    let largest_value_with_single_unit_resolution = 2_u64 * 10_u64.pow(num_significant_digits);

    let unit_magnitude = ((lowest_discernible_value as f64).ln() / 2_f64.ln()) as u32;
    let unit_magnitude_mask: u64  = (1_u64 << unit_magnitude) - 1;

    // find nearest power of 2 to largest_value_with_single_unit_resolution
    let sub_bucket_count_magnitude: u32 =
    ((largest_value_with_single_unit_resolution as f64).ln() / 2_f64.ln()).ceil() as u32;

    // ugly looking... how should ternaries be done?
    let sub_bucket_half_count_magnitude: u32 = (if sub_bucket_count_magnitude > 1 { sub_bucket_count_magnitude } else { 1 }) - 1;
    let sub_bucket_count: usize = 2_usize.pow(sub_bucket_half_count_magnitude + 1);
    let sub_bucket_half_count: usize = sub_bucket_count / 2;
    // TODO is this cast OK?
    let sub_bucket_mask = ((sub_bucket_count - 1) << unit_magnitude) as u64;

    let counts_arr_len = counts_arr_len(highest_trackable_value, sub_bucket_count, unit_magnitude);
    let bucket_count = buckets_needed_for_value(highest_trackable_value, sub_bucket_count, unit_magnitude);

    let leading_zero_count_base: usize = (64_u32 - unit_magnitude - sub_bucket_half_count_magnitude - 1) as usize;

    SimpleHdrHistogram {
        leading_zeros_count_base: leading_zero_count_base,
        sub_bucket_mask: sub_bucket_mask,
        unit_magnitude: unit_magnitude,
        sub_bucket_count: sub_bucket_count,
        sub_bucket_half_count: sub_bucket_half_count,
        sub_bucket_half_count_magnitude: sub_bucket_half_count_magnitude,
        counts: vec![0; counts_arr_len],
        counts_array_length: counts_arr_len,
        normalizing_index_offset: 0_usize, // 0 for normal Histogram ctor in Java impl
        min_non_zero_value: u64::max_value(),
        total_count: 0,
        max_value: 0,
        unit_magnitude_mask: unit_magnitude_mask
    }
}

fn buckets_needed_for_value(value: u64, sub_bucket_count: usize, unit_magnitude: u32) -> usize {

    // TODO is this cast ok?
    let mut smallest_untrackable_value: u64 = (sub_bucket_count << unit_magnitude) as u64;
    let mut buckets_needed: usize = 1;

    while smallest_untrackable_value <= value {
        if smallest_untrackable_value > u64::max_value() / 2 {
            return buckets_needed + 1;
        }

        smallest_untrackable_value = smallest_untrackable_value << 1;
        buckets_needed += 1;
    }

    return buckets_needed;
}

fn counts_arr_len_for_buckets(buckets: usize, sub_bucket_count: usize) -> usize {
    (buckets + 1) * (sub_bucket_count / 2)
}

fn counts_arr_len(value: u64, sub_bucket_count: usize, unit_magnitude: u32) -> usize {
    counts_arr_len_for_buckets(buckets_needed_for_value(value, sub_bucket_count, unit_magnitude), sub_bucket_count)
}<commit_msg>Simplify tests that expect success<commit_after>use hdr_histogram::simple_hdr_histogram::*;

#[test]
fn count_at_value_on_empty() {
    let mut the_hist = init_histo(1, 100000, 3);

    assert_eq!(the_hist.get_count_at_value(1).unwrap(), 0);
    assert_eq!(the_hist.get_count_at_value(5000).unwrap(), 0);
    assert_eq!(the_hist.get_count_at_value(100000).unwrap(), 0);
}

#[test]
fn count_at_value_after_record() {
    let mut the_hist = init_histo(1, 100000, 3);

    the_hist.record_single_value(5000).unwrap();

    assert_eq!(the_hist.get_count_at_value(1).unwrap(), 0);
    assert_eq!(the_hist.get_count_at_value(5000).unwrap(), 1);
    assert_eq!(the_hist.get_count_at_value(100000).unwrap(), 0);
}

#[test]
fn can_get_count_after_record() {
    let mut the_hist = init_histo(1, 100000, 3);
    the_hist.record_single_value(5000).unwrap();

    let count = the_hist.get_count();
    assert_eq!(count, 1);
}

#[test]
fn can_get_max_after_record() {
    let mut the_hist = init_histo(1, 100000, 3);
    the_hist.record_single_value(5000).unwrap();

    let max = the_hist.get_max();
    assert_eq!(max, 5000);
}

#[test]
fn can_record_single_value() {
    let mut the_hist = init_histo(1, 100000, 3);
    the_hist.record_single_value(5000).unwrap();
}

#[test]
fn can_compute_indexes_for_smallest_value() {
    let the_hist = init_histo(1, 100000, 3);
    let value = 1;
    assert_eq!(the_hist.get_bucket_index(value), 0);
    assert_eq!(the_hist.get_sub_bucket_index(value, 0), 1);
    assert_eq!(the_hist.counts_array_index(value), 1);
}

#[test]
fn can_compute_counts_array_index() {
    let the_hist = init_histo(1, 100000, 3);
    let result = the_hist.counts_array_index(5000);

    assert_eq!(result, 3298);
}

#[test]
fn can_get_bucket_index() {
    let the_hist = init_histo(1, 100000, 3);
    let result = the_hist.get_bucket_index(5000);
    assert_eq!(result, 2)
}

#[test]
fn can_get_sub_bucket_index() {
    let the_hist = init_histo(1, 100000, 3);
    let result = the_hist.get_sub_bucket_index(5000, 2);
    assert_eq!(result, 1250)
}

/// lowest_discernible_value: must be >= 1
/// highest_trackable_value: must be >= 2 * lowest_discernible_value
/// num_significant_digits: must be <= 5
fn init_histo(lowest_discernible_value: u64, highest_trackable_value: u64, num_significant_digits: u32) -> SimpleHdrHistogram<u64> {

    assert!(lowest_discernible_value >= 1);
    assert!(highest_trackable_value >= 2 * lowest_discernible_value);
    assert!(num_significant_digits <= 5);

    let largest_value_with_single_unit_resolution = 2_u64 * 10_u64.pow(num_significant_digits);

    let unit_magnitude = ((lowest_discernible_value as f64).ln() / 2_f64.ln()) as u32;
    let unit_magnitude_mask: u64  = (1_u64 << unit_magnitude) - 1;

    // find nearest power of 2 to largest_value_with_single_unit_resolution
    let sub_bucket_count_magnitude: u32 =
    ((largest_value_with_single_unit_resolution as f64).ln() / 2_f64.ln()).ceil() as u32;

    // ugly looking... how should ternaries be done?
    let sub_bucket_half_count_magnitude: u32 = (if sub_bucket_count_magnitude > 1 { sub_bucket_count_magnitude } else { 1 }) - 1;
    let sub_bucket_count: usize = 2_usize.pow(sub_bucket_half_count_magnitude + 1);
    let sub_bucket_half_count: usize = sub_bucket_count / 2;
    // TODO is this cast OK?
    let sub_bucket_mask = ((sub_bucket_count - 1) << unit_magnitude) as u64;

    let counts_arr_len = counts_arr_len(highest_trackable_value, sub_bucket_count, unit_magnitude);
    let bucket_count = buckets_needed_for_value(highest_trackable_value, sub_bucket_count, unit_magnitude);

    let leading_zero_count_base: usize = (64_u32 - unit_magnitude - sub_bucket_half_count_magnitude - 1) as usize;

    SimpleHdrHistogram {
        leading_zeros_count_base: leading_zero_count_base,
        sub_bucket_mask: sub_bucket_mask,
        unit_magnitude: unit_magnitude,
        sub_bucket_count: sub_bucket_count,
        sub_bucket_half_count: sub_bucket_half_count,
        sub_bucket_half_count_magnitude: sub_bucket_half_count_magnitude,
        counts: vec![0; counts_arr_len],
        counts_array_length: counts_arr_len,
        normalizing_index_offset: 0_usize, // 0 for normal Histogram ctor in Java impl
        min_non_zero_value: u64::max_value(),
        total_count: 0,
        max_value: 0,
        unit_magnitude_mask: unit_magnitude_mask
    }
}

fn buckets_needed_for_value(value: u64, sub_bucket_count: usize, unit_magnitude: u32) -> usize {

    // TODO is this cast ok?
    let mut smallest_untrackable_value: u64 = (sub_bucket_count << unit_magnitude) as u64;
    let mut buckets_needed: usize = 1;

    while smallest_untrackable_value <= value {
        if smallest_untrackable_value > u64::max_value() / 2 {
            return buckets_needed + 1;
        }

        smallest_untrackable_value = smallest_untrackable_value << 1;
        buckets_needed += 1;
    }

    return buckets_needed;
}

fn counts_arr_len_for_buckets(buckets: usize, sub_bucket_count: usize) -> usize {
    (buckets + 1) * (sub_bucket_count / 2)
}

fn counts_arr_len(value: u64, sub_bucket_count: usize, unit_magnitude: u32) -> usize {
    counts_arr_len_for_buckets(buckets_needed_for_value(value, sub_bucket_count, unit_magnitude), sub_bucket_count)
}<|endoftext|>


<commit_before>use super::{CollisionDetails, CollisionObjectResults};

#[derive(Clone)]
pub struct CollisionResults<T: Clone> {
    pub collided: bool,
    pub details: Option<CollisionDetails>,
    pub time: Option<f64>,
    pub data: Option<T>
}

impl<T: Clone> CollisionResults<T> {
    pub fn new_with_location(location: usize, object_results: CollisionObjectResults<T>) -> Self {
        CollisionResults {
            collided: object_results.collided,
            details: match object_results.details {
                None => None,
                Some(obj_details) => Some(CollisionDetails::new(location, obj_details))
            },
            time: object_results.time,
            data: object_results.data
        }
    }

    pub fn no_collision() -> CollisionResults<T> {
        CollisionResults {
            collided: false,
            details: None,
            time: None,
            data: None,
        }
    }
}

impl<T: Clone> From<CollisionObjectResults<T>> for CollisionResults<T> {
    fn from(obj_result: CollisionObjectResults<T>) -> Self {
            CollisionResults::new_with_location(0, obj_result)
    }
}<commit_msg>Enable Debug on Collision Results<commit_after>use super::{CollisionDetails, CollisionObjectResults};

#[derive(Clone, Debug)]
pub struct CollisionResults<T: Clone> {
    pub collided: bool,
    pub details: Option<CollisionDetails>,
    pub time: Option<f64>,
    pub data: Option<T>
}

impl<T: Clone> CollisionResults<T> {
    pub fn new_with_location(location: usize, object_results: CollisionObjectResults<T>) -> Self {
        CollisionResults {
            collided: object_results.collided,
            details: match object_results.details {
                None => None,
                Some(obj_details) => Some(CollisionDetails::new(location, obj_details))
            },
            time: object_results.time,
            data: object_results.data
        }
    }

    pub fn no_collision() -> CollisionResults<T> {
        CollisionResults {
            collided: false,
            details: None,
            time: None,
            data: None,
        }
    }
}

impl<T: Clone> From<CollisionObjectResults<T>> for CollisionResults<T> {
    fn from(obj_result: CollisionObjectResults<T>) -> Self {
            CollisionResults::new_with_location(0, obj_result)
    }
}<|endoftext|>


<commit_before>//! Structs using the builder pattern that make it easier to create records in tests.

use std::collections::HashMap;
use std::io::Read;

use chrono;
use chrono::Utc;
use diesel::prelude::*;
use flate2::write::GzEncoder;
use flate2::Compression;
use semver;
use tar;

use cargo_registry::util::CargoResult;

use models::{Crate, CrateDownload, Keyword, Version};
use models::{NewCrate, NewVersion};
use schema::*;
use views::krate_publish as u;

/// A builder to create version records for the purpose of inserting directly into the database.
pub struct VersionBuilder<'a> {
    num: semver::Version,
    license: Option<&'a str>,
    license_file: Option<&'a str>,
    features: HashMap<String, Vec<String>>,
    dependencies: Vec<(i32, Option<&'static str>)>,
    yanked: bool,
}

impl<'a> VersionBuilder<'a> {
    /// Creates a VersionBuilder from a string slice `num` representing the version's number.
    ///
    /// # Panics
    ///
    /// Panics if `num` cannot be parsed as a valid `semver::Version`.
    pub fn new(num: &str) -> Self {
        let num = semver::Version::parse(num).unwrap_or_else(|e| {
            panic!("The version {} is not valid: {}", num, e);
        });

        VersionBuilder {
            num,
            license: None,
            license_file: None,
            features: HashMap::new(),
            dependencies: Vec::new(),
            yanked: false,
        }
    }

    /// Sets the version's `license` value.
    pub fn license(mut self, license: Option<&'a str>) -> Self {
        self.license = license;
        self
    }

    /// Adds a dependency to this version.
    pub fn dependency(mut self, dependency: &Crate, target: Option<&'static str>) -> Self {
        self.dependencies.push((dependency.id, target));
        self
    }

    /// Sets the version's `yanked` value.
    pub fn yanked(self, yanked: bool) -> Self {
        Self { yanked, ..self }
    }

    fn build(self, crate_id: i32, connection: &PgConnection) -> CargoResult<Version> {
        use diesel::{insert_into, update};

        let license = match self.license {
            Some(license) => Some(license.to_owned()),
            None => None,
        };

        let mut vers = NewVersion::new(
            crate_id,
            &self.num,
            &self.features,
            license,
            self.license_file,
            None,
        )?.save(connection, &[])?;

        if self.yanked {
            vers = update(&vers)
                .set(versions::yanked.eq(true))
                .get_result(connection)?;
        }

        let new_deps = self
            .dependencies
            .into_iter()
            .map(|(crate_id, target)| {
                (
                    dependencies::version_id.eq(vers.id),
                    dependencies::req.eq(">= 0"),
                    dependencies::crate_id.eq(crate_id),
                    dependencies::target.eq(target),
                    dependencies::optional.eq(false),
                    dependencies::default_features.eq(false),
                    dependencies::features.eq(Vec::<String>::new()),
                )
            }).collect::<Vec<_>>();
        insert_into(dependencies::table)
            .values(&new_deps)
            .execute(connection)?;

        Ok(vers)
    }
}

impl<'a> From<&'a str> for VersionBuilder<'a> {
    fn from(num: &'a str) -> Self {
        VersionBuilder::new(num)
    }
}

/// A builder to create crate records for the purpose of inserting directly into the database.
/// If you want to test logic that happens as part of a publish request, use `PublishBuilder`
/// instead.
pub struct CrateBuilder<'a> {
    owner_id: i32,
    krate: NewCrate<'a>,
    downloads: Option<i32>,
    recent_downloads: Option<i32>,
    versions: Vec<VersionBuilder<'a>>,
    keywords: Vec<&'a str>,
}

impl<'a> CrateBuilder<'a> {
    /// Create a new instance with the given crate name and owner. If the owner with the given ID
    /// doesn't exist in the database, `expect_build` will fail.
    pub fn new(name: &str, owner_id: i32) -> CrateBuilder<'_> {
        CrateBuilder {
            owner_id,
            krate: NewCrate {
                name,
                ..NewCrate::default()
            },
            downloads: None,
            recent_downloads: None,
            versions: Vec::new(),
            keywords: Vec::new(),
        }
    }

    /// Sets the crate's `description` value.
    pub fn description(mut self, description: &'a str) -> Self {
        self.krate.description = Some(description);
        self
    }

    /// Sets the crate's `documentation` URL.
    pub fn documentation(mut self, documentation: &'a str) -> Self {
        self.krate.documentation = Some(documentation);
        self
    }

    /// Sets the crate's `homepage` URL.
    pub fn homepage(mut self, homepage: &'a str) -> Self {
        self.krate.homepage = Some(homepage);
        self
    }

    /// Sets the crate's `readme` content.
    pub fn readme(mut self, readme: &'a str) -> Self {
        self.krate.readme = Some(readme);
        self
    }

    /// Sets the crate's `max_upload_size` override value.
    pub fn max_upload_size(mut self, max_upload_size: i32) -> Self {
        self.krate.max_upload_size = Some(max_upload_size);
        self
    }

    /// Sets the crate's number of downloads that happened more than 90 days ago. The total
    /// number of downloads for this crate will be this plus the number of recent downloads.
    pub fn downloads(mut self, downloads: i32) -> Self {
        self.downloads = Some(downloads);
        self
    }

    /// Sets the crate's number of downloads in the last 90 days. The total number of downloads
    /// for this crate will be this plus the number of downloads set with the `downloads` method.
    pub fn recent_downloads(mut self, recent_downloads: i32) -> Self {
        self.recent_downloads = Some(recent_downloads);
        self
    }

    /// Adds a version record to be associated with the crate record when the crate record is
    /// built.
    pub fn version<T: Into<VersionBuilder<'a>>>(mut self, version: T) -> Self {
        self.versions.push(version.into());
        self
    }

    /// Adds a keyword to the crate.
    pub fn keyword(mut self, keyword: &'a str) -> Self {
        self.keywords.push(keyword);
        self
    }

    fn build(mut self, connection: &PgConnection) -> CargoResult<Crate> {
        use diesel::{insert_into, select, update};

        let mut krate = self
            .krate
            .create_or_update(connection, None, self.owner_id)?;

        // Since we are using `NewCrate`, we can't set all the
        // crate properties in a single DB call.

        let old_downloads = self.downloads.unwrap_or(0) - self.recent_downloads.unwrap_or(0);
        let now = Utc::now();
        let old_date = now.naive_utc().date() - chrono::Duration::days(91);

        if let Some(downloads) = self.downloads {
            let crate_download = CrateDownload {
                crate_id: krate.id,
                downloads: old_downloads,
                date: old_date,
            };

            insert_into(crate_downloads::table)
                .values(&crate_download)
                .execute(connection)?;
            krate.downloads = downloads;
            update(&krate).set(&krate).execute(connection)?;
        }

        if self.recent_downloads.is_some() {
            let crate_download = CrateDownload {
                crate_id: krate.id,
                downloads: self.recent_downloads.unwrap(),
                date: now.naive_utc().date(),
            };

            insert_into(crate_downloads::table)
                .values(&crate_download)
                .execute(connection)?;

            no_arg_sql_function!(refresh_recent_crate_downloads, ());
            select(refresh_recent_crate_downloads).execute(connection)?;
        }

        if self.versions.is_empty() {
            self.versions.push(VersionBuilder::new("0.99.0"));
        }

        for version_builder in self.versions {
            version_builder.build(krate.id, connection)?;
        }

        if !self.keywords.is_empty() {
            Keyword::update_crate(connection, &krate, &self.keywords)?;
        }

        Ok(krate)
    }

    /// Consumes the builder and creates the crate record in the database.
    ///
    /// # Panics
    ///
    /// Panics (and fails the test) if any part of inserting the crate record fails.
    pub fn expect_build(self, connection: &PgConnection) -> Crate {
        let name = self.krate.name;
        self.build(connection).unwrap_or_else(|e| {
            panic!("Unable to create crate {}: {:?}", name, e);
        })
    }
}

lazy_static! {
    // The bytes of an empty tarball is not an empty vector of bytes because of tarball headers.
    // Unless files are added to a PublishBuilder, the `.crate` tarball that gets uploaded
    // will be empty, so precompute the empty tarball bytes to use as a default.
    static ref EMPTY_TARBALL_BYTES: Vec<u8> = {
        let mut empty_tarball = vec![];
        {
            let mut ar =
                tar::Builder::new(GzEncoder::new(&mut empty_tarball, Compression::default()));
            t!(ar.finish());
        }
        empty_tarball
    };
}

/// A builder for constructing a crate for the purposes of testing publishing. If you only need
/// a crate to exist and don't need to test behavior caused by the publish request, inserting
/// a crate into the database directly by using CrateBuilder will be faster.
pub struct PublishBuilder {
    pub krate_name: String,
    version: semver::Version,
    tarball: Vec<u8>,
    deps: Vec<u::CrateDependency>,
}

impl PublishBuilder {
    /// Create a request to publish a crate with the given name, version 1.0.0, and no files
    /// in its tarball.
    pub fn new(krate_name: &str) -> Self {
        PublishBuilder {
            krate_name: krate_name.into(),
            version: semver::Version::parse("1.0.0").unwrap(),
            tarball: EMPTY_TARBALL_BYTES.to_vec(),
            deps: vec![],
        }
    }

    /// Set the version of the crate being published to something other than the default of 1.0.0.
    pub fn version(mut self, version: &str) -> Self {
        self.version = semver::Version::parse(version).unwrap();
        self
    }

    /// Set the files in the crate's tarball.
    pub fn files(mut self, files: &[(&str, &[u8])]) -> Self {
        let mut slices = files.iter().map(|p| p.1).collect::<Vec<_>>();
        let files = files
            .iter()
            .zip(&mut slices)
            .map(|(&(name, _), data)| {
                let len = data.len() as u64;
                (name, data as &mut Read, len)
            }).collect::<Vec<_>>();

        let mut tarball = Vec::new();
        {
            let mut ar = tar::Builder::new(GzEncoder::new(&mut tarball, Compression::default()));
            for (name, ref mut data, size) in files {
                let mut header = tar::Header::new_gnu();
                t!(header.set_path(name));
                header.set_size(size);
                header.set_cksum();
                t!(ar.append(&header, data));
            }
            t!(ar.finish());
        }

        self.tarball = tarball;
        self
    }

    /// Add a dependency to this crate. Make sure the dependency already exists in the
    /// database or publish will fail.
    pub fn dependency(mut self, dep: &str) -> Self {
        let dep = u::CrateDependency {
            name: u::CrateName(dep.to_string()),
            optional: false,
            default_features: true,
            features: Vec::new(),
            version_req: u::CrateVersionReq(semver::VersionReq::parse(">= 0").unwrap()),
            target: None,
            kind: None,
            explicit_name_in_toml: None,
        };

        self.deps.push(dep);
        self
    }

    /// Add a renamed dependency to this crate. Make sure the dependency already exists in the
    /// database or publish will fail.
    pub fn renamed_dependency(mut self, dep: &str, new_name: &str) -> Self {
        let dep = u::CrateDependency {
            name: u::CrateName(dep.to_string()),
            optional: false,
            default_features: true,
            features: Vec::new(),
            version_req: u::CrateVersionReq(semver::VersionReq::parse(">= 0").unwrap()),
            target: None,
            kind: None,
            explicit_name_in_toml: Some(u::CrateName(new_name.to_string())),
        };

        self.deps.push(dep);
        self
    }

    /// Consume this builder to make the Put request body
    pub fn body(self) -> Vec<u8> {
        let new_crate = u::NewCrate {
            name: u::CrateName(self.krate_name.clone()),
            vers: u::CrateVersion(self.version),
            features: HashMap::new(),
            deps: self.deps,
            authors: vec!["foo".to_string()],
            description: Some("description".to_string()),
            homepage: None,
            documentation: None,
            readme: None,
            readme_file: None,
            keywords: Some(u::KeywordList(Vec::new())),
            categories: Some(u::CategoryList(Vec::new())),
            license: Some("MIT".to_string()),
            license_file: None,
            repository: None,
            badges: Some(HashMap::new()),
            links: None,
        };

        ::new_crate_to_body_with_tarball(&new_crate, &self.tarball)
    }
}
<commit_msg>Extract a dependency builder<commit_after>//! Structs using the builder pattern that make it easier to create records in tests.

use std::collections::HashMap;
use std::io::Read;

use chrono;
use chrono::Utc;
use diesel::prelude::*;
use flate2::write::GzEncoder;
use flate2::Compression;
use semver;
use tar;

use cargo_registry::util::CargoResult;

use models::{Crate, CrateDownload, Keyword, Version};
use models::{NewCrate, NewVersion};
use schema::*;
use views::krate_publish as u;

/// A builder to create version records for the purpose of inserting directly into the database.
pub struct VersionBuilder<'a> {
    num: semver::Version,
    license: Option<&'a str>,
    license_file: Option<&'a str>,
    features: HashMap<String, Vec<String>>,
    dependencies: Vec<(i32, Option<&'static str>)>,
    yanked: bool,
}

impl<'a> VersionBuilder<'a> {
    /// Creates a VersionBuilder from a string slice `num` representing the version's number.
    ///
    /// # Panics
    ///
    /// Panics if `num` cannot be parsed as a valid `semver::Version`.
    pub fn new(num: &str) -> Self {
        let num = semver::Version::parse(num).unwrap_or_else(|e| {
            panic!("The version {} is not valid: {}", num, e);
        });

        VersionBuilder {
            num,
            license: None,
            license_file: None,
            features: HashMap::new(),
            dependencies: Vec::new(),
            yanked: false,
        }
    }

    /// Sets the version's `license` value.
    pub fn license(mut self, license: Option<&'a str>) -> Self {
        self.license = license;
        self
    }

    /// Adds a dependency to this version.
    pub fn dependency(mut self, dependency: &Crate, target: Option<&'static str>) -> Self {
        self.dependencies.push((dependency.id, target));
        self
    }

    /// Sets the version's `yanked` value.
    pub fn yanked(self, yanked: bool) -> Self {
        Self { yanked, ..self }
    }

    fn build(self, crate_id: i32, connection: &PgConnection) -> CargoResult<Version> {
        use diesel::{insert_into, update};

        let license = match self.license {
            Some(license) => Some(license.to_owned()),
            None => None,
        };

        let mut vers = NewVersion::new(
            crate_id,
            &self.num,
            &self.features,
            license,
            self.license_file,
            None,
        )?.save(connection, &[])?;

        if self.yanked {
            vers = update(&vers)
                .set(versions::yanked.eq(true))
                .get_result(connection)?;
        }

        let new_deps = self
            .dependencies
            .into_iter()
            .map(|(crate_id, target)| {
                (
                    dependencies::version_id.eq(vers.id),
                    dependencies::req.eq(">= 0"),
                    dependencies::crate_id.eq(crate_id),
                    dependencies::target.eq(target),
                    dependencies::optional.eq(false),
                    dependencies::default_features.eq(false),
                    dependencies::features.eq(Vec::<String>::new()),
                )
            }).collect::<Vec<_>>();
        insert_into(dependencies::table)
            .values(&new_deps)
            .execute(connection)?;

        Ok(vers)
    }
}

impl<'a> From<&'a str> for VersionBuilder<'a> {
    fn from(num: &'a str) -> Self {
        VersionBuilder::new(num)
    }
}

/// A builder to create crate records for the purpose of inserting directly into the database.
/// If you want to test logic that happens as part of a publish request, use `PublishBuilder`
/// instead.
pub struct CrateBuilder<'a> {
    owner_id: i32,
    krate: NewCrate<'a>,
    downloads: Option<i32>,
    recent_downloads: Option<i32>,
    versions: Vec<VersionBuilder<'a>>,
    keywords: Vec<&'a str>,
}

impl<'a> CrateBuilder<'a> {
    /// Create a new instance with the given crate name and owner. If the owner with the given ID
    /// doesn't exist in the database, `expect_build` will fail.
    pub fn new(name: &str, owner_id: i32) -> CrateBuilder<'_> {
        CrateBuilder {
            owner_id,
            krate: NewCrate {
                name,
                ..NewCrate::default()
            },
            downloads: None,
            recent_downloads: None,
            versions: Vec::new(),
            keywords: Vec::new(),
        }
    }

    /// Sets the crate's `description` value.
    pub fn description(mut self, description: &'a str) -> Self {
        self.krate.description = Some(description);
        self
    }

    /// Sets the crate's `documentation` URL.
    pub fn documentation(mut self, documentation: &'a str) -> Self {
        self.krate.documentation = Some(documentation);
        self
    }

    /// Sets the crate's `homepage` URL.
    pub fn homepage(mut self, homepage: &'a str) -> Self {
        self.krate.homepage = Some(homepage);
        self
    }

    /// Sets the crate's `readme` content.
    pub fn readme(mut self, readme: &'a str) -> Self {
        self.krate.readme = Some(readme);
        self
    }

    /// Sets the crate's `max_upload_size` override value.
    pub fn max_upload_size(mut self, max_upload_size: i32) -> Self {
        self.krate.max_upload_size = Some(max_upload_size);
        self
    }

    /// Sets the crate's number of downloads that happened more than 90 days ago. The total
    /// number of downloads for this crate will be this plus the number of recent downloads.
    pub fn downloads(mut self, downloads: i32) -> Self {
        self.downloads = Some(downloads);
        self
    }

    /// Sets the crate's number of downloads in the last 90 days. The total number of downloads
    /// for this crate will be this plus the number of downloads set with the `downloads` method.
    pub fn recent_downloads(mut self, recent_downloads: i32) -> Self {
        self.recent_downloads = Some(recent_downloads);
        self
    }

    /// Adds a version record to be associated with the crate record when the crate record is
    /// built.
    pub fn version<T: Into<VersionBuilder<'a>>>(mut self, version: T) -> Self {
        self.versions.push(version.into());
        self
    }

    /// Adds a keyword to the crate.
    pub fn keyword(mut self, keyword: &'a str) -> Self {
        self.keywords.push(keyword);
        self
    }

    fn build(mut self, connection: &PgConnection) -> CargoResult<Crate> {
        use diesel::{insert_into, select, update};

        let mut krate = self
            .krate
            .create_or_update(connection, None, self.owner_id)?;

        // Since we are using `NewCrate`, we can't set all the
        // crate properties in a single DB call.

        let old_downloads = self.downloads.unwrap_or(0) - self.recent_downloads.unwrap_or(0);
        let now = Utc::now();
        let old_date = now.naive_utc().date() - chrono::Duration::days(91);

        if let Some(downloads) = self.downloads {
            let crate_download = CrateDownload {
                crate_id: krate.id,
                downloads: old_downloads,
                date: old_date,
            };

            insert_into(crate_downloads::table)
                .values(&crate_download)
                .execute(connection)?;
            krate.downloads = downloads;
            update(&krate).set(&krate).execute(connection)?;
        }

        if self.recent_downloads.is_some() {
            let crate_download = CrateDownload {
                crate_id: krate.id,
                downloads: self.recent_downloads.unwrap(),
                date: now.naive_utc().date(),
            };

            insert_into(crate_downloads::table)
                .values(&crate_download)
                .execute(connection)?;

            no_arg_sql_function!(refresh_recent_crate_downloads, ());
            select(refresh_recent_crate_downloads).execute(connection)?;
        }

        if self.versions.is_empty() {
            self.versions.push(VersionBuilder::new("0.99.0"));
        }

        for version_builder in self.versions {
            version_builder.build(krate.id, connection)?;
        }

        if !self.keywords.is_empty() {
            Keyword::update_crate(connection, &krate, &self.keywords)?;
        }

        Ok(krate)
    }

    /// Consumes the builder and creates the crate record in the database.
    ///
    /// # Panics
    ///
    /// Panics (and fails the test) if any part of inserting the crate record fails.
    pub fn expect_build(self, connection: &PgConnection) -> Crate {
        let name = self.krate.name;
        self.build(connection).unwrap_or_else(|e| {
            panic!("Unable to create crate {}: {:?}", name, e);
        })
    }
}

lazy_static! {
    // The bytes of an empty tarball is not an empty vector of bytes because of tarball headers.
    // Unless files are added to a PublishBuilder, the `.crate` tarball that gets uploaded
    // will be empty, so precompute the empty tarball bytes to use as a default.
    static ref EMPTY_TARBALL_BYTES: Vec<u8> = {
        let mut empty_tarball = vec![];
        {
            let mut ar =
                tar::Builder::new(GzEncoder::new(&mut empty_tarball, Compression::default()));
            t!(ar.finish());
        }
        empty_tarball
    };
}

/// A builder for constructing a crate for the purposes of testing publishing. If you only need
/// a crate to exist and don't need to test behavior caused by the publish request, inserting
/// a crate into the database directly by using CrateBuilder will be faster.
pub struct PublishBuilder {
    pub krate_name: String,
    version: semver::Version,
    tarball: Vec<u8>,
    deps: Vec<u::CrateDependency>,
}

impl PublishBuilder {
    /// Create a request to publish a crate with the given name, version 1.0.0, and no files
    /// in its tarball.
    pub fn new(krate_name: &str) -> Self {
        PublishBuilder {
            krate_name: krate_name.into(),
            version: semver::Version::parse("1.0.0").unwrap(),
            tarball: EMPTY_TARBALL_BYTES.to_vec(),
            deps: vec![],
        }
    }

    /// Set the version of the crate being published to something other than the default of 1.0.0.
    pub fn version(mut self, version: &str) -> Self {
        self.version = semver::Version::parse(version).unwrap();
        self
    }

    /// Set the files in the crate's tarball.
    pub fn files(mut self, files: &[(&str, &[u8])]) -> Self {
        let mut slices = files.iter().map(|p| p.1).collect::<Vec<_>>();
        let files = files
            .iter()
            .zip(&mut slices)
            .map(|(&(name, _), data)| {
                let len = data.len() as u64;
                (name, data as &mut Read, len)
            }).collect::<Vec<_>>();

        let mut tarball = Vec::new();
        {
            let mut ar = tar::Builder::new(GzEncoder::new(&mut tarball, Compression::default()));
            for (name, ref mut data, size) in files {
                let mut header = tar::Header::new_gnu();
                t!(header.set_path(name));
                header.set_size(size);
                header.set_cksum();
                t!(ar.append(&header, data));
            }
            t!(ar.finish());
        }

        self.tarball = tarball;
        self
    }

    /// Add a dependency to this crate. Make sure the dependency already exists in the
    /// database or publish will fail.
    pub fn dependency(mut self, dep: &str) -> Self {
        let dep = DependencyBuilder::new(dep).build();
        self.deps.push(dep);
        self
    }

    /// Add a renamed dependency to this crate. Make sure the dependency already exists in the
    /// database or publish will fail.
    pub fn renamed_dependency(mut self, dep: &str, new_name: &str) -> Self {
        let dep = u::CrateDependency {
            name: u::CrateName(dep.to_string()),
            optional: false,
            default_features: true,
            features: Vec::new(),
            version_req: u::CrateVersionReq(semver::VersionReq::parse(">= 0").unwrap()),
            target: None,
            kind: None,
            explicit_name_in_toml: Some(u::CrateName(new_name.to_string())),
        };

        self.deps.push(dep);
        self
    }

    /// Consume this builder to make the Put request body
    pub fn body(self) -> Vec<u8> {
        let new_crate = u::NewCrate {
            name: u::CrateName(self.krate_name.clone()),
            vers: u::CrateVersion(self.version),
            features: HashMap::new(),
            deps: self.deps,
            authors: vec!["foo".to_string()],
            description: Some("description".to_string()),
            homepage: None,
            documentation: None,
            readme: None,
            readme_file: None,
            keywords: Some(u::KeywordList(Vec::new())),
            categories: Some(u::CategoryList(Vec::new())),
            license: Some("MIT".to_string()),
            license_file: None,
            repository: None,
            badges: Some(HashMap::new()),
            links: None,
        };

        ::new_crate_to_body_with_tarball(&new_crate, &self.tarball)
    }
}

/// A builder for constructing a dependency of another crate.
struct DependencyBuilder {
    name: String,
}

impl DependencyBuilder {
    /// Create a dependency on the crate with the given name.
    fn new(name: &str) -> Self {
        DependencyBuilder {
            name: name.to_string(),
        }
    }

    /// Consume this builder to create a `u::CrateDependency`. If the dependent crate doesn't
    /// already exist, publishing a crate with this dependency will fail.
    fn build(self) -> u::CrateDependency {
        u::CrateDependency {
            name: u::CrateName(self.name),
            optional: false,
            default_features: true,
            features: Vec::new(),
            version_req: u::CrateVersionReq(semver::VersionReq::parse(">= 0").unwrap()),
            target: None,
            kind: None,
            explicit_name_in_toml: None,
        }
    }
}
<|endoftext|>


<commit_before>use crate::tests;
use crate::*;

// use std::path;

#[test]
fn image_encode() {
    let (c, _e) = &mut tests::make_context();
    let image = graphics::Image::new(c, "/player.png").unwrap();
    image
        .encode(c, graphics::ImageFormat::Png, "/encode_test.png")
        .unwrap();
}

#[test]
fn save_screenshot() {
    let (c, _e) = &mut tests::make_context();
    graphics::clear(c, graphics::Color::new(0.1, 0.2, 0.3, 1.0));
    // Draw a triangle on it so you can see which way is right-side up.
    let tri_mesh = graphics::Mesh::new_polygon(
        c,
        graphics::DrawMode::stroke(10.0),
        &[
            graphics::Point2::new(100.0, 100.0),
            graphics::Point2::new(100.0, 200.0),
            graphics::Point2::new(200.0, 100.0),
        ],
        graphics::WHITE,
    )
    .unwrap();
    graphics::draw(c, &tri_mesh, graphics::DrawParam::default()).unwrap();
    graphics::present(c).unwrap();

    // Right now what we're screenshoting is not the front buffer, but the backbuffer.
    // I.e. since we're double buffering we're always one picture in the past.
    // Querying the front buffer can be much slower, so probably we should keep it as is.
    graphics::present(c).unwrap();

    let screenshot = graphics::screenshot(c).unwrap();
    screenshot
        .encode(c, graphics::ImageFormat::Png, "/screenshot_test.png")
        .unwrap();
}

#[test]
fn load_images() {
    let (c, _e) = &mut tests::make_context();
    let image = graphics::Image::new(c, "/player.png").unwrap();
    image
        .encode(c, graphics::ImageFormat::Png, "/player_save_test.png")
        .unwrap();
    let _i2 = graphics::Image::new(c, "/player_save_test.png").unwrap();
}

#[test]
fn sanity_check_window_sizes() {
    let (c, e) = &mut tests::make_context();

    // Make sure that window sizes are what we ask for, and not what hidpi gives us.
    let w = c.conf.window_mode.width;
    let h = c.conf.window_mode.height;
    let size = graphics::drawable_size(c);
    assert_eq!(w, size.0);
    assert_eq!(h, size.1);

    let outer_size = graphics::size(c);
    assert!(size.0 <= outer_size.0);
    assert!(size.1 <= outer_size.1);

    // Make sure resizing the window works.
    let w = 100.0;
    let h = 200.0;
    graphics::set_drawable_size(c, w, h).unwrap();
    // ahahaha this apparently REQUIRES a delay between setting
    // the size and it actually altering, at least on Linux X11
    std::thread::sleep(std::time::Duration::from_millis(100));
    // Maybe we need to run the event pump too?  It seems VERY flaky.
    // Sometimes you need one, sometimes you need both...
    e.poll_events(|event| {
        c.process_event(&event);
    });

    let size = graphics::drawable_size(c);
    assert_eq!(w, size.0);
    assert_eq!(h, size.1);
}

/// Ensure that the transform stack applies operations in the correct order.
#[test]
fn test_transform_stack_order() {
    let (ctx, _e) = &mut tests::make_context();
    let p1 = graphics::DrawParam::default();
    let p2 = graphics::DrawParam::default();
    let t1 = p1.to_matrix();
    let t2 = p2.to_matrix();
    graphics::push_transform(ctx, Some(t1));
    graphics::mul_transform(ctx, t2);
    let res = crate::nalgebra::Matrix4::<f32>::from(graphics::transform(ctx));
    let m1: crate::nalgebra::Matrix4<f32> = t1.into();
    let m2: crate::nalgebra::Matrix4<f32> = t2.into();
    assert_eq!(res, m2 * m1);
}
<commit_msg>screenshot has a primitive check for image contents now<commit_after>use crate::tests;
use crate::*;
use cgmath::Point2;

// use std::path;

#[test]
fn image_encode() {
    let (c, _e) = &mut tests::make_context();
    let image = graphics::Image::new(c, "/player.png").unwrap();
    image
        .encode(c, graphics::ImageFormat::Png, "/encode_test.png")
        .unwrap();
}

fn get_rgba_sample(rgba_buf: &[u8], width: usize, sample_pos: (usize, usize)) -> (u8, u8, u8, u8) {
    (
        rgba_buf[(width * sample_pos.1 + sample_pos.0) * 4 + 0],
        rgba_buf[(width * sample_pos.1 + sample_pos.0) * 4 + 1],
        rgba_buf[(width * sample_pos.1 + sample_pos.0) * 4 + 2],
        rgba_buf[(width * sample_pos.1 + sample_pos.0) * 4 + 3],
    )
}

#[test]
fn save_screenshot() {
    let (c, _e) = &mut tests::make_context();
    graphics::clear(c, graphics::Color::new(0.1, 0.2, 0.3, 1.0));

    let width = graphics::drawable_size(c).0;
    let height = graphics::drawable_size(c).1;

    let color_topleft = graphics::WHITE;
    let color_topright = graphics::Color::new(1.0, 0.0, 0.0, 1.0);
    let color_bottomleft = graphics::Color::new(0.0, 1.0, 0.0, 1.0);
    let color_bottomright = graphics::Color::new(0.0, 0.0, 1.0, 1.0);

    let rect = graphics::Mesh::new_rectangle(
        c,
        graphics::DrawMode::fill(),
        graphics::types::Rect {
            x: 0.0,
            y: 0.0,
            w: width / 2.0,
            h: height / 2.0,
        },
        graphics::WHITE,
    )
    .unwrap();

    graphics::draw(c, &rect, graphics::DrawParam::new().color(color_topleft)).unwrap();
    graphics::draw(
        c,
        &rect,
        graphics::DrawParam::new()
            .color(color_topright)
            .dest(Point2::new(width / 2.0, 0.0)),
    )
    .unwrap();
    graphics::draw(
        c,
        &rect,
        graphics::DrawParam::new()
            .color(color_bottomleft)
            .dest(Point2::new(0.0, height / 2.0)),
    )
    .unwrap();
    graphics::draw(
        c,
        &rect,
        graphics::DrawParam::new()
            .color(color_bottomright)
            .dest(Point2::new(width / 2.0, height / 2.0)),
    )
    .unwrap();

    // Don't do graphics::present(c) since calling it once (!) would mean that the result of our draw operation
    // went to the front buffer and the active screen texture is actually empty.
    c.gfx_context.encoder.flush(&mut *c.gfx_context.device);

    let screenshot = graphics::screenshot(c).unwrap();

    // Check if screenshot has right general properties
    assert_eq!(width as u16, screenshot.width);
    assert_eq!(height as u16, screenshot.height);
    assert_eq!(None, screenshot.blend_mode);

    // Image comparision or rendered output is hard, but we *know* that top left should be white.
    // So take a samples in the middle of each rectangle we drew and compare.
    // Note that we only use fully saturated colors to avoid any issues with color spaces.
    let rgba_buf = screenshot.to_rgba8(c).unwrap();
    let width = screenshot.width as usize;
    let quarter_size = (
        screenshot.width as usize / 4,
        screenshot.height as usize / 4,
    );
    assert_eq!(
        color_topleft.to_rgba(),
        get_rgba_sample(&rgba_buf, width, (quarter_size.0, quarter_size.1))
    );
    assert_eq!(
        color_topright.to_rgba(),
        get_rgba_sample(&rgba_buf, width, (quarter_size.0 * 3, quarter_size.1))
    );
    assert_eq!(
        color_bottomleft.to_rgba(),
        get_rgba_sample(&rgba_buf, width, (quarter_size.0, quarter_size.1 * 3))
    );
    assert_eq!(
        color_bottomright.to_rgba(),
        get_rgba_sample(&rgba_buf, width, (quarter_size.0 * 3, quarter_size.1 * 3))
    );

    // save screenshot (no check, just to see if it doesn't crash)
    screenshot
        .encode(c, graphics::ImageFormat::Png, "/screenshot_test.png")
        .unwrap();
}

#[test]
fn load_images() {
    let (c, _e) = &mut tests::make_context();
    let image = graphics::Image::new(c, "/player.png").unwrap();
    image
        .encode(c, graphics::ImageFormat::Png, "/player_save_test.png")
        .unwrap();
    let _i2 = graphics::Image::new(c, "/player_save_test.png").unwrap();
}

#[test]
fn sanity_check_window_sizes() {
    let (c, e) = &mut tests::make_context();

    // Make sure that window sizes are what we ask for, and not what hidpi gives us.
    let w = c.conf.window_mode.width;
    let h = c.conf.window_mode.height;
    let size = graphics::drawable_size(c);
    assert_eq!(w, size.0);
    assert_eq!(h, size.1);

    let outer_size = graphics::size(c);
    assert!(size.0 <= outer_size.0);
    assert!(size.1 <= outer_size.1);

    // Make sure resizing the window works.
    let w = 100.0;
    let h = 200.0;
    graphics::set_drawable_size(c, w, h).unwrap();
    // ahahaha this apparently REQUIRES a delay between setting
    // the size and it actually altering, at least on Linux X11
    std::thread::sleep(std::time::Duration::from_millis(100));
    // Maybe we need to run the event pump too?  It seems VERY flaky.
    // Sometimes you need one, sometimes you need both...
    e.poll_events(|event| {
        c.process_event(&event);
    });

    let size = graphics::drawable_size(c);
    assert_eq!(w, size.0);
    assert_eq!(h, size.1);
}

/// Ensure that the transform stack applies operations in the correct order.
#[test]
fn test_transform_stack_order() {
    let (ctx, _e) = &mut tests::make_context();
    let p1 = graphics::DrawParam::default();
    let p2 = graphics::DrawParam::default();
    let t1 = p1.to_matrix();
    let t2 = p2.to_matrix();
    graphics::push_transform(ctx, Some(t1));
    graphics::mul_transform(ctx, t2);
    let res = crate::nalgebra::Matrix4::<f32>::from(graphics::transform(ctx));
    let m1: crate::nalgebra::Matrix4<f32> = t1.into();
    let m2: crate::nalgebra::Matrix4<f32> = t2.into();
    assert_eq!(res, m2 * m1);
}
<|endoftext|>


<commit_before>extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;
use syn::{ItemFn, Stmt, Item, Block, Expr,
          spanned::Spanned,
          fold::Fold};

/// Parses a list of variable names separated by commas
///
/// This is how the compiler passes in arguments to our attribute -- it is
/// everything inside the delimiters after the attribute name.
///```rust,ignore
///     #[wlroots_dehandle(a, b, c)]
///```
struct Args;

impl Fold for Args {
    fn fold_block(&mut self, block: Block) -> Block {
        build_block(block.stmts.iter(), self)
    }
}

/// Attribute to automatically call the `run` method on handles with the
/// remaining block of code.
///
/// The name of the variable you want to use as the upgraded handle should be
/// provided as an argument to the attribute. It does not need to be the same
/// as the handle variable.
///
/// The syntax in the code should be `use $handle as $upgraded_handle`.
/// E.g the variable in the code that stores the handle should go on the
/// **left** and the variable you used in the attribute declaration should
/// go on the **right**.
///
/// # Panics
/// If the handle is invalid (e.g. default constructed, or is a dangling
/// handle) then your code will `panic!`.
///
/// If this is undesirable, please use the non-proc macro `with_handles!`.
///
/// # Example
///
/// ```rust,ignore
/// impl InputManagerHandler for InputManager {
///     #[wlroots_dehandle]
///     fn keyboard_added(&mut self,
///                       compositor_handle: CompositorHandle,
///                       keyboard: KeyboardHandle)
///                       -> Option<Box<Keyboard Handler>> {
///         {
///             #[dehandle] let compositor = compositor_handle;
///             #[dehandle] let keyboard = keyboard;
///             let server: &mut ::Server = compositor.into();
///             server.keyboards.push(keyboard.weak_reference());
///             // Now that we have at least one keyboard, update the seat capabilities.
///             #[dehandle] let seat = &server.seat.seat;
///             let mut capabilities = seat.capabilities();
///             capabilities.insert(Capability::Keyboard);
///             seat.set_capabilities(capabilities);
///             seat.set_keyboard(keyboard.input_device());
///         }
///         // Due to some weird closure inference rules, this has to be outside
///         // of the above block.
///         Some(Box::new(::Keyboard))
///     }
/// }
/// ```
#[proc_macro_attribute]
pub fn wlroots_dehandle(_args: TokenStream, input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as ItemFn);
    let output = Args.fold_item_fn(input);
    TokenStream::from(quote!(#output))
}

fn build_block(mut input: std::slice::Iter<Stmt>, args: &mut Args) -> Block {
    let mut output = vec![];
    let mut inner = None;
    while let Some(stmt) = input.next().cloned() {
        use syn::{Pat, punctuated::Pair};
        match stmt.clone() {
            // Recurse into function body
            Stmt::Item(Item::Fn(mut function)) => {
                let inner_block = function.block.clone();
                *function.block = build_block(inner_block.stmts.iter(), args);
                output.push(Stmt::Item(Item::Fn(function)))
            },
            Stmt::Local(mut local) => {
                // Ensure attribute is prefaced here
                let mut dehandle = false;
                for attribute in &local.attrs {
                    let meta = attribute.parse_meta();
                    match meta {
                        Ok(syn::Meta::Word(name)) => {
                            if name.to_string() == "dehandle" {
                                dehandle = true;
                                break;
                            }
                        },
                        _ => {}
                    }
                };
                let left_side = local.pats.first().map(Pair::into_value).cloned();
                let right_side = local.init.clone();
                match (dehandle, left_side, right_side) {
                    (true,
                     Some(Pat::Ident(dehandle_name)),
                     Some((_, body))) => {
                        inner = Some((body, dehandle_name));
                        break;
                    },
                    // Recurse into let call
                    (false, _, Some((_, body))) => {
                        let body = build_block_expr(*body.clone(), args);
                        let stream = quote_spanned!(stmt.span()=> #body);
                        let body: Expr = syn::parse_quote::parse(stream.into());
                        local.init.as_mut().unwrap().1 = Box::new(body);
                        output.push(Stmt::Local(local))
                    },
                    _ => output.push(Stmt::Local(local))
                }
            },
            Stmt::Expr(expr) => {
                let body = build_block_expr(expr, args);
                output.push(syn::parse_quote::parse(quote_spanned!(stmt.span()=> {#body}).into()))
            }
            Stmt::Semi(expr, _) => {
                let body = build_block_expr(expr, args);
                output.push(syn::parse_quote::parse(quote_spanned!(stmt.span()=> {#body;}).into()))
            }
            _ => output.push(stmt)
        }
    }
    if let Some((handle, dehandle)) = inner {
        let inner_block = build_block(input, args);
        let handle_call = syn::parse_quote::parse(quote_spanned!(handle.span()=>
            {(#handle).run(|#dehandle|{
                #inner_block
            }).expect(concat!("Could not upgrade handle ",
                              stringify!(#handle), " to ",
                              stringify!(#dehandle)))}
        ).into());
        output.push(handle_call);
    }
    parse_quote!({#(#output)*})
}

/// Tries to build a block from the expression.
fn build_block_expr(expr: Expr, args: &mut Args) -> Expr {
    match expr {
        Expr::Block(block) => {
            let block = build_block(block.block.stmts.iter(), args);
            syn::parse_quote::parse(quote_spanned!(block.span()=> #block))
        }
        Expr::Let(mut let_expr) => {
            *let_expr.expr = build_block_expr(*let_expr.expr.clone(), args);
            Expr::Let(let_expr)
        },
        Expr::If(mut if_expr) => {
            let then_branch = if_expr.then_branch.clone();
            let then_parsed = syn::parse_quote::parse(
                quote_spanned!(then_branch.span()=> #then_branch));
            let then_branch = build_block_expr(then_parsed, args);
            if_expr.then_branch = syn::parse_quote::parse(
                quote_spanned!(then_branch.span()=> #then_branch));
            if_expr.else_branch = match if_expr.else_branch.clone() {
                None => if_expr.else_branch,
                Some((token, else_branch)) => {
                    Some((token, Box::new( build_block_expr(*else_branch, args))))
                }
            };
            Expr::If(if_expr)
        },
        Expr::While(mut while_expr) => {
            let body = while_expr.body.clone();
            let body = build_block_expr(syn::parse_quote::parse(
                quote_spanned!(body.span()=> #body)), args);
            while_expr.body = parse_quote!(#body);
            Expr::While(while_expr)
        },
        Expr::ForLoop(mut for_expr) => {
            let body = for_expr.body.clone();
            let body = build_block_expr(parse_quote!(#body), args);
            for_expr.body = parse_quote!(#body);
            Expr::ForLoop(for_expr)
        },
        Expr::Loop(mut loop_expr) => {
            let body = loop_expr.body.clone();
            let body = build_block_expr(parse_quote!(#body), args);
            loop_expr.body = parse_quote!(#body);
            Expr::Loop(loop_expr)
        },
        Expr::Match(mut match_expr) => {
            for arm in &mut match_expr.arms {
                *arm.body = build_block_expr(*arm.body.clone(), args)
            }
            Expr::Match(match_expr)
        },
        Expr::Struct(mut struct_expr) => {
            for field in &mut struct_expr.fields {
                field.expr = build_block_expr(field.expr.clone(), args);
            }
            Expr::Struct(struct_expr)
        },
        Expr::Call(mut call_expr) => {
            for arg in &mut call_expr.args {
                *arg = build_block_expr(arg.clone(), args);
            }
            Expr::Call(call_expr)
        },
        Expr::MethodCall(mut call_expr) => {
            for arg in &mut call_expr.args {
                *arg = build_block_expr(arg.clone(), args);
            }
            Expr::MethodCall(call_expr)
        },
        Expr::Closure(mut closure_expr) => {
            *closure_expr.body = build_block_expr(*closure_expr.body.clone(),
                                                  args);
            Expr::Closure(closure_expr)
        },
        Expr::Unsafe(mut unsafe_expr) => {
            unsafe_expr.block = build_block(unsafe_expr.block.stmts.iter(),
                                            args);
            Expr::Unsafe(unsafe_expr)
        },
        Expr::Assign(mut assign_expr) => {
            *assign_expr.right = build_block_expr(*assign_expr.right.clone(),
                                                  args);
            Expr::Assign(assign_expr)
        },
        Expr::AssignOp(mut assign_expr) => {
            *assign_expr.right = build_block_expr(*assign_expr.right.clone(),
                                                  args);
            Expr::AssignOp(assign_expr)
        },
        Expr::Break(mut break_expr) => {
            match break_expr.expr {
                None => {},
                Some(ref mut expr) => {
                    **expr = build_block_expr(*expr.clone(), args);
                }
            }
            Expr::Break(break_expr)
        },
        Expr::Return(mut return_expr) => {
            match return_expr.expr {
                None => {},
                Some(ref mut expr) => {
                    **expr = build_block_expr(*expr.clone(), args);
                }
            }
            Expr::Return(return_expr)
        },
        Expr::Reference(mut reference_expr) => {
            *reference_expr.expr = build_block_expr(*reference_expr.expr.clone(),
                                                    args);
            Expr::Reference(reference_expr)
        },
        Expr::Paren(mut paren_expr) => {
            *paren_expr.expr = build_block_expr(*paren_expr.expr.clone(), args);
            Expr::Paren(paren_expr)
        },
        Expr::Unary(mut unary_expr) => {
            *unary_expr.expr = build_block_expr(*unary_expr.expr.clone(), args);
            Expr::Unary(unary_expr)
        },
        Expr::Binary(mut binary_expr) => {
            *binary_expr.left = build_block_expr(*binary_expr.left.clone(), args);
            *binary_expr.right = build_block_expr(*binary_expr.right.clone(), args);
            Expr::Binary(binary_expr)
        },
        v => {
            v
        }
    }
}
<commit_msg>Added ? to wlroots_dehandle<commit_after>extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;
use syn::{ItemFn, Stmt, Item, Block, Expr,
          spanned::Spanned,
          fold::Fold};

/// Parses a list of variable names separated by commas
///
/// This is how the compiler passes in arguments to our attribute -- it is
/// everything inside the delimiters after the attribute name.
///```rust,ignore
///     #[wlroots_dehandle(a, b, c)]
///```
struct Args;

impl Fold for Args {
    fn fold_block(&mut self, block: Block) -> Block {
        build_block(block.stmts.iter(), self)
    }
}

/// Attribute to automatically call the `run` method on handles with the
/// remaining block of code.
///
/// The name of the variable you want to use as the upgraded handle should be
/// provided as an argument to the attribute. It does not need to be the same
/// as the handle variable.
///
/// The syntax in the code should be `use $handle as $upgraded_handle`.
/// E.g the variable in the code that stores the handle should go on the
/// **left** and the variable you used in the attribute declaration should
/// go on the **right**.
///
/// # Panics
/// If the handle is invalid (e.g. default constructed, or is a dangling
/// handle) then your code will `panic!`.
///
/// If this is undesirable, please use the non-proc macro `with_handles!`.
///
/// # Example
///
/// ```rust,ignore
/// impl InputManagerHandler for InputManager {
///     #[wlroots_dehandle]
///     fn keyboard_added(&mut self,
///                       compositor_handle: CompositorHandle,
///                       keyboard: KeyboardHandle)
///                       -> Option<Box<Keyboard Handler>> {
///         {
///             #[dehandle] let compositor = compositor_handle;
///             #[dehandle] let keyboard = keyboard;
///             let server: &mut ::Server = compositor.into();
///             server.keyboards.push(keyboard.weak_reference());
///             // Now that we have at least one keyboard, update the seat capabilities.
///             #[dehandle] let seat = &server.seat.seat;
///             let mut capabilities = seat.capabilities();
///             capabilities.insert(Capability::Keyboard);
///             seat.set_capabilities(capabilities);
///             seat.set_keyboard(keyboard.input_device());
///         }
///         // Due to some weird closure inference rules, this has to be outside
///         // of the above block.
///         Some(Box::new(::Keyboard))
///     }
/// }
/// ```
#[proc_macro_attribute]
pub fn wlroots_dehandle(_args: TokenStream, input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as ItemFn);
    let output = Args.fold_item_fn(input);
    TokenStream::from(quote!(#output))
}

fn build_block(mut input: std::slice::Iter<Stmt>, args: &mut Args) -> Block {
    let mut output = vec![];
    let mut inner = None;
    let mut is_try = false;
    while let Some(stmt) = input.next().cloned() {
        use syn::{Pat, punctuated::Pair};
        match stmt.clone() {
            // Recurse into function body
            Stmt::Item(Item::Fn(mut function)) => {
                let inner_block = function.block.clone();
                *function.block = build_block(inner_block.stmts.iter(), args);
                output.push(Stmt::Item(Item::Fn(function)))
            },
            Stmt::Local(mut local) => {
                // Ensure attribute is prefaced here
                let mut dehandle = false;
                for attribute in &local.attrs {
                    let meta = attribute.parse_meta();
                    match meta {
                        Ok(syn::Meta::Word(name)) => {
                            if name.to_string() == "dehandle" {
                                dehandle = true;
                                break;
                            }
                        },
                        _ => {}
                    }
                };
                let left_side = local.pats.first().map(Pair::into_value).cloned();
                let right_side = local.init.clone();
                match (dehandle, left_side, right_side) {
                    (true,
                     Some(Pat::Ident(dehandle_name)),
                     Some((_, body))) => {
                        let mut body = *body;
                        is_try = match body.clone() {
                            syn::Expr::Try(syn::ExprTry { expr, .. }) => {
                                body = *expr.clone();
                                true
                            },
                            _ => false
                        };
                        inner = Some((body, dehandle_name));
                        break;
                    },
                    // Recurse into let call
                    (false, _, Some((_, body))) => {
                        let body = build_block_expr(*body.clone(), args);
                        let stream = quote_spanned!(stmt.span()=> #body);
                        let body: Expr = syn::parse_quote::parse(stream.into());
                        local.init.as_mut().unwrap().1 = Box::new(body);
                        output.push(Stmt::Local(local))
                    },
                    _ => output.push(Stmt::Local(local))
                }
            },
            Stmt::Expr(expr) => {
                let body = build_block_expr(expr, args);
                output.push(syn::parse_quote::parse(quote_spanned!(stmt.span()=> {#body}).into()))
            }
            Stmt::Semi(expr, _) => {
                let body = build_block_expr(expr, args);
                output.push(syn::parse_quote::parse(quote_spanned!(stmt.span()=> {#body;}).into()))
            }
            _ => output.push(stmt)
        }
    }
    if let Some((handle, dehandle)) = inner {
        let inner_block = build_block(input, args);
        let handle_call = if !is_try {
            syn::parse_quote::parse(
                quote_spanned!(handle.span()=>
                               {(#handle).run(|#dehandle|{
                                   #inner_block
                               }).expect(concat!("Could not upgrade handle ",
                                                 stringify!(#handle), " to ",
                                                 stringify!(#dehandle)))}).into())
        } else {
            syn::parse_quote::parse(
                quote_spanned!(handle.span()=>
                               {(#handle).run(|#dehandle|{
                                   #inner_block
                               })?}).into())
        };
        output.push(handle_call);
    }
    parse_quote!({#(#output)*})
}

/// Tries to build a block from the expression.
fn build_block_expr(expr: Expr, args: &mut Args) -> Expr {
    match expr {
        Expr::Block(block) => {
            let block = build_block(block.block.stmts.iter(), args);
            syn::parse_quote::parse(quote_spanned!(block.span()=> #block))
        }
        Expr::Let(mut let_expr) => {
            *let_expr.expr = build_block_expr(*let_expr.expr.clone(), args);
            Expr::Let(let_expr)
        },
        Expr::If(mut if_expr) => {
            let then_branch = if_expr.then_branch.clone();
            let then_parsed = syn::parse_quote::parse(
                quote_spanned!(then_branch.span()=> #then_branch));
            let then_branch = build_block_expr(then_parsed, args);
            if_expr.then_branch = syn::parse_quote::parse(
                quote_spanned!(then_branch.span()=> #then_branch));
            if_expr.else_branch = match if_expr.else_branch.clone() {
                None => if_expr.else_branch,
                Some((token, else_branch)) => {
                    Some((token, Box::new( build_block_expr(*else_branch, args))))
                }
            };
            Expr::If(if_expr)
        },
        Expr::While(mut while_expr) => {
            let body = while_expr.body.clone();
            let body = build_block_expr(syn::parse_quote::parse(
                quote_spanned!(body.span()=> #body)), args);
            while_expr.body = parse_quote!(#body);
            Expr::While(while_expr)
        },
        Expr::ForLoop(mut for_expr) => {
            let body = for_expr.body.clone();
            let body = build_block_expr(parse_quote!(#body), args);
            for_expr.body = parse_quote!(#body);
            Expr::ForLoop(for_expr)
        },
        Expr::Loop(mut loop_expr) => {
            let body = loop_expr.body.clone();
            let body = build_block_expr(parse_quote!(#body), args);
            loop_expr.body = parse_quote!(#body);
            Expr::Loop(loop_expr)
        },
        Expr::Match(mut match_expr) => {
            for arm in &mut match_expr.arms {
                *arm.body = build_block_expr(*arm.body.clone(), args)
            }
            Expr::Match(match_expr)
        },
        Expr::Struct(mut struct_expr) => {
            for field in &mut struct_expr.fields {
                field.expr = build_block_expr(field.expr.clone(), args);
            }
            Expr::Struct(struct_expr)
        },
        Expr::Call(mut call_expr) => {
            for arg in &mut call_expr.args {
                *arg = build_block_expr(arg.clone(), args);
            }
            Expr::Call(call_expr)
        },
        Expr::MethodCall(mut call_expr) => {
            for arg in &mut call_expr.args {
                *arg = build_block_expr(arg.clone(), args);
            }
            Expr::MethodCall(call_expr)
        },
        Expr::Closure(mut closure_expr) => {
            *closure_expr.body = build_block_expr(*closure_expr.body.clone(),
                                                  args);
            Expr::Closure(closure_expr)
        },
        Expr::Unsafe(mut unsafe_expr) => {
            unsafe_expr.block = build_block(unsafe_expr.block.stmts.iter(),
                                            args);
            Expr::Unsafe(unsafe_expr)
        },
        Expr::Assign(mut assign_expr) => {
            *assign_expr.right = build_block_expr(*assign_expr.right.clone(),
                                                  args);
            Expr::Assign(assign_expr)
        },
        Expr::AssignOp(mut assign_expr) => {
            *assign_expr.right = build_block_expr(*assign_expr.right.clone(),
                                                  args);
            Expr::AssignOp(assign_expr)
        },
        Expr::Break(mut break_expr) => {
            match break_expr.expr {
                None => {},
                Some(ref mut expr) => {
                    **expr = build_block_expr(*expr.clone(), args);
                }
            }
            Expr::Break(break_expr)
        },
        Expr::Return(mut return_expr) => {
            match return_expr.expr {
                None => {},
                Some(ref mut expr) => {
                    **expr = build_block_expr(*expr.clone(), args);
                }
            }
            Expr::Return(return_expr)
        },
        Expr::Reference(mut reference_expr) => {
            *reference_expr.expr = build_block_expr(*reference_expr.expr.clone(),
                                                    args);
            Expr::Reference(reference_expr)
        },
        Expr::Paren(mut paren_expr) => {
            *paren_expr.expr = build_block_expr(*paren_expr.expr.clone(), args);
            Expr::Paren(paren_expr)
        },
        Expr::Unary(mut unary_expr) => {
            *unary_expr.expr = build_block_expr(*unary_expr.expr.clone(), args);
            Expr::Unary(unary_expr)
        },
        Expr::Binary(mut binary_expr) => {
            *binary_expr.left = build_block_expr(*binary_expr.left.clone(), args);
            *binary_expr.right = build_block_expr(*binary_expr.right.clone(), args);
            Expr::Binary(binary_expr)
        },
        v => {
            v
        }
    }
}
<|endoftext|>


<commit_before>//! A generic ringbuffer

#![experimental]

use std::clone::Clone;
use std::vec::Vec;

use core::Time;

pub struct RingBuffer<T: Clone> {
    buf: Vec<T>,
    capacity: uint,
    size: uint,
    start_t: Time,
    end_t: Time,
}

impl<T: Clone> RingBuffer<T> {
    pub fn new(capacity: uint) -> RingBuffer<T> {
        RingBuffer {
            buf: Vec::with_capacity(capacity),
            capacity: capacity,
            size: 0,
            start_t: 0,
            end_t: 0
        }
    }

    pub fn get(&self, t: Time) -> Option<T> {
        if self.start_t <= t && t < self.end_t {
            Some(self.buf[(t % self.capacity as Time) as uint].clone())
        } else {
            None
        }
    }

    pub fn push(&mut self, data: T) {
        if self.size < self.capacity {
            self.buf.push(data);
            self.size += 1;
            self.end_t += 1;
        } else {
            self.buf[(self.end_t % self.capacity as Time) as uint] = data;
            self.start_t += 1;
            self.end_t += 1;
        }
    }
}

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

    #[test]
    fn test_push() {
        let mut rb = RingBuffer::<int>::new(2);

        rb.push(13);
        assert_eq!(rb.size, 1);
        assert_eq!(rb.start_t, 0);
        assert_eq!(rb.end_t, 1);
        assert_eq!(rb.buf[0], 13);

        rb.push(7);
        assert_eq!(rb.size, 2);
        assert_eq!(rb.start_t, 0);
        assert_eq!(rb.end_t, 2);
        assert_eq!(rb.buf[0], 13);
        assert_eq!(rb.buf[1], 7);

        rb.push(3);
        assert_eq!(rb.size, 2);
        assert_eq!(rb.start_t, 1);
        assert_eq!(rb.end_t, 3);
        assert_eq!(rb.buf[0], 3);
        assert_eq!(rb.buf[1], 7);
    }

    #[test]
    fn test_get() {
        let mut rb: RingBuffer<int> = RingBuffer {
            buf: vec![7,13],
            capacity: 2,
            size: 2,
            start_t: 7,
            end_t: 9
        };

        // Test with odd start
        assert_eq!(rb.get(6), None);
        assert_eq!(rb.get(7), Some(13));
        assert_eq!(rb.get(8), Some(7));
        assert_eq!(rb.get(9), None);

        // Test with even start
        rb.start_t = 6; rb.end_t = 8;
        assert_eq!(rb.get(5), None);
        assert_eq!(rb.get(6), Some(7));
        assert_eq!(rb.get(7), Some(13));
        assert_eq!(rb.get(8), None);
    }
}
<commit_msg>Update function and documentation for ringbuffer<commit_after>//! A generic ring buffer
//!
//! A ring buffer can continue adding data on to the end of itself indefinitely.
//! However, it has a limited capacity; when that capacity is reached, it will
//! remove the oldest data to make space.

#![unstable]

use std::clone::Clone;
use std::vec::Vec;

use core::Time;

/// A generic ring buffer
pub struct RingBuffer<T: Clone> {
    buf: Vec<T>,
    capacity: uint,
    size: uint,
    start_t: Time,
    end_t: Time,
}

impl<T: Clone> RingBuffer<T> {
    /// Returns an empty ring buffer that can hold at most `capacity` elements.
    pub fn new(capacity: uint) -> RingBuffer<T> {
        RingBuffer {
            buf: Vec::with_capacity(capacity),
            capacity: capacity,
            size: 0,
            start_t: 0,
            end_t: 0
        }
    }

    /// Attempts to return the data stored at time `t`. If the requested time is
    /// not in the buffer, instead returns `None`.
    pub fn get(&self, t: Time) -> Option<T> {
        if self.start_t <= t && t < self.end_t {
            Some(self.buf[(t % self.capacity as Time) as uint].clone())
        } else {
            None
        }
    }

    /// Pushes the supplied data onto the end of the buffer. If the buffer is
    /// full, this will overwrite the oldest data.
    pub fn push(&mut self, data: T) {
        if self.size < self.capacity {
            self.buf.push(data);
            self.size += 1;
            self.end_t += 1;
        } else {
            self.buf[(self.end_t % self.capacity as Time) as uint] = data;
            self.start_t += 1;
            self.end_t += 1;
        }
    }

    /// Attempts to change the value at time `t` to `data`. If the requested
    /// time is not in the buffer, instead returns `Err`.
    pub fn update(&mut self, t: Time, data: T) -> Result<(),()> {
        if self.start_t <= t && t < self.end_t {
            self.buf[(t % self.capacity as Time) as uint] = data;
            Ok(())
        } else {
            Err(())
        }
    }
}

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

    #[test]
    fn test_push() {
        let mut rb = RingBuffer::<int>::new(2);

        rb.push(13);
        assert_eq!(rb.size, 1);
        assert_eq!(rb.start_t, 0);
        assert_eq!(rb.end_t, 1);
        assert_eq!(rb.buf[0], 13);

        rb.push(7);
        assert_eq!(rb.size, 2);
        assert_eq!(rb.start_t, 0);
        assert_eq!(rb.end_t, 2);
        assert_eq!(rb.buf[0], 13);
        assert_eq!(rb.buf[1], 7);

        rb.push(3);
        assert_eq!(rb.size, 2);
        assert_eq!(rb.start_t, 1);
        assert_eq!(rb.end_t, 3);
        assert_eq!(rb.buf[0], 3);
        assert_eq!(rb.buf[1], 7);
    }

    #[test]
    fn test_get() {
        let mut rb: RingBuffer<int> = RingBuffer {
            buf: vec![7,13],
            capacity: 2,
            size: 2,
            start_t: 7,
            end_t: 9
        };

        // Test with odd start
        assert_eq!(rb.get(6), None);
        assert_eq!(rb.get(7), Some(13));
        assert_eq!(rb.get(8), Some(7));
        assert_eq!(rb.get(9), None);

        // Test with even start
        rb.start_t = 6; rb.end_t = 8;
        assert_eq!(rb.get(5), None);
        assert_eq!(rb.get(6), Some(7));
        assert_eq!(rb.get(7), Some(13));
        assert_eq!(rb.get(8), None);
    }

    #[test]
    fn test_update() {
        let mut rb: RingBuffer<int> = RingBuffer {
            buf: vec![7,13],
            capacity: 2,
            size: 2,
            start_t: 7,
            end_t: 9
        };

        // Test out of range
        assert_eq!(rb.update(6, 22), Err(()));
        assert_eq!(rb.update(9, 22), Err(()));

        // Test in range
        assert_eq!(rb.update(7, 22), Ok(()));
        assert_eq!(rb.buf[1], 22);
        assert_eq!(rb.update(8, 23), Ok(()));
        assert_eq!(rb.buf[0], 23);
    }
}
<|endoftext|>


<commit_before><commit_msg>interactive: add best command<commit_after><|endoftext|>


<commit_before>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Instant;
use std::ptr;
use std::mem;

use winapi::shared::minwindef::{TRUE, ULONG};
use winapi::shared::ntdef::NTSTATUS;
use winapi::shared::ntstatus::{STATUS_SUCCESS, STATUS_TIMEOUT};
use winapi::um::handleapi::CloseHandle;
use winapi::um::libloaderapi::{GetModuleHandleA, GetProcAddress};
use winapi::um::winnt::{ACCESS_MASK, GENERIC_READ, GENERIC_WRITE, LPCSTR};
use winapi::um::winnt::{BOOLEAN, HANDLE, LARGE_INTEGER, PLARGE_INTEGER, PVOID};

const STATE_UNPARKED: usize = 0;
const STATE_PARKED: usize = 1;
const STATE_TIMED_OUT: usize = 2;

#[allow(non_snake_case)]
pub struct KeyedEvent {
    handle: HANDLE,
    NtReleaseKeyedEvent: extern "system" fn(
        EventHandle: HANDLE,
        Key: PVOID,
        Alertable: BOOLEAN,
        Timeout: PLARGE_INTEGER,
    ) -> NTSTATUS,
    NtWaitForKeyedEvent: extern "system" fn(
        EventHandle: HANDLE,
        Key: PVOID,
        Alertable: BOOLEAN,
        Timeout: PLARGE_INTEGER,
    ) -> NTSTATUS,
}

impl KeyedEvent {
    unsafe fn wait_for(&self, key: PVOID, timeout: PLARGE_INTEGER) -> NTSTATUS {
        (self.NtWaitForKeyedEvent)(self.handle, key, 0, timeout)
    }

    unsafe fn release(&self, key: PVOID) -> NTSTATUS {
        (self.NtReleaseKeyedEvent)(self.handle, key, 0, ptr::null_mut())
    }

    #[allow(non_snake_case)]
    pub unsafe fn create() -> Option<KeyedEvent> {
        let ntdll = GetModuleHandleA(b"ntdll.dll\0".as_ptr() as LPCSTR);
        if ntdll.is_null() {
            return None;
        }

        let NtCreateKeyedEvent = GetProcAddress(ntdll, b"NtCreateKeyedEvent\0".as_ptr() as LPCSTR);
        if NtCreateKeyedEvent.is_null() {
            return None;
        }
        let NtReleaseKeyedEvent =
            GetProcAddress(ntdll, b"NtReleaseKeyedEvent\0".as_ptr() as LPCSTR);
        if NtReleaseKeyedEvent.is_null() {
            return None;
        }
        let NtWaitForKeyedEvent =
            GetProcAddress(ntdll, b"NtWaitForKeyedEvent\0".as_ptr() as LPCSTR);
        if NtWaitForKeyedEvent.is_null() {
            return None;
        }

        let NtCreateKeyedEvent: extern "system" fn(
            KeyedEventHandle: HANDLE,
            DesiredAccess: ACCESS_MASK,
            ObjectAttributes: PVOID,
            Flags: ULONG,
        ) -> NTSTATUS = mem::transmute(NtCreateKeyedEvent);
        let mut handle = mem::uninitialized();
        let status = NtCreateKeyedEvent(
            &mut handle,
            GENERIC_READ | GENERIC_WRITE,
            ptr::null_mut(),
            0,
        );
        if status != STATUS_SUCCESS {
            return None;
        }

        Some(KeyedEvent {
            handle: &mut handle,
            NtReleaseKeyedEvent: mem::transmute(NtReleaseKeyedEvent),
            NtWaitForKeyedEvent: mem::transmute(NtWaitForKeyedEvent),
        })
    }

    pub unsafe fn prepare_park(&'static self, key: &AtomicUsize) {
        key.store(STATE_PARKED, Ordering::Relaxed);
    }

    pub unsafe fn timed_out(&'static self, key: &AtomicUsize) -> bool {
        key.load(Ordering::Relaxed) == STATE_TIMED_OUT
    }

    pub unsafe fn park(&'static self, key: &AtomicUsize) {
        let status = self.wait_for(key as *const _ as PVOID, ptr::null_mut());
        debug_assert_eq!(status, STATUS_SUCCESS);
    }

    pub unsafe fn park_until(&'static self, key: &AtomicUsize, timeout: Instant) -> bool {
        let now = Instant::now();
        if timeout <= now {
            // If another thread unparked us, we need to call
            // NtWaitForKeyedEvent otherwise that thread will stay stuck at
            // NtReleaseKeyedEvent.
            if key.swap(STATE_TIMED_OUT, Ordering::Relaxed) == STATE_UNPARKED {
                self.park(key);
                return true;
            }
            return false;
        }

        // NT uses a timeout in units of 100ns. We use a negative value to
        // indicate a relative timeout based on a monotonic clock.
        let mut nt_timeout: LARGE_INTEGER = mem::zeroed();
        let diff = timeout - now;
        let value = (diff.as_secs() as i64)
            .checked_mul(-10000000)
            .and_then(|x| x.checked_sub((diff.subsec_nanos() as i64 + 99) / 100));

        match value {
            Some(x) => *nt_timeout.QuadPart_mut() = x,
            None => {
                // Timeout overflowed, just sleep indefinitely
                self.park(key);
                return true;
            }
        };

        let status = self.wait_for(key as *const _ as PVOID, &mut nt_timeout);
        if status == STATUS_SUCCESS {
            return true;
        }
        debug_assert_eq!(status, STATUS_TIMEOUT);

        // If another thread unparked us, we need to call NtWaitForKeyedEvent
        // otherwise that thread will stay stuck at NtReleaseKeyedEvent.
        if key.swap(STATE_TIMED_OUT, Ordering::Relaxed) == STATE_UNPARKED {
            self.park(key);
            return true;
        }
        false
    }

    pub unsafe fn unpark_lock(&'static self, key: &AtomicUsize) -> UnparkHandle {
        // If the state was STATE_PARKED then we need to wake up the thread
        if key.swap(STATE_UNPARKED, Ordering::Relaxed) == STATE_PARKED {
            UnparkHandle {
                key: key,
                keyed_event: self,
            }
        } else {
            UnparkHandle {
                key: ptr::null(),
                keyed_event: self,
            }
        }
    }
}

impl Drop for KeyedEvent {
    fn drop(&mut self) {
        unsafe {
            let ok = CloseHandle(self.handle);
            debug_assert_eq!(ok, TRUE);
        }
    }
}

// Handle for a thread that is about to be unparked. We need to mark the thread
// as unparked while holding the queue lock, but we delay the actual unparking
// until after the queue lock is released.
pub struct UnparkHandle {
    key: *const AtomicUsize,
    keyed_event: &'static KeyedEvent,
}

impl UnparkHandle {
    // Wakes up the parked thread. This should be called after the queue lock is
    // released to avoid blocking the queue for too long.
    pub unsafe fn unpark(self) {
        if !self.key.is_null() {
            let status = self.keyed_event.release(self.key as PVOID);
            debug_assert_eq!(status, STATUS_SUCCESS);
        }
    }
}
<commit_msg>Fix prototype for NtCreateKeyedEvent<commit_after>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Instant;
use std::ptr;
use std::mem;

use winapi::shared::minwindef::{TRUE, ULONG};
use winapi::shared::ntdef::NTSTATUS;
use winapi::shared::ntstatus::{STATUS_SUCCESS, STATUS_TIMEOUT};
use winapi::um::handleapi::CloseHandle;
use winapi::um::libloaderapi::{GetModuleHandleA, GetProcAddress};
use winapi::um::winnt::{ACCESS_MASK, GENERIC_READ, GENERIC_WRITE, LPCSTR};
use winapi::um::winnt::{BOOLEAN, HANDLE, LARGE_INTEGER, PHANDLE, PLARGE_INTEGER, PVOID};

const STATE_UNPARKED: usize = 0;
const STATE_PARKED: usize = 1;
const STATE_TIMED_OUT: usize = 2;

#[allow(non_snake_case)]
pub struct KeyedEvent {
    handle: HANDLE,
    NtReleaseKeyedEvent: extern "system" fn(
        EventHandle: HANDLE,
        Key: PVOID,
        Alertable: BOOLEAN,
        Timeout: PLARGE_INTEGER,
    ) -> NTSTATUS,
    NtWaitForKeyedEvent: extern "system" fn(
        EventHandle: HANDLE,
        Key: PVOID,
        Alertable: BOOLEAN,
        Timeout: PLARGE_INTEGER,
    ) -> NTSTATUS,
}

impl KeyedEvent {
    unsafe fn wait_for(&self, key: PVOID, timeout: PLARGE_INTEGER) -> NTSTATUS {
        (self.NtWaitForKeyedEvent)(self.handle, key, 0, timeout)
    }

    unsafe fn release(&self, key: PVOID) -> NTSTATUS {
        (self.NtReleaseKeyedEvent)(self.handle, key, 0, ptr::null_mut())
    }

    #[allow(non_snake_case)]
    pub unsafe fn create() -> Option<KeyedEvent> {
        let ntdll = GetModuleHandleA(b"ntdll.dll\0".as_ptr() as LPCSTR);
        if ntdll.is_null() {
            return None;
        }

        let NtCreateKeyedEvent = GetProcAddress(ntdll, b"NtCreateKeyedEvent\0".as_ptr() as LPCSTR);
        if NtCreateKeyedEvent.is_null() {
            return None;
        }
        let NtReleaseKeyedEvent =
            GetProcAddress(ntdll, b"NtReleaseKeyedEvent\0".as_ptr() as LPCSTR);
        if NtReleaseKeyedEvent.is_null() {
            return None;
        }
        let NtWaitForKeyedEvent =
            GetProcAddress(ntdll, b"NtWaitForKeyedEvent\0".as_ptr() as LPCSTR);
        if NtWaitForKeyedEvent.is_null() {
            return None;
        }

        let NtCreateKeyedEvent: extern "system" fn(
            KeyedEventHandle: PHANDLE,
            DesiredAccess: ACCESS_MASK,
            ObjectAttributes: PVOID,
            Flags: ULONG,
        ) -> NTSTATUS = mem::transmute(NtCreateKeyedEvent);
        let mut handle = mem::uninitialized();
        let status = NtCreateKeyedEvent(
            &mut handle,
            GENERIC_READ | GENERIC_WRITE,
            ptr::null_mut(),
            0,
        );
        if status != STATUS_SUCCESS {
            return None;
        }

        Some(KeyedEvent {
            handle,
            NtReleaseKeyedEvent: mem::transmute(NtReleaseKeyedEvent),
            NtWaitForKeyedEvent: mem::transmute(NtWaitForKeyedEvent),
        })
    }

    pub unsafe fn prepare_park(&'static self, key: &AtomicUsize) {
        key.store(STATE_PARKED, Ordering::Relaxed);
    }

    pub unsafe fn timed_out(&'static self, key: &AtomicUsize) -> bool {
        key.load(Ordering::Relaxed) == STATE_TIMED_OUT
    }

    pub unsafe fn park(&'static self, key: &AtomicUsize) {
        let status = self.wait_for(key as *const _ as PVOID, ptr::null_mut());
        debug_assert_eq!(status, STATUS_SUCCESS);
    }

    pub unsafe fn park_until(&'static self, key: &AtomicUsize, timeout: Instant) -> bool {
        let now = Instant::now();
        if timeout <= now {
            // If another thread unparked us, we need to call
            // NtWaitForKeyedEvent otherwise that thread will stay stuck at
            // NtReleaseKeyedEvent.
            if key.swap(STATE_TIMED_OUT, Ordering::Relaxed) == STATE_UNPARKED {
                self.park(key);
                return true;
            }
            return false;
        }

        // NT uses a timeout in units of 100ns. We use a negative value to
        // indicate a relative timeout based on a monotonic clock.
        let mut nt_timeout: LARGE_INTEGER = mem::zeroed();
        let diff = timeout - now;
        let value = (diff.as_secs() as i64)
            .checked_mul(-10000000)
            .and_then(|x| x.checked_sub((diff.subsec_nanos() as i64 + 99) / 100));

        match value {
            Some(x) => *nt_timeout.QuadPart_mut() = x,
            None => {
                // Timeout overflowed, just sleep indefinitely
                self.park(key);
                return true;
            }
        };

        let status = self.wait_for(key as *const _ as PVOID, &mut nt_timeout);
        if status == STATUS_SUCCESS {
            return true;
        }
        debug_assert_eq!(status, STATUS_TIMEOUT);

        // If another thread unparked us, we need to call NtWaitForKeyedEvent
        // otherwise that thread will stay stuck at NtReleaseKeyedEvent.
        if key.swap(STATE_TIMED_OUT, Ordering::Relaxed) == STATE_UNPARKED {
            self.park(key);
            return true;
        }
        false
    }

    pub unsafe fn unpark_lock(&'static self, key: &AtomicUsize) -> UnparkHandle {
        // If the state was STATE_PARKED then we need to wake up the thread
        if key.swap(STATE_UNPARKED, Ordering::Relaxed) == STATE_PARKED {
            UnparkHandle {
                key: key,
                keyed_event: self,
            }
        } else {
            UnparkHandle {
                key: ptr::null(),
                keyed_event: self,
            }
        }
    }
}

impl Drop for KeyedEvent {
    fn drop(&mut self) {
        unsafe {
            let ok = CloseHandle(self.handle);
            debug_assert_eq!(ok, TRUE);
        }
    }
}

// Handle for a thread that is about to be unparked. We need to mark the thread
// as unparked while holding the queue lock, but we delay the actual unparking
// until after the queue lock is released.
pub struct UnparkHandle {
    key: *const AtomicUsize,
    keyed_event: &'static KeyedEvent,
}

impl UnparkHandle {
    // Wakes up the parked thread. This should be called after the queue lock is
    // released to avoid blocking the queue for too long.
    pub unsafe fn unpark(self) {
        if !self.key.is_null() {
            let status = self.keyed_event.release(self.key as PVOID);
            debug_assert_eq!(status, STATUS_SUCCESS);
        }
    }
}
<|endoftext|>