<commit_before>mod package_update_worker;
mod rolling_update_worker;

use self::{package_update_worker::PackageUpdateWorker,
           rolling_update_worker::RollingUpdateWorker};
use crate::{census::CensusRing,
            manager::service::{Service,
                               UpdateStrategy}};
use futures::future::{self,
                      AbortHandle};
use habitat_common::outputln;
use habitat_core::{package::PackageIdent,
                   service::ServiceGroup};
use parking_lot::{Mutex,
                  RwLock};
use std::{self,
          collections::HashMap,
          future::Future,
          sync::Arc,
          time::Duration};

static LOGKEY: &str = "SU";

/// A handle to an update worker that automatically aborts the worker when dropped.
struct Worker(AbortHandle);

impl Drop for Worker {
    fn drop(&mut self) { self.0.abort(); }
}

/// The `ServiceUpdater` is in charge of updating a Service when a change in version of a package
/// has been published to a depot channel or installed to the local package cache. To use an update
/// strategy, the supervisor must be configured to watch a depot for new versions.
pub struct ServiceUpdater {
    butterfly:   habitat_butterfly::Server,
    census_ring: Arc<RwLock<CensusRing>>,
    updates:     Arc<Mutex<HashMap<ServiceGroup, PackageIdent>>>,
    workers:     HashMap<ServiceGroup, Worker>,
    period:      Duration,
}

impl ServiceUpdater {
    pub fn new(butterfly: habitat_butterfly::Server,
               census_ring: Arc<RwLock<CensusRing>>,
               period: Duration)
               -> Self {
        ServiceUpdater { butterfly,
                         census_ring,
                         updates: Arc::default(),
                         workers: HashMap::new(),
                         period }
    }

    /// Register a service for updates. If the service has already
    /// been registered, the old worker is removed and a new one is
    /// started in its place.
    pub fn register(&mut self, service: &Service) {
        // Defensivly remove the service to prevent multiple update workers from running.
        self.remove(&service.service_group);
        // Determine what kind of worker we should use
        let service_group = service.service_group.clone();
        match service.update_strategy() {
            UpdateStrategy::None => {}
            UpdateStrategy::AtOnce => {
                let worker = self.at_once_worker(service);
                self.spawn_worker(service_group, worker);
            }
            UpdateStrategy::Rolling => {
                let worker = self.rolling_worker(service, Arc::clone(&self.census_ring));
                self.spawn_worker(service_group, worker);
            }
        };
    }

    /// Unregister a service from updates (eg if the service was unloaded).
    pub fn remove(&mut self, service_group: &ServiceGroup) {
        self.workers.remove(service_group);
        self.updates.lock().remove(service_group);
    }

    /// Check if this service has an update. If it does return the package ident of the update.
    ///
    /// Once an update is detected, this function will always return an update until the service is
    /// removed from the `ServiceUpdater`. The expectation is that when an update is detected the
    /// service will be restarted inorder for the update to take effect. As part of this restart,
    /// the service should be removed from the `ServiceUpdater`.
    pub fn has_update(&self, service_group: &ServiceGroup) -> Option<PackageIdent> {
        self.updates.lock().get(service_group).cloned()
    }

    fn at_once_worker(&mut self, service: &Service) -> impl Future<Output = ()> + Send + 'static {
        debug!("'{}' service updater spawning at-once worker watching for changes to '{}' from \
                channel '{}'",
               service.service_group,
               service.spec_ident(),
               service.channel());
        let service_group = service.service_group.clone();
        let full_ident = service.pkg.ident.clone();
        let updates = Arc::clone(&self.updates);
        let package_update_worker = PackageUpdateWorker::new(service, self.period);
        async move {
            let new_ident = package_update_worker.update().await;
            debug!("'{}' at-once updater found update from '{}' to '{}'",
                   service_group, full_ident, new_ident);
            Self::update_message(&new_ident, full_ident.as_ref());
            updates.lock().insert(service_group, new_ident);
        }
    }

    fn rolling_worker(&mut self,
                      service: &Service,
                      census_ring: Arc<RwLock<CensusRing>>)
                      -> impl Future<Output = ()> + Send + 'static {
        debug!("'{}' service updater spawning rolling worker watching for changes to '{}' from \
                channel '{}'",
               service.service_group,
               service.spec_ident(),
               service.channel());
        let service_group = service.service_group.clone();
        let full_ident = service.pkg.ident.clone();
        let updates = Arc::clone(&self.updates);
        let worker =
            RollingUpdateWorker::new(service, census_ring, self.butterfly.clone(), self.period);
        async move {
            let new_ident = worker.run().await;
            debug!("'{}' rolling updater found update from '{}' to '{}'",
                   service_group, full_ident, new_ident);
            Self::update_message(&new_ident, full_ident.as_ref());
            updates.lock().insert(service_group, new_ident);
        }
    }

    fn update_message(new_ident: &PackageIdent, current_ident: &PackageIdent) {
        if new_ident > current_ident {
            outputln!("Updating from {} to {}", current_ident, new_ident);
        } else {
            outputln!("Rolling back from {} to {}", current_ident, new_ident);
        }
    }

    /// Make the worker abortable and spawn it
    fn spawn_worker(&mut self,
                    service_group: ServiceGroup,
                    worker: impl Future<Output = ()> + Send + 'static) {
        let (worker, abort_handle) = future::abortable(worker);
        self.workers.insert(service_group, Worker(abort_handle));
        tokio::spawn(worker);
    }
}
<commit_msg>Add some debug logging to the service updater<commit_after>mod package_update_worker;
mod rolling_update_worker;

use self::{package_update_worker::PackageUpdateWorker,
           rolling_update_worker::RollingUpdateWorker};
use crate::{census::CensusRing,
            manager::service::{Service,
                               UpdateStrategy}};
use futures::future::{self,
                      AbortHandle};
use habitat_common::outputln;
use habitat_core::{package::PackageIdent,
                   service::ServiceGroup};
use parking_lot::{Mutex,
                  RwLock};
use std::{self,
          collections::HashMap,
          future::Future,
          sync::Arc,
          time::Duration};

static LOGKEY: &str = "SU";

/// A handle to an update worker that automatically aborts the worker when dropped.
struct Worker(AbortHandle);

impl Drop for Worker {
    fn drop(&mut self) { self.0.abort(); }
}

/// The `ServiceUpdater` is in charge of updating a Service when a change in version of a package
/// has been published to a depot channel or installed to the local package cache. To use an update
/// strategy, the supervisor must be configured to watch a depot for new versions.
pub struct ServiceUpdater {
    butterfly:   habitat_butterfly::Server,
    census_ring: Arc<RwLock<CensusRing>>,
    updates:     Arc<Mutex<HashMap<ServiceGroup, PackageIdent>>>,
    workers:     HashMap<ServiceGroup, Worker>,
    period:      Duration,
}

impl ServiceUpdater {
    pub fn new(butterfly: habitat_butterfly::Server,
               census_ring: Arc<RwLock<CensusRing>>,
               period: Duration)
               -> Self {
        ServiceUpdater { butterfly,
                         census_ring,
                         updates: Arc::default(),
                         workers: HashMap::new(),
                         period }
    }

    /// Register a service for updates. If the service has already
    /// been registered, the old worker is removed and a new one is
    /// started in its place.
    pub fn register(&mut self, service: &Service) {
        // Defensivly remove the service to prevent multiple update
        // workers from running.
        debug!("Removing any previously-registered updater for {}", service);
        self.remove(&service.service_group);
        // Determine what kind of worker we should use
        let service_group = service.service_group.clone();
        match service.update_strategy() {
            UpdateStrategy::None => {
                debug!("No updater registered for for {}", service);
            }
            UpdateStrategy::AtOnce => {
                debug!("Registering at-once updater for {}", service);
                let worker = self.at_once_worker(service);
                self.spawn_worker(service_group, worker);
            }
            UpdateStrategy::Rolling => {
                debug!("Registering rolling updater for {}", service);
                let worker = self.rolling_worker(service, Arc::clone(&self.census_ring));
                self.spawn_worker(service_group, worker);
            }
        };
    }

    /// Unregister a service from updates (eg if the service was unloaded).
    pub fn remove(&mut self, service_group: &ServiceGroup) {
        self.workers.remove(service_group);
        self.updates.lock().remove(service_group);
    }

    /// Check if this service has an update. If it does return the package ident of the update.
    ///
    /// Once an update is detected, this function will always return an update until the service is
    /// removed from the `ServiceUpdater`. The expectation is that when an update is detected the
    /// service will be restarted inorder for the update to take effect. As part of this restart,
    /// the service should be removed from the `ServiceUpdater`.
    pub fn has_update(&self, service_group: &ServiceGroup) -> Option<PackageIdent> {
        self.updates.lock().get(service_group).cloned()
    }

    fn at_once_worker(&mut self, service: &Service) -> impl Future<Output = ()> + Send + 'static {
        debug!("'{}' service updater spawning at-once worker watching for changes to '{}' from \
                channel '{}'",
               service.service_group,
               service.spec_ident(),
               service.channel());
        let service_group = service.service_group.clone();
        let full_ident = service.pkg.ident.clone();
        let updates = Arc::clone(&self.updates);
        let package_update_worker = PackageUpdateWorker::new(service, self.period);
        async move {
            let new_ident = package_update_worker.update().await;
            debug!("'{}' at-once updater found update from '{}' to '{}'",
                   service_group, full_ident, new_ident);
            Self::update_message(&new_ident, full_ident.as_ref());
            updates.lock().insert(service_group, new_ident);
        }
    }

    fn rolling_worker(&mut self,
                      service: &Service,
                      census_ring: Arc<RwLock<CensusRing>>)
                      -> impl Future<Output = ()> + Send + 'static {
        debug!("'{}' service updater spawning rolling worker watching for changes to '{}' from \
                channel '{}'",
               service.service_group,
               service.spec_ident(),
               service.channel());
        let service_group = service.service_group.clone();
        let full_ident = service.pkg.ident.clone();
        let updates = Arc::clone(&self.updates);
        let worker =
            RollingUpdateWorker::new(service, census_ring, self.butterfly.clone(), self.period);
        async move {
            let new_ident = worker.run().await;
            debug!("'{}' rolling updater found update from '{}' to '{}'",
                   service_group, full_ident, new_ident);
            Self::update_message(&new_ident, full_ident.as_ref());
            updates.lock().insert(service_group, new_ident);
        }
    }

    fn update_message(new_ident: &PackageIdent, current_ident: &PackageIdent) {
        if new_ident > current_ident {
            outputln!("Updating from {} to {}", current_ident, new_ident);
        } else {
            outputln!("Rolling back from {} to {}", current_ident, new_ident);
        }
    }

    /// Make the worker abortable and spawn it
    fn spawn_worker(&mut self,
                    service_group: ServiceGroup,
                    worker: impl Future<Output = ()> + Send + 'static) {
        let (worker, abort_handle) = future::abortable(worker);
        self.workers.insert(service_group, Worker(abort_handle));
        tokio::spawn(worker);
    }
}
<|endoftext|>


<commit_before>use rustler::types::truthy::Truthy;
use rustler::Encoder;
use rustler::{NifMap, NifRecord, NifStruct, NifTuple, NifUnitEnum, NifUntaggedEnum};

#[derive(NifTuple)]
pub struct AddTuple {
    lhs: i32,
    rhs: i32,
}

#[rustler::nif]
pub fn tuple_echo(tuple: AddTuple) -> AddTuple {
    tuple
}

#[derive(NifRecord)]
#[rustler(encode, decode)] // Added to check encode/decode attribute, #180
#[must_use] // Added to check attribute order (see similar issue #152)
#[tag = "record"]
pub struct AddRecord {
    lhs: i32,
    rhs: i32,
}

#[rustler::nif]
pub fn record_echo(record: AddRecord) -> AddRecord {
    record
}

#[derive(NifMap)]
pub struct AddMap {
    lhs: i32,
    rhs: i32,
}

#[rustler::nif]
pub fn map_echo(map: AddMap) -> AddMap {
    map
}

#[derive(Debug, NifStruct)]
#[must_use] // Added to test Issue #152
#[module = "AddStruct"]
pub struct AddStruct {
    lhs: i32,
    rhs: i32,
}

#[rustler::nif]
pub fn struct_echo(add_struct: AddStruct) -> AddStruct {
    add_struct
}

#[derive(NifUnitEnum)]
pub enum UnitEnum {
    FooBar,
    Baz,
}

#[rustler::nif]
pub fn unit_enum_echo(unit_enum: UnitEnum) -> UnitEnum {
    unit_enum
}

#[derive(NifUntaggedEnum)]
pub enum UntaggedEnum {
    Foo(u32),
    Bar(String),
    Baz(AddStruct),
    Bool(bool),
}

#[rustler::nif]
pub fn untagged_enum_echo(untagged_enum: UntaggedEnum) -> UntaggedEnum {
    untagged_enum
}

