<commit_before>use super::TestDatabase;
use crate::db::CratesIoData;
use crate::docbuilder::BuildResult;
use crate::utils::{Dependency, MetadataPackage, Target};
use failure::Error;

#[must_use = "FakeRelease does nothing until you call .create()"]
pub(crate) struct FakeRelease<'a> {
    db: &'a TestDatabase,
    package: MetadataPackage,
    build_result: BuildResult,
    /// name, content
    source_files: Vec<(&'a str, &'a [u8])>,
    /// name, content
    rustdoc_files: Vec<(&'a str, &'a [u8])>,
    doc_targets: Vec<String>,
    default_target: Option<&'a str>,
    cratesio_data: CratesIoData,
    has_docs: bool,
    has_examples: bool,
}

impl<'a> FakeRelease<'a> {
    pub(super) fn new(db: &'a TestDatabase) -> Self {
        FakeRelease {
            db,
            package: MetadataPackage {
                id: "fake-package-id".into(),
                name: "fake-package".into(),
                version: "1.0.0".into(),
                license: Some("MIT".into()),
                repository: Some("https://git.example.com".into()),
                homepage: Some("https://www.example.com".into()),
                description: Some("Fake package".into()),
                documentation: Some("https://docs.example.com".into()),
                dependencies: vec![Dependency {
                    name: "fake-dependency".into(),
                    req: "^1.0.0".into(),
                    kind: None,
                }],
                targets: vec![Target::dummy_lib("fake_package".into(), None)],
                readme: None,
                keywords: vec!["fake".into(), "package".into()],
                authors: vec!["Fake Person <fake@example.com>".into()],
            },
            build_result: BuildResult {
                rustc_version: "rustc 2.0.0-nightly (000000000 1970-01-01)".into(),
                docsrs_version: "docs.rs 1.0.0 (000000000 1970-01-01)".into(),
                build_log: "It works!".into(),
                successful: true,
            },
            source_files: Vec::new(),
            rustdoc_files: Vec::new(),
            doc_targets: Vec::new(),
            default_target: None,
            cratesio_data: CratesIoData {
                release_time: time::get_time(),
                yanked: false,
                downloads: 0,
                owners: Vec::new(),
            },
            has_docs: true,
            has_examples: false,
        }
    }

    pub(crate) fn name(mut self, new: &str) -> Self {
        self.package.name = new.into();
        self.package.id = format!("{}-id", new);
        self.package.targets[0].name = new.into();
        self
    }

    pub(crate) fn version(mut self, new: &str) -> Self {
        self.package.version = new.into();
        self
    }

    pub(crate) fn build_result_successful(mut self, new: bool) -> Self {
        self.build_result.successful = new;
        self
    }

    pub(crate) fn cratesio_data_yanked(mut self, new: bool) -> Self {
        self.cratesio_data.yanked = new;
        self
    }

    pub(crate) fn rustdoc_file(mut self, path: &'a str, data: &'a [u8]) -> Self {
        self.rustdoc_files.push((path, data));
        self
    }

    pub(crate) fn source_file(mut self, path: &'a str, data: &'a [u8]) -> Self {
        self.source_files.push((path, data));
        self
    }

    pub(crate) fn default_target(mut self, target: &'a str) -> Self {
        self.default_target = Some(target);
        self
    }

    pub(crate) fn binary(mut self, bin: bool) -> Self {
        self.has_docs = !bin;
        if bin {
            for target in self.package.targets.iter_mut() {
                target.crate_types = vec!["bin".into()];
            }
        }
        self
    }

    pub(crate) fn add_platform<S: Into<String>>(mut self, platform: S) -> Self {
        let name = self.package.targets[0].name.clone();
        let target = Target::dummy_lib(name, Some(platform.into()));
        self.package.targets.push(target);
        self
    }

    pub(crate) fn create(self) -> Result<i32, Error> {
        use std::fs;
        use std::path::Path;

        let tempdir = tempdir::TempDir::new("docs.rs-fake")?;
        let package = self.package;
        let db = self.db;

        let upload_files = |prefix: &str, files: &[(&str, &[u8])], target: Option<&str>| {
            let mut path_prefix = tempdir.path().join(prefix);
            if let Some(target) = target {
                path_prefix.push(target);
            }
            fs::create_dir(&path_prefix)?;

            for (path, data) in files {
                // allow `src/main.rs`
                if let Some(parent) = Path::new(path).parent() {
                    fs::create_dir_all(path_prefix.join(parent))?;
                }
                let file = path_prefix.join(&path);
                log::debug!("writing file {}", file.display());
                fs::write(file, data)?;
            }

            let prefix = format!("{}/{}/{}/{}", prefix, package.name, package.version, target.unwrap_or(""));
            log::debug!("adding directory {} from {}", prefix, path_prefix.display());
            crate::db::add_path_into_database(&db.conn(), &prefix, path_prefix)
        };

        let index = [&package.name, "index.html"].join("/");
        let mut rustdoc_files = self.rustdoc_files;
        if package.is_library() && !rustdoc_files.iter().any(|(path, _)| path == &index) {
            rustdoc_files.push((&index, b"default index content"));
        }
        for (source_path, data) in &self.source_files {
            if source_path.starts_with("src/") {
                let updated = ["src", &package.name, &source_path[4..]].join("/");
                rustdoc_files.push((Box::leak(Box::new(updated)), data));
            }
        }
        let rustdoc_meta = upload_files("rustdoc", &rustdoc_files, None)?;
        log::debug!("added rustdoc files {}", rustdoc_meta);
        let source_meta = upload_files("source", &self.source_files, None)?;
        log::debug!("added source files {}", source_meta);

        for target in &package.targets[1..] {
            let platform = target.src_path.as_ref().unwrap();
            upload_files("rustdoc", &rustdoc_files, Some(platform))?;
            log::debug!("added platform files for {}", platform);
        }

        let release_id = crate::db::add_package_into_database(
            &db.conn(),
            &package,
            tempdir.path(),
            &self.build_result,
            self.default_target.unwrap_or("x86_64-unknown-linux-gnu"),
            Some(source_meta),
            self.doc_targets,
            &self.cratesio_data,
            self.has_docs,
            self.has_examples,
        )?;
        crate::db::add_build_into_database(&db.conn(), &release_id, &self.build_result)?;

        Ok(release_id)
    }
}
<commit_msg>Fix tests<commit_after>use super::TestDatabase;
use crate::db::CratesIoData;
use crate::docbuilder::BuildResult;
use crate::utils::{Dependency, MetadataPackage, Target};
use failure::Error;

#[must_use = "FakeRelease does nothing until you call .create()"]
pub(crate) struct FakeRelease<'a> {
    db: &'a TestDatabase,
    package: MetadataPackage,
    build_result: BuildResult,
    /// name, content
    source_files: Vec<(&'a str, &'a [u8])>,
    /// name, content
    rustdoc_files: Vec<(&'a str, &'a [u8])>,
    doc_targets: Vec<String>,
    default_target: Option<&'a str>,
    cratesio_data: CratesIoData,
    has_docs: bool,
    has_examples: bool,
}

impl<'a> FakeRelease<'a> {
    pub(super) fn new(db: &'a TestDatabase) -> Self {
        FakeRelease {
            db,
            package: MetadataPackage {
                id: "fake-package-id".into(),
                name: "fake-package".into(),
                version: "1.0.0".into(),
                license: Some("MIT".into()),
                repository: Some("https://git.example.com".into()),
                homepage: Some("https://www.example.com".into()),
                description: Some("Fake package".into()),
                documentation: Some("https://docs.example.com".into()),
                dependencies: vec![Dependency {
                    name: "fake-dependency".into(),
                    req: "^1.0.0".into(),
                    kind: None,
                }],
                targets: vec![Target::dummy_lib("fake_package".into(), None)],
                readme: None,
                keywords: vec!["fake".into(), "package".into()],
                authors: vec!["Fake Person <fake@example.com>".into()],
            },
            build_result: BuildResult {
                rustc_version: "rustc 2.0.0-nightly (000000000 1970-01-01)".into(),
                docsrs_version: "docs.rs 1.0.0 (000000000 1970-01-01)".into(),
                build_log: "It works!".into(),
                successful: true,
            },
            source_files: Vec::new(),
            rustdoc_files: Vec::new(),
            doc_targets: Vec::new(),
            default_target: None,
            cratesio_data: CratesIoData {
                release_time: time::get_time(),
                yanked: false,
                downloads: 0,
                owners: Vec::new(),
            },
            has_docs: true,
            has_examples: false,
        }
    }

    pub(crate) fn name(mut self, new: &str) -> Self {
        self.package.name = new.into();
        self.package.id = format!("{}-id", new);
        self.package.targets[0].name = new.into();
        self
    }

    pub(crate) fn version(mut self, new: &str) -> Self {
        self.package.version = new.into();
        self
    }

    pub(crate) fn build_result_successful(mut self, new: bool) -> Self {
        self.build_result.successful = new;
        self
    }

    pub(crate) fn cratesio_data_yanked(mut self, new: bool) -> Self {
        self.cratesio_data.yanked = new;
        self
    }

    pub(crate) fn rustdoc_file(mut self, path: &'a str, data: &'a [u8]) -> Self {
        self.rustdoc_files.push((path, data));
        self
    }

    pub(crate) fn source_file(mut self, path: &'a str, data: &'a [u8]) -> Self {
        self.source_files.push((path, data));
        self
    }

    pub(crate) fn default_target(mut self, target: &'a str) -> Self {
        self.default_target = Some(target);
        self
    }

    pub(crate) fn binary(mut self, bin: bool) -> Self {
        self.has_docs = !bin;
        if bin {
            for target in self.package.targets.iter_mut() {
                target.crate_types = vec!["bin".into()];
            }
        }
        self
    }

    pub(crate) fn add_platform<S: Into<String>>(mut self, platform: S) -> Self {
        let name = self.package.targets[0].name.clone();
        let target = Target::dummy_lib(name, Some(platform.into()));
        self.package.targets.push(target);
        self
    }

    pub(crate) fn create(self) -> Result<i32, Error> {
        use std::fs;
        use std::path::Path;

        let tempdir = tempdir::TempDir::new("docs.rs-fake")?;
        let package = self.package;
        let db = self.db;

        let upload_files = |prefix: &str, files: &[(&str, &[u8])], target: Option<&str>| {
            let mut path_prefix = tempdir.path().join(prefix);
            if let Some(target) = target {
                path_prefix.push(target);
            }
            fs::create_dir(&path_prefix)?;

            for (path, data) in files {
                // allow `src/main.rs`
                if let Some(parent) = Path::new(path).parent() {
                    fs::create_dir_all(path_prefix.join(parent))?;
                }
                let file = path_prefix.join(&path);
                log::debug!("writing file {}", file.display());
                fs::write(file, data)?;
            }

            let prefix = format!("{}/{}/{}/{}", prefix, package.name, package.version, target.unwrap_or(""));
            log::debug!("adding directory {} from {}", prefix, path_prefix.display());
            crate::db::add_path_into_database(&db.conn(), &prefix, path_prefix)
        };

        let index = [&package.name, "index.html"].join("/");
        let mut rustdoc_files = self.rustdoc_files;
        if package.is_library() && !rustdoc_files.iter().any(|(path, _)| path == &index) {
            rustdoc_files.push((&index, b"default index content"));
        }
        for (source_path, data) in &self.source_files {
            if source_path.starts_with("src/") {
                let updated = ["src", &package.name, &source_path[4..]].join("/");
                rustdoc_files.push((Box::leak(Box::new(updated)), data));
            }
        }
        let rustdoc_meta = upload_files("rustdoc", &rustdoc_files, None)?;
        log::debug!("added rustdoc files {}", rustdoc_meta);
        let source_meta = upload_files("source", &self.source_files, None)?;
        log::debug!("added source files {}", source_meta);

        for target in &package.targets[1..] {
            let platform = target.src_path.as_ref().unwrap();
            upload_files("rustdoc", &rustdoc_files, Some(platform))?;
            log::debug!("added platform files for {}", platform);
        }

        let release_id = crate::db::add_package_into_database(
            &db.conn(),
            &package,
            tempdir.path(),
            &self.build_result,
            self.default_target.unwrap_or("x86_64-unknown-linux-gnu"),
            Some(source_meta),
            self.doc_targets,
            &self.cratesio_data,
            self.has_docs,
            self.has_examples,
        )?;
        crate::db::add_build_into_database(&db.conn(), release_id, &self.build_result)?;

        Ok(release_id)
    }
}
<|endoftext|>