#[derive(NifUntaggedEnum)]
pub enum UntaggedEnumWithTruthy {
    Baz(AddStruct),
    Truthy(Truthy),
}

#[rustler::nif]
pub fn untagged_enum_with_truthy(untagged_enum: UntaggedEnumWithTruthy) -> UntaggedEnumWithTruthy {
    untagged_enum
}

#[derive(NifTuple)]
pub struct Newtype(i64);

#[rustler::nif]
pub fn newtype_echo(newtype: Newtype) -> Newtype {
    newtype
}

#[derive(NifTuple)]
pub struct TupleStruct(i64, i64, i64);

#[rustler::nif]
pub fn tuplestruct_echo(tuplestruct: TupleStruct) -> TupleStruct {
    tuplestruct
}

#[derive(NifRecord)]
#[tag = "newtype"]
pub struct NewtypeRecord(i64);

#[rustler::nif]
pub fn newtype_record_echo(newtype: NewtypeRecord) -> NewtypeRecord {
    newtype
}

#[derive(NifRecord)]
#[tag = "tuplestruct"]
pub struct TupleStructRecord(i64, i64, i64);

#[rustler::nif]
pub fn tuplestruct_record_echo(tuplestruct: TupleStructRecord) -> TupleStructRecord {
    tuplestruct
}

pub mod reserved_keywords {
    use rustler::{Encoder, NifMap, NifRecord, NifStruct, NifTuple, NifUntaggedEnum};

    #[derive(NifMap, Debug)]
    pub struct Map {
        r#override: i32,
    }

    #[derive(NifStruct, Debug)]
    #[module = "Struct"]
    pub struct Struct {
        r#override: i32,
    }

    #[derive(NifTuple, Debug)]
    pub struct Tuple {
        r#override: i32,
    }

    #[derive(NifRecord, Debug)]
    #[tag = "record"]
    pub struct Record {
        r#override: i32,
    }

    #[derive(NifUntaggedEnum)]
    pub enum ReservedKeywords {
        Struct(Struct),
        Map(Map),
        Tuple(Tuple),
        Record(Record)
    }

    #[rustler::nif]
    pub fn reserved_keywords_type_echo(reserved: ReservedKeywords) -> ReservedKeywords {
        reserved
    }
}
<commit_msg>Cargo fmt<commit_after>use rustler::types::truthy::Truthy;
use rustler::Encoder;
use rustler::{NifMap, NifRecord, NifStruct, NifTuple, NifUnitEnum, NifUntaggedEnum};

#[derive(NifTuple)]
pub struct AddTuple {
    lhs: i32,
    rhs: i32,
}

#[rustler::nif]
pub fn tuple_echo(tuple: AddTuple) -> AddTuple {
    tuple
}

#[derive(NifRecord)]
#[rustler(encode, decode)] // Added to check encode/decode attribute, #180
#[must_use] // Added to check attribute order (see similar issue #152)
#[tag = "record"]
pub struct AddRecord {
    lhs: i32,
    rhs: i32,
}

#[rustler::nif]
pub fn record_echo(record: AddRecord) -> AddRecord {
    record
}

#[derive(NifMap)]
pub struct AddMap {
    lhs: i32,
    rhs: i32,
}

#[rustler::nif]
pub fn map_echo(map: AddMap) -> AddMap {
    map
}

#[derive(Debug, NifStruct)]
#[must_use] // Added to test Issue #152
#[module = "AddStruct"]
pub struct AddStruct {
    lhs: i32,
    rhs: i32,
}

#[rustler::nif]
pub fn struct_echo(add_struct: AddStruct) -> AddStruct {
    add_struct
}

#[derive(NifUnitEnum)]
pub enum UnitEnum {
    FooBar,
    Baz,
}

#[rustler::nif]
pub fn unit_enum_echo(unit_enum: UnitEnum) -> UnitEnum {
    unit_enum
}

#[derive(NifUntaggedEnum)]
pub enum UntaggedEnum {
    Foo(u32),
    Bar(String),
    Baz(AddStruct),
    Bool(bool),
}

#[rustler::nif]
pub fn untagged_enum_echo(untagged_enum: UntaggedEnum) -> UntaggedEnum {
    untagged_enum
}

#[derive(NifUntaggedEnum)]
pub enum UntaggedEnumWithTruthy {
    Baz(AddStruct),
    Truthy(Truthy),
}

#[rustler::nif]
pub fn untagged_enum_with_truthy(untagged_enum: UntaggedEnumWithTruthy) -> UntaggedEnumWithTruthy {
    untagged_enum
}

#[derive(NifTuple)]
pub struct Newtype(i64);

#[rustler::nif]
pub fn newtype_echo(newtype: Newtype) -> Newtype {
    newtype
}

#[derive(NifTuple)]
pub struct TupleStruct(i64, i64, i64);

#[rustler::nif]
pub fn tuplestruct_echo(tuplestruct: TupleStruct) -> TupleStruct {
    tuplestruct
}

#[derive(NifRecord)]
#[tag = "newtype"]
pub struct NewtypeRecord(i64);

#[rustler::nif]
pub fn newtype_record_echo(newtype: NewtypeRecord) -> NewtypeRecord {
    newtype
}

#[derive(NifRecord)]
#[tag = "tuplestruct"]
pub struct TupleStructRecord(i64, i64, i64);

#[rustler::nif]
pub fn tuplestruct_record_echo(tuplestruct: TupleStructRecord) -> TupleStructRecord {
    tuplestruct
}

pub mod reserved_keywords {
    use rustler::{Encoder, NifMap, NifRecord, NifStruct, NifTuple, NifUntaggedEnum};

    #[derive(NifMap, Debug)]
    pub struct Map {
        r#override: i32,
    }

    #[derive(NifStruct, Debug)]
    #[module = "Struct"]
    pub struct Struct {
        r#override: i32,
    }

    #[derive(NifTuple, Debug)]
    pub struct Tuple {
        r#override: i32,
    }

    #[derive(NifRecord, Debug)]
    #[tag = "record"]
    pub struct Record {
        r#override: i32,
    }

    #[derive(NifUntaggedEnum)]
    pub enum ReservedKeywords {
        Struct(Struct),
        Map(Map),
        Tuple(Tuple),
        Record(Record),
    }

    #[rustler::nif]
    pub fn reserved_keywords_type_echo(reserved: ReservedKeywords) -> ReservedKeywords {
        reserved
    }
}
<|endoftext|>


<commit_before>// Needed for reading a Json File
// extern crate rustc_serialize;
// use rustc_serialize::json::Json;
// use std::fs::File;
// use std::io::Read;

use uuid::Uuid;

use libimagstore::store::Store;
use libimagstore::storeid::IntoStoreId;
use module_path::ModuleEntryPath;

use error::{TodoError, TodoErrorKind};

/// With the uuid we get the storeid and than we can delete the entry
pub fn deleteFunc(uuid: Uuid, store : &Store) {
	// With this we can read from a .json File
	// let mut file = File::open("text.json").unwrap();
	// let mut data = String::new();
	// file.rad_to_string(&mut data).unwrap();
	//
	// let jeson = Json::from_str(&data).unwrap();
	// println!("{}", json.find_path(&["uuid"]).unwrap());

	// With the uuid we get the storeid
	let store_id = ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid();
	// It deletes an entry
	if let Err(e) = store.delete(store_id) {
		return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))).unwrap();
	}

}

<commit_msg>Change the Error handling and remove unsed code<commit_after>use uuid::Uuid;

use libimagstore::store::Store;
use libimagstore::storeid::IntoStoreId;
use module_path::ModuleEntryPath;

use error::{TodoError, TodoErrorKind};

/// With the uuid we get the storeid and then we can delete the entry
pub fn deleteFunc(uuid: Uuid, store : &Store) -> Result<(),TodoError> {
	// With the uuid we get the storeid
	let store_id = ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid();
	// It deletes an entry
	match store.delete(store_id) {
		Ok(val) => Ok(val),
		Err(e) => Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))),
	}
}

<|endoftext|>


<commit_before>use core::mem::*;

use std::rc::Rc;

#[test]
fn size_of_basic() {
    assert_eq!(size_of::<u8>(), 1);
    assert_eq!(size_of::<u16>(), 2);
    assert_eq!(size_of::<u32>(), 4);
    assert_eq!(size_of::<u64>(), 8);
}

#[test]
#[cfg(target_pointer_width = "16")]
fn size_of_16() {
    assert_eq!(size_of::<usize>(), 2);
    assert_eq!(size_of::<*const usize>(), 2);
}

#[test]
#[cfg(target_pointer_width = "32")]
fn size_of_32() {
    assert_eq!(size_of::<usize>(), 4);
    assert_eq!(size_of::<*const usize>(), 4);
}

#[test]
#[cfg(target_pointer_width = "64")]
fn size_of_64() {
    assert_eq!(size_of::<usize>(), 8);
    assert_eq!(size_of::<*const usize>(), 8);
}

#[test]
fn size_of_val_basic() {
    assert_eq!(size_of_val(&1u8), 1);
    assert_eq!(size_of_val(&1u16), 2);
    assert_eq!(size_of_val(&1u32), 4);
    assert_eq!(size_of_val(&1u64), 8);
}

#[test]
fn align_of_basic() {
    assert_eq!(align_of::<u8>(), 1);
    assert_eq!(align_of::<u16>(), 2);
    assert_eq!(align_of::<u32>(), 4);
}

#[test]
#[cfg(target_pointer_width = "16")]
fn align_of_16() {
    assert_eq!(align_of::<usize>(), 2);
    assert_eq!(align_of::<*const usize>(), 2);
}

#[test]
#[cfg(target_pointer_width = "32")]
fn align_of_32() {
    assert_eq!(align_of::<usize>(), 4);
    assert_eq!(align_of::<*const usize>(), 4);
}

#[test]
#[cfg(target_pointer_width = "64")]
fn align_of_64() {
    assert_eq!(align_of::<usize>(), 8);
    assert_eq!(align_of::<*const usize>(), 8);
}

#[test]
fn align_of_val_basic() {
    assert_eq!(align_of_val(&1u8), 1);
    assert_eq!(align_of_val(&1u16), 2);
    assert_eq!(align_of_val(&1u32), 4);
}

#[test]
fn test_swap() {
    let mut x = 31337;
    let mut y = 42;
    swap(&mut x, &mut y);
    assert_eq!(x, 42);
    assert_eq!(y, 31337);
}

#[test]
fn test_replace() {
    let mut x = Some("test".to_string());
    let y = replace(&mut x, None);
    assert!(x.is_none());
    assert!(y.is_some());
}

#[test]
fn test_transmute_copy() {
    assert_eq!(1, unsafe { transmute_copy(&1) });
}

#[test]
fn test_transmute() {
    trait Foo {
        fn dummy(&self) {}
    }
    impl Foo for isize {}

    let a = box 100isize as Box<dyn Foo>;
    unsafe {
        let x: ::core::raw::TraitObject = transmute(a);
        assert!(*(x.data as *const isize) == 100);
        let _x: Box<dyn Foo> = transmute(x);
    }

    unsafe {
        assert_eq!(transmute::<_, Vec<u8>>("L".to_string()), [76]);
    }
}

#[test]
#[allow(dead_code)]
fn test_discriminant_send_sync() {
    enum Regular {
        A,
        B(i32),
    }
    enum NotSendSync {
        A(*const i32),
    }

    fn is_send_sync<T: Send + Sync>() {}

    is_send_sync::<Discriminant<Regular>>();
    is_send_sync::<Discriminant<NotSendSync>>();
}

#[test]
#[cfg(not(bootstrap))]
fn assume_init_good() {
    const TRUE: bool = unsafe { MaybeUninit::<bool>::new(true).assume_init() };

    assert!(TRUE);
}

#[test]
fn uninit_write_slice() {
    let mut dst = [MaybeUninit::new(255); 64];
    let src = [0; 64];

    assert_eq!(MaybeUninit::write_slice(&mut dst, &src), &src);
}

#[test]
#[should_panic(expected = "source slice length (32) does not match destination slice length (64)")]
fn uninit_write_slice_panic_lt() {
    let mut dst = [MaybeUninit::uninit(); 64];
    let src = [0; 32];

    MaybeUninit::write_slice(&mut dst, &src);
}

#[test]
#[should_panic(expected = "source slice length (128) does not match destination slice length (64)")]
fn uninit_write_slice_panic_gt() {
    let mut dst = [MaybeUninit::uninit(); 64];
    let src = [0; 128];

    MaybeUninit::write_slice(&mut dst, &src);
}

#[test]
fn uninit_clone_from_slice() {
    let mut dst = [MaybeUninit::new(255); 64];
    let src = [0; 64];

    assert_eq!(MaybeUninit::write_slice_cloned(&mut dst, &src), &src);
}

#[test]
#[should_panic(expected = "destination and source slices have different lengths")]
fn uninit_write_slice_cloned_panic_lt() {
    let mut dst = [MaybeUninit::uninit(); 64];
    let src = [0; 32];

    MaybeUninit::write_slice_cloned(&mut dst, &src);
}