<commit_before>#![allow(
    clippy::boxed_local,
    clippy::ptr_arg,
    clippy::trivially_copy_pass_by_ref
)]

use cxx::{CxxString, UniquePtr};
use std::fmt::{self, Display};

#[cxx::bridge(namespace = tests)]
pub mod ffi {
    struct Shared {
        z: usize,
    }

    extern "C" {
        include!("tests/ffi/tests.h");

        type C;

        fn c_return_primitive() -> usize;
        fn c_return_shared() -> Shared;
        fn c_return_box() -> Box<R>;
        fn c_return_unique_ptr() -> UniquePtr<C>;
        fn c_return_ref(shared: &Shared) -> &usize;
        fn c_return_str(shared: &Shared) -> &str;
        fn c_return_sliceu8(shared: &Shared) -> &[u8];
        fn c_return_rust_string() -> String;
        fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
        fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
        fn c_return_unique_ptr_vector_f64() -> UniquePtr<CxxVector<f64>>;
        fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;

        fn c_take_primitive(n: usize);
        fn c_take_shared(shared: Shared);
        fn c_take_box(r: Box<R>);
        fn c_take_unique_ptr(c: UniquePtr<C>);
        fn c_take_ref_r(r: &R);
        fn c_take_ref_c(c: &C);
        fn c_take_str(s: &str);
        fn c_take_sliceu8(s: &[u8]);
        fn c_take_rust_string(s: String);
        fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
        fn c_take_unique_ptr_vector_u8(s: UniquePtr<CxxVector<u8>>);
        fn c_take_unique_ptr_vector_f64(s: UniquePtr<CxxVector<f64>>);
        fn c_take_unique_ptr_vector_shared(s: UniquePtr<CxxVector<Shared>>);
        fn c_take_vec_u8(v: &Vec<u8>);
        fn c_take_vec_shared(v: &Vec<Shared>);
        fn c_take_callback(callback: fn(String) -> usize);

        fn c_try_return_void() -> Result<()>;
        fn c_try_return_primitive() -> Result<usize>;
        fn c_fail_return_primitive() -> Result<usize>;
        fn c_try_return_box() -> Result<Box<R>>;
        fn c_try_return_ref(s: &String) -> Result<&String>;
        fn c_try_return_str(s: &str) -> Result<&str>;
        fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
        fn c_try_return_rust_string() -> Result<String>;
        fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;

        fn get(self: &C) -> usize;
        fn set(self: &mut C, n: usize) -> usize;
        fn get2(&self) -> usize;
        fn set2(&mut self, n: usize) -> usize;
    }

    extern "Rust" {
        type R;
        type R2;

        fn r_return_primitive() -> usize;
        fn r_return_shared() -> Shared;
        fn r_return_box() -> Box<R>;
        fn r_return_unique_ptr() -> UniquePtr<C>;
        fn r_return_ref(shared: &Shared) -> &usize;
        fn r_return_str(shared: &Shared) -> &str;
        fn r_return_rust_string() -> String;
        fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;

        fn r_take_primitive(n: usize);
        fn r_take_shared(shared: Shared);
        fn r_take_box(r: Box<R>);
        fn r_take_unique_ptr(c: UniquePtr<C>);
        fn r_take_ref_r(r: &R);
        fn r_take_ref_c(c: &C);
        fn r_take_str(s: &str);
        fn r_take_sliceu8(s: &[u8]);
        fn r_take_rust_string(s: String);
        fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);

        fn r_try_return_void() -> Result<()>;
        fn r_try_return_primitive() -> Result<usize>;
        fn r_fail_return_primitive() -> Result<usize>;

        fn r_return_r2(n: usize) -> Box<R2>;
        fn get(self: &R2) -> usize;
        fn set(self: &mut R2, n: usize) -> usize;
    }
}

pub type R = usize;

pub struct R2(usize);

impl R2 {
    fn get(&self) -> usize {
        self.0
    }

    fn set(&mut self, n: usize) -> usize {
        self.0 = n;
        n
    }
}

#[derive(Debug)]
struct Error;

impl std::error::Error for Error {}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("rust error")
    }
}

fn r_return_primitive() -> usize {
    2020
}

fn r_return_shared() -> ffi::Shared {
    ffi::Shared { z: 2020 }
}

fn r_return_box() -> Box<R> {
    Box::new(2020)
}

fn r_return_unique_ptr() -> UniquePtr<ffi::C> {
    extern "C" {
        fn cxx_test_suite_get_unique_ptr() -> *mut ffi::C;
    }
    unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr()) }
}

fn r_return_ref(shared: &ffi::Shared) -> &usize {
    &shared.z
}

fn r_return_str(shared: &ffi::Shared) -> &str {
    let _ = shared;
    "2020"
}

fn r_return_rust_string() -> String {
    "2020".to_owned()
}

fn r_return_unique_ptr_string() -> UniquePtr<CxxString> {
    extern "C" {
        fn cxx_test_suite_get_unique_ptr_string() -> *mut CxxString;
    }
    unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr_string()) }
}

fn r_take_primitive(n: usize) {
    assert_eq!(n, 2020);
}

fn r_take_shared(shared: ffi::Shared) {
    assert_eq!(shared.z, 2020);
}

fn r_take_box(r: Box<R>) {
    let _ = r;
}

fn r_take_unique_ptr(c: UniquePtr<ffi::C>) {
    let _ = c;
}

fn r_take_ref_r(r: &R) {
    let _ = r;
}

fn r_take_ref_c(c: &ffi::C) {
    let _ = c;
}

fn r_take_str(s: &str) {
    assert_eq!(s, "2020");
}

fn r_take_rust_string(s: String) {
    assert_eq!(s, "2020");
}

fn r_take_sliceu8(s: &[u8]) {
    assert_eq!(s.len(), 5);
    assert_eq!(std::str::from_utf8(s).unwrap(), "2020\0");
}

fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
    assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
}

fn r_try_return_void() -> Result<(), Error> {
    Ok(())
}

fn r_try_return_primitive() -> Result<usize, Error> {
    Ok(2020)
}

fn r_fail_return_primitive() -> Result<usize, Error> {
    Err(Error)
}

fn r_return_r2(n: usize) -> Box<R2> {
    Box::new(R2(n))
}
<commit_msg>Use more appropriate name for vector arguments in tests<commit_after>#![allow(
    clippy::boxed_local,
    clippy::ptr_arg,
    clippy::trivially_copy_pass_by_ref
)]

use cxx::{CxxString, UniquePtr};
use std::fmt::{self, Display};

#[cxx::bridge(namespace = tests)]
pub mod ffi {
    struct Shared {
        z: usize,
    }

    extern "C" {
        include!("tests/ffi/tests.h");

        type C;

        fn c_return_primitive() -> usize;
        fn c_return_shared() -> Shared;
        fn c_return_box() -> Box<R>;
        fn c_return_unique_ptr() -> UniquePtr<C>;
        fn c_return_ref(shared: &Shared) -> &usize;
        fn c_return_str(shared: &Shared) -> &str;
        fn c_return_sliceu8(shared: &Shared) -> &[u8];
        fn c_return_rust_string() -> String;
        fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
        fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
        fn c_return_unique_ptr_vector_f64() -> UniquePtr<CxxVector<f64>>;
        fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;

        fn c_take_primitive(n: usize);
        fn c_take_shared(shared: Shared);
        fn c_take_box(r: Box<R>);
        fn c_take_unique_ptr(c: UniquePtr<C>);
        fn c_take_ref_r(r: &R);
        fn c_take_ref_c(c: &C);
        fn c_take_str(s: &str);
        fn c_take_sliceu8(s: &[u8]);
        fn c_take_rust_string(s: String);
        fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
        fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
        fn c_take_unique_ptr_vector_f64(v: UniquePtr<CxxVector<f64>>);
        fn c_take_unique_ptr_vector_shared(v: UniquePtr<CxxVector<Shared>>);
        fn c_take_vec_u8(v: &Vec<u8>);
        fn c_take_vec_shared(v: &Vec<Shared>);
        fn c_take_callback(callback: fn(String) -> usize);

        fn c_try_return_void() -> Result<()>;
        fn c_try_return_primitive() -> Result<usize>;
        fn c_fail_return_primitive() -> Result<usize>;
        fn c_try_return_box() -> Result<Box<R>>;
        fn c_try_return_ref(s: &String) -> Result<&String>;
        fn c_try_return_str(s: &str) -> Result<&str>;
        fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
        fn c_try_return_rust_string() -> Result<String>;
        fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;

        fn get(self: &C) -> usize;
        fn set(self: &mut C, n: usize) -> usize;
        fn get2(&self) -> usize;
        fn set2(&mut self, n: usize) -> usize;
    }

    extern "Rust" {
        type R;
        type R2;

        fn r_return_primitive() -> usize;
        fn r_return_shared() -> Shared;
        fn r_return_box() -> Box<R>;
        fn r_return_unique_ptr() -> UniquePtr<C>;
        fn r_return_ref(shared: &Shared) -> &usize;
        fn r_return_str(shared: &Shared) -> &str;
        fn r_return_rust_string() -> String;
        fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;

        fn r_take_primitive(n: usize);
        fn r_take_shared(shared: Shared);
        fn r_take_box(r: Box<R>);
        fn r_take_unique_ptr(c: UniquePtr<C>);
        fn r_take_ref_r(r: &R);
        fn r_take_ref_c(c: &C);
        fn r_take_str(s: &str);
        fn r_take_sliceu8(s: &[u8]);
        fn r_take_rust_string(s: String);
        fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);

        fn r_try_return_void() -> Result<()>;
        fn r_try_return_primitive() -> Result<usize>;
        fn r_fail_return_primitive() -> Result<usize>;

        fn r_return_r2(n: usize) -> Box<R2>;
        fn get(self: &R2) -> usize;
        fn set(self: &mut R2, n: usize) -> usize;
    }
}

pub type R = usize;

pub struct R2(usize);

impl R2 {
    fn get(&self) -> usize {
        self.0
    }

    fn set(&mut self, n: usize) -> usize {
        self.0 = n;
        n
    }
}

#[derive(Debug)]
struct Error;

impl std::error::Error for Error {}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("rust error")
    }
}

fn r_return_primitive() -> usize {
    2020
}

fn r_return_shared() -> ffi::Shared {
    ffi::Shared { z: 2020 }
}

fn r_return_box() -> Box<R> {
    Box::new(2020)
}

fn r_return_unique_ptr() -> UniquePtr<ffi::C> {
    extern "C" {
        fn cxx_test_suite_get_unique_ptr() -> *mut ffi::C;
    }
    unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr()) }
}

fn r_return_ref(shared: &ffi::Shared) -> &usize {
    &shared.z
}

fn r_return_str(shared: &ffi::Shared) -> &str {
    let _ = shared;
    "2020"
}

fn r_return_rust_string() -> String {
    "2020".to_owned()
}

fn r_return_unique_ptr_string() -> UniquePtr<CxxString> {
    extern "C" {
        fn cxx_test_suite_get_unique_ptr_string() -> *mut CxxString;
    }
    unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr_string()) }
}

fn r_take_primitive(n: usize) {
    assert_eq!(n, 2020);
}

fn r_take_shared(shared: ffi::Shared) {
    assert_eq!(shared.z, 2020);
}

fn r_take_box(r: Box<R>) {
    let _ = r;
}

fn r_take_unique_ptr(c: UniquePtr<ffi::C>) {
    let _ = c;
}

fn r_take_ref_r(r: &R) {
    let _ = r;
}

fn r_take_ref_c(c: &ffi::C) {
    let _ = c;
}

fn r_take_str(s: &str) {
    assert_eq!(s, "2020");
}

fn r_take_rust_string(s: String) {
    assert_eq!(s, "2020");
}

fn r_take_sliceu8(s: &[u8]) {
    assert_eq!(s.len(), 5);
    assert_eq!(std::str::from_utf8(s).unwrap(), "2020\0");
}

fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
    assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
}

fn r_try_return_void() -> Result<(), Error> {
    Ok(())
}

fn r_try_return_primitive() -> Result<usize, Error> {
    Ok(2020)
}

fn r_fail_return_primitive() -> Result<usize, Error> {
    Err(Error)
}

fn r_return_r2(n: usize) -> Box<R2> {
    Box::new(R2(n))
}
<|endoftext|>


<commit_before>#[macro_use]
mod common;

use quickcheck::{quickcheck, Arbitrary, Gen};
use zmq::Message;

// A pair which contains two non-equal values
#[derive(Clone, Debug)]
struct NePair<T>(T, T);

impl<T> Arbitrary for NePair<T>
where
    T: Eq + Arbitrary,
{
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        let v1 = T::arbitrary(g);
        let v2 = (0..).map(|_| T::arbitrary(g)).find(|v| *v != v1).unwrap();
        NePair(v1, v2)
    }
}

quickcheck! {
    fn msg_cmp_eq(input: Vec<u8>) -> bool {
        Message::from(&input) == Message::from(&input)
    }

    fn msg_cmp_ne(input: NePair<Vec<u8>>) -> bool {
        Message::from(&input.0) != Message::from(&input.1)
    }

    fn msg_vec_roundtrip(input: Vec<u8>) -> bool {
        let original = Message::from(&input.clone());
        Message::from(input) == original
    }
}
<commit_msg>Fix a clippy warning<commit_after>#[macro_use]
mod common;

use quickcheck::{quickcheck, Arbitrary, Gen};
use zmq::Message;

// A pair which contains two non-equal values
#[derive(Clone, Debug)]
struct NePair<T>(T, T);

impl<T> Arbitrary for NePair<T>
where
    T: Eq + Arbitrary,
{
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        let v1 = T::arbitrary(g);
        let v2 = (0..).map(|_| T::arbitrary(g)).find(|v| *v != v1).unwrap();
        NePair(v1, v2)
    }
}

quickcheck! {
    fn msg_cmp_eq(input: Vec<u8>) -> bool {
        Message::from(&input) == Message::from(&input)
    }

    fn msg_cmp_ne(input: NePair<Vec<u8>>) -> bool {
        Message::from(&input.0) != Message::from(&input.1)
    }

    fn msg_vec_roundtrip(input: Vec<u8>) -> bool {
        let original = Message::from(&input);
        Message::from(input) == original
    }
}
<|endoftext|>


<commit_before>//! Wrapper for the `wlr_box` type.
//! Note that we renamed it to `Area` to avoid conflicts with Rust's Box.

use libc::{c_double, c_float, c_int};

use wlroots_sys::{wl_output_transform, wlr_box, wlr_box_closest_point, wlr_box_contains_point,
                  wlr_box_empty, wlr_box_intersection, wlr_box_rotated_bounds, wlr_box_transform};

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
/// Result of applying an intersection of two `Area`s.
pub enum IntersectionResult {
    /// This area is the intersection between the two points.
    Intersection(Area),
    /// There was not an intersection
    NoIntersection
}

#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
pub struct Origin {
    pub x: c_int,
    pub y: c_int
}

impl Origin {
    pub fn new(x: c_int, y: c_int) -> Self {
        Origin { x, y }
    }
}

impl Into<Area> for Origin {
    fn into(self) -> Area {
        Area::new(self, Size::default())
    }
}

#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
pub struct Size {
    pub width: c_int,
    pub height: c_int
}

impl Size {
    pub fn new(width: c_int, height: c_int) -> Self {
        Size { width, height }
    }
}

impl Into<Area> for Size {
    fn into(self) -> Area {
        Area::new(Origin::default(), self)
    }
}

#[derive(Debug, Clone, Copy, Default, Eq, PartialEq)]
/// Generic geometry-like struct. Container an origin (x, y) point and bounds
/// (width, height).
pub struct Area {
    pub origin: Origin,
    pub size: Size
}

impl Into<wlr_box> for Area {
    fn into(self) -> wlr_box {
        wlr_box { x: self.origin.x,
                  y: self.origin.y,
                  width: self.size.width,
                  height: self.size.height }
    }
}

impl Area {
    pub fn new(origin: Origin, size: Size) -> Self {
        Area { origin, size }
    }

    /// Construct an Area from a `wlr_box`.
    pub fn from_box(wlr_box: wlr_box) -> Self {
        Area { origin: Origin { x: wlr_box.x,
                                y: wlr_box.y },
               size: Size { width: wlr_box.width,
                            height: wlr_box.height } }
    }

    /// Makes a new `Area` with width and height set to the values in the given
    /// `Size`.
    pub fn with_size(self, size: Size) -> Self {
        Area { size, ..self }
    }

    /// Makes a new `Area` with x and y set to the value in the given `Origin`.
    pub fn with_origin(self, origin: Origin) -> Self {
        Area { origin, ..self }
    }

    /// Finds the closest point within the box to the given point.
    /// If the (x, y) point lies outside of the box, then it finds the closest
    /// corner and returns that.
    ///
    /// Returned value is in form of (x, y).
    pub fn closest_point(self, x: c_double, y: c_double) -> (c_double, c_double) {
        unsafe {
            let (mut dest_x, mut dest_y) = (0.0, 0.0);
            wlr_box_closest_point(&mut self.into(), x, y, &mut dest_x, &mut dest_y);
            (dest_x, dest_y)
        }
    }

    /// Gets the intersection of the two areas.
    pub fn intersection(self, other_box: Area) -> IntersectionResult {
        unsafe {
            let res = Area::default();
            let is_empty = wlr_box_intersection(&self.into(), &other_box.into(), &mut res.into());
            if is_empty {
                IntersectionResult::NoIntersection
            } else {
                IntersectionResult::Intersection(res)
            }
        }
    }

    /// Determines if the box contains the given point.
    pub fn contains_point(self, x: c_double, y: c_double) -> bool {
        unsafe { wlr_box_contains_point(&mut self.into(), x, y) }
    }

    /// Determines if the box is empty (e.g if the bounds give it an area of 0).
    pub fn is_empty(self) -> bool {
        unsafe { wlr_box_empty(&mut self.into()) }
    }

    /// Transforms the box coordinates and bounds according to the
    /// output transformation.
    ///
    /// e.g: If it's `WL_OUTPUT_TRANSFORM_90` then it will flip the Area 90° clockwise.
    pub fn transform(self, transform: wl_output_transform, width: c_int, height: c_int) -> Area {
        unsafe {
            let res = Area::default();
            wlr_box_transform(&mut self.into(), transform, width, height, &mut res.into());
            res
        }
    }

    /// Creates the smallest box that contains the box rotated about its center.
    pub fn rotated_bounds(self, rotation: c_float) -> Area {
        unsafe {
            let dest = Area::default();
            wlr_box_rotated_bounds(&self.into(), rotation, &mut dest.into());
            dest
        }
    }
}
<commit_msg>Use the now standard wlr_box call syntax<commit_after>//! Wrapper for the `wlr_box` type.
//! Note that we renamed it to `Area` to avoid conflicts with Rust's Box.

use libc::{c_double, c_float, c_int};

use wlroots_sys::{wl_output_transform, wlr_box, wlr_box_closest_point, wlr_box_contains_point,
                  wlr_box_empty, wlr_box_intersection, wlr_box_rotated_bounds, wlr_box_transform};

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
/// Result of applying an intersection of two `Area`s.
pub enum IntersectionResult {
    /// This area is the intersection between the two points.
    Intersection(Area),
    /// There was not an intersection
    NoIntersection
}

#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
pub struct Origin {
    pub x: c_int,
    pub y: c_int
}

impl Origin {
    pub fn new(x: c_int, y: c_int) -> Self {
        Origin { x, y }
    }
}

impl Into<Area> for Origin {
    fn into(self) -> Area {
        Area::new(self, Size::default())
    }
}

#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
pub struct Size {
    pub width: c_int,
    pub height: c_int
}

impl Size {
    pub fn new(width: c_int, height: c_int) -> Self {
        Size { width, height }
    }
}

impl Into<Area> for Size {
    fn into(self) -> Area {
        Area::new(Origin::default(), self)
    }
}

#[derive(Debug, Clone, Copy, Default, Eq, PartialEq)]
/// Generic geometry-like struct. Container an origin (x, y) point and bounds
/// (width, height).
pub struct Area {
    pub origin: Origin,
    pub size: Size
}

impl Into<wlr_box> for Area {
    fn into(self) -> wlr_box {
        wlr_box { x: self.origin.x,
                  y: self.origin.y,
                  width: self.size.width,
                  height: self.size.height }
    }
}

impl Area {
    pub fn new(origin: Origin, size: Size) -> Self {
        Area { origin, size }
    }

    /// Construct an Area from a `wlr_box`.
    pub fn from_box(wlr_box: wlr_box) -> Self {
        Area { origin: Origin { x: wlr_box.x,
                                y: wlr_box.y },
               size: Size { width: wlr_box.width,
                            height: wlr_box.height } }
    }

    /// Makes a new `Area` with width and height set to the values in the given
    /// `Size`.
    pub fn with_size(self, size: Size) -> Self {
        Area { size, ..self }
    }

    /// Makes a new `Area` with x and y set to the value in the given `Origin`.
    pub fn with_origin(self, origin: Origin) -> Self {
        Area { origin, ..self }
    }

    /// Finds the closest point within the box to the given point.
    /// If the (x, y) point lies outside of the box, then it finds the closest
    /// corner and returns that.
    ///
    /// Returned value is in form of (x, y).
    pub fn closest_point(self, x: c_double, y: c_double) -> (c_double, c_double) {
        unsafe {
            let (mut dest_x, mut dest_y) = (0.0, 0.0);
            wlr_box_closest_point(&mut self.into(), x, y, &mut dest_x, &mut dest_y);
            (dest_x, dest_y)
        }
    }

    /// Gets the intersection of the two areas.
    pub fn intersection(self, other_box: Area) -> IntersectionResult {
        unsafe {
            let res = Area::default();
            let is_empty = wlr_box_intersection(&mut res.into(), &self.into(), &other_box.into());
            if is_empty {
                IntersectionResult::NoIntersection
            } else {
                IntersectionResult::Intersection(res)
            }
        }
    }

    /// Determines if the box contains the given point.
    pub fn contains_point(self, x: c_double, y: c_double) -> bool {
        unsafe { wlr_box_contains_point(&mut self.into(), x, y) }
    }