#[test]
#[should_panic(expected = "destination and source slices have different lengths")]
fn uninit_write_slice_cloned_panic_gt() {
    let mut dst = [MaybeUninit::uninit(); 64];
    let src = [0; 128];

    MaybeUninit::write_slice_cloned(&mut dst, &src);
}

#[test]
#[cfg(panic = "unwind")]
fn uninit_write_slice_cloned_mid_panic() {
    use std::panic;

    enum IncrementOrPanic {
        Increment(Rc<()>),
        ExpectedPanic,
        UnexpectedPanic,
    }

    impl Clone for IncrementOrPanic {
        fn clone(&self) -> Self {
            match self {
                Self::Increment(rc) => Self::Increment(rc.clone()),
                Self::ExpectedPanic => panic!("expected panic on clone"),
                Self::UnexpectedPanic => panic!("unexpected panic on clone"),
            }
        }
    }

    let rc = Rc::new(());

    let mut dst = [
        MaybeUninit::uninit(),
        MaybeUninit::uninit(),
        MaybeUninit::uninit(),
        MaybeUninit::uninit(),
    ];

    let src = [
        IncrementOrPanic::Increment(rc.clone()),
        IncrementOrPanic::Increment(rc.clone()),
        IncrementOrPanic::ExpectedPanic,
        IncrementOrPanic::UnexpectedPanic,
    ];

    let err = panic::catch_unwind(panic::AssertUnwindSafe(|| {
        MaybeUninit::write_slice_cloned(&mut dst, &src);
    }));

    drop(src);

    match err {
        Ok(_) => unreachable!(),
        Err(payload) => {
            payload
                .downcast::<&'static str>()
                .and_then(|s| if *s == "expected panic on clone" { Ok(s) } else { Err(s) })
                .unwrap_or_else(|p| panic::resume_unwind(p));

            assert_eq!(Rc::strong_count(&rc), 1)
        }
    }
}

#[test]
fn uninit_write_slice_cloned_no_drop() {
    let rc = Rc::new(());

    let mut dst = [MaybeUninit::uninit()];
    let src = [rc.clone()];

    MaybeUninit::write_slice_cloned(&mut dst, &src);

    drop(src);

    assert_eq!(Rc::strong_count(&rc), 2);
}
<commit_msg>Auto merge of #80123 - DrMeepster:maybe_uninit_write_slice, r=RalfJung<commit_after>use core::mem::*;

#[cfg(panic = "unwind")]
use std::rc::Rc;

#[test]
fn size_of_basic() {
    assert_eq!(size_of::<u8>(), 1);
    assert_eq!(size_of::<u16>(), 2);
    assert_eq!(size_of::<u32>(), 4);
    assert_eq!(size_of::<u64>(), 8);
}

#[test]
#[cfg(target_pointer_width = "16")]
fn size_of_16() {
    assert_eq!(size_of::<usize>(), 2);
    assert_eq!(size_of::<*const usize>(), 2);
}

#[test]
#[cfg(target_pointer_width = "32")]
fn size_of_32() {
    assert_eq!(size_of::<usize>(), 4);
    assert_eq!(size_of::<*const usize>(), 4);
}

#[test]
#[cfg(target_pointer_width = "64")]
fn size_of_64() {
    assert_eq!(size_of::<usize>(), 8);
    assert_eq!(size_of::<*const usize>(), 8);
}

#[test]
fn size_of_val_basic() {
    assert_eq!(size_of_val(&1u8), 1);
    assert_eq!(size_of_val(&1u16), 2);
    assert_eq!(size_of_val(&1u32), 4);
    assert_eq!(size_of_val(&1u64), 8);
}

#[test]
fn align_of_basic() {
    assert_eq!(align_of::<u8>(), 1);
    assert_eq!(align_of::<u16>(), 2);
    assert_eq!(align_of::<u32>(), 4);
}

#[test]
#[cfg(target_pointer_width = "16")]
fn align_of_16() {
    assert_eq!(align_of::<usize>(), 2);
    assert_eq!(align_of::<*const usize>(), 2);
}

#[test]
#[cfg(target_pointer_width = "32")]
fn align_of_32() {
    assert_eq!(align_of::<usize>(), 4);
    assert_eq!(align_of::<*const usize>(), 4);
}

#[test]
#[cfg(target_pointer_width = "64")]
fn align_of_64() {
    assert_eq!(align_of::<usize>(), 8);
    assert_eq!(align_of::<*const usize>(), 8);
}

#[test]
fn align_of_val_basic() {
    assert_eq!(align_of_val(&1u8), 1);
    assert_eq!(align_of_val(&1u16), 2);
    assert_eq!(align_of_val(&1u32), 4);
}

#[test]
fn test_swap() {
    let mut x = 31337;
    let mut y = 42;
    swap(&mut x, &mut y);
    assert_eq!(x, 42);
    assert_eq!(y, 31337);
}

#[test]
fn test_replace() {
    let mut x = Some("test".to_string());
    let y = replace(&mut x, None);
    assert!(x.is_none());
    assert!(y.is_some());
}

#[test]
fn test_transmute_copy() {
    assert_eq!(1, unsafe { transmute_copy(&1) });
}

#[test]
fn test_transmute() {
    trait Foo {
        fn dummy(&self) {}
    }
    impl Foo for isize {}

    let a = box 100isize as Box<dyn Foo>;
    unsafe {
        let x: ::core::raw::TraitObject = transmute(a);
        assert!(*(x.data as *const isize) == 100);
        let _x: Box<dyn Foo> = transmute(x);
    }

    unsafe {
        assert_eq!(transmute::<_, Vec<u8>>("L".to_string()), [76]);
    }
}

#[test]
#[allow(dead_code)]
fn test_discriminant_send_sync() {
    enum Regular {
        A,
        B(i32),
    }
    enum NotSendSync {
        A(*const i32),
    }

    fn is_send_sync<T: Send + Sync>() {}

    is_send_sync::<Discriminant<Regular>>();
    is_send_sync::<Discriminant<NotSendSync>>();
}

#[test]
#[cfg(not(bootstrap))]
fn assume_init_good() {
    const TRUE: bool = unsafe { MaybeUninit::<bool>::new(true).assume_init() };

    assert!(TRUE);
}

#[test]
fn uninit_write_slice() {
    let mut dst = [MaybeUninit::new(255); 64];
    let src = [0; 64];

    assert_eq!(MaybeUninit::write_slice(&mut dst, &src), &src);
}

#[test]
#[should_panic(expected = "source slice length (32) does not match destination slice length (64)")]
fn uninit_write_slice_panic_lt() {
    let mut dst = [MaybeUninit::uninit(); 64];
    let src = [0; 32];

    MaybeUninit::write_slice(&mut dst, &src);
}

#[test]
#[should_panic(expected = "source slice length (128) does not match destination slice length (64)")]
fn uninit_write_slice_panic_gt() {
    let mut dst = [MaybeUninit::uninit(); 64];
    let src = [0; 128];

    MaybeUninit::write_slice(&mut dst, &src);
}

#[test]
fn uninit_clone_from_slice() {
    let mut dst = [MaybeUninit::new(255); 64];
    let src = [0; 64];

    assert_eq!(MaybeUninit::write_slice_cloned(&mut dst, &src), &src);
}

#[test]
#[should_panic(expected = "destination and source slices have different lengths")]
fn uninit_write_slice_cloned_panic_lt() {
    let mut dst = [MaybeUninit::uninit(); 64];
    let src = [0; 32];

    MaybeUninit::write_slice_cloned(&mut dst, &src);
}

#[test]
#[should_panic(expected = "destination and source slices have different lengths")]
fn uninit_write_slice_cloned_panic_gt() {
    let mut dst = [MaybeUninit::uninit(); 64];
    let src = [0; 128];

    MaybeUninit::write_slice_cloned(&mut dst, &src);
}

#[test]
#[cfg(panic = "unwind")]
fn uninit_write_slice_cloned_mid_panic() {
    use std::panic;

    enum IncrementOrPanic {
        Increment(Rc<()>),
        ExpectedPanic,
        UnexpectedPanic,
    }

    impl Clone for IncrementOrPanic {
        fn clone(&self) -> Self {
            match self {
                Self::Increment(rc) => Self::Increment(rc.clone()),
                Self::ExpectedPanic => panic!("expected panic on clone"),
                Self::UnexpectedPanic => panic!("unexpected panic on clone"),
            }
        }
    }

    let rc = Rc::new(());

    let mut dst = [
        MaybeUninit::uninit(),
        MaybeUninit::uninit(),
        MaybeUninit::uninit(),
        MaybeUninit::uninit(),
    ];

    let src = [
        IncrementOrPanic::Increment(rc.clone()),
        IncrementOrPanic::Increment(rc.clone()),
        IncrementOrPanic::ExpectedPanic,
        IncrementOrPanic::UnexpectedPanic,
    ];

    let err = panic::catch_unwind(panic::AssertUnwindSafe(|| {
        MaybeUninit::write_slice_cloned(&mut dst, &src);
    }));

    drop(src);

    match err {
        Ok(_) => unreachable!(),
        Err(payload) => {
            payload
                .downcast::<&'static str>()
                .and_then(|s| if *s == "expected panic on clone" { Ok(s) } else { Err(s) })
                .unwrap_or_else(|p| panic::resume_unwind(p));

            assert_eq!(Rc::strong_count(&rc), 1)
        }
    }
}

#[test]
fn uninit_write_slice_cloned_no_drop() {
    #[derive(Clone)]
    struct Bomb;

    impl Drop for Bomb {
        fn drop(&mut self) {
            panic!("dropped a bomb! kaboom")
        }
    }

    let mut dst = [MaybeUninit::uninit()];
    let src = [Bomb];

    MaybeUninit::write_slice_cloned(&mut dst, &src);

    forget(src);
}
<|endoftext|>


<commit_before>extern crate libc;

use libc::c_char;

use std::ffi::{
    CStr,
    CString,
};

#[no_mangle]
pub extern fn hello() {
    println!("hello")
}

#[no_mangle]
pub extern fn add(a: i64, b: i64) -> i64 {
    a + b
}

#[no_mangle]
pub extern fn length(str: *const c_char) -> i64 {
    let c_str = unsafe { CStr::from_ptr(str) };

    c_str.to_bytes().len() as i64
}

fn to_str<'a>(c_str: *const c_char) -> &'a str {
    unsafe { CStr::from_ptr(c_str) }
        .to_str()
        .unwrap()

}

fn to_c_string(string: String) -> *mut c_char {
    CString::new(string)
        .unwrap()
        .into_raw()
}

#[no_mangle]
pub extern fn duplicate(
    count: i64,
    c_msg: *const c_char,
) -> *mut c_char {
    let msg = to_str(c_msg);

    let out = std::iter::repeat(msg)
        .take(count as usize)
        .collect::<String>();

    to_c_string(out)
}

#[no_mangle]
pub extern fn release(msg: *mut c_char) {
    unsafe { CString::from_raw(msg) };
}

#[repr(C)]
pub struct DuplicateString {
    msg: *const c_char,
    count: i32,
}

#[no_mangle]
pub extern fn add_duplicate_strings(
    c_ds1: *const DuplicateString,
    c_ds2: *const DuplicateString,
    c_result: *mut DuplicateString,
) {
    let (ds1, ds2, mut result) = unsafe { (
        &*c_ds1,
        &*c_ds2,
        &mut *c_result
    ) };

    let (ds1msg, ds2msg) = (to_str(ds1.msg), to_str(ds2.msg));

    result.msg = to_c_string([ds1msg, ds2msg].join("|"));
    result.count = ds1.count + ds2.count;
}

#[repr(C)]
pub struct Point {
    x: i32,
    y: i32,
}

#[no_mangle]
pub extern fn add_points(
    c_p1: *const Point,
    c_p2: *const Point,
    c_result: *mut Point,
) {
    let (p1, p2, mut result) = unsafe { (&*c_p1, &*c_p2, &mut *c_result) };

    result.x = p1.x + p2.x;
    result.y = p1.y + p2.y;
}

mod tokens {

    struct Token {
        name: String,
        created: i64,
        expire: i64
    }

    impl Token {
        fn new(string: String) -> Option<Token> { // TODO(gardell): Return Result with appropriate error code
            let mut pieces = string.split(':');
            match (pieces.next(), pieces.next(), pieces.next()) {
                (Some(name), Some(created), Some(expire))
                    => match (created.parse(), expire.parse()) {
                        (Ok(created_int), Ok(expire_int))
                        => Some(Token{
                            name: name.to_owned(),
                            created: created_int,
                            expire: expire_int
                        }),
                        _ => None
                    },
                _ => None
            }
        }
    }
}<commit_msg>Token parser<commit_after>extern crate libc;

use libc::c_char;

use std::ffi::{
    CStr,
    CString,
};