    /// Determines if the box is empty (e.g if the bounds give it an area of 0).
    pub fn is_empty(self) -> bool {
        unsafe { wlr_box_empty(&mut self.into()) }
    }

    /// Transforms the box coordinates and bounds according to the
    /// output transformation.
    ///
    /// e.g: If it's `WL_OUTPUT_TRANSFORM_90` then it will flip the Area 90° clockwise.
    pub fn transform(self, transform: wl_output_transform, width: c_int, height: c_int) -> Area {
        unsafe {
            let res = Area::default();
            wlr_box_transform(&mut res.into(), &mut self.into(), transform, width, height);
            res
        }
    }

    /// Creates the smallest box that contains the box rotated about its center.
    pub fn rotated_bounds(self, rotation: c_float) -> Area {
        unsafe {
            let dest = Area::default();
            wlr_box_rotated_bounds(&mut dest.into(), &self.into(), rotation);
            dest
        }
    }
}
<|endoftext|>


<commit_before>use crate::cxx_vector::{CxxVector, VectorElement};
use crate::fmt::display;
use crate::kind::Trivial;
use crate::string::CxxString;
use crate::ExternType;
use core::ffi::c_void;
use core::fmt::{self, Debug, Display};
use core::marker::PhantomData;
use core::mem::{self, MaybeUninit};
use core::ops::{Deref, DerefMut};
use core::pin::Pin;

/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
#[repr(C)]
pub struct UniquePtr<T>
where
    T: UniquePtrTarget,
{
    repr: MaybeUninit<*mut c_void>,
    ty: PhantomData<T>,
}

impl<T> UniquePtr<T>
where
    T: UniquePtrTarget,
{
    /// Makes a new UniquePtr wrapping a null pointer.
    ///
    /// Matches the behavior of default-constructing a std::unique\_ptr.
    pub fn null() -> Self {
        UniquePtr {
            repr: T::__null(),
            ty: PhantomData,
        }
    }

    /// Allocates memory on the heap and makes a UniquePtr pointing to it.
    pub fn new(value: T) -> Self
    where
        T: ExternType<Kind = Trivial>,
    {
        UniquePtr {
            repr: T::__new(value),
            ty: PhantomData,
        }
    }

    /// Checks whether the UniquePtr does not own an object.
    ///
    /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
    pub fn is_null(&self) -> bool {
        let ptr = unsafe { T::__get(self.repr) };
        ptr.is_null()
    }

    /// Returns a reference to the object owned by this UniquePtr if any,
    /// otherwise None.
    pub fn as_ref(&self) -> Option<&T> {
        unsafe { T::__get(self.repr).as_ref() }
    }

    /// Returns a mutable pinned reference to the object owned by this UniquePtr
    /// if any, otherwise None.
    pub fn as_mut(&mut self) -> Option<Pin<&mut T>> {
        unsafe {
            let mut_reference = (T::__get(self.repr) as *mut T).as_mut()?;
            Some(Pin::new_unchecked(mut_reference))
        }
    }

    /// Returns a mutable pinned reference to the object owned by this
    /// UniquePtr.
    ///
    /// # Panics
    ///
    /// Panics if the UniquePtr holds a null pointer.
    pub fn pin_mut(&mut self) -> Pin<&mut T> {
        match self.as_mut() {
            Some(target) => target,
            None => panic!(
                "called pin_mut on a null UniquePtr<{}>",
                display(T::__typename),
            ),
        }
    }

    /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
    ///
    /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
    pub fn into_raw(self) -> *mut T {
        let ptr = unsafe { T::__release(self.repr) };
        mem::forget(self);
        ptr
    }

    /// Constructs a UniquePtr retaking ownership of a pointer previously
    /// obtained from `into_raw`.
    ///
    /// # Safety
    ///
    /// This function is unsafe because improper use may lead to memory
    /// problems. For example a double-free may occur if the function is called
    /// twice on the same raw pointer.
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        UniquePtr {
            repr: unsafe { T::__raw(raw) },
            ty: PhantomData,
        }
    }
}

unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}

impl<T> Drop for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    fn drop(&mut self) {
        unsafe { T::__drop(self.repr) }
    }
}

impl<T> Deref for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        match self.as_ref() {
            Some(target) => target,
            None => panic!(
                "called deref on a null UniquePtr<{}>",
                display(T::__typename),
            ),
        }
    }
}

impl<T> DerefMut for UniquePtr<T>
where
    T: UniquePtrTarget + Unpin,
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        match self.as_mut() {
            Some(target) => Pin::into_inner(target),
            None => panic!(
                "called deref_mut on a null UniquePtr<{}>",
                display(T::__typename),
            ),
        }
    }
}

impl<T> Debug for UniquePtr<T>
where
    T: Debug + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Debug::fmt(value, formatter),
        }
    }
}

impl<T> Display for UniquePtr<T>
where
    T: Display + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Display::fmt(value, formatter),
        }
    }
}

// UniquePtr is not a self-referential type and is safe to move out of a Pin,
// regardless whether the pointer's target is Unpin.
impl<T> Unpin for UniquePtr<T> where T: UniquePtrTarget {}

/// Trait bound for types which may be used as the `T` inside of a
/// `UniquePtr<T>` in generic code.
///
/// This trait has no publicly callable or implementable methods. Implementing
/// it outside of the CXX codebase is not supported.
///
/// # Example
///
/// A bound `T: UniquePtrTarget` may be necessary when manipulating
/// [`UniquePtr`] in generic code.
///
/// ```
/// use cxx::memory::{UniquePtr, UniquePtrTarget};
/// use std::fmt::Display;
///
/// pub fn take_generic_ptr<T>(ptr: UniquePtr<T>)
/// where
///     T: UniquePtrTarget + Display,
/// {
///     println!("the unique_ptr points to: {}", *ptr);
/// }
/// ```
///
/// Writing the same generic function without a `UniquePtrTarget` trait bound
/// would not compile.
pub unsafe trait UniquePtrTarget {
    #[doc(hidden)]
    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
    #[doc(hidden)]
    fn __null() -> MaybeUninit<*mut c_void>;
    #[doc(hidden)]
    fn __new(value: Self) -> MaybeUninit<*mut c_void>
    where
        Self: Sized,
    {
        // Opaque C types do not get this method because they can never exist by
        // value on the Rust side of the bridge.
        let _ = value;
        unreachable!()
    }
    #[doc(hidden)]
    unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>;
    #[doc(hidden)]
    unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self;
    #[doc(hidden)]
    unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self;
    #[doc(hidden)]
    unsafe fn __drop(repr: MaybeUninit<*mut c_void>);
}

extern "C" {
    #[link_name = "cxxbridge1$unique_ptr$std$string$null"]
    fn unique_ptr_std_string_null(this: *mut MaybeUninit<*mut c_void>);
    #[link_name = "cxxbridge1$unique_ptr$std$string$raw"]
    fn unique_ptr_std_string_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxString);
    #[link_name = "cxxbridge1$unique_ptr$std$string$get"]
    fn unique_ptr_std_string_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxString;
    #[link_name = "cxxbridge1$unique_ptr$std$string$release"]
    fn unique_ptr_std_string_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxString;
    #[link_name = "cxxbridge1$unique_ptr$std$string$drop"]
    fn unique_ptr_std_string_drop(this: *mut MaybeUninit<*mut c_void>);
}

unsafe impl UniquePtrTarget for CxxString {
    fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("CxxString")
    }
    fn __null() -> MaybeUninit<*mut c_void> {
        let mut repr = MaybeUninit::uninit();
        unsafe {
            unique_ptr_std_string_null(&mut repr);
        }
        repr
    }
    unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
        let mut repr = MaybeUninit::uninit();
        unsafe { unique_ptr_std_string_raw(&mut repr, raw) }
        repr
    }
    unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
        unsafe { unique_ptr_std_string_get(&repr) }
    }
    unsafe fn __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self {
        unsafe { unique_ptr_std_string_release(&mut repr) }
    }
    unsafe fn __drop(mut repr: MaybeUninit<*mut c_void>) {
        unsafe { unique_ptr_std_string_drop(&mut repr) }
    }
}

unsafe impl<T> UniquePtrTarget for CxxVector<T>
where
    T: VectorElement,
{
    fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "CxxVector<{}>", display(T::__typename))
    }
    fn __null() -> MaybeUninit<*mut c_void> {
        T::__unique_ptr_null()
    }
    unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
        unsafe { T::__unique_ptr_raw(raw) }
    }
    unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
        unsafe { T::__unique_ptr_get(repr) }
    }
    unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self {
        unsafe { T::__unique_ptr_release(repr) }
    }
    unsafe fn __drop(repr: MaybeUninit<*mut c_void>) {
        unsafe { T::__unique_ptr_drop(repr) }
    }
}
<commit_msg>Move Unpin impl near Drop impl<commit_after>use crate::cxx_vector::{CxxVector, VectorElement};
use crate::fmt::display;
use crate::kind::Trivial;
use crate::string::CxxString;
use crate::ExternType;
use core::ffi::c_void;
use core::fmt::{self, Debug, Display};
use core::marker::PhantomData;
use core::mem::{self, MaybeUninit};
use core::ops::{Deref, DerefMut};
use core::pin::Pin;

/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
#[repr(C)]
pub struct UniquePtr<T>
where
    T: UniquePtrTarget,
{
    repr: MaybeUninit<*mut c_void>,
    ty: PhantomData<T>,
}

impl<T> UniquePtr<T>
where
    T: UniquePtrTarget,
{
    /// Makes a new UniquePtr wrapping a null pointer.
    ///
    /// Matches the behavior of default-constructing a std::unique\_ptr.
    pub fn null() -> Self {
        UniquePtr {
            repr: T::__null(),
            ty: PhantomData,
        }
    }

    /// Allocates memory on the heap and makes a UniquePtr pointing to it.
    pub fn new(value: T) -> Self
    where
        T: ExternType<Kind = Trivial>,
    {
        UniquePtr {
            repr: T::__new(value),
            ty: PhantomData,
        }
    }

    /// Checks whether the UniquePtr does not own an object.
    ///
    /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
    pub fn is_null(&self) -> bool {
        let ptr = unsafe { T::__get(self.repr) };
        ptr.is_null()
    }

    /// Returns a reference to the object owned by this UniquePtr if any,
    /// otherwise None.
    pub fn as_ref(&self) -> Option<&T> {
        unsafe { T::__get(self.repr).as_ref() }
    }

    /// Returns a mutable pinned reference to the object owned by this UniquePtr
    /// if any, otherwise None.
    pub fn as_mut(&mut self) -> Option<Pin<&mut T>> {
        unsafe {
            let mut_reference = (T::__get(self.repr) as *mut T).as_mut()?;
            Some(Pin::new_unchecked(mut_reference))
        }
    }

    /// Returns a mutable pinned reference to the object owned by this
    /// UniquePtr.
    ///
    /// # Panics
    ///
    /// Panics if the UniquePtr holds a null pointer.
    pub fn pin_mut(&mut self) -> Pin<&mut T> {
        match self.as_mut() {
            Some(target) => target,
            None => panic!(
                "called pin_mut on a null UniquePtr<{}>",
                display(T::__typename),
            ),
        }
    }

    /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
    ///
    /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
    pub fn into_raw(self) -> *mut T {
        let ptr = unsafe { T::__release(self.repr) };
        mem::forget(self);
        ptr
    }

    /// Constructs a UniquePtr retaking ownership of a pointer previously
    /// obtained from `into_raw`.
    ///
    /// # Safety
    ///
    /// This function is unsafe because improper use may lead to memory
    /// problems. For example a double-free may occur if the function is called
    /// twice on the same raw pointer.
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        UniquePtr {
            repr: unsafe { T::__raw(raw) },
            ty: PhantomData,
        }
    }
}

unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}

// UniquePtr is not a self-referential type and is safe to move out of a Pin,
// regardless whether the pointer's target is Unpin.
impl<T> Unpin for UniquePtr<T> where T: UniquePtrTarget {}

impl<T> Drop for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    fn drop(&mut self) {
        unsafe { T::__drop(self.repr) }
    }
}

impl<T> Deref for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        match self.as_ref() {
            Some(target) => target,
            None => panic!(
                "called deref on a null UniquePtr<{}>",
                display(T::__typename),
            ),
        }
    }
}

impl<T> DerefMut for UniquePtr<T>
where
    T: UniquePtrTarget + Unpin,
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        match self.as_mut() {
            Some(target) => Pin::into_inner(target),
            None => panic!(
                "called deref_mut on a null UniquePtr<{}>",
                display(T::__typename),
            ),
        }
    }
}

impl<T> Debug for UniquePtr<T>
where
    T: Debug + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Debug::fmt(value, formatter),
        }
    }
}

impl<T> Display for UniquePtr<T>
where
    T: Display + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Display::fmt(value, formatter),
        }
    }
}

/// Trait bound for types which may be used as the `T` inside of a
/// `UniquePtr<T>` in generic code.
///
/// This trait has no publicly callable or implementable methods. Implementing
/// it outside of the CXX codebase is not supported.
///
/// # Example
///
/// A bound `T: UniquePtrTarget` may be necessary when manipulating
/// [`UniquePtr`] in generic code.
///
/// ```
/// use cxx::memory::{UniquePtr, UniquePtrTarget};
/// use std::fmt::Display;
///
/// pub fn take_generic_ptr<T>(ptr: UniquePtr<T>)
/// where
///     T: UniquePtrTarget + Display,
/// {
///     println!("the unique_ptr points to: {}", *ptr);
/// }
/// ```
///
/// Writing the same generic function without a `UniquePtrTarget` trait bound
/// would not compile.
pub unsafe trait UniquePtrTarget {
    #[doc(hidden)]
    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
    #[doc(hidden)]
    fn __null() -> MaybeUninit<*mut c_void>;
    #[doc(hidden)]
    fn __new(value: Self) -> MaybeUninit<*mut c_void>
    where
        Self: Sized,
    {
        // Opaque C types do not get this method because they can never exist by
        // value on the Rust side of the bridge.
        let _ = value;
        unreachable!()
    }
    #[doc(hidden)]
    unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>;
    #[doc(hidden)]
    unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self;
    #[doc(hidden)]
    unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self;
    #[doc(hidden)]
    unsafe fn __drop(repr: MaybeUninit<*mut c_void>);
}

extern "C" {
    #[link_name = "cxxbridge1$unique_ptr$std$string$null"]
    fn unique_ptr_std_string_null(this: *mut MaybeUninit<*mut c_void>);
    #[link_name = "cxxbridge1$unique_ptr$std$string$raw"]
    fn unique_ptr_std_string_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxString);
    #[link_name = "cxxbridge1$unique_ptr$std$string$get"]
    fn unique_ptr_std_string_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxString;
    #[link_name = "cxxbridge1$unique_ptr$std$string$release"]
    fn unique_ptr_std_string_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxString;
    #[link_name = "cxxbridge1$unique_ptr$std$string$drop"]
    fn unique_ptr_std_string_drop(this: *mut MaybeUninit<*mut c_void>);
}

unsafe impl UniquePtrTarget for CxxString {
    fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("CxxString")
    }
    fn __null() -> MaybeUninit<*mut c_void> {
        let mut repr = MaybeUninit::uninit();
        unsafe {
            unique_ptr_std_string_null(&mut repr);
        }
        repr
    }
    unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
        let mut repr = MaybeUninit::uninit();
        unsafe { unique_ptr_std_string_raw(&mut repr, raw) }
        repr
    }
    unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
        unsafe { unique_ptr_std_string_get(&repr) }
    }
    unsafe fn __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self {
        unsafe { unique_ptr_std_string_release(&mut repr) }
    }
    unsafe fn __drop(mut repr: MaybeUninit<*mut c_void>) {
        unsafe { unique_ptr_std_string_drop(&mut repr) }
    }
}

unsafe impl<T> UniquePtrTarget for CxxVector<T>
where
    T: VectorElement,
{
    fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "CxxVector<{}>", display(T::__typename))
    }
    fn __null() -> MaybeUninit<*mut c_void> {
        T::__unique_ptr_null()
    }
    unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
        unsafe { T::__unique_ptr_raw(raw) }
    }
    unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
        unsafe { T::__unique_ptr_get(repr) }
    }
    unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self {
        unsafe { T::__unique_ptr_release(repr) }
    }
    unsafe fn __drop(repr: MaybeUninit<*mut c_void>) {
        unsafe { T::__unique_ptr_drop(repr) }
    }
}
<|endoftext|>


<commit_before>use {node, routing, time, hash, storage};
use std::collections::VecDeque;
use std::str::FromStr;
use std::net;
use node::receptions;

pub const POLL_FREQUENCY_MS: u64 = 50;
pub const TRIES: u8 = 5;

#[test]
fn node_ping() {
   let alpha = node::Node::new().unwrap();
   let beta  = node::Node::new().unwrap();
   let beta_seed = beta.resources.local_info();
   let span = time::Duration::seconds(1);

   // Bootstrapping alpha:
   assert!(alpha.bootstrap_until(beta_seed, 1).is_ok());

   let beta_receptions = beta.receptions()
      .during(span)
      .from(alpha.id().clone())
      .of_kind(receptions::KindFilter::Ping);

   // Alpha pings beta.
   assert!(alpha.resources.ping(&beta.local_info()).is_ok());
   assert_eq!(1, beta_receptions.count());
}

#[test]
fn reception_iterator_times_out_correctly() {
   let alpha = node::Node::new().unwrap();
   let span = time::Duration::seconds(1);
   let maximum = time::Duration::seconds(3);
   let receptions = alpha.receptions().during(span);

   let before = time::SteadyTime::now();

   // nothing is happening, so this should time out in around a second (not necessarily precise)
   assert_eq!(0, receptions.count());

   let after = time::SteadyTime::now();

   assert!(after - before < maximum);
}

#[test]
fn bootstrapping_and_finding_on_simulated_network() {
   let mut nodes = simulated_network(30);

   // Head finds tail in a few steps.
   let head = nodes.pop_front().unwrap();
   let tail = nodes.pop_back().unwrap();

   assert_eq!(head.resources.locate(tail.id()).unwrap().id, tail.resources.local_info().id);
}

#[test]
fn finding_on_simulated_unresponsive_network() {

   let mut nodes = simulated_network(30);
   nodes.drain(10..20);
   assert_eq!(nodes.len(), 20);

   // Head finds tail in a few steps.
   let head = nodes.pop_front().unwrap();
   let tail = nodes.pop_back().unwrap();

   assert_eq!(head.resources.locate(tail.id()).unwrap().id, tail.resources.local_info().id);
}

#[test]
#[ignore]
fn finding_a_nonexisting_node_in_a_simulated_network_times_out() {

   let mut nodes = simulated_network(30);

   // Head finds tail in a few steps.
   let head = nodes.pop_front().unwrap();

   let random_hash = hash::SubotaiHash::random();
   assert!(head.resources.locate(&random_hash).is_err());
}

fn simulated_network(network_size: usize) -> VecDeque<node::Node> {
   let nodes: VecDeque<node::Node> = (0..network_size).map(|_| { node::Node::new().unwrap() }).collect();
   {
      let origin = nodes.front().unwrap();
      // Initial handshake pass
      for node in nodes.iter().skip(1) {
         assert!(node.bootstrap_until(origin.resources.local_info(), 1).is_ok());
      }

      for node in nodes.iter().skip(1) {
         assert!(node.bootstrap(origin.resources.local_info()).is_ok());
      }
   }
   nodes
}

#[test]
fn updating_table_with_full_bucket_starts_the_conflict_resolution_mechanism()
{
   let node = node::Node::new().unwrap();
   node.resources.table.fill_bucket(8, routing::K_FACTOR as u8); // Bucket completely full

   let mut id = node.id().clone();
   id.flip_bit(8);
   id.raw[0] = 0xFF;
   let info = node_info_no_net(id);

   node.resources.update_table(info);
   assert_eq!(node.resources.conflicts.lock().unwrap().len(), 1);
}

#[test]
fn generating_a_conflict_causes_a_ping_to_the_evicted_node()
{
   let alpha = node::Node::new().unwrap();
   let beta = node::Node::new().unwrap();
   alpha.resources.update_table(beta.resources.local_info());

   let index = alpha.resources.table.bucket_for_node(beta.id());

   // We fill the bucket corresponding to Beta until we are ready to cause a conflict.
   alpha.resources.table.fill_bucket(index, (routing::K_FACTOR -1) as u8);

   // We expect a ping to beta
   let pings = beta.receptions()
      .of_kind(receptions::KindFilter::Ping)
      .during(time::Duration::seconds(2));

   // Adding a new node causes a conflict.
   let mut id = beta.id().clone();
   id.raw[0] = 0xFF;
   let info = node_info_no_net(id);
   alpha.resources.update_table(info);

   assert_eq!(pings.count(), 1);
}

#[test]
fn generating_too_many_conflicts_causes_the_node_to_enter_defensive_state()
{
   let node = node::Node::new().unwrap();

   for index in 0..(routing::K_FACTOR + routing::MAX_CONFLICTS) {
      let mut id = node.id().clone();
      id.flip_bit(140); // Arbitrary bucket
      id.raw[0] = index as u8;
      let info = node_info_no_net(id);
      node.resources.update_table(info);
   }

   let state = *node.resources.state.read().unwrap();
   match state {
      node::State::Defensive => (),
      _ => panic!(),
   }

   // Trying to add new conflictive nodes while in defensive state will fail.
   let mut id = node.id().clone();
   id.flip_bit(140); // Arbitrary bucket
   id.raw[0] = 0xFF;
   let info = node_info_no_net(id.clone());

   node.resources.update_table(info);
   assert!(node.resources.table.specific_node(&id).is_none());

   // However, if they would fall in a different bucket, it's ok.
   id.flip_bit(155);
   let info = node_info_no_net(id.clone());
   node.resources.update_table(info);
   assert!(node.resources.table.specific_node(&id).is_some());
}

#[test]
fn remote_key_value_storage()
{
   let alpha = node::Node::new().unwrap();
   let beta  = node::Node::new().unwrap();

   assert!(alpha.bootstrap_until(beta.resources.local_info(), 1).is_ok());

   let key = hash::SubotaiHash::random();
   let value = hash::SubotaiHash::random();
   let mut beta_receptions =
      beta.receptions()
          .of_kind(receptions::KindFilter::Store)
          .during(time::Duration::seconds(1));

   let mut alpha_receptions =
      alpha.receptions()
           .of_kind(receptions::KindFilter::StoreResponse)
           .during(time::Duration::seconds(1));

   assert_eq!(alpha.resources.store_remotely(&beta.resources.local_info(), key.clone(), value.clone()).unwrap(),
              storage::StoreResult::Success);
   assert!(alpha_receptions.next().is_some());
   assert!(beta_receptions.next().is_some());

   let retrieved_value = beta.resources.storage.get(&key).unwrap();
   assert_eq!(value, retrieved_value);
}