#[no_mangle]
pub extern fn hello() {
    println!("hello")
}

#[no_mangle]
pub extern fn add(a: i64, b: i64) -> i64 {
    a + b
}

#[no_mangle]
pub extern fn length(str: *const c_char) -> i64 {
    let c_str = unsafe { CStr::from_ptr(str) };

    c_str.to_bytes().len() as i64
}

fn to_str<'a>(c_str: *const c_char) -> &'a str {
    unsafe { CStr::from_ptr(c_str) }
        .to_str()
        .unwrap()

}

fn to_c_string(string: String) -> *mut c_char {
    CString::new(string)
        .unwrap()
        .into_raw()
}

#[no_mangle]
pub extern fn duplicate(
    count: i64,
    c_msg: *const c_char,
) -> *mut c_char {
    let msg = to_str(c_msg);

    let out = std::iter::repeat(msg)
        .take(count as usize)
        .collect::<String>();

    to_c_string(out)
}

#[no_mangle]
pub extern fn release(msg: *mut c_char) {
    unsafe { CString::from_raw(msg) };
}

#[repr(C)]
pub struct DuplicateString {
    msg: *const c_char,
    count: i32,
}

#[no_mangle]
pub extern fn add_duplicate_strings(
    c_ds1: *const DuplicateString,
    c_ds2: *const DuplicateString,
    c_result: *mut DuplicateString,
) {
    let (ds1, ds2, mut result) = unsafe { (
        &*c_ds1,
        &*c_ds2,
        &mut *c_result
    ) };

    let (ds1msg, ds2msg) = (to_str(ds1.msg), to_str(ds2.msg));

    result.msg = to_c_string([ds1msg, ds2msg].join("|"));
    result.count = ds1.count + ds2.count;
}

#[repr(C)]
pub struct Point {
    x: i32,
    y: i32,
}

#[no_mangle]
pub extern fn add_points(
    c_p1: *const Point,
    c_p2: *const Point,
    c_result: *mut Point,
) {
    let (p1, p2, mut result) = unsafe { (&*c_p1, &*c_p2, &mut *c_result) };

    result.x = p1.x + p2.x;
    result.y = p1.y + p2.y;
}

mod tokens {

    struct Token {
        name: String,
        created: i64,
        expire: i64
    }

    impl Token {
        fn new(string: String) -> Option<Token> {
            // TODO(gardell): Return Result with appropriate error code

            let parse = |p| { p.parse().ok() };
            let mut pieces = string.split(':');

            match (
                pieces.next(),
                pieces.next().and_then(parse),
                pieces.next().and_then(parse)
            ) {
                (Some(name), Some(created), Some(expire))
                => Some(Token{
                    name: name.to_owned(),
                    created: created,
                    expire: expire
                }),
                _ => None
            }
        }
    }
}<|endoftext|>


<commit_before>//! User sessions.
//!
//! Actix provides a general solution for session management. Session
//! middlewares could provide different implementations which could
//! be accessed via general session api.
//!
//! By default, only cookie session backend is implemented. Other
//! backend implementations can be added.
//!
//! In general, you insert a *session* middleware and initialize it
//! , such as a `CookieSessionBackend`. To access session data,
//! [*Session*](struct.Session.html) extractor must be used. Session
//! extractor allows us to get or set session data.
//!
//! ```rust
//! use actix_web::{web, App, HttpServer, HttpResponse, Error};
//! use actix_session::{Session, CookieSession};
//!
//! fn index(session: Session) -> Result<&'static str, Error> {
//!     // access session data
//!     if let Some(count) = session.get::<i32>("counter")? {
//!         println!("SESSION value: {}", count);
//!         session.set("counter", count+1)?;
//!     } else {
//!         session.set("counter", 1)?;
//!     }
//!
//!     Ok("Welcome!")
//! }
//!
//! fn main() -> std::io::Result<()> {
//! # std::thread::spawn(||
//!     HttpServer::new(
//!         || App::new().middleware(
//!               CookieSession::signed(&[0; 32]) // <- create cookie based session middleware
//!                     .secure(false)
//!              )
//!             .service(web::resource("/").to(|| HttpResponse::Ok())))
//!         .bind("127.0.0.1:59880")?
//!         .run()
//! # );
//! # Ok(())
//! }
//! ```
use std::cell::RefCell;
use std::rc::Rc;

use actix_web::dev::{ServiceFromRequest, ServiceRequest, ServiceResponse};
use actix_web::{Error, FromRequest, HttpMessage};
use hashbrown::HashMap;
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json;

mod cookie;
pub use crate::cookie::CookieSession;

/// The high-level interface you use to modify session data.
///
/// Session object could be obtained with
/// [`RequestSession::session`](trait.RequestSession.html#tymethod.session)
/// method. `RequestSession` trait is implemented for `HttpRequest`.
///
/// ```rust
/// use actix_session::Session;
/// use actix_web::*;
///
/// fn index(session: Session) -> Result<&'static str> {
///     // access session data
///     if let Some(count) = session.get::<i32>("counter")? {
///         session.set("counter", count + 1)?;
///     } else {
///         session.set("counter", 1)?;
///     }
///
///     Ok("Welcome!")
/// }
/// # fn main() {}
/// ```
pub struct Session(Rc<RefCell<SessionInner>>);

#[derive(Default)]
struct SessionInner {
    state: HashMap<String, String>,
    changed: bool,
}

impl Session {
    /// Get a `value` from the session.
    pub fn get<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>, Error> {
        if let Some(s) = self.0.borrow().state.get(key) {
            Ok(Some(serde_json::from_str(s)?))
        } else {
            Ok(None)
        }
    }

    /// Set a `value` from the session.
    pub fn set<T: Serialize>(&self, key: &str, value: T) -> Result<(), Error> {
        let mut inner = self.0.borrow_mut();
        inner.changed = true;
        inner
            .state
            .insert(key.to_owned(), serde_json::to_string(&value)?);
        Ok(())
    }

    /// Remove value from the session.
    pub fn remove(&self, key: &str) {
        let mut inner = self.0.borrow_mut();
        inner.changed = true;
        inner.state.remove(key);
    }

    /// Clear the session.
    pub fn clear(&self) {
        let mut inner = self.0.borrow_mut();
        inner.changed = true;
        inner.state.clear()
    }

    pub fn set_session<P>(
        data: impl Iterator<Item = (String, String)>,
        req: &mut ServiceRequest<P>,
    ) {
        let session = Session::get_session(req);
        let mut inner = session.0.borrow_mut();
        inner.state.extend(data);
    }

    pub fn get_changes<B>(
        res: &mut ServiceResponse<B>,
    ) -> Option<impl Iterator<Item = (String, String)>> {
        if let Some(s_impl) = res
            .request()
            .extensions()
            .get::<Rc<RefCell<SessionInner>>>()
        {
            let state =
                std::mem::replace(&mut s_impl.borrow_mut().state, HashMap::new());
            Some(state.into_iter())
        } else {
            None
        }
    }

    fn get_session<R: HttpMessage>(req: R) -> Session {
        if let Some(s_impl) = req.extensions().get::<Rc<RefCell<SessionInner>>>() {
            return Session(Rc::clone(&s_impl));
        }
        let inner = Rc::new(RefCell::new(SessionInner::default()));
        req.extensions_mut().insert(inner.clone());
        Session(inner)
    }
}

/// Extractor implementation for Session type.
///
/// ```rust
/// # use actix_web::*;
/// use actix_session::Session;
///
/// fn index(session: Session) -> Result<&'static str> {
///     // access session data
///     if let Some(count) = session.get::<i32>("counter")? {
///         session.set("counter", count + 1)?;
///     } else {
///         session.set("counter", 1)?;
///     }
///
///     Ok("Welcome!")
/// }
/// # fn main() {}
/// ```
impl<P> FromRequest<P> for Session {
    type Error = Error;
    type Future = Result<Session, Error>;

    #[inline]
    fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
        Ok(Session::get_session(req))
    }
}
<commit_msg>add session test<commit_after>//! User sessions.
//!
//! Actix provides a general solution for session management. Session
//! middlewares could provide different implementations which could
//! be accessed via general session api.
//!
//! By default, only cookie session backend is implemented. Other
//! backend implementations can be added.
//!
//! In general, you insert a *session* middleware and initialize it
//! , such as a `CookieSessionBackend`. To access session data,
//! [*Session*](struct.Session.html) extractor must be used. Session
//! extractor allows us to get or set session data.
//!
//! ```rust
//! use actix_web::{web, App, HttpServer, HttpResponse, Error};
//! use actix_session::{Session, CookieSession};
//!
//! fn index(session: Session) -> Result<&'static str, Error> {
//!     // access session data
//!     if let Some(count) = session.get::<i32>("counter")? {
//!         println!("SESSION value: {}", count);
//!         session.set("counter", count+1)?;
//!     } else {
//!         session.set("counter", 1)?;
//!     }
//!
//!     Ok("Welcome!")
//! }
//!
//! fn main() -> std::io::Result<()> {
//! # std::thread::spawn(||
//!     HttpServer::new(
//!         || App::new().middleware(
//!               CookieSession::signed(&[0; 32]) // <- create cookie based session middleware
//!                     .secure(false)
//!              )
//!             .service(web::resource("/").to(|| HttpResponse::Ok())))
//!         .bind("127.0.0.1:59880")?
//!         .run()
//! # );
//! # Ok(())
//! }
//! ```
use std::cell::RefCell;
use std::rc::Rc;

use actix_web::dev::{ServiceFromRequest, ServiceRequest, ServiceResponse};
use actix_web::{Error, FromRequest, HttpMessage};
use hashbrown::HashMap;
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json;

mod cookie;
pub use crate::cookie::CookieSession;

/// The high-level interface you use to modify session data.
///
/// Session object could be obtained with
/// [`RequestSession::session`](trait.RequestSession.html#tymethod.session)
/// method. `RequestSession` trait is implemented for `HttpRequest`.
///
/// ```rust
/// use actix_session::Session;
/// use actix_web::*;
///
/// fn index(session: Session) -> Result<&'static str> {
///     // access session data
///     if let Some(count) = session.get::<i32>("counter")? {
///         session.set("counter", count + 1)?;
///     } else {
///         session.set("counter", 1)?;
///     }
///
///     Ok("Welcome!")
/// }
/// # fn main() {}
/// ```
pub struct Session(Rc<RefCell<SessionInner>>);

#[derive(Default)]
struct SessionInner {
    state: HashMap<String, String>,
    changed: bool,
}

impl Session {
    /// Get a `value` from the session.
    pub fn get<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>, Error> {
        if let Some(s) = self.0.borrow().state.get(key) {
            Ok(Some(serde_json::from_str(s)?))
        } else {
            Ok(None)
        }
    }

    /// Set a `value` from the session.
    pub fn set<T: Serialize>(&self, key: &str, value: T) -> Result<(), Error> {
        let mut inner = self.0.borrow_mut();
        inner.changed = true;
        inner
            .state
            .insert(key.to_owned(), serde_json::to_string(&value)?);
        Ok(())
    }

    /// Remove value from the session.
    pub fn remove(&self, key: &str) {
        let mut inner = self.0.borrow_mut();
        inner.changed = true;
        inner.state.remove(key);
    }

    /// Clear the session.
    pub fn clear(&self) {
        let mut inner = self.0.borrow_mut();
        inner.changed = true;
        inner.state.clear()
    }

    pub fn set_session<P>(
        data: impl Iterator<Item = (String, String)>,
        req: &mut ServiceRequest<P>,
    ) {
        let session = Session::get_session(req);
        let mut inner = session.0.borrow_mut();
        inner.state.extend(data);
    }

    pub fn get_changes<B>(
        res: &mut ServiceResponse<B>,
    ) -> Option<impl Iterator<Item = (String, String)>> {
        if let Some(s_impl) = res
            .request()
            .extensions()
            .get::<Rc<RefCell<SessionInner>>>()
        {
            let state =
                std::mem::replace(&mut s_impl.borrow_mut().state, HashMap::new());
            Some(state.into_iter())
        } else {
            None
        }
    }

    fn get_session<R: HttpMessage>(req: R) -> Session {
        if let Some(s_impl) = req.extensions().get::<Rc<RefCell<SessionInner>>>() {
            return Session(Rc::clone(&s_impl));
        }
        let inner = Rc::new(RefCell::new(SessionInner::default()));
        req.extensions_mut().insert(inner.clone());
        Session(inner)
    }
}

/// Extractor implementation for Session type.
///
/// ```rust
/// # use actix_web::*;
/// use actix_session::Session;
///
/// fn index(session: Session) -> Result<&'static str> {
///     // access session data
///     if let Some(count) = session.get::<i32>("counter")? {
///         session.set("counter", count + 1)?;
///     } else {
///         session.set("counter", 1)?;
///     }
///
///     Ok("Welcome!")
/// }
/// # fn main() {}
/// ```
impl<P> FromRequest<P> for Session {
    type Error = Error;
    type Future = Result<Session, Error>;

    #[inline]
    fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
        Ok(Session::get_session(req))
    }
}

#[cfg(test)]
mod tests {
    use actix_web::{test, HttpResponse};

    use super::*;

    #[test]
    fn session() {
        let mut req = test::TestRequest::default().to_service();

        Session::set_session(
            vec![("key".to_string(), "\"value\"".to_string())].into_iter(),
            &mut req,
        );
        let session = Session::get_session(&mut req);
        let res = session.get::<String>("key").unwrap();
        assert_eq!(res, Some("value".to_string()));

        session.set("key2", "value2".to_string()).unwrap();
        session.remove("key");

        let mut res = req.into_response(HttpResponse::Ok().finish());
        let changes: Vec<_> = Session::get_changes(&mut res).unwrap().collect();
        assert_eq!(changes, [("key2".to_string(), "\"value2\"".to_string())]);
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use errors::*;

/// Manages tracking of write locks
pub struct WriteLockManager {
  /// Map of port to subscription ids
  write_locks: HashMap<String, String>,
}

impl WriteLockManager {
  /// Create a new WriteLockManager instance
  pub fn new() -> WriteLockManager {
    WriteLockManager { write_locks: HashMap::new() }
  }

  /// Is the port write locked by the given sub_id
  pub fn is_port_write_locked_by(&self, port_name: &String, sub_id: &String) -> bool {
    match self.write_locks.get(port_name) {
      None => false,
      Some(sid) => sid == sub_id,
    }
  }

  /// Is the port write locked at all
  pub fn is_port_write_locked(&self, port_name: &String) -> bool {
    self.write_locks.get(port_name).is_some()
  }

  pub fn is_port_locked_by_someone_else(&self, port_name: &String, sub_id: &String) -> bool {
    match self.write_locks.get(port_name) {
      None => false,
      Some(sid) => sid != sub_id,
    }
  }

  /// Check if sub id has write lock on this port, if it doesn't,
  /// return error
  pub fn check_owns_write_lock(&self, port_name: &String, sub_id: &String) -> Result<()> {
    match self.write_locks.get(port_name) {
      None => Err(ErrorKind::NeedWriteLock(port_name.to_string()).into()),
      Some(sid) => {
        if sid != sub_id {
          Err(ErrorKind::AlreadyWriteLocked(port_name.to_string()).into())
        } else {
          Ok(())
        }
      }
    }
  }

  // Clear a write lock, without checking subscriber id
  pub fn clear_lock(&mut self, port_name: &String) {
    self.write_locks.remove(port_name);
  }

  // Release the write lock for the given port and sub id
  pub fn unlock_port(&mut self, port_name: &String, sub_id: &String) -> Result<()> {
    match self.is_port_locked_by_someone_else(port_name, sub_id) {
      false => {
        self.write_locks.remove(port_name);
        Ok(())
      }
      true => Err(ErrorKind::AlreadyWriteLocked(port_name.to_string()).into()),
    }
  }

  pub fn unlock_port_if_locked_by(&mut self, port_name: &String, sub_id: &String) {
    if self.is_port_write_locked_by(port_name, sub_id){
      // Should not panic since we are the one who locked it
      self.unlock_port(&port_name, sub_id).unwrap();
    }
  }

  // Release all write locks held by this sub_id
  pub fn unlock_all_ports_for_sub(&mut self, sub_id: &String) {
    let mut to_delete = Vec::<String>::new();
    for port_name in self.write_locks.keys() {
      if self
           .write_locks
           .get(port_name)
           .map(|sid| sid == sub_id)
           .unwrap_or(false) {
        to_delete.push(port_name.to_string());
      }
    }
    for delete_port in to_delete.iter() {
      self.write_locks.remove(delete_port);
    }
  }

  // Try and lock the port
  pub fn lock_port(&mut self, port_name: &String, sub_id: &String) -> Result<()> {
    match self.is_port_locked_by_someone_else(port_name, sub_id) {
      false => {
        self
          .write_locks
          .insert(port_name.to_string(), sub_id.to_string());
        Ok(())
      }
      true => Err(ErrorKind::AlreadyWriteLocked(port_name.to_string()).into()),
    }

  }
}

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

  fn check_not_locked_by_anyone(
    wl_manager: &WriteLockManager,
    port: &String,
    sub_ids: Vec<&String>,
  ) {
    for sub_id in sub_ids.iter() {
      assert_eq!(
        false,
        wl_manager.is_port_write_locked_by(port, sub_id),
        "Port '{}' should not be locked by '{}'",
        port,
        sub_id
      );
      assert_eq!(
        false,
        wl_manager.is_port_locked_by_someone_else(port, sub_id),
        "Port '{}' should not be locked by someone else",
        port
      );

    }
  }

  fn check_locked_by_sub(
    wl_manager: &WriteLockManager,
    port: &String,
    sub_locker: &String,
    sub_ids: Vec<&String>,
  ) {
    assert_eq!(
      true,
      wl_manager.is_port_write_locked_by(port, sub_locker),
      "Port '{}' should not be locked by '{}'",
      port,
      sub_locker
    );
    for sub_id in sub_ids.iter() {
      assert_eq!(
        true,
        wl_manager.is_port_locked_by_someone_else(port, sub_id),
        "Port '{}' should not be locked by someone else",
        port
      );
    }
  }

  #[test]
  fn test_locking() {
    let wl_manager = &mut WriteLockManager::new();
    let sub_id1: String = "SUB_ID1".to_owned();
    let sub_id3: String = "SUB_ID2".to_owned();
    let sub_id2: String = "SUB_ID3".to_owned();
    let port: String = "/dev/TTY_USB".to_owned();
    // Ports should not be locked
    check_not_locked_by_anyone(&wl_manager, &port, vec![&sub_id1, &sub_id2, &sub_id3]);
    // sub_id1 locking a port should work
    assert_eq!(
      true,
      wl_manager
        .lock_port(&port, &sub_id1)
        .map(|_| true)
        .unwrap_or(false),
      "Sub_id '{}' locking port '{}' should succeed",
      sub_id1,
      port
    );
    //Port should now be locked by sub_id1
    check_locked_by_sub(&wl_manager, &port, &sub_id1, vec![&sub_id2, &sub_id3]);
    // sub_id2 should fail locking port already locked
    assert_eq!(
      true,
      wl_manager
        .lock_port(&port, &sub_id2)
        .map(|_| false)
        .unwrap_or(true),
      "Sub_id '{}' locking port '{}' should fail",
      sub_id1,
      port
    );
    // sub_id2 should fail unlocking port locked by sub_id1
    assert_eq!(
      true,
      wl_manager
        .unlock_port(&port, &sub_id2)
        .map(|_| false)
        .unwrap_or(true),
      "Sub_id '{}' unlocking port '{}' should fail",
      sub_id1,
      port
    );
    // sub_id1 should be able to unlock it
    assert_eq!(
      true,
      wl_manager
        .unlock_port(&port, &sub_id1)
        .map(|_| true)
        .unwrap_or(false),
      "Sub_id '{}' unlocking port '{}' should succeed",
      sub_id1,
      port
    );
    // Ports should not be locked
    check_not_locked_by_anyone(&wl_manager, &port, vec![&sub_id1, &sub_id2, &sub_id3]);
    // TODO: Finish testing all other methods
  }

}
<commit_msg>Reorganize writelock manager tests slightly<commit_after>use std::collections::HashMap;

use errors::*;

/// Manages tracking of write locks
pub struct WriteLockManager {
  /// Map of port to subscription ids
  write_locks: HashMap<String, String>,
}

impl WriteLockManager {
  /// Create a new WriteLockManager instance
  pub fn new() -> WriteLockManager {
    WriteLockManager { write_locks: HashMap::new() }
  }

  /// Is the port write locked by the given sub_id
  pub fn is_port_write_locked_by(&self, port_name: &String, sub_id: &String) -> bool {
    match self.write_locks.get(port_name) {
      None => false,
      Some(sid) => sid == sub_id,
    }
  }

  /// Is the port write locked at all
  pub fn is_port_write_locked(&self, port_name: &String) -> bool {
    self.write_locks.get(port_name).is_some()
  }

  pub fn is_port_locked_by_someone_else(&self, port_name: &String, sub_id: &String) -> bool {
    match self.write_locks.get(port_name) {
      None => false,
      Some(sid) => sid != sub_id,
    }
  }

  /// Check if sub id has write lock on this port, if it doesn't,
  /// return error
  pub fn check_owns_write_lock(&self, port_name: &String, sub_id: &String) -> Result<()> {
    match self.write_locks.get(port_name) {
      None => Err(ErrorKind::NeedWriteLock(port_name.to_string()).into()),
      Some(sid) => {
        if sid != sub_id {
          Err(ErrorKind::AlreadyWriteLocked(port_name.to_string()).into())
        } else {
          Ok(())
        }
      }
    }
  }

  // Clear a write lock, without checking subscriber id
  pub fn clear_lock(&mut self, port_name: &String) {
    self.write_locks.remove(port_name);
  }

  // Release the write lock for the given port and sub id
  pub fn unlock_port(&mut self, port_name: &String, sub_id: &String) -> Result<()> {
    match self.is_port_locked_by_someone_else(port_name, sub_id) {
      false => {
        self.write_locks.remove(port_name);
        Ok(())
      }
      true => Err(ErrorKind::AlreadyWriteLocked(port_name.to_string()).into()),
    }
  }

  pub fn unlock_port_if_locked_by(&mut self, port_name: &String, sub_id: &String) {
    if self.is_port_write_locked_by(port_name, sub_id) {
      // Should not panic since we are the one who locked it
      self.unlock_port(&port_name, sub_id).unwrap();
    }
  }

  // Release all write locks held by this sub_id
  pub fn unlock_all_ports_for_sub(&mut self, sub_id: &String) {
    let mut to_delete = Vec::<String>::new();
    for port_name in self.write_locks.keys() {
      if self
           .write_locks
           .get(port_name)
           .map(|sid| sid == sub_id)
           .unwrap_or(false) {
        to_delete.push(port_name.to_string());
      }
    }
    for delete_port in to_delete.iter() {
      self.write_locks.remove(delete_port);
    }
  }

  // Try and lock the port
  pub fn lock_port(&mut self, port_name: &String, sub_id: &String) -> Result<()> {
    match self.is_port_locked_by_someone_else(port_name, sub_id) {
      false => {
        self
          .write_locks
          .insert(port_name.to_string(), sub_id.to_string());
        Ok(())
      }
      true => Err(ErrorKind::AlreadyWriteLocked(port_name.to_string()).into()),
    }

  }
}

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

  #[test]
  fn test_locking() {

    /// Utility method
    fn check_not_locked_by_anyone(
      wl_manager: &WriteLockManager,
      port: &String,
      sub_ids: Vec<&String>,
    ) {
      for sub_id in sub_ids.iter() {
        assert_eq!(
          false,
          wl_manager.is_port_write_locked_by(port, sub_id),
          "Port '{}' should not be locked by '{}'",
          port,
          sub_id
        );
        assert_eq!(
          false,
          wl_manager.is_port_locked_by_someone_else(port, sub_id),
          "Port '{}' should not be locked by someone else",
          port
        );

      }
    }

    /// Utility method
    fn check_locked_by_sub(
      wl_manager: &WriteLockManager,
      port: &String,
      sub_locker: &String,
      sub_ids: Vec<&String>,
    ) {
      assert_eq!(
        true,
        wl_manager.is_port_write_locked_by(port, sub_locker),
        "Port '{}' should not be locked by '{}'",
        port,
        sub_locker
      );
      for sub_id in sub_ids.iter() {
        assert_eq!(
          true,
          wl_manager.is_port_locked_by_someone_else(port, sub_id),
          "Port '{}' should not be locked by someone else",
          port
        );
      }
    }

    let wl_manager = &mut WriteLockManager::new();
    let sub_id1: String = "SUB_ID1".to_owned();
    let sub_id3: String = "SUB_ID2".to_owned();
    let sub_id2: String = "SUB_ID3".to_owned();
    let port: String = "/dev/TTY_USB".to_owned();
    // Ports should not be locked
    check_not_locked_by_anyone(&wl_manager, &port, vec![&sub_id1, &sub_id2, &sub_id3]);
    // sub_id1 locking a port should work
    assert_eq!(
      true,
      wl_manager
        .lock_port(&port, &sub_id1)
        .map(|_| true)
        .unwrap_or(false),
      "Sub_id '{}' locking port '{}' should succeed",
      sub_id1,
      port
    );
    //Port should now be locked by sub_id1
    check_locked_by_sub(&wl_manager, &port, &sub_id1, vec![&sub_id2, &sub_id3]);
    // sub_id2 should fail locking port already locked
    assert_eq!(
      true,
      wl_manager
        .lock_port(&port, &sub_id2)
        .map(|_| false)
        .unwrap_or(true),
      "Sub_id '{}' locking port '{}' should fail",
      sub_id1,
      port
    );
    // sub_id2 should fail unlocking port locked by sub_id1
    assert_eq!(
      true,
      wl_manager
        .unlock_port(&port, &sub_id2)
        .map(|_| false)
        .unwrap_or(true),
      "Sub_id '{}' unlocking port '{}' should fail",
      sub_id1,
      port
    );
    // sub_id1 should be able to unlock it
    assert_eq!(
      true,
      wl_manager
        .unlock_port(&port, &sub_id1)
        .map(|_| true)
        .unwrap_or(false),
      "Sub_id '{}' unlocking port '{}' should succeed",
      sub_id1,
      port
    );
    // Ports should not be locked
    check_not_locked_by_anyone(&wl_manager, &port, vec![&sub_id1, &sub_id2, &sub_id3]);
    // TODO: Finish testing all other methods
  }

}
<|endoftext|>