#[test]
fn node_probing_in_simulated_network()
{
   let mut nodes = simulated_network(40);
   // We manually collect the info tags of all nodes.
   let mut info_nodes: Vec<routing::NodeInfo> = nodes
      .iter()
      .map(|ref node| node.resources.local_info())
      .collect();

   let head = nodes.pop_front().unwrap();
   let tail = nodes.pop_back().unwrap();
   let probe_results = head.resources.probe(tail.id(), routing::K_FACTOR).unwrap();

   // We sort our manual collection by distance to the tail node.
   info_nodes.sort_by(|ref info_a, ref info_b| (&info_a.id ^ tail.id()).cmp(&(&info_b.id ^ tail.id())));
   info_nodes.truncate(routing::K_FACTOR); // This guarantees us the closest ids to the tail

   assert_eq!(info_nodes.len(), probe_results.len());

   for (a, b) in probe_results.iter().zip(info_nodes.iter()) {
      assert_eq!(a.id, b.id);
   }
}

#[test]
fn node_probing_in_simulated_unresponsive_network()
{
   let mut nodes = simulated_network(40);
   // We manually collect the info tags of all nodes.
   let mut info_nodes: Vec<routing::NodeInfo> = nodes
      .iter()
      .map(|ref node| node.resources.local_info())
      .collect();

   nodes.drain(10..20);
   let head = nodes.pop_front().unwrap();
   let tail = nodes.pop_back().unwrap();
   let probe_results = head.resources.probe(tail.id(), routing::K_FACTOR).unwrap();

   // We sort our manual collection by distance to the tail node.
   info_nodes.sort_by(|ref info_a, ref info_b| (&info_a.id ^ tail.id()).cmp(&(&info_b.id ^ tail.id())));
   info_nodes.truncate(routing::K_FACTOR); // This guarantees us the closest ids to the tail

   assert_eq!(info_nodes.len(), probe_results.len());
   for (a, b) in probe_results.iter().zip(info_nodes.iter()) {
      assert_eq!(a.id, b.id);
   }
}

#[test]
fn store_retrieve_in_simulated_network()
{
   let mut nodes = simulated_network(40);
   let (key,value) = (hash::SubotaiHash::random(), hash::SubotaiHash::random());
   let head = nodes.pop_front().unwrap();
   let tail = nodes.pop_back().unwrap();

   head.store(&key, &value).unwrap();
   let retrieved_value = tail.retrieve(&key).unwrap();;

   assert_eq!(value, retrieved_value);
}

fn node_info_no_net(id : hash::SubotaiHash) -> routing::NodeInfo {
   routing::NodeInfo {
      id : id,
      address : net::SocketAddr::from_str("0.0.0.0:0").unwrap(),
   }
}
<commit_msg>WIP debugging a store_retrieve test<commit_after>use {node, routing, time, hash, storage};
use std::collections::VecDeque;
use std::str::FromStr;
use std::net;
use node::receptions;

pub const POLL_FREQUENCY_MS: u64 = 50;
pub const TRIES: u8 = 5;

#[test]
fn node_ping() {
   let alpha = node::Node::new().unwrap();
   let beta  = node::Node::new().unwrap();
   let beta_seed = beta.resources.local_info();
   let span = time::Duration::seconds(1);

   // Bootstrapping alpha:
   assert!(alpha.bootstrap_until(beta_seed, 1).is_ok());

   let beta_receptions = beta.receptions()
      .during(span)
      .from(alpha.id().clone())
      .of_kind(receptions::KindFilter::Ping);

   // Alpha pings beta.
   assert!(alpha.resources.ping(&beta.local_info()).is_ok());
   assert_eq!(1, beta_receptions.count());
}

#[test]
fn reception_iterator_times_out_correctly() {
   let alpha = node::Node::new().unwrap();
   let span = time::Duration::seconds(1);
   let maximum = time::Duration::seconds(3);
   let receptions = alpha.receptions().during(span);

   let before = time::SteadyTime::now();

   // nothing is happening, so this should time out in around a second (not necessarily precise)
   assert_eq!(0, receptions.count());

   let after = time::SteadyTime::now();

   assert!(after - before < maximum);
}

#[test]
fn bootstrapping_and_finding_on_simulated_network() {
   let mut nodes = simulated_network(30);

   // Head finds tail in a few steps.
   let head = nodes.pop_front().unwrap();
   let tail = nodes.pop_back().unwrap();

   assert_eq!(head.resources.locate(tail.id()).unwrap().id, tail.resources.local_info().id);
}

#[test]
fn finding_on_simulated_unresponsive_network() {

   let mut nodes = simulated_network(30);
   nodes.drain(10..20);
   assert_eq!(nodes.len(), 20);

   // Head finds tail in a few steps.
   let head = nodes.pop_front().unwrap();
   let tail = nodes.pop_back().unwrap();

   assert_eq!(head.resources.locate(tail.id()).unwrap().id, tail.resources.local_info().id);
}

#[test]
#[ignore]
fn finding_a_nonexisting_node_in_a_simulated_network_times_out() {

   let mut nodes = simulated_network(30);

   // Head finds tail in a few steps.
   let head = nodes.pop_front().unwrap();

   let random_hash = hash::SubotaiHash::random();
   assert!(head.resources.locate(&random_hash).is_err());
}

fn simulated_network(network_size: usize) -> VecDeque<node::Node> {
   let nodes: VecDeque<node::Node> = (0..network_size).map(|_| { node::Node::new().unwrap() }).collect();
   {
      let origin = nodes.front().unwrap();
      // Initial handshake pass
      for node in nodes.iter().skip(1) {
         assert!(node.bootstrap_until(origin.resources.local_info(), 1).is_ok());
      }

      for node in nodes.iter().skip(1) {
         assert!(node.bootstrap(origin.resources.local_info()).is_ok());
      }
   }
   nodes
}

#[test]
fn updating_table_with_full_bucket_starts_the_conflict_resolution_mechanism()
{
   let node = node::Node::new().unwrap();
   node.resources.table.fill_bucket(8, routing::K_FACTOR as u8); // Bucket completely full

   let mut id = node.id().clone();
   id.flip_bit(8);
   id.raw[0] = 0xFF;
   let info = node_info_no_net(id);

   node.resources.update_table(info);
   assert_eq!(node.resources.conflicts.lock().unwrap().len(), 1);
}

#[test]
fn generating_a_conflict_causes_a_ping_to_the_evicted_node()
{
   let alpha = node::Node::new().unwrap();
   let beta = node::Node::new().unwrap();
   alpha.resources.update_table(beta.resources.local_info());

   let index = alpha.resources.table.bucket_for_node(beta.id());

   // We fill the bucket corresponding to Beta until we are ready to cause a conflict.
   alpha.resources.table.fill_bucket(index, (routing::K_FACTOR -1) as u8);

   // We expect a ping to beta
   let pings = beta.receptions()
      .of_kind(receptions::KindFilter::Ping)
      .during(time::Duration::seconds(2));

   // Adding a new node causes a conflict.
   let mut id = beta.id().clone();
   id.raw[0] = 0xFF;
   let info = node_info_no_net(id);
   alpha.resources.update_table(info);

   assert_eq!(pings.count(), 1);
}

#[test]
fn generating_too_many_conflicts_causes_the_node_to_enter_defensive_state()
{
   let node = node::Node::new().unwrap();

   for index in 0..(routing::K_FACTOR + routing::MAX_CONFLICTS) {
      let mut id = node.id().clone();
      id.flip_bit(140); // Arbitrary bucket
      id.raw[0] = index as u8;
      let info = node_info_no_net(id);
      node.resources.update_table(info);
   }

   let state = *node.resources.state.read().unwrap();
   match state {
      node::State::Defensive => (),
      _ => panic!(),
   }

   // Trying to add new conflictive nodes while in defensive state will fail.
   let mut id = node.id().clone();
   id.flip_bit(140); // Arbitrary bucket
   id.raw[0] = 0xFF;
   let info = node_info_no_net(id.clone());

   node.resources.update_table(info);
   assert!(node.resources.table.specific_node(&id).is_none());

   // However, if they would fall in a different bucket, it's ok.
   id.flip_bit(155);
   let info = node_info_no_net(id.clone());
   node.resources.update_table(info);
   assert!(node.resources.table.specific_node(&id).is_some());
}

#[test]
fn remote_key_value_storage()
{
   let alpha = node::Node::new().unwrap();
   let beta  = node::Node::new().unwrap();

   assert!(alpha.bootstrap_until(beta.resources.local_info(), 1).is_ok());

   let key = hash::SubotaiHash::random();
   let value = hash::SubotaiHash::random();
   let mut beta_receptions =
      beta.receptions()
          .of_kind(receptions::KindFilter::Store)
          .during(time::Duration::seconds(1));

   let mut alpha_receptions =
      alpha.receptions()
           .of_kind(receptions::KindFilter::StoreResponse)
           .during(time::Duration::seconds(1));

   assert_eq!(alpha.resources.store_remotely(&beta.resources.local_info(), key.clone(), value.clone()).unwrap(),
              storage::StoreResult::Success);
   assert!(alpha_receptions.next().is_some());
   assert!(beta_receptions.next().is_some());

   let retrieved_value = beta.resources.storage.get(&key).unwrap();
   assert_eq!(value, retrieved_value);
}

#[test]
fn node_probing_in_simulated_network()
{
   let mut nodes = simulated_network(40);
   // We manually collect the info tags of all nodes.
   let mut info_nodes: Vec<routing::NodeInfo> = nodes
      .iter()
      .map(|ref node| node.resources.local_info())
      .collect();

   let head = nodes.pop_front().unwrap();
   let tail = nodes.pop_back().unwrap();
   let probe_results = head.resources.probe(tail.id(), routing::K_FACTOR).unwrap();

   // We sort our manual collection by distance to the tail node.
   info_nodes.sort_by(|ref info_a, ref info_b| (&info_a.id ^ tail.id()).cmp(&(&info_b.id ^ tail.id())));
   info_nodes.truncate(routing::K_FACTOR); // This guarantees us the closest ids to the tail

   assert_eq!(info_nodes.len(), probe_results.len());

   for (a, b) in probe_results.iter().zip(info_nodes.iter()) {
      assert_eq!(a.id, b.id);
   }
}

#[test]
fn node_probing_in_simulated_unresponsive_network()
{
   let mut nodes = simulated_network(40);
   // We manually collect the info tags of all nodes.
   let mut info_nodes: Vec<routing::NodeInfo> = nodes
      .iter()
      .map(|ref node| node.resources.local_info())
      .collect();

   nodes.drain(10..20);
   let head = nodes.pop_front().unwrap();
   let tail = nodes.pop_back().unwrap();
   let probe_results = head.resources.probe(tail.id(), routing::K_FACTOR).unwrap();

   // We sort our manual collection by distance to the tail node.
   info_nodes.sort_by(|ref info_a, ref info_b| (&info_a.id ^ tail.id()).cmp(&(&info_b.id ^ tail.id())));
   info_nodes.truncate(routing::K_FACTOR); // This guarantees us the closest ids to the tail

   assert_eq!(info_nodes.len(), probe_results.len());
   for (a, b) in probe_results.iter().zip(info_nodes.iter()) {
      assert_eq!(a.id, b.id);
   }
}

#[test]
fn store_retrieve_in_tiny_network()
{
   let alpha = node::Node::new().unwrap();
   let beta = node::Node::new().unwrap();

   alpha.bootstrap_until(beta.local_info(), 1);

   let (key, value) = (hash::SubotaiHash::random(), hash::SubotaiHash::random());

   alpha.store(&key, &value).unwrap();
   assert_eq!(beta.retrieve(&key).unwrap(), value);
}

#[test]
fn store_retrieve_in_simulated_network()
{
   let mut nodes = simulated_network(40);
   let (key,value) = (hash::SubotaiHash::random(), hash::SubotaiHash::random());
   let head = nodes.pop_front().unwrap();
   let tail = nodes.pop_back().unwrap();

   head.store(&key, &value).unwrap();
   let retrieved_value = tail.retrieve(&key).unwrap();

   assert_eq!(value, retrieved_value);
}

fn node_info_no_net(id : hash::SubotaiHash) -> routing::NodeInfo {
   routing::NodeInfo {
      id : id,
      address : net::SocketAddr::from_str("0.0.0.0:0").unwrap(),
   }
}
<|endoftext|>


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

use cargo::ops;
use cargo::util::print_available_packages;

pub fn cli() -> App {
    subcommand("pkgid")
        .about("Print a fully qualified package specification")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(Arg::with_name("spec"))
        .arg_package("Argument to get the package ID specifier for")
        .arg_manifest_path()
        .after_help("Run `cargo help pkgid` for more detailed information.\n")
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;
    if !args.is_present("spec") && args.is_present_with_zero_values("package") {
        print_available_packages(&ws)?
    }
    let spec = args.value_of("spec").or_else(|| args.value_of("package"));
    let spec = ops::pkgid(&ws, spec)?;
    cargo::drop_println!(config, "{}", spec);
    Ok(())
}
<commit_msg>fix: remove unnecessary arg value existence check<commit_after>use crate::command_prelude::*;

use cargo::ops;
use cargo::util::print_available_packages;