<commit_before>
use std::sync::Mutex;
use rand;
use rand::Rng;
use std::ptr;

static GRID_WDH : i32 = 256;

lazy_static! {
    static ref GRID: Mutex<Vec<u8>> = {
        let mut v = Vec::new();
        v.resize((GRID_WDH * GRID_WDH) as usize, 0);
        Mutex::new(v)
    };
}

#[no_mangle]
pub extern fn gol_randomize() -> () {
    let mut grid = GRID.lock().unwrap();
    let mut rng = rand::thread_rng();

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let idx = (x + y * GRID_WDH) as usize;
            grid[idx] = if rng.gen() { 1 } else { 0 };
        }
    }
}

#[no_mangle]
pub extern fn gol_step() -> () {

    // Allocate new grid without wasting time setting it to any value
    let grid_size = (GRID_WDH * GRID_WDH) as usize;
    let mut new_grid = Vec::with_capacity(grid_size);
    unsafe { new_grid.set_len(grid_size); }

    let mut grid = GRID.lock().unwrap();

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let torus_idx = |x: i32, y: i32| -> u8 {
                let wrapx = if x < 0 { GRID_WDH - 1 } else { if x > GRID_WDH - 1 { 0 } else { x } };
                let wrapy = if y < 0 { GRID_WDH - 1 } else { if y > GRID_WDH - 1 { 0 } else { y } };
                let idx = wrapx + wrapy * GRID_WDH;
                grid[idx as usize]
            };

            let idx = (x + y * GRID_WDH) as usize;
            let alive = grid[idx];
            let alive_nb = torus_idx(x + 1, y    ) +
                           torus_idx(x    , y + 1) +
                           torus_idx(x - 1, y    ) +
                           torus_idx(x    , y - 1) +
                           torus_idx(x + 1, y + 1) +
                           torus_idx(x - 1, y - 1) +
                           torus_idx(x + 1, y - 1) +
                           torus_idx(x - 1, y + 1);

            new_grid[idx] = if alive_nb == 3 || (alive == 1 && alive_nb == 2) { 1 } else { 0 };
        }
    }

    * grid = new_grid;
}

#[no_mangle]
pub extern fn gol_draw(w: i32, h: i32, fb: *mut u32) -> () {

    // Clear background
    unsafe { ptr::write_bytes(fb, 64, (w * h) as usize); }

    let grid = GRID.lock().unwrap();

    // Center
    let xoffs = w / 2 - GRID_WDH / 2;
    let yoffs = h / 2 - GRID_WDH / 2;

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let idx_fb = (xoffs + x) + (yoffs + y) * w;

            // Out of bounds check for the FB
            if idx_fb < 0 || idx_fb > w * h - 1 { continue; }

            let idx_grid = x + y * GRID_WDH;

            unsafe {
                * fb.offset(idx_fb as isize) =
                    if grid[idx_grid as usize] == 1 { 0x00FFFFFF } else { 0 };
            }
        }
    }
}

#[no_mangle]
pub extern fn gol_set_pattern(w: i32, h: i32, pat: *mut u8) -> () {

    let mut grid = GRID.lock().unwrap();

    // Clear grid
    let grid_size = GRID_WDH * GRID_WDH;
    grid.clear();
    grid.resize(grid_size as usize, 0);

    // Center
    let xoffs = GRID_WDH / 2 - w / 2;
    let yoffs = GRID_WDH / 2 - h / 2;

    for y in 0..h {
        for x in 0..w {
            let idx_grid = (xoffs + x) + (yoffs + y) * GRID_WDH;

            // Out of bounds check for the grid
            if idx_grid < 0 || idx_grid > grid_size - 1 { continue; }

            let idx_pat = x + y * w;
            unsafe { grid[idx_grid as usize] = * pat.offset(idx_pat as isize); }
        }
    }
}

<commit_msg>Split GoL computation into interior and boundary regions, using 1D and 2D indexing, respectively<commit_after>
use std::sync::Mutex;
use rand;
use rand::Rng;
use std::ptr;

static GRID_WDH : i32 = 256;

lazy_static! {
    static ref GRID: Mutex<Vec<u8>> = {
        let mut v = Vec::new();
        v.resize((GRID_WDH * GRID_WDH) as usize, 0);
        Mutex::new(v)
    };
}

#[no_mangle]
pub extern fn gol_randomize() -> () {
    let mut grid = GRID.lock().unwrap();
    let mut rng = rand::thread_rng();

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let idx = (x + y * GRID_WDH) as usize;
            grid[idx] = if rng.gen() { 1 } else { 0 };
        }
    }
}

#[no_mangle]
pub extern fn gol_step() -> () {
    // Allocate new grid without wasting time setting it to any value
    let grid_size = (GRID_WDH * GRID_WDH) as usize;
    let mut new_grid = Vec::with_capacity(grid_size);
    unsafe { new_grid.set_len(grid_size); }

    let mut grid = GRID.lock().unwrap();

    // Compute the four borders
    for side in 0..4 {
        let mut x;
        let mut y;
        let xincr;
        let yincr;
        match side {
            0 => { x = 0           ; y = 0           ; xincr = 1; yincr = 0; },
            1 => { x = 0           ; y = GRID_WDH - 1; xincr = 1; yincr = 0; },
            2 => { x = 0           ; y = 0           ; xincr = 0; yincr = 1; },
            3 => { x = GRID_WDH - 1; y = 0           ; xincr = 0; yincr = 1; },
            _ => panic!("invalid side")
        }

        while x < GRID_WDH && y < GRID_WDH {
            // We're at the boundary, wrap
            let torus_idx = |x: i32, y: i32| -> u8 {
                let wrapx = if x < 0 { GRID_WDH - 1 } else { if x > GRID_WDH - 1 { 0 } else { x } };
                let wrapy = if y < 0 { GRID_WDH - 1 } else { if y > GRID_WDH - 1 { 0 } else { y } };
                let idx = wrapx + wrapy * GRID_WDH;
                grid[idx as usize]
            };

            // 2D indexing, faster to wrap
            let idx = (x + y * GRID_WDH) as usize;
            let alive = grid[idx];
            let alive_nb = torus_idx(x + 1, y    ) +
                           torus_idx(x    , y + 1) +
                           torus_idx(x - 1, y    ) +
                           torus_idx(x    , y - 1) +
                           torus_idx(x + 1, y + 1) +
                           torus_idx(x - 1, y - 1) +
                           torus_idx(x + 1, y - 1) +
                           torus_idx(x - 1, y + 1);

            new_grid[idx] = if alive_nb == 3 || (alive == 1 && alive_nb == 2) { 1 } else { 0 };

            x += xincr;
            y += yincr;
        }
    }

    // Compute interior
    for y in 1..GRID_WDH - 1 {
        for x in 1..GRID_WDH - 1 {
            // 1D indexing, no wrapping needed
            let idx = x + y * GRID_WDH;
            let alive = grid[idx as usize];
            let alive_nb = grid[(idx + 1           ) as usize] +
                           grid[(idx - 1           ) as usize] +
                           grid[(idx     + GRID_WDH) as usize] +
                           grid[(idx     - GRID_WDH) as usize] +
                           grid[(idx + 1 + GRID_WDH) as usize] +
                           grid[(idx + 1 - GRID_WDH) as usize] +
                           grid[(idx - 1 + GRID_WDH) as usize] +
                           grid[(idx - 1 - GRID_WDH) as usize];

            new_grid[idx as usize] =
                if alive_nb == 3 || (alive == 1 && alive_nb == 2) { 1 } else { 0 };
        }
    }

    * grid = new_grid;
}

#[no_mangle]
pub extern fn gol_draw(w: i32, h: i32, fb: *mut u32) -> () {
    // Clear background
    unsafe { ptr::write_bytes(fb, 64, (w * h) as usize); }

    let grid = GRID.lock().unwrap();

    // Center
    let xoffs = w / 2 - GRID_WDH / 2;
    let yoffs = h / 2 - GRID_WDH / 2;

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let idx_fb = (xoffs + x) + (yoffs + y) * w;

            // Out of bounds check for the FB
            if idx_fb < 0 || idx_fb > w * h - 1 { continue; }

            let idx_grid = x + y * GRID_WDH;

            unsafe {
                * fb.offset(idx_fb as isize) =
                    if grid[idx_grid as usize] == 1 { 0x00FFFFFF } else { 0 };
            }
        }
    }
}

#[no_mangle]
pub extern fn gol_set_pattern(w: i32, h: i32, pat: *mut u8) -> () {
    let mut grid = GRID.lock().unwrap();

    // Clear grid
    let grid_size = GRID_WDH * GRID_WDH;
    grid.clear();
    grid.resize(grid_size as usize, 0);

    // Center
    let xoffs = GRID_WDH / 2 - w / 2;
    let yoffs = GRID_WDH / 2 - h / 2;

    for y in 0..h {
        for x in 0..w {
            let idx_grid = (xoffs + x) + (yoffs + y) * GRID_WDH;

            // Out of bounds check for the grid
            if idx_grid < 0 || idx_grid > grid_size - 1 { continue; }

            let idx_pat = x + y * w;
            unsafe { grid[idx_grid as usize] = * pat.offset(idx_pat as isize); }
        }
    }
}

<|endoftext|>


<commit_before>#![feature(async_await)]
#![feature(test)]
#![deny(warnings)]

extern crate test;

use std::net::SocketAddr;

use futures_util::future::join_all;
use tokio::runtime::current_thread::Runtime;

use hyper::{Body, Method, Request, Response, Server};
use hyper::client::HttpConnector;

#[bench]
fn http1_get(b: &mut test::Bencher) {
    opts()
        .bench(b)
}

#[bench]
fn http1_post(b: &mut test::Bencher) {
    opts()
        .method(Method::POST)
        .request_body(b"foo bar baz quux")
        .bench(b)
}

#[bench]
fn http1_body_both_100kb(b: &mut test::Bencher) {
    let body = &[b'x'; 1024 * 100];
    opts()
        .method(Method::POST)
        .request_body(body)
        .response_body(body)
        .bench(b)
}

#[bench]
fn http1_body_both_10mb(b: &mut test::Bencher) {
    let body = &[b'x'; 1024 * 1024 * 10];
    opts()
        .method(Method::POST)
        .request_body(body)
        .response_body(body)
        .bench(b)
}

#[bench]
fn http1_parallel_x10_empty(b: &mut test::Bencher) {
    opts()
        .parallel(10)
        .bench(b)
}

#[bench]
fn http1_parallel_x10_req_10mb(b: &mut test::Bencher) {
    let body = &[b'x'; 1024 * 1024 * 10];
    opts()
        .parallel(10)
        .method(Method::POST)
        .request_body(body)
        .bench(b)
}

#[bench]
fn http2_get(b: &mut test::Bencher) {
    opts()
        .http2()
        .bench(b)
}

#[bench]
fn http2_post(b: &mut test::Bencher) {
    opts()
        .http2()
        .method(Method::POST)
        .request_body(b"foo bar baz quux")
        .bench(b)
}

#[bench]
fn http2_req_100kb(b: &mut test::Bencher) {
    let body = &[b'x'; 1024 * 100];
    opts()
        .http2()
        .method(Method::POST)
        .request_body(body)
        .bench(b)
}

#[bench]
fn http2_parallel_x10_empty(b: &mut test::Bencher) {
    opts()
        .http2()
        .parallel(10)
        .bench(b)
}

#[bench]
fn http2_parallel_x10_req_10mb(b: &mut test::Bencher) {
    let body = &[b'x'; 1024 * 1024 * 10];
    opts()
        .http2()
        .parallel(10)
        .method(Method::POST)
        .request_body(body)
        .http2_stream_window(std::u32::MAX >> 1)
        .http2_conn_window(std::u32::MAX >> 1)
        .bench(b)
}

// ==== Benchmark Options =====

struct Opts {
    http2: bool,
    http2_stream_window: Option<u32>,
    http2_conn_window: Option<u32>,
    parallel_cnt: u32,
    request_method: Method,
    request_body: Option<&'static [u8]>,
    response_body: &'static [u8],
}