pub fn cli() -> App {
    subcommand("pkgid")
        .about("Print a fully qualified package specification")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(Arg::with_name("spec"))
        .arg_package("Argument to get the package ID specifier for")
        .arg_manifest_path()
        .after_help("Run `cargo help pkgid` for more detailed information.\n")
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;
    if args.is_present_with_zero_values("package") {
        print_available_packages(&ws)?
    }
    let spec = args.value_of("spec").or_else(|| args.value_of("package"));
    let spec = ops::pkgid(&ws, spec)?;
    cargo::drop_println!(config, "{}", spec);
    Ok(())
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use url::form_urlencoded;
use groupable::Groupable;

pub fn parse (encoded_string : &str) -> HashMap<String, Vec<String>> {
    form_urlencoded::parse_str(encoded_string).into_iter().group()
}

#[test]
fn parses_encoded_string_with_duplicate_keys() {
    let map = parse("foo=bar&message=hello&message=world");
    assert_eq!(map["foo".to_string()],
                vec!["bar".to_string()]);
    // Ensure the ordering is correct
    assert_eq!(map["message".to_string()],
                vec!["hello".to_string(), "world".to_string()]);
}

#[test]
fn parses_urlencoded_characters() {
    let map = parse("message=hello%20world");

    assert_eq!(map["message".to_string()],
                vec!["hello world".to_string()]);
}
<commit_msg>fix(url): parse_str(s) is now parse(s.as_bytes())<commit_after>use std::collections::HashMap;
use url::form_urlencoded;
use groupable::Groupable;

pub fn parse (encoded_string : &str) -> HashMap<String, Vec<String>> {
    form_urlencoded::parse(encoded_string.as_bytes()).into_iter().group()
}

#[test]
fn parses_encoded_string_with_duplicate_keys() {
    let map = parse("foo=bar&message=hello&message=world");
    assert_eq!(map["foo".to_string()],
                vec!["bar".to_string()]);
    // Ensure the ordering is correct
    assert_eq!(map["message".to_string()],
                vec!["hello".to_string(), "world".to_string()]);
}

#[test]
fn parses_urlencoded_characters() {
    let map = parse("message=hello%20world");

    assert_eq!(map["message".to_string()],
                vec!["hello world".to_string()]);
}
<|endoftext|>


<commit_before>
/// Ensures alignment of at least 16 bytes.
#[repr(C, align(16))]
pub struct Align16<T>(pub T);

/// Ensures alignment of at least 512 bytes.
#[repr(C, align(512))]
pub struct Align512<T>(pub T);

/// Ensures alignment of at least 4K bytes.
#[repr(C, align(4096))]
pub struct Align4K<T>(pub T);

/// Helper to implement generic alignment operator.
pub trait AlignTo {
	type TAlign;
	/// Aligns the given value to a multiple of the align value.
	///
	/// Debug asserts that align is a power of two, otherwise calculates an incorrect result.
	fn align_to(self, align: Self::TAlign) -> Self;
	/// Checks if the given value is aligned to a multiple of the align value.
	///
	/// Debug asserts that align is a power of two, otherwise calculates an incorrect result.
	fn aligned_to(self, align: Self::TAlign) -> bool;
}

macro_rules! impl_align_to {
	($ty:ty) => {
		impl AlignTo for $ty {
			type TAlign = $ty;
			#[inline(always)]
			fn align_to(self, align: $ty) -> $ty {
				debug_assert!(align.is_power_of_two(), "align ({:#x}) is not a power of two", align);
				let mask = align - 1;
				self.wrapping_add(mask) & !mask
			}
			#[inline(always)]
			fn aligned_to(self, align: $ty) -> bool {
				debug_assert!(align.is_power_of_two(), "align ({:#x}) is not a power of two", align);
				let mask = align - 1;
				self & mask == 0
			}
		}
	};
}
impl_align_to!(u8);
impl_align_to!(u16);
impl_align_to!(u32);
impl_align_to!(u64);
impl_align_to!(u128);
impl_align_to!(usize);

impl<T> AlignTo for *const T {
	type TAlign = usize;
	#[inline(always)]
	fn align_to(self, align: usize) -> *const T {
		(self as usize).align_to(align) as *const T
	}
	#[inline(always)]
	fn aligned_to(self, align: usize) -> bool {
		(self as usize).aligned_to(align)
	}
}

impl<T> AlignTo for *mut T {
	type TAlign = usize;
	#[inline(always)]
	fn align_to(self, align: usize) -> *mut T {
		(self as usize).align_to(align) as *mut T
	}
	#[inline(always)]
	fn aligned_to(self, align: usize) -> bool {
		(self as usize).aligned_to(align)
	}
}

#[test]
fn test_align_to() {
	assert_eq!(0, 0_u32.align_to(256_u32));
	assert_eq!(0, (!0_u32).align_to(256_u32));
	assert_eq!(128, 65_u32.align_to(64_u32));
	assert_eq!(64, 64_u32.align_to(64_u32));
}
<commit_msg>Remove Align structs (#240)<commit_after>
/// Helper to implement generic alignment operator.
pub trait AlignTo {
	type TAlign;
	/// Aligns the given value to a multiple of the align value.
	///
	/// Debug asserts that align is a power of two, otherwise calculates an incorrect result.
	fn align_to(self, align: Self::TAlign) -> Self;
	/// Checks if the given value is aligned to a multiple of the align value.
	///
	/// Debug asserts that align is a power of two, otherwise calculates an incorrect result.
	fn aligned_to(self, align: Self::TAlign) -> bool;
}

macro_rules! impl_align_to {
	($ty:ty) => {
		impl AlignTo for $ty {
			type TAlign = $ty;
			#[inline(always)]
			fn align_to(self, align: $ty) -> $ty {
				debug_assert!(align.is_power_of_two(), "align ({:#x}) is not a power of two", align);
				let mask = align - 1;
				self.wrapping_add(mask) & !mask
			}
			#[inline(always)]
			fn aligned_to(self, align: $ty) -> bool {
				debug_assert!(align.is_power_of_two(), "align ({:#x}) is not a power of two", align);
				let mask = align - 1;
				self & mask == 0
			}
		}
	};
}
impl_align_to!(u8);
impl_align_to!(u16);
impl_align_to!(u32);
impl_align_to!(u64);
impl_align_to!(u128);
impl_align_to!(usize);

impl<T> AlignTo for *const T {
	type TAlign = usize;
	#[inline(always)]
	fn align_to(self, align: usize) -> *const T {
		(self as usize).align_to(align) as *const T
	}
	#[inline(always)]
	fn aligned_to(self, align: usize) -> bool {
		(self as usize).aligned_to(align)
	}
}

impl<T> AlignTo for *mut T {
	type TAlign = usize;
	#[inline(always)]
	fn align_to(self, align: usize) -> *mut T {
		(self as usize).align_to(align) as *mut T
	}
	#[inline(always)]
	fn aligned_to(self, align: usize) -> bool {
		(self as usize).aligned_to(align)
	}
}

#[test]
fn test_align_to() {
	assert_eq!(0, 0_u32.align_to(256_u32));
	assert_eq!(0, (!0_u32).align_to(256_u32));
	assert_eq!(128, 65_u32.align_to(64_u32));
	assert_eq!(64, 64_u32.align_to(64_u32));
}
<|endoftext|>


<commit_before>// -*- rust-indent-offset: 2 -*-
// More compact, just for slides.

use std::iter::Iterator;

/// Convenient type synonym for a common pattern of usage.
/// More generally, Vec could be replaced by a Semigroup (Add).
pub type Validation<T, E> = Result<T, Vec<E>>;

#[inline]
pub fn single<T, E>(result: Result<T, E>) -> Validation<T, E> {
  result.map_err(|e| vec![e])
}

/// Combine successful results with `f`, but accumulate errors.
/// Important: any error causes the whole result to be an error!
///
/// Optimization trick: mutate result1's error vector.
pub fn add_with<V, T, U, E, F>(result1: Validation<V, E>,
                               result2: Validation<T, E>,
                               f: F) -> Validation<U, E>
  where F: Fn(V, T) -> U
{
  match (result1, result2) {
    (Ok(v),       Ok(t))   => Ok(f(v, t)),
    (Ok(..),      Err(e2)) => Err(e2),
    (Err(e1),     Ok(..))  => Err(e1),
    (Err(mut e1), Err(e2)) => Err({ e1.extend(e2.into_iter()); e1 })
  }
}

/// Combine a stream of Result to a Validation, accumulating successes.
///
/// Optimization trick: mutate success vector.
pub fn combine_results<T,
                       E,
                       I>(iter: I)
  -> Validation<Vec<T>, E> where
  I: Iterator<Item = Result<T, E>>
{
  iter.map(single)
      .fold(Ok(vec![]),
            |v, t|
            add_with(v, t,
                     |mut x, y| {
                       x.push(y);
                       x
                     }))
}
<commit_msg>Relax Fn to FnOnce.<commit_after>// -*- rust-indent-offset: 2 -*-
// More compact, just for slides.

use std::iter::Iterator;

/// Convenient type synonym for a common pattern of usage.
/// More generally, Vec could be replaced by a Semigroup (Add).
pub type Validation<T, E> = Result<T, Vec<E>>;

#[inline]
pub fn single<T, E>(result: Result<T, E>) -> Validation<T, E> {
  result.map_err(|e| vec![e])
}

/// Combine successful results with `f`, but accumulate errors.
/// Important: any error causes the whole result to be an error!
///
/// Optimization trick: mutate result1's error vector.
pub fn add_with<V, T, U, E, F>(result1: Validation<V, E>,
                               result2: Validation<T, E>,
                               f: F) -> Validation<U, E>
  where F: FnOnce(V, T) -> U
{
  match (result1, result2) {
    (Ok(v),       Ok(t))   => Ok(f(v, t)),
    (Ok(..),      Err(e2)) => Err(e2),
    (Err(e1),     Ok(..))  => Err(e1),
    (Err(mut e1), Err(e2)) => Err({ e1.extend(e2.into_iter()); e1 })
  }
}

/// Combine a stream of Result to a Validation, accumulating successes.
///
/// Optimization trick: mutate success vector.
pub fn combine_results<T,
                       E,
                       I>(iter: I)
  -> Validation<Vec<T>, E> where
  I: Iterator<Item = Result<T, E>>
{
  iter.map(single)
      .fold(Ok(vec![]),
            |v, t|
            add_with(v, t,
                     |mut x, y| {
                       x.push(y);
                       x
                     }))
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017-2018 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

use imgui::{ImMouseButton, Ui};

use model::bitboard::BitBoardExt;
use model::{FieldCoord, Model, Move};
use view::board_parts::*;
use view::vec2::Vec2;
use view::Event;

const SQRT_3: f32 = 1.732_050_807_568_877_f32;

// Color format is 0xaa_bb_gg_rr
const SELECT_HIGHLIGHT: u32 = 0xcc_35_bf_ff;
const LAST_MOVE_HIGHLIGHT: u32 = 0xc3_49_f8_f2;
/// The highlight for a piece capture by surrounding or exchanging.
const CAPTURE_HIGHLIGHT: u32 = 0xcf_40_40_ff;

/// The alpha used for a removed hex and any highlights on it.
const REMOVED_HEX_ALPHA: u8 = 0x50;
const EXTANT_HEX_ALPHA: u8 = 0xff;

pub fn board(ui: &Ui, model: &Model, size: Vec2) -> Option<Event> {
    let mouse_click = ui.imgui().is_mouse_clicked(ImMouseButton::Left);
    let mouse_pos = Vec2::from(ui.imgui().mouse_pos());
    let cursor_pos = Vec2::from(ui.get_cursor_screen_pos());

    let side_len = {
        // hex_spacing  =          m * side_len + b
        // board_width  =          8 * side_len + 6 * SQRT_3 * hex_spacing
        // board_height = 5 * SQRT_3 * side_len +          4 * hex_spacing
        let (m, b) = HEX_SPACING_COEFF;
        let width = (size.x - 6.0 * SQRT_3 * b) / (8.0 + 6.0 * SQRT_3 * m);
        let height = (size.y - 4.0 * b) / (5.0 * SQRT_3 + 4.0 * m);

        width.min(height)
    };
    let origin = cursor_pos + size / 2.0;

    let extant_hexes = model.board.extant_hexes();

    for hex in &extant_hexes {
        draw_hex(ui, EXTANT_HEX_ALPHA, hex, origin, side_len);
    }

    if let Some(ref mv) = model.last_move {
        for hex in &mv.removed_hexes {
            draw_hex(ui, REMOVED_HEX_ALPHA, &hex, origin, side_len);
        }

        for piece in &mv.removed_pieces {
            let color = if model.board.is_hex_extant(piece.to_hex().to_index()) {
                CAPTURE_HIGHLIGHT
            } else {
                set_alpha(CAPTURE_HIGHLIGHT, REMOVED_HEX_ALPHA)
            };
            draw_field(ui, color, piece, origin, side_len);
        }

        if let Move::Move(from, to, color) = mv.mv {
            let from_color = if model.board.is_hex_extant(from.to_index()) {
                LAST_MOVE_HIGHLIGHT
            } else {
                set_alpha(LAST_MOVE_HIGHLIGHT, REMOVED_HEX_ALPHA)
            };

            let from = FieldCoord::from_bitboard(from, color);
            draw_field(ui, from_color, &from, origin, side_len);

            let to = FieldCoord::from_bitboard(to, color);
            draw_field(ui, LAST_MOVE_HIGHLIGHT, &to, origin, side_len);
        }
    }

    if let Some(ref coord) = model.selected_piece {
        draw_field(ui, SELECT_HIGHLIGHT, coord, origin, side_len);
        for coord in model.board.available_moves_for_piece(coord) {
            draw_field_dot(ui, SELECT_HIGHLIGHT, &coord, origin, side_len);
        }
    }

    let mut hover_field = pixel_to_field(mouse_pos, origin, side_len);
    if !hover_field
        .map(|field| model.board.is_hex_extant(field.to_hex().to_index()))
        .unwrap_or(false)
    {
        hover_field = None;
    }
    if let Some(ref coord) = hover_field {
        if model.exchanging
            && coord.color() != model.board.turn
            && model.board.is_piece_on_field(coord)
        {
            draw_field(ui, CAPTURE_HIGHLIGHT, coord, origin, side_len);
        }
    }

    for hex in &extant_hexes {
        for f in 0..6 {
            let coord = hex.to_field(f);
            if model.board.is_piece_on_field(&coord) {
                draw_piece(ui, &coord, origin, side_len);
            }
        }
    }

    ui.dummy(size);

    if mouse_click {
        hover_field.map(Event::Click)
    } else {
        None
    }
}
<commit_msg>Use Option::filter<commit_after>/*
 * Copyright (C) 2017-2018 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

use imgui::{ImMouseButton, Ui};

use model::bitboard::BitBoardExt;
use model::{FieldCoord, Model, Move};
use view::board_parts::*;
use view::vec2::Vec2;
use view::Event;

const SQRT_3: f32 = 1.732_050_807_568_877_f32;

// Color format is 0xaa_bb_gg_rr
const SELECT_HIGHLIGHT: u32 = 0xcc_35_bf_ff;
const LAST_MOVE_HIGHLIGHT: u32 = 0xc3_49_f8_f2;
/// The highlight for a piece capture by surrounding or exchanging.
const CAPTURE_HIGHLIGHT: u32 = 0xcf_40_40_ff;

/// The alpha used for a removed hex and any highlights on it.
const REMOVED_HEX_ALPHA: u8 = 0x50;
const EXTANT_HEX_ALPHA: u8 = 0xff;

pub fn board(ui: &Ui, model: &Model, size: Vec2) -> Option<Event> {
    let mouse_click = ui.imgui().is_mouse_clicked(ImMouseButton::Left);
    let mouse_pos = Vec2::from(ui.imgui().mouse_pos());
    let cursor_pos = Vec2::from(ui.get_cursor_screen_pos());

    let side_len = {
        // hex_spacing  =          m * side_len + b
        // board_width  =          8 * side_len + 6 * SQRT_3 * hex_spacing
        // board_height = 5 * SQRT_3 * side_len +          4 * hex_spacing
        let (m, b) = HEX_SPACING_COEFF;
        let width = (size.x - 6.0 * SQRT_3 * b) / (8.0 + 6.0 * SQRT_3 * m);
        let height = (size.y - 4.0 * b) / (5.0 * SQRT_3 + 4.0 * m);

        width.min(height)
    };
    let origin = cursor_pos + size / 2.0;

    let extant_hexes = model.board.extant_hexes();

    for hex in &extant_hexes {
        draw_hex(ui, EXTANT_HEX_ALPHA, hex, origin, side_len);
    }

    if let Some(ref mv) = model.last_move {
        for hex in &mv.removed_hexes {
            draw_hex(ui, REMOVED_HEX_ALPHA, &hex, origin, side_len);
        }

        for piece in &mv.removed_pieces {
            let color = if model.board.is_hex_extant(piece.to_hex().to_index()) {
                CAPTURE_HIGHLIGHT
            } else {
                set_alpha(CAPTURE_HIGHLIGHT, REMOVED_HEX_ALPHA)
            };
            draw_field(ui, color, piece, origin, side_len);
        }

        if let Move::Move(from, to, color) = mv.mv {
            let from_color = if model.board.is_hex_extant(from.to_index()) {
                LAST_MOVE_HIGHLIGHT
            } else {
                set_alpha(LAST_MOVE_HIGHLIGHT, REMOVED_HEX_ALPHA)
            };

            let from = FieldCoord::from_bitboard(from, color);
            draw_field(ui, from_color, &from, origin, side_len);

            let to = FieldCoord::from_bitboard(to, color);
            draw_field(ui, LAST_MOVE_HIGHLIGHT, &to, origin, side_len);
        }
    }

    if let Some(ref coord) = model.selected_piece {
        draw_field(ui, SELECT_HIGHLIGHT, coord, origin, side_len);
        for coord in model.board.available_moves_for_piece(coord) {
            draw_field_dot(ui, SELECT_HIGHLIGHT, &coord, origin, side_len);
        }
    }

    let hover_field = pixel_to_field(mouse_pos, origin, side_len)
        .filter(|field| model.board.is_hex_extant(field.to_hex().to_index()));

    if let Some(ref coord) = hover_field {
        if model.exchanging
            && coord.color() != model.board.turn
            && model.board.is_piece_on_field(coord)
        {
            draw_field(ui, CAPTURE_HIGHLIGHT, coord, origin, side_len);
        }
    }

    for hex in &extant_hexes {
        for f in 0..6 {
            let coord = hex.to_field(f);
            if model.board.is_piece_on_field(&coord) {
                draw_piece(ui, &coord, origin, side_len);
            }
        }
    }

    ui.dummy(size);

    hover_field.filter(|_| mouse_click).map(Event::Click)
}
<|endoftext|>


<commit_before>pub mod text;
<commit_msg>Added combinators to parser module.<commit_after>pub mod combinators;
<|endoftext|>


<commit_before>pub mod number;
pub mod identifier;
<commit_msg>Add the expression module to the main lib<commit_after>pub mod number;
pub mod identifier;
pub mod expression;
<|endoftext|>


<commit_before>use super::SlotClock;

#[derive(Debug, PartialEq)]
pub enum Error {}

/// Determines the present slot based upon the present system time.
pub struct TestingSlotClock {
    slot: u64,
}

impl TestingSlotClock {
    /// Create a new `TestingSlotClock`.
    ///
    /// Returns an Error if `slot_duration_seconds == 0`.
    pub fn new(slot: u64) -> TestingSlotClock {
        TestingSlotClock { slot }
    }

    pub fn set_slot(&mut self, slot: u64) {
        self.slot = slot;
    }
}

impl SlotClock for TestingSlotClock {
    type Error = Error;

    fn present_slot(&self) -> Result<Option<u64>, Error> {
        Ok(Some(self.slot))
    }
}

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

    #[test]
    fn test_slot_now() {
        let mut clock = TestingSlotClock::new(10);
        assert_eq!(clock.present_slot(), Ok(Some(10)));
        clock.set_slot(123);
        assert_eq!(clock.present_slot(), Ok(Some(123)));
    }
}
<commit_msg>Make TestingSlotClock thread-safe<commit_after>use super::SlotClock;
use std::sync::RwLock;

#[derive(Debug, PartialEq)]
pub enum Error {}

/// Determines the present slot based upon the present system time.
pub struct TestingSlotClock {
    slot: RwLock<u64>,
}

impl TestingSlotClock {
    /// Create a new `TestingSlotClock`.
    ///
    /// Returns an Error if `slot_duration_seconds == 0`.
    pub fn new(slot: u64) -> TestingSlotClock {
        TestingSlotClock {
            slot: RwLock::new(slot),
        }
    }

    pub fn set_slot(&self, slot: u64) {
        *self.slot.write().expect("TestingSlotClock poisoned.") = slot;
    }
}

impl SlotClock for TestingSlotClock {
    type Error = Error;

    fn present_slot(&self) -> Result<Option<u64>, Error> {
        let slot = *self.slot.read().expect("TestingSlotClock poisoned.");
        Ok(Some(slot))
    }
}

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

    #[test]
    fn test_slot_now() {
        let clock = TestingSlotClock::new(10);
        assert_eq!(clock.present_slot(), Ok(Some(10)));
        clock.set_slot(123);
        assert_eq!(clock.present_slot(), Ok(Some(123)));
    }
}
<|endoftext|>