fn opts() -> Opts {
    Opts {
        http2: false,
        http2_stream_window: None,
        http2_conn_window: None,
        parallel_cnt: 1,
        request_method: Method::GET,
        request_body: None,
        response_body: b"Hello",
    }
}

impl Opts {
    fn http2(mut self) -> Self {
        self.http2 = true;
        self
    }

    fn http2_stream_window(mut self, sz: impl Into<Option<u32>>) -> Self {
        self.http2_stream_window = sz.into();
        self
    }

    fn http2_conn_window(mut self, sz: impl Into<Option<u32>>) -> Self {
        self.http2_conn_window = sz.into();
        self
    }

    fn method(mut self, m: Method) -> Self {
        self.request_method = m;
        self
    }

    fn request_body(mut self, body: &'static [u8]) -> Self {
        self.request_body = Some(body);
        self
    }

    fn response_body(mut self, body: &'static [u8]) -> Self {
        self.response_body = body;
        self
    }

    fn parallel(mut self, cnt: u32) -> Self {
        assert!(cnt > 0, "parallel count must be larger than 0");
        self.parallel_cnt = cnt;
        self
    }

    fn bench(self, b: &mut test::Bencher) {
        let _ = pretty_env_logger::try_init();
        // Create a runtime of current thread.
        let mut rt = Runtime::new().unwrap();

        b.bytes = self.response_body.len() as u64 + self.request_body.map(|b| b.len()).unwrap_or(0) as u64;

        let addr = spawn_server(&mut rt, &self);

        let connector = HttpConnector::new(1);
        let client = hyper::Client::builder()
            .http2_only(self.http2)
            .http2_initial_stream_window_size(self.http2_stream_window)
            .http2_initial_connection_window_size(self.http2_conn_window)
            .build::<_, Body>(connector);

        let url: hyper::Uri = format!("http://{}/hello", addr).parse().unwrap();

        let make_request = || {
            let body = self
                .request_body
                .map(Body::from)
                .unwrap_or_else(|| Body::empty());
            let mut req = Request::new(body);
            *req.method_mut() = self.request_method.clone();
            *req.uri_mut() = url.clone();
            req
        };

        let send_request = |req: Request<Body>| {
            let fut = client.request(req);
            async {
                let res = fut.await.expect("client wait");
                let mut body = res.into_body();
                while let Some(_chunk) = body.next().await {}
            }
        };

        if self.parallel_cnt == 1 {
            b.iter(|| {
                let req = make_request();
                rt.block_on(send_request(req));
            });

        } else {
            b.iter(|| {
                let futs = (0..self.parallel_cnt)
                    .map(|_| {
                        let req = make_request();
                        send_request(req)
                    });
                // Await all spawned futures becoming completed.
                rt.block_on(join_all(futs));
            });
        }
    }
}

fn spawn_server(rt: &mut Runtime, opts: &Opts) -> SocketAddr {
    use hyper::service::{make_service_fn, service_fn};
    let addr = "127.0.0.1:0".parse().unwrap();

    let body = opts.response_body;
    let srv = Server::bind(&addr)
        .http2_only(opts.http2)
        .http2_initial_stream_window_size_(opts.http2_stream_window)
        .http2_initial_connection_window_size_(opts.http2_conn_window)
        .serve(make_service_fn( move |_| async move {
            Ok::<_, hyper::Error>(service_fn(move |req: Request<Body>| async move {
                let mut req_body = req.into_body();
                while let Some(_chunk) = req_body.next().await {}
                Ok::<_, hyper::Error>(Response::new(Body::from(body)))
            }))
        }));
    let addr = srv.local_addr();
    rt.spawn(async {
        if let Err(err) = srv.await {
            panic!("server error: {}", err);
        }
    });
    return addr
}
<commit_msg>test(end_to_end): ignore unimplemented h2 benchmarks<commit_after>#![feature(async_await)]
#![feature(test)]
#![deny(warnings)]

extern crate test;

use std::net::SocketAddr;

use futures_util::future::join_all;
use tokio::runtime::current_thread::Runtime;

use hyper::{Body, Method, Request, Response, Server};
use hyper::client::HttpConnector;

#[bench]
fn http1_get(b: &mut test::Bencher) {
    opts()
        .bench(b)
}

#[bench]
fn http1_post(b: &mut test::Bencher) {
    opts()
        .method(Method::POST)
        .request_body(b"foo bar baz quux")
        .bench(b)
}

#[bench]
fn http1_body_both_100kb(b: &mut test::Bencher) {
    let body = &[b'x'; 1024 * 100];
    opts()
        .method(Method::POST)
        .request_body(body)
        .response_body(body)
        .bench(b)
}

#[bench]
fn http1_body_both_10mb(b: &mut test::Bencher) {
    let body = &[b'x'; 1024 * 1024 * 10];
    opts()
        .method(Method::POST)
        .request_body(body)
        .response_body(body)
        .bench(b)
}

#[bench]
fn http1_parallel_x10_empty(b: &mut test::Bencher) {
    opts()
        .parallel(10)
        .bench(b)
}

#[bench]
fn http1_parallel_x10_req_10mb(b: &mut test::Bencher) {
    let body = &[b'x'; 1024 * 1024 * 10];
    opts()
        .parallel(10)
        .method(Method::POST)
        .request_body(body)
        .bench(b)
}

#[bench]
#[ignore]
fn http2_get(b: &mut test::Bencher) {
    // FIXME: re-implement tests when `h2` upgrades to `async/await`
    opts()
        .http2()
        .bench(b)
}

#[bench]
#[ignore]
fn http2_post(b: &mut test::Bencher) {
    // FIXME: re-implement tests when `h2` upgrades to `async/await`
    opts()
        .http2()
        .method(Method::POST)
        .request_body(b"foo bar baz quux")
        .bench(b)
}

#[bench]
#[ignore]
fn http2_req_100kb(b: &mut test::Bencher) {
    // FIXME: re-implement tests when `h2` upgrades to `async/await`
    let body = &[b'x'; 1024 * 100];
    opts()
        .http2()
        .method(Method::POST)
        .request_body(body)
        .bench(b)
}

#[bench]
#[ignore]
fn http2_parallel_x10_empty(b: &mut test::Bencher) {
    // FIXME: re-implement tests when `h2` upgrades to `async/await`
    opts()
        .http2()
        .parallel(10)
        .bench(b)
}

#[bench]
#[ignore]
fn http2_parallel_x10_req_10mb(b: &mut test::Bencher) {
    // FIXME: re-implement tests when `h2` upgrades to `async/await`
    let body = &[b'x'; 1024 * 1024 * 10];
    opts()
        .http2()
        .parallel(10)
        .method(Method::POST)
        .request_body(body)
        .http2_stream_window(std::u32::MAX >> 1)
        .http2_conn_window(std::u32::MAX >> 1)
        .bench(b)
}

// ==== Benchmark Options =====

struct Opts {
    http2: bool,
    http2_stream_window: Option<u32>,
    http2_conn_window: Option<u32>,
    parallel_cnt: u32,
    request_method: Method,
    request_body: Option<&'static [u8]>,
    response_body: &'static [u8],
}

fn opts() -> Opts {
    Opts {
        http2: false,
        http2_stream_window: None,
        http2_conn_window: None,
        parallel_cnt: 1,
        request_method: Method::GET,
        request_body: None,
        response_body: b"Hello",
    }
}

impl Opts {
    fn http2(mut self) -> Self {
        self.http2 = true;
        self
    }

    fn http2_stream_window(mut self, sz: impl Into<Option<u32>>) -> Self {
        self.http2_stream_window = sz.into();
        self
    }

    fn http2_conn_window(mut self, sz: impl Into<Option<u32>>) -> Self {
        self.http2_conn_window = sz.into();
        self
    }

    fn method(mut self, m: Method) -> Self {
        self.request_method = m;
        self
    }

    fn request_body(mut self, body: &'static [u8]) -> Self {
        self.request_body = Some(body);
        self
    }

    fn response_body(mut self, body: &'static [u8]) -> Self {
        self.response_body = body;
        self
    }

    fn parallel(mut self, cnt: u32) -> Self {
        assert!(cnt > 0, "parallel count must be larger than 0");
        self.parallel_cnt = cnt;
        self
    }

    fn bench(self, b: &mut test::Bencher) {
        let _ = pretty_env_logger::try_init();
        // Create a runtime of current thread.
        let mut rt = Runtime::new().unwrap();

        b.bytes = self.response_body.len() as u64 + self.request_body.map(|b| b.len()).unwrap_or(0) as u64;

        let addr = spawn_server(&mut rt, &self);

        let connector = HttpConnector::new(1);
        let client = hyper::Client::builder()
            .http2_only(self.http2)
            .http2_initial_stream_window_size(self.http2_stream_window)
            .http2_initial_connection_window_size(self.http2_conn_window)
            .build::<_, Body>(connector);

        let url: hyper::Uri = format!("http://{}/hello", addr).parse().unwrap();

        let make_request = || {
            let body = self
                .request_body
                .map(Body::from)
                .unwrap_or_else(|| Body::empty());
            let mut req = Request::new(body);
            *req.method_mut() = self.request_method.clone();
            *req.uri_mut() = url.clone();
            req
        };

        let send_request = |req: Request<Body>| {
            let fut = client.request(req);
            async {
                let res = fut.await.expect("client wait");
                let mut body = res.into_body();
                while let Some(_chunk) = body.next().await {}
            }
        };

        if self.parallel_cnt == 1 {
            b.iter(|| {
                let req = make_request();
                rt.block_on(send_request(req));
            });

        } else {
            b.iter(|| {
                let futs = (0..self.parallel_cnt)
                    .map(|_| {
                        let req = make_request();
                        send_request(req)
                    });
                // Await all spawned futures becoming completed.
                rt.block_on(join_all(futs));
            });
        }
    }
}

fn spawn_server(rt: &mut Runtime, opts: &Opts) -> SocketAddr {
    use hyper::service::{make_service_fn, service_fn};
    let addr = "127.0.0.1:0".parse().unwrap();

    let body = opts.response_body;
    let srv = Server::bind(&addr)
        .http2_only(opts.http2)
        .http2_initial_stream_window_size_(opts.http2_stream_window)
        .http2_initial_connection_window_size_(opts.http2_conn_window)
        .serve(make_service_fn( move |_| async move {
            Ok::<_, hyper::Error>(service_fn(move |req: Request<Body>| async move {
                let mut req_body = req.into_body();
                while let Some(_chunk) = req_body.next().await {}
                Ok::<_, hyper::Error>(Response::new(Body::from(body)))
            }))
        }));
    let addr = srv.local_addr();
    rt.spawn(async {
        if let Err(err) = srv.await {
            panic!("server error: {}", err);
        }
    });
    return addr
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate intmap;
extern crate rand;
extern crate test;

extern crate indexmap;

use indexmap::IndexMap;
use intmap::IntMap;
use std::collections::HashMap;

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

    const VEC_COUNT: usize = 1000;

    // ********** Built in **********

    #[bench]
    fn u64_insert_built_in(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);
        let mut map = HashMap::with_capacity(data.len());

        b.iter(|| {
            map.clear();

            for s in data.iter() {
                test::black_box(map.insert(s, s));
            }
        });
    }

    #[bench]
    fn u64_get_built_in(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);
        let mut map: HashMap<&u64, &u64> = HashMap::with_capacity(data.len());

        for s in data.iter() {
            test::black_box(map.insert(s, s));
        }

        b.iter(|| {
            for s in data.iter() {
                test::black_box({
                    map.contains_key(s);
                });
            }
        });
    }

    // ********** IndexMap **********

    #[bench]
    fn u64_insert_indexmap(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);
        let mut map = IndexMap::with_capacity(data.len());

        b.iter(|| {
            map.clear();

            for s in data.iter() {
                test::black_box(map.insert(s, s));
            }
        });
    }

    #[bench]
    fn u64_get_indexmap(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);
        let mut map: IndexMap<&u64, &u64> = IndexMap::with_capacity(data.len());

        for s in data.iter() {
            test::black_box(map.insert(s, s));
        }

        b.iter(|| {
            for s in data.iter() {
                test::black_box({
                    map.contains_key(s);
                });
            }
        });
    }

    // ********** Intmap **********

    #[bench]
    fn u64_insert_intmap(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);

        let mut map = IntMap::with_capacity(data.len());

        b.iter(|| {
            map.clear();
            for s in data.iter() {
                test::black_box(map.insert(*s, s));
            }
        });
    }

    #[bench]
    fn u64_insert_intmap_entry(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);

        let mut map = IntMap::with_capacity(data.len());

        b.iter(|| {
            map.clear();

            for s in data.iter() {
                test::black_box(match map.entry(*s) {
                    Entry::Occupied(_) => panic!("unexpected while insert, i = {}", s),
                    Entry::Vacant(entry) => entry.insert(s),
                });
            }
        });
    }

    #[bench]
    fn u64_get_intmap(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);

        let mut map = IntMap::with_capacity(data.len());
        for s in data.iter() {
            map.insert(*s, s);
        }

        b.iter(|| {
            for s in data.iter() {
                test::black_box(map.contains_key(*s));
            }
        });
    }

    // ********** Misc **********

    fn get_random_range(count: usize) -> Vec<u64> {
        use rand::prelude::StdRng;
        use rand::{Rng, SeedableRng};

        let mut vec = Vec::new();
        let mut rng = StdRng::seed_from_u64(4242);

        for _ in 0..count {
            vec.push(rng.gen::<u64>());
        }

        vec.sort();
        vec.dedup();

        vec
    }
}
<commit_msg>Add benchmark for resize<commit_after>#![feature(test)]

extern crate intmap;
extern crate rand;
extern crate test;

extern crate indexmap;

use indexmap::IndexMap;
use intmap::IntMap;
use std::collections::HashMap;

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

    const VEC_COUNT: usize = 10_000;

    // ********** Built in **********

    #[bench]
    fn u64_insert_built_in(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);
        let mut map = HashMap::with_capacity(data.len());

        b.iter(|| {
            map.clear();

            for s in data.iter() {
                test::black_box(map.insert(s, s));
            }
        });
    }

    #[bench]
    fn u64_insert_built_in_without_capacity(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);

        b.iter(|| {
            let mut map = HashMap::new();

            for s in data.iter() {
                test::black_box(map.insert(s, s));
            }

            test::black_box(&map);
        });
    }

    #[bench]
    fn u64_get_built_in(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);
        let mut map: HashMap<&u64, &u64> = HashMap::with_capacity(data.len());

        for s in data.iter() {
            test::black_box(map.insert(s, s));
        }

        b.iter(|| {
            for s in data.iter() {
                test::black_box({
                    map.contains_key(s);
                });
            }
        });
    }

    // ********** IndexMap **********

    #[bench]
    fn u64_insert_indexmap(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);
        let mut map = IndexMap::with_capacity(data.len());

        b.iter(|| {
            map.clear();

            for s in data.iter() {
                test::black_box(map.insert(s, s));
            }
        });
    }

    #[bench]
    fn u64_get_indexmap(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);
        let mut map: IndexMap<&u64, &u64> = IndexMap::with_capacity(data.len());

        for s in data.iter() {
            test::black_box(map.insert(s, s));
        }

        b.iter(|| {
            for s in data.iter() {
                test::black_box({
                    map.contains_key(s);
                });
            }
        });
    }

    // ********** Intmap **********

    #[bench]
    fn u64_insert_intmap(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);
        let mut map = IntMap::with_capacity(data.len());

        b.iter(|| {
            map.clear();

            for s in data.iter() {
                test::black_box(map.insert(*s, s));
            }
        });
    }

    #[bench]
    fn u64_insert_intmap_entry(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);

        let mut map = IntMap::with_capacity(data.len());

        b.iter(|| {
            map.clear();

            for s in data.iter() {
                test::black_box(match map.entry(*s) {
                    Entry::Occupied(_) => panic!("unexpected while insert, i = {}", s),
                    Entry::Vacant(entry) => entry.insert(s),
                });
            }
        });
    }

    #[bench]
    fn u64_insert_intmap_without_capacity(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);

        b.iter(|| {
            let mut map = IntMap::new();

            for s in data.iter() {
                test::black_box(map.insert(*s, s));
            }

            test::black_box(&map);
        });
    }

    #[bench]
    fn u64_resize_intmap(b: &mut Bencher) {
        b.iter(|| {
            let mut map: IntMap<u64> = IntMap::new();
            map.reserve(VEC_COUNT);
            test::black_box(&map);
        });
    }

    #[bench]
    fn u64_get_intmap(b: &mut Bencher) {
        let data = get_random_range(VEC_COUNT);

        let mut map = IntMap::with_capacity(data.len());
        for s in data.iter() {
            map.insert(*s, s);
        }

        b.iter(|| {
            for s in data.iter() {
                test::black_box(map.contains_key(*s));
            }
        });
    }

    // ********** Misc **********

    fn get_random_range(count: usize) -> Vec<u64> {
        use rand::prelude::StdRng;
        use rand::{Rng, SeedableRng};

        let mut vec = Vec::new();
        let mut rng = StdRng::seed_from_u64(4242);

        for _ in 0..count {
            vec.push(rng.gen::<u64>());
        }

        vec.sort();
        vec.dedup();

        vec
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "cargo-clippy", allow(clone_on_ref_ptr))]
#![cfg_attr(feature = "cargo-clippy", allow(not_unsafe_ptr_arg_deref))]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]

extern crate cairo;
extern crate cairo_sys;
extern crate cssparser;
extern crate float_cmp;
extern crate glib;
extern crate glib_sys;
extern crate itertools;
extern crate libc;
extern crate nalgebra;
extern crate num_traits;
extern crate owning_ref;
extern crate pango;
extern crate pango_cairo_sys;
extern crate pango_sys;
extern crate pangocairo;
extern crate rayon;
extern crate regex;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate downcast_rs;

pub use color::{rsvg_css_parse_color, ColorKind, ColorSpec};

pub use defs::{rsvg_defs_free, rsvg_defs_lookup, rsvg_defs_new};

pub use drawing_ctx::{
    rsvg_drawing_ctx_add_node_and_ancestors_to_stack,
    rsvg_drawing_ctx_draw_node_from_stack,
    rsvg_drawing_ctx_free,
    rsvg_drawing_ctx_get_ink_rect,
    rsvg_drawing_ctx_new,
};

pub use load::{rsvg_load_new_node, rsvg_load_set_node_atts, rsvg_load_set_svg_node_atts};

pub use node::{
    rsvg_node_add_child,
    rsvg_node_children_iter_begin,
    rsvg_node_children_iter_end,
    rsvg_node_children_iter_next,
    rsvg_node_find_last_chars_child,
    rsvg_node_get_parent,
    rsvg_node_ref,
    rsvg_node_unref,
};

pub use tree::{
    rsvg_tree_cascade,
    rsvg_tree_free,
    rsvg_tree_get_root,
    rsvg_tree_is_root,
    rsvg_tree_new,
    rsvg_tree_root_is_svg,
};

pub use parsers::rsvg_css_parse_number_optional_number;

pub use property_bag::{
    rsvg_property_bag_free,
    rsvg_property_bag_iter_begin,
    rsvg_property_bag_iter_end,
    rsvg_property_bag_iter_next,
    rsvg_property_bag_new,
};

pub use state::rsvg_state_parse_style_pair;

pub use structure::rsvg_node_svg_get_size;

pub use text::{rsvg_node_chars_append, rsvg_node_chars_new};

#[macro_use]
mod log;

#[macro_use]
mod coord_units;

#[macro_use]
mod float_eq_cairo;

#[macro_use]
mod property_macros;

mod aspect_ratio;
mod attributes;
mod bbox;
mod clip_path;
mod color;
mod cond;
mod defs;
mod drawing_ctx;
mod error;
pub mod filters;
mod font_props;
mod gradient;
mod handle;
mod image;
mod iri;
mod length;
mod link;
mod load;
mod marker;
mod mask;
mod node;
mod paint_server;
mod parsers;
mod path_builder;
mod path_parser;
mod pattern;
mod property_bag;
mod rect;
mod shapes;
mod space;
pub mod srgb;
mod state;
mod stop;
mod structure;
pub mod surface_utils;
mod text;
mod transform;
mod tree;
mod unitinterval;
mod util;
mod viewbox;
mod viewport;
<commit_msg>Remove unused macro_use<commit_after>#![cfg_attr(feature = "cargo-clippy", allow(clone_on_ref_ptr))]
#![cfg_attr(feature = "cargo-clippy", allow(not_unsafe_ptr_arg_deref))]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]

extern crate cairo;
extern crate cairo_sys;
extern crate cssparser;
extern crate float_cmp;
extern crate glib;
extern crate glib_sys;
extern crate itertools;
extern crate libc;
extern crate nalgebra;
extern crate num_traits;
extern crate owning_ref;
extern crate pango;
extern crate pango_cairo_sys;
extern crate pango_sys;
extern crate pangocairo;
extern crate rayon;
extern crate regex;

#[macro_use]
extern crate lazy_static;

extern crate downcast_rs;

pub use color::{rsvg_css_parse_color, ColorKind, ColorSpec};

pub use defs::{rsvg_defs_free, rsvg_defs_lookup, rsvg_defs_new};

pub use drawing_ctx::{
    rsvg_drawing_ctx_add_node_and_ancestors_to_stack,
    rsvg_drawing_ctx_draw_node_from_stack,
    rsvg_drawing_ctx_free,
    rsvg_drawing_ctx_get_ink_rect,
    rsvg_drawing_ctx_new,
};

pub use load::{rsvg_load_new_node, rsvg_load_set_node_atts, rsvg_load_set_svg_node_atts};

pub use node::{
    rsvg_node_add_child,
    rsvg_node_children_iter_begin,
    rsvg_node_children_iter_end,
    rsvg_node_children_iter_next,
    rsvg_node_find_last_chars_child,
    rsvg_node_get_parent,
    rsvg_node_ref,
    rsvg_node_unref,
};

pub use tree::{
    rsvg_tree_cascade,
    rsvg_tree_free,
    rsvg_tree_get_root,
    rsvg_tree_is_root,
    rsvg_tree_new,
    rsvg_tree_root_is_svg,
};

pub use parsers::rsvg_css_parse_number_optional_number;

pub use property_bag::{
    rsvg_property_bag_free,
    rsvg_property_bag_iter_begin,
    rsvg_property_bag_iter_end,
    rsvg_property_bag_iter_next,
    rsvg_property_bag_new,
};

pub use state::rsvg_state_parse_style_pair;

pub use structure::rsvg_node_svg_get_size;

pub use text::{rsvg_node_chars_append, rsvg_node_chars_new};

#[macro_use]
mod log;

#[macro_use]
mod coord_units;

#[macro_use]
mod float_eq_cairo;

#[macro_use]
mod property_macros;

mod aspect_ratio;
mod attributes;
mod bbox;
mod clip_path;
mod color;
mod cond;
mod defs;
mod drawing_ctx;
mod error;
pub mod filters;
mod font_props;
mod gradient;
mod handle;
mod image;
mod iri;
mod length;
mod link;
mod load;
mod marker;
mod mask;
mod node;
mod paint_server;
mod parsers;
mod path_builder;
mod path_parser;
mod pattern;
mod property_bag;
mod rect;
mod shapes;
mod space;
pub mod srgb;
mod state;
mod stop;
mod structure;
pub mod surface_utils;
mod text;
mod transform;
mod tree;
mod unitinterval;
mod util;
mod viewbox;
mod viewport;
<|endoftext|>


<commit_before>use parser::ArgumentParser;
use super::StoreOption;
use test_parser::{check_ok,check_err};

#[test]
fn test_opt() {
    let mut val = None;
    let mut ap = ArgumentParser::new();
    ap.refer(&mut val)
      .add_option(["-s", "--set"], box StoreOption::<int>,
        "Set string value");
    assert_eq!(val, None);
    check_ok(&ap, ["./argparse_test"]);
    assert_eq!(val, None);
    check_ok(&ap, ["./argparse_test", "-s", "10"]);
    assert_eq!(val, Some(10i));
    check_ok(&ap, ["./argparse_test", "--set", "11"]);
    assert_eq!(val, Some(11));
    check_err(&ap, ["./argparse_test", "--set"]);
}
<commit_msg>Add a test for StoreOption::<String><commit_after>use parser::ArgumentParser;
use super::StoreOption;
use test_parser::{check_ok,check_err};

#[test]
fn test_opt() {
    let mut val = None;
    let mut ap = ArgumentParser::new();
    ap.refer(&mut val)
      .add_option(["-s", "--set"], box StoreOption::<int>,
        "Set int value");
    assert_eq!(val, None);
    check_ok(&ap, ["./argparse_test"]);
    assert_eq!(val, None);
    check_ok(&ap, ["./argparse_test", "-s", "10"]);
    assert_eq!(val, Some(10i));
    check_ok(&ap, ["./argparse_test", "--set", "11"]);
    assert_eq!(val, Some(11));
    check_err(&ap, ["./argparse_test", "--set"]);
}

#[test]
fn test_str() {
    let mut val = None;
    let mut ap = ArgumentParser::new();
    ap.refer(&mut val)
      .add_option(["-s", "--set"], box StoreOption::<String>,
        "Set string value");
    assert_eq!(val, None);
    check_ok(&ap, ["./argparse_test"]);
    assert_eq!(val, None);
    check_ok(&ap, ["./argparse_test", "-s", "10"]);
    assert_eq!(val, Some("10".to_string()));
    check_ok(&ap, ["./argparse_test", "--set", "11"]);
    assert_eq!(val, Some("11".to_string()));
    check_err(&ap, ["./argparse_test", "--set"]);
}
<|endoftext|>