<commit_before>use crate::entities::*;
use crate::enums::*;
use crate::*;

use std::fs::{create_dir_all, remove_dir_all};
use std::path::Path;
use std::process::Command;
use std::thread::panicking;
use std::time::SystemTime;

extern crate glob;
use glob::glob;

struct Oda {
    temp_path: String,
    input_path: String,
    output_path: String,
    oda_path: String,
}

impl Drop for Oda {
    fn drop(&mut self) {
        if panicking() {
            println!("Test drawings at '{}'", self.temp_path);
        } else {
            remove_dir_all(Path::new(&self.temp_path)).unwrap();
        }
    }
}

impl Oda {
    pub fn convert_drawing(&self, drawing: &Drawing, version: AcadVersion) -> Drawing {
        drawing
            .save_file(&format!("{}/drawing.dxf", self.input_path))
            .unwrap();
        // e.g.,
        //   ODAFileConverter.exe input_dir output_dir ACAD2000 DXF 0 1
        let mut oda_convert = Command::new(&self.oda_path)
            .arg(&self.input_path)
            .arg(&self.output_path)
            .arg(&Oda::version_string(version))
            .arg("DXF")
            .arg("0") // recurse
            .arg("1") // audit
            .spawn()
            .expect("Failed to spawn ODA converter");
        let exit_code = oda_convert
            .wait()
            .expect("Failed to wait for ODA converter");
        assert!(exit_code.success());
        Drawing::load_file(&format!("{}/drawing.dxf", self.output_path)).unwrap()
    }
    fn version_string(version: AcadVersion) -> String {
        let s = match version {
            AcadVersion::R9 => "ACAD9",
            AcadVersion::R10 => "ACAD10",
            AcadVersion::R12 => "ACAD12",
            AcadVersion::R13 => "ACAD13",
            AcadVersion::R14 => "ACAD14",
            AcadVersion::R2000 => "ACAD2000",
            AcadVersion::R2004 => "ACAD2004",
            AcadVersion::R2007 => "ACAD2007",
            AcadVersion::R2010 => "ACAD2010",
            AcadVersion::R2013 => "ACAD2013",
            _ => panic!("Unsupported ODA version {}", version),
        };
        String::from(s)
    }
}

macro_rules! require_oda {
    () => {{
        // Find ODA converter.  Final path looks something like:
        //   C:\Program Files\ODA\ODAFileConverter_title 20.12.0\ODAFileConverter.exe
        let mut full_oda_path = None;
        for entry in glob("C:/Program Files/ODA/ODAFileConverter*/ODAFileConverter.exe")
            .expect("failed to glob for ODA converter")
        {
            match entry {
                Ok(path) if path.is_file() => full_oda_path = Some(path),
                Ok(_) => (),
                Err(_) => (),
            }
        }
        if full_oda_path == None {
            // didn't find ODA converter directory
            return;
        }
        let full_oda_path = full_oda_path.unwrap();

        // make and report temporary directory
        let nanos = format!(
            "{}",
            SystemTime::now()
                .duration_since(SystemTime::UNIX_EPOCH)
                .unwrap()
                .as_nanos()
        );
        let temp_path = format!("{}/integration-tests/{}", env!("OUT_DIR"), nanos);
        let input_path = format!("{}/input", temp_path);
        let output_path = format!("{}/output", temp_path);
        create_dir_all(Path::new(&temp_path)).unwrap();
        create_dir_all(Path::new(&input_path)).unwrap();
        create_dir_all(Path::new(&output_path)).unwrap();
        Oda {
            temp_path,
            input_path,
            output_path,
            oda_path: String::from(full_oda_path.to_str().unwrap()),
        }
    }};
}

#[test]
fn simple_line_can_be_read_by_oda() {
    let oda = require_oda!();
    let mut drawing = Drawing::new();
    drawing.add_entity(Entity {
        common: Default::default(),
        specific: EntityType::Line(Line {
            p1: Point::new(1.0, 2.0, 3.0),
            p2: Point::new(4.0, 5.0, 6.0),
            ..Default::default()
        }),
    });

    let round_tripped = oda.convert_drawing(&drawing, AcadVersion::R2000);
    let entities = round_tripped.entities().collect::<Vec<_>>();
    assert_eq!(1, entities.len());
    match entities[0].specific {
        EntityType::Line(ref line) => {
            assert_eq!(Point::new(1.0, 2.0, 3.0), line.p1);
            assert_eq!(Point::new(4.0, 5.0, 6.0), line.p2);
        }
        _ => panic!("expected a line"),
    }
}
<commit_msg>report error log if ODA converter tests fail<commit_after>use crate::entities::*;
use crate::enums::*;
use crate::*;

use std::fs::{create_dir_all, read_to_string, remove_dir_all};
use std::path::Path;
use std::process::Command;
use std::thread::panicking;
use std::time::SystemTime;

extern crate glob;
use glob::glob;

struct Oda {
    temp_path: String,
    input_path: String,
    output_path: String,
    oda_path: String,
}

impl Drop for Oda {
    fn drop(&mut self) {
        if panicking() {
            println!("Test drawings at '{}'", self.temp_path);
        } else {
            remove_dir_all(Path::new(&self.temp_path)).unwrap();
        }
    }
}

impl Oda {
    pub fn convert_drawing(&self, drawing: &Drawing, version: AcadVersion) -> Drawing {
        drawing
            .save_file(&format!("{}/drawing.dxf", self.input_path))
            .unwrap();
        // e.g.,
        //   ODAFileConverter.exe input_dir output_dir ACAD2000 DXF 0 1
        let mut oda_convert = Command::new(&self.oda_path)
            .arg(&self.input_path)
            .arg(&self.output_path)
            .arg(&Oda::version_string(version))
            .arg("DXF")
            .arg("0") // recurse
            .arg("1") // audit
            .spawn()
            .expect("Failed to spawn ODA converter");
        let exit_code = oda_convert
            .wait()
            .expect("Failed to wait for ODA converter");
        let mut error_messages = String::from("");
        for entry in glob(format!("{}/*.err", &self.output_path).as_str())
            .expect("failed to glob for ODA error logs")
        {
            match entry {
                Ok(path) if path.is_file() => {
                    error_messages.push_str(format!("{}:\n", path.to_str().unwrap()).as_str());
                    let error_contents = read_to_string(path).unwrap();
                    error_messages.push_str(error_contents.as_str());
                    error_messages.push_str("\n\n");
                }
                Ok(_) => (),
                Err(_) => (),
            }
        }
        if !error_messages.is_empty() {
            panic!(format!("Error converting files:\n{}", error_messages));
        }

        assert!(exit_code.success());
        Drawing::load_file(&format!("{}/drawing.dxf", self.output_path)).unwrap()
    }
    fn version_string(version: AcadVersion) -> String {
        let s = match version {
            AcadVersion::R9 => "ACAD9",
            AcadVersion::R10 => "ACAD10",
            AcadVersion::R12 => "ACAD12",
            AcadVersion::R13 => "ACAD13",
            AcadVersion::R14 => "ACAD14",
            AcadVersion::R2000 => "ACAD2000",
            AcadVersion::R2004 => "ACAD2004",
            AcadVersion::R2007 => "ACAD2007",
            AcadVersion::R2010 => "ACAD2010",
            AcadVersion::R2013 => "ACAD2013",
            _ => panic!("Unsupported ODA version {}", version),
        };
        String::from(s)
    }
}

macro_rules! require_oda {
    () => {{
        // Find ODA converter.  Final path looks something like:
        //   C:\Program Files\ODA\ODAFileConverter_title 20.12.0\ODAFileConverter.exe
        let mut full_oda_path = None;
        for entry in glob("C:/Program Files/ODA/ODAFileConverter*/ODAFileConverter.exe")
            .expect("failed to glob for ODA converter")
        {
            match entry {
                Ok(path) if path.is_file() => full_oda_path = Some(path),
                Ok(_) => (),
                Err(_) => (),
            }
        }
        if full_oda_path == None {
            // didn't find ODA converter directory
            return;
        }
        let full_oda_path = full_oda_path.unwrap();

        // make and report temporary directory
        let nanos = format!(
            "{}",
            SystemTime::now()
                .duration_since(SystemTime::UNIX_EPOCH)
                .unwrap()
                .as_nanos()
        );
        let temp_path = format!("{}/integration-tests/{}", env!("OUT_DIR"), nanos);
        let input_path = format!("{}/input", temp_path);
        let output_path = format!("{}/output", temp_path);
        create_dir_all(Path::new(&temp_path)).unwrap();
        create_dir_all(Path::new(&input_path)).unwrap();
        create_dir_all(Path::new(&output_path)).unwrap();
        Oda {
            temp_path,
            input_path,
            output_path,
            oda_path: String::from(full_oda_path.to_str().unwrap()),
        }
    }};
}

#[test]
fn simple_line_can_be_read_by_oda() {
    let oda = require_oda!();
    let mut drawing = Drawing::new();
    drawing.add_entity(Entity {
        common: Default::default(),
        specific: EntityType::Line(Line {
            p1: Point::new(1.0, 2.0, 3.0),
            p2: Point::new(4.0, 5.0, 6.0),
            ..Default::default()
        }),
    });

    let round_tripped = oda.convert_drawing(&drawing, AcadVersion::R2000);
    let entities = round_tripped.entities().collect::<Vec<_>>();
    assert_eq!(1, entities.len());
    match entities[0].specific {
        EntityType::Line(ref line) => {
            assert_eq!(Point::new(1.0, 2.0, 3.0), line.p1);
            assert_eq!(Point::new(4.0, 5.0, 6.0), line.p2);
        }
        _ => panic!("expected a line"),
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use common::*;
use message;

pub type SegmentId = u32;

pub struct SegmentReader<'self> {
    messageReader : * message::MessageReader<'self>,
    segment : &'self [Word]
}

impl <'self> SegmentReader<'self> {

    pub unsafe fn getStartPtr(&self) -> *Word {
        std::cast::transmute(self.segment.unsafe_ref(0))
    }

    pub unsafe fn containsInterval(&self, from : *Word, to : *Word) -> bool {
        let fromAddr : uint = std::cast::transmute(from);
        let toAddr : uint = std::cast::transmute(to);
        let thisBegin : uint = std::cast::transmute(self.segment.unsafe_ref(0));
        let thisEnd : uint = std::cast::transmute(
            self.segment.unsafe_ref(self.segment.len()));
        return (fromAddr >= thisBegin && toAddr <= thisEnd);
        // TODO readLimiter
    }
}

pub struct SegmentBuilder {
    messageBuilder : *mut message::MessageBuilder,
    id : SegmentId,
    ptr : *mut Word,
    pos : WordCount,
    size : WordCount
}

impl SegmentBuilder {

    pub fn new(messageBuilder : *mut message::MessageBuilder,
               size : WordCount) -> SegmentBuilder {
        let idx = unsafe {((*messageBuilder).segments.len() - 1) as SegmentId};
        SegmentBuilder {
            messageBuilder : messageBuilder,
            ptr : unsafe {(*messageBuilder).segments[idx].unsafe_mut_ref(0)},
            id : idx,
            pos : 0,
            size : size
        }
    }

    pub fn getWordOffsetTo(&mut self, ptr : *mut Word) -> WordCount {
        let thisAddr : uint = self.ptr.to_uint();
        let ptrAddr : uint = ptr.to_uint();
        assert!(ptrAddr >= thisAddr);
        let result = (ptrAddr - thisAddr) / BYTES_PER_WORD;
        return result;
    }

    pub fn allocate(&mut self, amount : WordCount) -> Option<*mut Word> {
        if (amount > self.size - self.pos) {
            return None;
        } else {
            let result = unsafe { self.ptr.offset(self.pos as int) };
            self.pos += amount;
            return Some(result);
        }
    }

    pub fn available(&self) -> WordCount {
        self.size - self.pos
    }

    #[inline]
    pub unsafe fn getPtrUnchecked(&mut self, offset : WordCount) -> *mut Word {
        self.ptr.offset(offset as int)
    }

    pub fn asReader<T>(&mut self, f : &fn(&SegmentReader) -> T) -> T {
        unsafe {
            do (*self.messageBuilder).asReader |messageReader| {
                f(&SegmentReader {
                        messageReader : std::ptr::to_unsafe_ptr(messageReader),
                        segment : messageReader.segments[self.id]
                    })
            }
        }
    }
}

pub trait Arena<'a> {
    fn tryGetSegment(&self, id : SegmentId) -> *SegmentReader<'a>;
}

pub struct ReaderArena<'a> {
    message : message::MessageReader<'a>,
    segment0 : SegmentReader<'a>,

    moreSegments : Option<~[SegmentReader<'a>]>
    //XXX should this be a map as in capnproto-c++?
}

impl <'a> Arena<'a> for ReaderArena<'a> {
    fn tryGetSegment(&self, id : SegmentId) -> *SegmentReader<'a> {
        if (id == 0) {
            return std::ptr::to_unsafe_ptr(&self.segment0);
        } else {
            match self.moreSegments {
                None => {fail!("no segments!")}
                Some(ref segs) => {
                    unsafe {segs.unsafe_ref(id as uint - 1)}
                }
            }
        }
    }
}

pub struct BuilderArena<'a> {
    message : *message::MessageBuilder,
    segment0 : SegmentBuilder
}

impl <'a> Arena<'a> for BuilderArena<'a> {
    fn tryGetSegment(&self, _id : SegmentId) -> *SegmentReader<'a> {
        fail!()
    }
}
<commit_msg>didn't need that<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use common::*;
use message;

pub type SegmentId = u32;

pub struct SegmentReader<'self> {
    messageReader : * message::MessageReader<'self>,
    segment : &'self [Word]
}

impl <'self> SegmentReader<'self> {

    pub unsafe fn getStartPtr(&self) -> *Word {
        self.segment.unsafe_ref(0)
    }

    pub unsafe fn containsInterval(&self, from : *Word, to : *Word) -> bool {
        let fromAddr : uint = std::cast::transmute(from);
        let toAddr : uint = std::cast::transmute(to);
        let thisBegin : uint = std::cast::transmute(self.segment.unsafe_ref(0));
        let thisEnd : uint = std::cast::transmute(
            self.segment.unsafe_ref(self.segment.len()));
        return (fromAddr >= thisBegin && toAddr <= thisEnd);
        // TODO readLimiter
    }
}

pub struct SegmentBuilder {
    messageBuilder : *mut message::MessageBuilder,
    id : SegmentId,
    ptr : *mut Word,
    pos : WordCount,
    size : WordCount
}

impl SegmentBuilder {

    pub fn new(messageBuilder : *mut message::MessageBuilder,
               size : WordCount) -> SegmentBuilder {
        let idx = unsafe {((*messageBuilder).segments.len() - 1) as SegmentId};
        SegmentBuilder {
            messageBuilder : messageBuilder,
            ptr : unsafe {(*messageBuilder).segments[idx].unsafe_mut_ref(0)},
            id : idx,
            pos : 0,
            size : size
        }
    }

    pub fn getWordOffsetTo(&mut self, ptr : *mut Word) -> WordCount {
        let thisAddr : uint = self.ptr.to_uint();
        let ptrAddr : uint = ptr.to_uint();
        assert!(ptrAddr >= thisAddr);
        let result = (ptrAddr - thisAddr) / BYTES_PER_WORD;
        return result;
    }

    pub fn allocate(&mut self, amount : WordCount) -> Option<*mut Word> {
        if (amount > self.size - self.pos) {
            return None;
        } else {
            let result = unsafe { self.ptr.offset(self.pos as int) };
            self.pos += amount;
            return Some(result);
        }
    }

    pub fn available(&self) -> WordCount {
        self.size - self.pos
    }

    #[inline]
    pub unsafe fn getPtrUnchecked(&mut self, offset : WordCount) -> *mut Word {
        self.ptr.offset(offset as int)
    }

    pub fn asReader<T>(&mut self, f : &fn(&SegmentReader) -> T) -> T {
        unsafe {
            do (*self.messageBuilder).asReader |messageReader| {
                f(&SegmentReader {
                        messageReader : std::ptr::to_unsafe_ptr(messageReader),
                        segment : messageReader.segments[self.id]
                    })
            }
        }
    }
}

pub trait Arena<'a> {
    fn tryGetSegment(&self, id : SegmentId) -> *SegmentReader<'a>;
}

pub struct ReaderArena<'a> {
    message : message::MessageReader<'a>,
    segment0 : SegmentReader<'a>,

    moreSegments : Option<~[SegmentReader<'a>]>
    //XXX should this be a map as in capnproto-c++?
}

impl <'a> Arena<'a> for ReaderArena<'a> {
    fn tryGetSegment(&self, id : SegmentId) -> *SegmentReader<'a> {
        if (id == 0) {
            return std::ptr::to_unsafe_ptr(&self.segment0);
        } else {
            match self.moreSegments {
                None => {fail!("no segments!")}
                Some(ref segs) => {
                    unsafe {segs.unsafe_ref(id as uint - 1)}
                }
            }
        }
    }
}

pub struct BuilderArena<'a> {
    message : *message::MessageBuilder,
    segment0 : SegmentBuilder
}

impl <'a> Arena<'a> for BuilderArena<'a> {
    fn tryGetSegment(&self, _id : SegmentId) -> *SegmentReader<'a> {
        fail!()
    }
}
<|endoftext|>


<commit_before>/*
Copyright (C) 2018-2019 de4dot@gmail.com

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

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

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

use super::enums::FormatterOutputTextKind;
use super::FormatterOutput;
#[cfg(not(feature = "std"))]
use alloc::string::String;

/// Implements [`FormatterOutput`] and writes all output to a string
///
/// [`FormatterOutput`]: trait.FormatterOutput.html
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
pub struct StringOutput {
	sb: String,
}

impl StringOutput {
	/// Constructor
	#[cfg_attr(has_must_use, must_use)]
	#[inline]
	pub fn new() -> Self {
		Self { sb: String::new() }
	}

	/// Constructor
	///
	/// # Arguments
	///
	/// `capacity`: Initial capacity
	#[cfg_attr(has_must_use, must_use)]
	#[inline]
	pub fn with_capacity(capacity: usize) -> Self {
		Self { sb: String::with_capacity(capacity) }
	}

	/// Clears the internal string so this instance can be re-used for the next instruction
	#[cfg_attr(has_must_use, must_use)]
	#[inline]
	pub fn clear(&mut self) {
		self.sb.clear()
	}

	/// Gets the current string
	#[cfg_attr(has_must_use, must_use)]
	#[inline]
	pub fn get(&self) -> &str {
		&self.sb
	}
}

impl FormatterOutput for StringOutput {
	#[inline]
	fn write(&mut self, text: &str, _kind: FormatterOutputTextKind) {
		self.sb.push_str(text);
	}
}
<commit_msg>Fix warning<commit_after>/*
Copyright (C) 2018-2019 de4dot@gmail.com

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

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

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

use super::enums::FormatterOutputTextKind;
use super::FormatterOutput;
#[cfg(not(feature = "std"))]
use alloc::string::String;

/// Implements [`FormatterOutput`] and writes all output to a string
///
/// [`FormatterOutput`]: trait.FormatterOutput.html
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
pub struct StringOutput {
	sb: String,
}

impl StringOutput {
	/// Constructor
	#[cfg_attr(has_must_use, must_use)]
	#[inline]
	pub fn new() -> Self {
		Self { sb: String::new() }
	}

	/// Constructor
	///
	/// # Arguments
	///
	/// `capacity`: Initial capacity
	#[cfg_attr(has_must_use, must_use)]
	#[inline]
	pub fn with_capacity(capacity: usize) -> Self {
		Self { sb: String::with_capacity(capacity) }
	}

	/// Clears the internal string so this instance can be re-used for the next instruction
	#[inline]
	pub fn clear(&mut self) {
		self.sb.clear()
	}

	/// Gets the current string
	#[cfg_attr(has_must_use, must_use)]
	#[inline]
	pub fn get(&self) -> &str {
		&self.sb
	}
}

impl FormatterOutput for StringOutput {
	#[inline]
	fn write(&mut self, text: &str, _kind: FormatterOutputTextKind) {
		self.sb.push_str(text);
	}
}
<|endoftext|>


<commit_before>//! This module provides a simple API over signals implemented with boxed closures.
//!
//! To simplify the API, the implementation is very heavily implemented by macros. As such, the
//! documentation for the API is a bit hidden by the types creates by the macros. The signal allows
//! connecting a single closure that can be signaled multiple times.
//!
//! # Usage
//!
//! This module is all macros, to use it you should declare the create in your main.rs or lib.rs
//! as:
//!
//! ```ignore
//! #[macro_use] extern crate rex_utils;
//! ```
//!
//! # Declaring a signal
//!
//! The first part of the signal API is declaring the signal with the type of the arguments. This
//! is done with the ```signal_decl!``` macro, that accepts a type name and argument types. The
//! created type has three methods. The ```connect(&mut self, f: Box<FnMut(...)>)``` we will
//! discuss later with the ```signal!``` macro. The ```signal(&mut self, ...)``` is used by the owner
//! of the signal to trigger the connected closure. Lastly, a ```new()``` method for creating an
//! instance of signal (the ```Default``` trait can also be used). For example, a "text change"
//! event commonly seen in GUI toolkits would look like this:
//!
//! ```ignore
//! // This is how we will declare the type of the signal. This signal passes an owned string
//! // and an isize.
//! signal_decl!{TextChangedEvent(String, i32)}
//!
//! // Now, let's create a fake textbox that will have this signal. Pretend that we have implemented
//! // the rest.
//! struct TextBox {
//!     on_text_changed: TextChangedEvent,
//! }
//!
//! let tb = TextBox {
//!     on_text_changed: TextChangedEvent::new(),
//!     // Also the default trait can be used:
//!     // on_text_changed: Default::default()
//! };
//!
//! // Let's ignore for now how to connect a closure to a signal.
//! // Now let's signal the closure.
//! tb.on_text_changed.signal("Please enter text".to_string(), 0);
//! ```
//!
//! # Receiving and dispatching signaled signals
//!
//! The second part of the signal API is declaring the signal receiver. The signal receiver can
//! be thought of as the object that the triggered signal is sent to. This helps decouple the
//! closure that is connected to the signal from needing to have a reference to the object the
//! closure will use. This also allows the closure to have a mutable reference and sidestep many
//! lifetime issues with closures used in signals and moves the complexity to the implementation.
//!
//! A signal receiver is declared with the ```signalreceiver_decl!``` macro, that accepts the type
//! of the object that the signal will be "posted" to. The created type has two methods. The first,
//! ```run(& mut self, &mut ObjType)``` to dispatch any incoming signals. Additionally a
//! ```new()``` method to create a type (though the Default trait can also be used).
//! For example, here is how we would create a signal receiver for our App struct:
//!
//! ```ignore
//! struct App {
//!     bytes_changed: i32
//! }
//!
//! signalreceiver_decl!{AppSignalReceiver(App)}
//!
//!
//! // Say we have an instance of our App
//! let app = App { bytes_changed: 0 };
//!
//! // Now let's create an instace of the signal receiver
//! let sr = AppSignalReceiver::new();
//! // Additionally, the Default trait can be used
//! // let sr: AppSignalReceiver = Default::default();
//!
//! // We will ignore for now how signals are connected and posted.
//! // Once a signal is posted, to run the closure that was connected to our object we will use
//! // the run method.
//! sr.run(app)
//! ```
//!
//! # Connecting a closure to a signal on a specific receiver
//!
//! So now we just need to put everything together. For that we will use the last macro,
//! ```signal!(signal_receiver with |obj, type..| <closure body>)```. Though the macro seems to
//! accept a closure the macro really splits it up into 2 seperate closures to allow the decoupling
//! from the signal and the signal receiver. This macro will create the boxed closure that can be
//! passed to the signal's ```connect``` method. Let's continue with the (contrived) example:
//!
//! ```ignore
//! tb.connect(
//!     signal!(sr with |obj, str_changed, index_changed| obj.bytes_changed = str_changed.len())
//! );
//! ```
//!
//! Note: Due to the closure arguments not being proper closure arguments, there is a bit of magic
//! there. Specifically, the type of obj is ```&mut Type```, where Type is the type supplied to
//! the signal_receiver.
//!
//! # Complete Example
//!
//! Here is a complete example based on what we had til now:
//!
//! ```ignore
//! // An event signaled when text is changed in a text box
//! signal_decl!{TextChangedEvent(String, i32)}
//!
//! // A fake text box
//! struct TextBox {
//!     on_text_changed: TextChangedEvent,
//! }
//!
//! // A fake app interested in changed to a text box
//! struct App {
//!     bytes_changed: i32
//! }
//!
//! // The signal receiver for our fake app
//! signalreceiver_decl!{AppSignalReceiver(App)}
//!
//!
//! // Let's create all of our objects
//! let tb = TextBox {
//!     on_text_changed: TextChangedEvent::new(),
//! };
//!
//! let app = App { bytes_changed: 0 };
//!
//! let sr = AppSignalReceiver::new();
//!
//!
//! // Now let's connect a closure to the signal
//! tb.connect(
//!     signal!(sr with |obj, str_changed, index_changed| {
//!         println!("Closure is being run!");
//!         obj.bytes_changed = str_changed.len());
//! });
//!
//! // Now let's signal the closure.
//! tb.on_text_changed.signal("Some text".to_string(), 0);
//!
//! // For now the closure has not run yet!
//! assert_eq!(app.bytes_changed, 0);
//!
//! // Once we let the signal receiver run all the queued closure will be run
//! sr.run(app)
//!
//! assert_eq!(app.bytes_changed, 9);
//! ```

#[macro_use]

/// Internal macro used by the signal module, should not be used.
#[macro_export]
macro_rules! ident_zip_signal {
    ( () ; ( $($id: ident,)* ) ; ( $($idr:ident: $tyr:ty,)* ) ) => {
        pub fn signal( &mut self, $($idr : $tyr,)* ) {
            if let Some(ref mut f) = self.s {
                f($($idr),*);
            }
        }
    };
    ( ($t0:ty, $($ty:ty,)*) ; ($id0:ident, $($id: ident,)*) ; ($($idr:ident: $tyr:ty,)*) ) => {
        ident_zip_signal!{($($ty,)*) ; ($($id,)*) ; ( $($idr: $tyr,)* $id0: $t0, ) }
    }
}

/// A macro used to declare a signals.
///
/// See the documentation in the ```signals``` module for more information.
#[macro_export]
macro_rules! signal_decl {
    ( $name:ident($($t:ty ),*) ) => {

        pub struct $name {
            s: Option<Box<FnMut($($t),*)>>,
        }

        impl $name {
            #[allow(dead_code)]
            pub fn new() -> $name {
                Default::default()
            }

            ident_zip_signal!{($($t,)*) ; (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s,
                t, u, v, w, x, y, z,); ()}

            pub fn connect(&mut self, f: Box<FnMut($($t),*)>) {
                self.s = Some(f);
            }
        }

        impl Default for $name {
            fn default() -> Self {
                $name {
                    s: None,
                }
            }
        }

    }
}

/// A macro used for creating a closure to connect to a signal.
///
/// See the documentation in the ```signals``` module for more information.
#[macro_export]
macro_rules! signal {
    ( $sr:ident with |$obj:ident, $($id:ident),*| $bl:expr ) => ( {
        let sender_clone = $sr.sender.clone();
        Box::new(move |$($id),*| {
            sender_clone.send(Box::new(move |$obj|
                $bl
            )).unwrap();
        })
    })
}

/// A macro used for creating a signal receiver.
///
/// See the documentation in the ```signals``` module for more information.
#[macro_export]
macro_rules! signalreceiver_decl {
    ( $name: ident($t:ty) ) => {
        struct $name {
            receiver: ::std::sync::mpsc::Receiver<Box<FnMut(&mut $t)>>,
            sender: ::std::sync::mpsc::Sender<Box<FnMut(&mut $t)>>,
        }

        impl $name {
            fn new() -> $name {
                let (sender, receiver) = ::std::sync::mpsc::channel();
                $name {
                    sender: sender,
                    receiver: receiver,
                }
            }

            fn run(&mut self, ss: &mut $t) {
                loop {
                    match self.receiver.try_recv() {
                        Ok(mut handler) => handler(ss),
                        Err(_) => break,
                    }
                }
            }
        }
    }
}
<commit_msg>Make the signals run method only need a ref rather than a mut ref<commit_after>//! This module provides a simple API over signals implemented with boxed closures.
//!
//! To simplify the API, the implementation is very heavily implemented by macros. As such, the
//! documentation for the API is a bit hidden by the types creates by the macros. The signal allows
//! connecting a single closure that can be signaled multiple times.
//!
//! # Usage
//!
//! This module is all macros, to use it you should declare the create in your main.rs or lib.rs
//! as:
//!
//! ```ignore
//! #[macro_use] extern crate rex_utils;
//! ```
//!
//! # Declaring a signal
//!
//! The first part of the signal API is declaring the signal with the type of the arguments. This
//! is done with the ```signal_decl!``` macro, that accepts a type name and argument types. The
//! created type has three methods. The ```connect(&mut self, f: Box<FnMut(...)>)``` we will
//! discuss later with the ```signal!``` macro. The ```signal(&mut self, ...)``` is used by the owner
//! of the signal to trigger the connected closure. Lastly, a ```new()``` method for creating an
//! instance of signal (the ```Default``` trait can also be used). For example, a "text change"
//! event commonly seen in GUI toolkits would look like this:
//!
//! ```ignore
//! // This is how we will declare the type of the signal. This signal passes an owned string
//! // and an isize.
//! signal_decl!{TextChangedEvent(String, i32)}
//!
//! // Now, let's create a fake textbox that will have this signal. Pretend that we have implemented
//! // the rest.
//! struct TextBox {
//!     on_text_changed: TextChangedEvent,
//! }
//!
//! let tb = TextBox {
//!     on_text_changed: TextChangedEvent::new(),
//!     // Also the default trait can be used:
//!     // on_text_changed: Default::default()
//! };
//!
//! // Let's ignore for now how to connect a closure to a signal.
//! // Now let's signal the closure.
//! tb.on_text_changed.signal("Please enter text".to_string(), 0);
//! ```
//!
//! # Receiving and dispatching signaled signals
//!
//! The second part of the signal API is declaring the signal receiver. The signal receiver can
//! be thought of as the object that the triggered signal is sent to. This helps decouple the
//! closure that is connected to the signal from needing to have a reference to the object the
//! closure will use. This also allows the closure to have a mutable reference and sidestep many
//! lifetime issues with closures used in signals and moves the complexity to the implementation.
//!
//! A signal receiver is declared with the ```signalreceiver_decl!``` macro, that accepts the type
//! of the object that the signal will be "posted" to. The created type has two methods. The first,
//! ```run(&self, &mut ObjType)``` to dispatch any incoming signals. Additionally a
//! ```new()``` method to create a type (though the Default trait can also be used).
//! For example, here is how we would create a signal receiver for our App struct:
//!
//! ```ignore
//! struct App {
//!     bytes_changed: i32
//! }
//!
//! signalreceiver_decl!{AppSignalReceiver(App)}
//!
//!
//! // Say we have an instance of our App
//! let app = App { bytes_changed: 0 };
//!
//! // Now let's create an instace of the signal receiver
//! let sr = AppSignalReceiver::new();
//! // Additionally, the Default trait can be used
//! // let sr: AppSignalReceiver = Default::default();
//!
//! // We will ignore for now how signals are connected and posted.
//! // Once a signal is posted, to run the closure that was connected to our object we will use
//! // the run method.
//! sr.run(app)
//! ```
//!
//! # Connecting a closure to a signal on a specific receiver
//!
//! So now we just need to put everything together. For that we will use the last macro,
//! ```signal!(signal_receiver with |obj, type..| <closure body>)```. Though the macro seems to
//! accept a closure the macro really splits it up into 2 seperate closures to allow the decoupling
//! from the signal and the signal receiver. This macro will create the boxed closure that can be
//! passed to the signal's ```connect``` method. Let's continue with the (contrived) example:
//!
//! ```ignore
//! tb.connect(
//!     signal!(sr with |obj, str_changed, index_changed| obj.bytes_changed = str_changed.len())
//! );
//! ```
//!
//! Note: Due to the closure arguments not being proper closure arguments, there is a bit of magic
//! there. Specifically, the type of obj is ```&mut Type```, where Type is the type supplied to
//! the signal_receiver.
//!
//! # Complete Example
//!
//! Here is a complete example based on what we had til now:
//!
//! ```ignore
//! // An event signaled when text is changed in a text box
//! signal_decl!{TextChangedEvent(String, i32)}
//!
//! // A fake text box
//! struct TextBox {
//!     on_text_changed: TextChangedEvent,
//! }
//!
//! // A fake app interested in changed to a text box
//! struct App {
//!     bytes_changed: i32
//! }
//!
//! // The signal receiver for our fake app
//! signalreceiver_decl!{AppSignalReceiver(App)}
//!
//!
//! // Let's create all of our objects
//! let tb = TextBox {
//!     on_text_changed: TextChangedEvent::new(),
//! };
//!
//! let app = App { bytes_changed: 0 };
//!
//! let sr = AppSignalReceiver::new();
//!
//!
//! // Now let's connect a closure to the signal
//! tb.connect(
//!     signal!(sr with |obj, str_changed, index_changed| {
//!         println!("Closure is being run!");
//!         obj.bytes_changed = str_changed.len());
//! });
//!
//! // Now let's signal the closure.
//! tb.on_text_changed.signal("Some text".to_string(), 0);
//!
//! // For now the closure has not run yet!
//! assert_eq!(app.bytes_changed, 0);
//!
//! // Once we let the signal receiver run all the queued closure will be run
//! sr.run(app)
//!
//! assert_eq!(app.bytes_changed, 9);
//! ```

#[macro_use]

/// Internal macro used by the signal module, should not be used.
#[macro_export]
macro_rules! ident_zip_signal {
    ( () ; ( $($id: ident,)* ) ; ( $($idr:ident: $tyr:ty,)* ) ) => {
        pub fn signal( &mut self, $($idr : $tyr,)* ) {
            if let Some(ref mut f) = self.s {
                f($($idr),*);
            }
        }
    };
    ( ($t0:ty, $($ty:ty,)*) ; ($id0:ident, $($id: ident,)*) ; ($($idr:ident: $tyr:ty,)*) ) => {
        ident_zip_signal!{($($ty,)*) ; ($($id,)*) ; ( $($idr: $tyr,)* $id0: $t0, ) }
    }
}

/// A macro used to declare a signals.
///
/// See the documentation in the ```signals``` module for more information.
#[macro_export]
macro_rules! signal_decl {
    ( $name:ident($($t:ty ),*) ) => {

        pub struct $name {
            s: Option<Box<FnMut($($t),*)>>,
        }

        impl $name {
            #[allow(dead_code)]
            pub fn new() -> $name {
                Default::default()
            }

            ident_zip_signal!{($($t,)*) ; (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s,
                t, u, v, w, x, y, z,); ()}

            pub fn connect(&mut self, f: Box<FnMut($($t),*)>) {
                self.s = Some(f);
            }
        }

        impl Default for $name {
            fn default() -> Self {
                $name {
                    s: None,
                }
            }
        }

    }
}

/// A macro used for creating a closure to connect to a signal.
///
/// See the documentation in the ```signals``` module for more information.
#[macro_export]
macro_rules! signal {
    ( $sr:ident with |$obj:ident, $($id:ident),*| $bl:expr ) => ( {
        let sender_clone = $sr.sender.clone();
        Box::new(move |$($id),*| {
            sender_clone.send(Box::new(move |$obj|
                $bl
            )).unwrap();
        })
    })
}

/// A macro used for creating a signal receiver.
///
/// See the documentation in the ```signals``` module for more information.
#[macro_export]
macro_rules! signalreceiver_decl {
    ( $name: ident($t:ty) ) => {
        struct $name {
            receiver: ::std::sync::mpsc::Receiver<Box<FnMut(&mut $t)>>,
            sender: ::std::sync::mpsc::Sender<Box<FnMut(&mut $t)>>,
        }

        impl $name {
            fn new() -> $name {
                let (sender, receiver) = ::std::sync::mpsc::channel();
                $name {
                    sender: sender,
                    receiver: receiver,
                }
            }

            fn run(&self, ss: &mut $t) {
                loop {
                    match self.receiver.try_recv() {
                        Ok(mut handler) => handler(ss),
                        Err(_) => break,
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::api::raii::{Publisher, Service, Subscriber};
use crate::api::resolve::get_unused_args;
use crate::api::{Parameter, Rate, Ros, SystemState, Topic};
use crate::error::{ErrorKind, Result};
use crate::rosxmlrpc::Response;
use crate::tcpros::{Client, Message, ServicePair, ServiceResult};
use crate::time::{Duration, Time};
use crate::util::FAILED_TO_LOCK;
use ctrlc;
use lazy_static::lazy_static;
use log::info;
use std::sync::Mutex;
use std::time;

lazy_static! {
    static ref ROS: Mutex<Option<Ros>> = Mutex::new(None);
}

#[inline]
pub fn init(name: &str) {
    try_init(name).expect("ROS init failed!");
}

pub fn try_init(name: &str) -> Result<()> {
    let mut ros = ROS.lock().expect(FAILED_TO_LOCK);
    if ros.is_some() {
        bail!(ErrorKind::MultipleInitialization);
    }
    let client = Ros::new(name)?;
    let shutdown_sender = client.shutdown_sender();
    ctrlc::set_handler(move || {
        if shutdown_sender.send(()).is_err() {
            info!("ROS client is already down");
        }
    })?;
    *ros = Some(client);
    Ok(())
}

macro_rules! ros {
    () => {
        ROS.lock()
            .expect(FAILED_TO_LOCK)
            .as_mut()
            .expect(UNINITIALIZED)
    };
}

#[inline]
pub fn args() -> Vec<String> {
    get_unused_args()
}

#[inline]
pub fn uri() -> String {
    ros!().uri().into()
}

#[inline]
pub fn name() -> String {
    ros!().name().into()
}

#[inline]
pub fn hostname() -> String {
    ros!().hostname().into()
}

#[inline]
pub fn now() -> Time {
    ros!().now()
}

#[inline]
pub fn sleep(d: Duration) {
    ros!().sleep(d)
}

#[inline]
pub fn rate(rate: f64) -> Rate {
    ros!().rate(rate)
}

#[inline]
pub fn is_ok() -> bool {
    ros!().is_ok()
}

#[inline]
pub fn spin() {
    // Spinner drop locks the thread until a kill request is received
    let _spinner = { ros!().spin() };
}

#[inline]
pub fn shutdown() -> bool {
    ros!().shutdown_sender().send(()).is_ok()
}

#[inline]
pub fn param(name: &str) -> Option<Parameter> {
    ros!().param(name)
}

#[inline]
pub fn parameters() -> Response<Vec<String>> {
    ros!().parameters()
}

#[inline]
pub fn state() -> Response<SystemState> {
    ros!().state()
}

#[inline]
pub fn topics() -> Response<Vec<Topic>> {
    ros!().topics()
}

#[inline]
pub fn client<T: ServicePair>(service: &str) -> Result<Client<T>> {
    ros!().client::<T>(service)
}

#[inline]
pub fn wait_for_service(service: &str, timeout: Option<time::Duration>) -> Result<()> {
    ros!().wait_for_service(service, timeout)
}

#[inline]
pub fn service<T, F>(service: &str, handler: F) -> Result<Service>
where
    T: ServicePair,
    F: Fn(T::Request) -> ServiceResult<T::Response> + Send + Sync + 'static,
{
    ros!().service::<T, F>(service, handler)
}

#[inline]
pub fn subscribe<T, F>(topic: &str, queue_size: usize, callback: F) -> Result<Subscriber>
where
    T: Message,
    F: Fn(T) -> () + Send + 'static,
{
    ros!().subscribe::<T, F>(topic, queue_size, callback)
}

#[inline]
pub fn publish<T>(topic: &str, queue_size: usize) -> Result<Publisher<T>>
where
    T: Message,
{
    ros!().publish::<T>(topic, queue_size)
}

#[inline]
pub fn log(level: i8, msg: String, file: &str, line: u32) {
    ros!().log(level, msg, file, line)
}

static UNINITIALIZED: &str = "ROS uninitialized. Please run ros::init(name) first!";
<commit_msg>Allow optionally not capturing SIGINT<commit_after>use crate::api::raii::{Publisher, Service, Subscriber};
use crate::api::resolve::get_unused_args;
use crate::api::{Parameter, Rate, Ros, SystemState, Topic};
use crate::error::{ErrorKind, Result};
use crate::rosxmlrpc::Response;
use crate::tcpros::{Client, Message, ServicePair, ServiceResult};
use crate::time::{Duration, Time};
use crate::util::FAILED_TO_LOCK;
use ctrlc;
use lazy_static::lazy_static;
use log::info;
use std::sync::Mutex;
use std::time;

lazy_static! {
    static ref ROS: Mutex<Option<Ros>> = Mutex::new(None);
}

#[inline]
pub fn init(name: &str) {
    try_init(name).expect("ROS init failed!");
}

#[inline]
pub fn try_init(name: &str) -> Result<()> {
    try_init_with_options(name, true)
}

pub fn try_init_with_options(name: &str, capture_sigint: bool) -> Result<()> {
    let mut ros = ROS.lock().expect(FAILED_TO_LOCK);
    if ros.is_some() {
        bail!(ErrorKind::MultipleInitialization);
    }
    let client = Ros::new(name)?;
    if capture_sigint {
        let shutdown_sender = client.shutdown_sender();
        ctrlc::set_handler(move || {
            if shutdown_sender.send(()).is_err() {
                info!("ROS client is already down");
            }
        })?;
    }
    *ros = Some(client);
    Ok(())
}

macro_rules! ros {
    () => {
        ROS.lock()
            .expect(FAILED_TO_LOCK)
            .as_mut()
            .expect(UNINITIALIZED)
    };
}

#[inline]
pub fn args() -> Vec<String> {
    get_unused_args()
}

#[inline]
pub fn uri() -> String {
    ros!().uri().into()
}

#[inline]
pub fn name() -> String {
    ros!().name().into()
}

#[inline]
pub fn hostname() -> String {
    ros!().hostname().into()
}

#[inline]
pub fn now() -> Time {
    ros!().now()
}

#[inline]
pub fn sleep(d: Duration) {
    ros!().sleep(d)
}

#[inline]
pub fn rate(rate: f64) -> Rate {
    ros!().rate(rate)
}

#[inline]
pub fn is_ok() -> bool {
    ros!().is_ok()
}

#[inline]
pub fn spin() {
    // Spinner drop locks the thread until a kill request is received
    let _spinner = { ros!().spin() };
}

#[inline]
pub fn shutdown() -> bool {
    ros!().shutdown_sender().send(()).is_ok()
}

#[inline]
pub fn param(name: &str) -> Option<Parameter> {
    ros!().param(name)
}

#[inline]
pub fn parameters() -> Response<Vec<String>> {
    ros!().parameters()
}

#[inline]
pub fn state() -> Response<SystemState> {
    ros!().state()
}

#[inline]
pub fn topics() -> Response<Vec<Topic>> {
    ros!().topics()
}

#[inline]
pub fn client<T: ServicePair>(service: &str) -> Result<Client<T>> {
    ros!().client::<T>(service)
}

#[inline]
pub fn wait_for_service(service: &str, timeout: Option<time::Duration>) -> Result<()> {
    ros!().wait_for_service(service, timeout)
}

#[inline]
pub fn service<T, F>(service: &str, handler: F) -> Result<Service>
where
    T: ServicePair,
    F: Fn(T::Request) -> ServiceResult<T::Response> + Send + Sync + 'static,
{
    ros!().service::<T, F>(service, handler)
}

#[inline]
pub fn subscribe<T, F>(topic: &str, queue_size: usize, callback: F) -> Result<Subscriber>
where
    T: Message,
    F: Fn(T) -> () + Send + 'static,
{
    ros!().subscribe::<T, F>(topic, queue_size, callback)
}

#[inline]
pub fn publish<T>(topic: &str, queue_size: usize) -> Result<Publisher<T>>
where
    T: Message,
{
    ros!().publish::<T>(topic, queue_size)
}

#[inline]
pub fn log(level: i8, msg: String, file: &str, line: u32) {
    ros!().log(level, msg, file, line)
}

static UNINITIALIZED: &str = "ROS uninitialized. Please run ros::init(name) first!";
<|endoftext|>


<commit_before>use std::{
    sync::{
        atomic::{AtomicBool, AtomicUsize, Ordering},
        Arc,
    },
    thread,
};

use docopt::Docopt;
use rand::{thread_rng, Rng};
use serde::Deserialize;

#[cfg_attr(
    // only enable jemalloc on linux and macos by default
    all(
        any(target_os = "linux", target_os = "macos"),
        not(feature = "no_jemalloc"),
    ),
    global_allocator
)]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

static TOTAL: AtomicUsize = AtomicUsize::new(0);
static SEQ: AtomicUsize = AtomicUsize::new(0);

const USAGE: &str = "
Usage: stress [--threads=<#>] [--burn-in] [--duration=<s>] \
    [--key-len=<l>] [--val-len=<l>] \
    [--get-prop=<p>] \
    [--set-prop=<p>] \
    [--del-prop=<p>] \
    [--cas-prop=<p>] \
    [--scan-prop=<p>] \
    [--merge-prop=<p>] \
    [--entries=<n>] \
    [--sequential] \
    [--total-ops=<n>]

Options:
    --threads=<#>      Number of threads [default: 4].
    --burn-in          Don't halt until we receive a signal.
    --duration=<s>     Seconds to run for [default: 10].
    --key-len=<l>      The length of keys [default: 10].
    --val-len=<l>      The length of values [default: 100].
    --get-prop=<p>     The relative proportion of get requests [default: 94].
    --set-prop=<p>     The relative proportion of set requests [default: 2].
    --del-prop=<p>     The relative proportion of del requests [default: 1].
    --cas-prop=<p>     The relative proportion of cas requests [default: 1].
    --scan-prop=<p>    The relative proportion of scan requests [default: 1].
    --merge-prop=<p>   The relative proportion of merge requests [default: 1].
    --entries=<n>      The total keyspace [default: 100000].
    --sequential       Run the test in sequential mode instead of random.
    --total-ops=<n>    Stop test after executing a total number of operations.
";

#[derive(Deserialize, Clone)]
struct Args {
    flag_threads: usize,
    flag_burn_in: bool,
    flag_duration: u64,
    flag_key_len: usize,
    flag_val_len: usize,
    flag_get_prop: usize,
    flag_set_prop: usize,
    flag_del_prop: usize,
    flag_cas_prop: usize,
    flag_scan_prop: usize,
    flag_merge_prop: usize,
    flag_entries: usize,
    flag_sequential: bool,
    flag_total_ops: Option<usize>,
}

// defaults will be applied later based on USAGE above
static mut ARGS: Args = Args {
    flag_threads: 0,
    flag_burn_in: false,
    flag_duration: 0,
    flag_key_len: 0,
    flag_val_len: 0,
    flag_get_prop: 0,
    flag_set_prop: 0,
    flag_del_prop: 0,
    flag_cas_prop: 0,
    flag_scan_prop: 0,
    flag_merge_prop: 0,
    flag_entries: 0,
    flag_sequential: false,
    flag_total_ops: None,
};

fn report(shutdown: Arc<AtomicBool>) {
    let mut last = 0;
    while !shutdown.load(Ordering::Relaxed) {
        thread::sleep(std::time::Duration::from_secs(1));
        let total = TOTAL.load(Ordering::Acquire);

        println!("did {} ops, {}mb RSS", total - last, rss() / (1024 * 1024));

        last = total;
    }
}

fn concatenate_merge(
    _key: &[u8],              // the key being merged
    old_value: Option<&[u8]>, // the previous value, if one existed
    merged_bytes: &[u8],      // the new bytes being merged in
) -> Option<Vec<u8>> {
    // set the new value, return None to delete
    let mut ret = old_value.map(|ov| ov.to_vec()).unwrap_or_else(|| vec![]);

    ret.extend_from_slice(merged_bytes);

    Some(ret)
}

fn run(tree: Arc<sled::Db>, shutdown: Arc<AtomicBool>) {
    let args = unsafe { ARGS.clone() };

    let get_max = args.flag_get_prop;
    let set_max = get_max + args.flag_set_prop;
    let del_max = set_max + args.flag_del_prop;
    let cas_max = del_max + args.flag_cas_prop;
    let merge_max = cas_max + args.flag_merge_prop;
    let scan_max = merge_max + args.flag_scan_prop;

    let bytes = |len| -> Vec<u8> {
        let i = if args.flag_sequential {
            SEQ.fetch_add(1, Ordering::Relaxed)
        } else {
            thread_rng().gen::<usize>()
        } % args.flag_entries;

        let i_bytes: [u8; std::mem::size_of::<usize>()] =
            unsafe { std::mem::transmute(i) };

        i_bytes.iter().cycle().take(len).cloned().collect()
    };
    let mut rng = thread_rng();

    while !shutdown.load(Ordering::Relaxed) {
        let op = TOTAL.fetch_add(1, Ordering::Release);
        let key = bytes(args.flag_key_len);
        let choice = rng.gen_range(0, scan_max + 1);

        match choice {
            v if v <= get_max => {
                tree.get(&key).unwrap();
            }
            v if v > get_max && v <= set_max => {
                tree.insert(&key, bytes(args.flag_val_len)).unwrap();
            }
            v if v > set_max && v <= del_max => {
                tree.remove(&key).unwrap();
            }
            v if v > del_max && v <= cas_max => {
                let old_k = bytes(args.flag_val_len);

                let old = if rng.gen::<bool>() {
                    Some(old_k.as_slice())
                } else {
                    None
                };

                let new = if rng.gen::<bool>() {
                    Some(bytes(args.flag_val_len))
                } else {
                    None
                };

                if let Err(e) = tree.compare_and_swap(&key, old, new) {
                    panic!("operational error: {:?}", e);
                }
            }
            v if v > cas_max && v <= merge_max => {
                tree.merge(&key, bytes(args.flag_val_len)).unwrap();
            }
            _ => {
                let iter = tree.range(key..).map(|res| res.unwrap());

                if op % 2 == 0 {
                    let _ = iter.take(rng.gen_range(0, 15)).collect::<Vec<_>>();
                } else {
                    let _ = iter
                        .rev()
                        .take(rng.gen_range(0, 15))
                        .collect::<Vec<_>>();
                }
            }
        }
    }
}

fn rss() -> usize {
    #[cfg(target_os = "linux")]
    {
        use std::io::prelude::*;
        use std::io::BufReader;

        let mut buf = String::new();
        let mut f =
            BufReader::new(std::fs::File::open("/proc/self/statm").unwrap());
        f.read_line(&mut buf).unwrap();
        let mut parts = buf.split_whitespace();
        let rss_pages = parts.nth(1).unwrap().parse::<usize>().unwrap();
        rss_pages * 4096
    }
    #[cfg(not(target_os = "linux"))]
    {
        0
    }
}

fn main() {
    #[cfg(feature = "logging")]
    setup_logger();

    let args = unsafe {
        ARGS = Docopt::new(USAGE)
            .and_then(|d| d.argv(std::env::args()).deserialize())
            .unwrap_or_else(|e| e.exit());
        ARGS.clone()
    };

    let shutdown = Arc::new(AtomicBool::new(false));

    let config = sled::Config::new()
        .cache_capacity(256 * 1024 * 1024)
        .flush_every_ms(Some(200))
        .snapshot_after_ops(100_000_000_000)
        .print_profile_on_drop(true);

    let tree = Arc::new(config.open().unwrap());
    tree.set_merge_operator(concatenate_merge);

    let mut threads = vec![];

    let now = std::time::Instant::now();

    let n_threads = args.flag_threads;

    for i in 0..=n_threads {
        let tree = tree.clone();
        let shutdown = shutdown.clone();

        let t = if i == 0 {
            thread::Builder::new()
                .name("reporter".into())
                .spawn(move || report(shutdown))
                .unwrap()
        } else {
            thread::spawn(move || run(tree, shutdown))
        };

        threads.push(t);
    }

    if let Some(ops) = args.flag_total_ops {
        assert!(!args.flag_burn_in, "don't set both --burn-in and --total-ops");
        while TOTAL.load(Ordering::Relaxed) < ops {
            thread::sleep(std::time::Duration::from_millis(50));
        }
        shutdown.store(true, Ordering::SeqCst);
    } else if !args.flag_burn_in {
        thread::sleep(std::time::Duration::from_secs(unsafe {
            ARGS.flag_duration
        }));
        shutdown.store(true, Ordering::SeqCst);
    }

    for t in threads.into_iter() {
        t.join().unwrap();
    }

    let ops = TOTAL.load(Ordering::SeqCst);
    let time = now.elapsed().as_secs() as usize;

    println!(
        "did {} total ops in {} seconds. {} ops/s",
        ops,
        time,
        (ops * 1_000) / (time * 1_000)
    );
}

#[cfg(feature = "logging")]
pub fn setup_logger() {
    use std::io::Write;

    color_backtrace::install();

    fn tn() -> String {
        std::thread::current().name().unwrap_or("unknown").to_owned()
    }

    let mut builder = env_logger::Builder::new();
    builder
        .format(|buf, record| {
            writeln!(
                buf,
                "{:05} {:25} {:10} {}",
                record.level(),
                tn(),
                record.module_path().unwrap().split("::").last().unwrap(),
                record.args()
            )
        })
        .filter(None, log::LevelFilter::Info);

    if std::env::var("RUST_LOG").is_ok() {
        builder.parse(&std::env::var("RUST_LOG").unwrap());
    }

    let _r = builder.try_init();
}
<commit_msg>optimize key generation in stress2<commit_after>use std::{
    sync::{
        atomic::{AtomicBool, AtomicUsize, Ordering},
        Arc,
    },
    thread,
};

use docopt::Docopt;
use rand::{thread_rng, Rng};
use serde::Deserialize;

#[cfg_attr(
    // only enable jemalloc on linux and macos by default
    all(
        any(target_os = "linux", target_os = "macos"),
        not(feature = "no_jemalloc"),
    ),
    global_allocator
)]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

static TOTAL: AtomicUsize = AtomicUsize::new(0);
static SEQ: AtomicUsize = AtomicUsize::new(0);

const USAGE: &str = "
Usage: stress [--threads=<#>] [--burn-in] [--duration=<s>] \
    [--key-len=<l>] [--val-len=<l>] \
    [--get-prop=<p>] \
    [--set-prop=<p>] \
    [--del-prop=<p>] \
    [--cas-prop=<p>] \
    [--scan-prop=<p>] \
    [--merge-prop=<p>] \
    [--entries=<n>] \
    [--sequential] \
    [--total-ops=<n>]

Options:
    --threads=<#>      Number of threads [default: 4].
    --burn-in          Don't halt until we receive a signal.
    --duration=<s>     Seconds to run for [default: 10].
    --key-len=<l>      The length of keys [default: 10].
    --val-len=<l>      The length of values [default: 100].
    --get-prop=<p>     The relative proportion of get requests [default: 94].
    --set-prop=<p>     The relative proportion of set requests [default: 2].
    --del-prop=<p>     The relative proportion of del requests [default: 1].
    --cas-prop=<p>     The relative proportion of cas requests [default: 1].
    --scan-prop=<p>    The relative proportion of scan requests [default: 1].
    --merge-prop=<p>   The relative proportion of merge requests [default: 1].
    --entries=<n>      The total keyspace [default: 100000].
    --sequential       Run the test in sequential mode instead of random.
    --total-ops=<n>    Stop test after executing a total number of operations.
";

#[derive(Deserialize, Clone)]
struct Args {
    flag_threads: usize,
    flag_burn_in: bool,
    flag_duration: u64,
    flag_key_len: usize,
    flag_val_len: usize,
    flag_get_prop: usize,
    flag_set_prop: usize,
    flag_del_prop: usize,
    flag_cas_prop: usize,
    flag_scan_prop: usize,
    flag_merge_prop: usize,
    flag_entries: usize,
    flag_sequential: bool,
    flag_total_ops: Option<usize>,
}

// defaults will be applied later based on USAGE above
static mut ARGS: Args = Args {
    flag_threads: 0,
    flag_burn_in: false,
    flag_duration: 0,
    flag_key_len: 0,
    flag_val_len: 0,
    flag_get_prop: 0,
    flag_set_prop: 0,
    flag_del_prop: 0,
    flag_cas_prop: 0,
    flag_scan_prop: 0,
    flag_merge_prop: 0,
    flag_entries: 0,
    flag_sequential: false,
    flag_total_ops: None,
};

fn report(shutdown: Arc<AtomicBool>) {
    let mut last = 0;
    while !shutdown.load(Ordering::Relaxed) {
        thread::sleep(std::time::Duration::from_secs(1));
        let total = TOTAL.load(Ordering::Acquire);

        println!("did {} ops, {}mb RSS", total - last, rss() / (1024 * 1024));

        last = total;
    }
}

fn concatenate_merge(
    _key: &[u8],              // the key being merged
    old_value: Option<&[u8]>, // the previous value, if one existed
    merged_bytes: &[u8],      // the new bytes being merged in
) -> Option<Vec<u8>> {
    // set the new value, return None to delete
    let mut ret = old_value.map(|ov| ov.to_vec()).unwrap_or_else(|| vec![]);

    ret.extend_from_slice(merged_bytes);

    Some(ret)
}

fn run(tree: Arc<sled::Db>, shutdown: Arc<AtomicBool>) {
    let args = unsafe { ARGS.clone() };

    let get_max = args.flag_get_prop;
    let set_max = get_max + args.flag_set_prop;
    let del_max = set_max + args.flag_del_prop;
    let cas_max = del_max + args.flag_cas_prop;
    let merge_max = cas_max + args.flag_merge_prop;
    let scan_max = merge_max + args.flag_scan_prop;

    let bytes = |len| -> Vec<u8> {
        let i = if args.flag_sequential {
            SEQ.fetch_add(1, Ordering::Relaxed)
        } else {
            thread_rng().gen::<usize>()
        } % args.flag_entries;

        let i_bytes = i.to_be_bytes();

        i_bytes.iter().cycle().take(len).copied().collect()
    };
    let mut rng = thread_rng();

    while !shutdown.load(Ordering::Relaxed) {
        let op = TOTAL.fetch_add(1, Ordering::Release);
        let key = bytes(args.flag_key_len);
        let choice = rng.gen_range(0, scan_max + 1);

        match choice {
            v if v <= get_max => {
                tree.get(&key).unwrap();
            }
            v if v > get_max && v <= set_max => {
                tree.insert(&key, bytes(args.flag_val_len)).unwrap();
            }
            v if v > set_max && v <= del_max => {
                tree.remove(&key).unwrap();
            }
            v if v > del_max && v <= cas_max => {
                let old_k = bytes(args.flag_val_len);

                let old = if rng.gen::<bool>() {
                    Some(old_k.as_slice())
                } else {
                    None
                };

                let new = if rng.gen::<bool>() {
                    Some(bytes(args.flag_val_len))
                } else {
                    None
                };

                if let Err(e) = tree.compare_and_swap(&key, old, new) {
                    panic!("operational error: {:?}", e);
                }
            }
            v if v > cas_max && v <= merge_max => {
                tree.merge(&key, bytes(args.flag_val_len)).unwrap();
            }
            _ => {
                let iter = tree.range(key..).map(|res| res.unwrap());

                if op % 2 == 0 {
                    let _ = iter.take(rng.gen_range(0, 15)).collect::<Vec<_>>();
                } else {
                    let _ = iter
                        .rev()
                        .take(rng.gen_range(0, 15))
                        .collect::<Vec<_>>();
                }
            }
        }
    }
}

fn rss() -> usize {
    #[cfg(target_os = "linux")]
    {
        use std::io::prelude::*;
        use std::io::BufReader;

        let mut buf = String::new();
        let mut f =
            BufReader::new(std::fs::File::open("/proc/self/statm").unwrap());
        f.read_line(&mut buf).unwrap();
        let mut parts = buf.split_whitespace();
        let rss_pages = parts.nth(1).unwrap().parse::<usize>().unwrap();
        rss_pages * 4096
    }
    #[cfg(not(target_os = "linux"))]
    {
        0
    }
}

fn main() {
    #[cfg(feature = "logging")]
    setup_logger();

    let args = unsafe {
        ARGS = Docopt::new(USAGE)
            .and_then(|d| d.argv(std::env::args()).deserialize())
            .unwrap_or_else(|e| e.exit());
        ARGS.clone()
    };

    let shutdown = Arc::new(AtomicBool::new(false));

    let config = sled::Config::new()
        .cache_capacity(256 * 1024 * 1024)
        .flush_every_ms(Some(200))
        .snapshot_after_ops(100_000_000_000)
        .print_profile_on_drop(true);

    let tree = Arc::new(config.open().unwrap());
    tree.set_merge_operator(concatenate_merge);

    let mut threads = vec![];

    let now = std::time::Instant::now();

    let n_threads = args.flag_threads;

    for i in 0..=n_threads {
        let tree = tree.clone();
        let shutdown = shutdown.clone();

        let t = if i == 0 {
            thread::Builder::new()
                .name("reporter".into())
                .spawn(move || report(shutdown))
                .unwrap()
        } else {
            thread::spawn(move || run(tree, shutdown))
        };

        threads.push(t);
    }

    if let Some(ops) = args.flag_total_ops {
        assert!(!args.flag_burn_in, "don't set both --burn-in and --total-ops");
        while TOTAL.load(Ordering::Relaxed) < ops {
            thread::sleep(std::time::Duration::from_millis(50));
        }
        shutdown.store(true, Ordering::SeqCst);
    } else if !args.flag_burn_in {
        thread::sleep(std::time::Duration::from_secs(unsafe {
            ARGS.flag_duration
        }));
        shutdown.store(true, Ordering::SeqCst);
    }

    for t in threads.into_iter() {
        t.join().unwrap();
    }

    let ops = TOTAL.load(Ordering::SeqCst);
    let time = now.elapsed().as_secs() as usize;

    println!(
        "did {} total ops in {} seconds. {} ops/s",
        ops,
        time,
        (ops * 1_000) / (time * 1_000)
    );
}

#[cfg(feature = "logging")]
pub fn setup_logger() {
    use std::io::Write;

    color_backtrace::install();

    fn tn() -> String {
        std::thread::current().name().unwrap_or("unknown").to_owned()
    }

    let mut builder = env_logger::Builder::new();
    builder
        .format(|buf, record| {
            writeln!(
                buf,
                "{:05} {:25} {:10} {}",
                record.level(),
                tn(),
                record.module_path().unwrap().split("::").last().unwrap(),
                record.args()
            )
        })
        .filter(None, log::LevelFilter::Info);

    if std::env::var("RUST_LOG").is_ok() {
        builder.parse(&std::env::var("RUST_LOG").unwrap());
    }

    let _r = builder.try_init();
}
<|endoftext|>


<commit_before>// program should terminate even if a thread is blocked on I/O.
// https://github.com/fortanix/rust-sgx/issues/109

// run-pass
// ignore-emscripten no threads support

use std::{net::TcpListener, sync::mpsc, thread};

fn main() {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        let listen = TcpListener::bind("0.0.0.0:0").unwrap();
        tx.send(()).unwrap();
        while let Ok(_) = listen.accept() {}
    });
    rx.recv().unwrap();
    for _ in 0..3 { thread::yield_now(); }
    println!("Exiting main thread");
}
<commit_msg>Don't run a publically reachable server in tests<commit_after>// program should terminate even if a thread is blocked on I/O.
// https://github.com/fortanix/rust-sgx/issues/109

// run-pass
// ignore-emscripten no threads support

use std::{net::TcpListener, sync::mpsc, thread};

fn main() {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        let listen = TcpListener::bind("127.0.0.1:0").unwrap();
        tx.send(()).unwrap();
        while let Ok(_) = listen.accept() {}
    });
    rx.recv().unwrap();
    for _ in 0..3 { thread::yield_now(); }
    println!("Exiting main thread");
}
<|endoftext|>


<commit_before>use std::any::{Any, TypeId};
use std::fmt;

use fxhash::FxHashMap;

#[derive(Default)]
/// A type map of request extensions.
pub struct Extensions {
    map: FxHashMap<TypeId, Box<dyn Any>>,
}

impl Extensions {
    /// Create an empty `Extensions`.
    #[inline]
    pub fn new() -> Extensions {
        Extensions {
            map: FxHashMap::default(),
        }
    }

    /// Insert a type into this `Extensions`.
    ///
    /// If a extension of this type already existed, it will
    /// be returned.
    pub fn insert<T: 'static>(&mut self, val: T) {
        self.map.insert(TypeId::of::<T>(), Box::new(val));
    }

    /// Check if container contains entry
    pub fn contains<T: 'static>(&self) -> bool {
        self.map.get(&TypeId::of::<T>()).is_some()
    }

    /// Get a reference to a type previously inserted on this `Extensions`.
    pub fn get<T: 'static>(&self) -> Option<&T> {
        self.map
            .get(&TypeId::of::<T>())
            .and_then(|boxed| (&**boxed as &(dyn Any + 'static)).downcast_ref())
    }

    /// Get a mutable reference to a type previously inserted on this `Extensions`.
    pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
        self.map
            .get_mut(&TypeId::of::<T>())
            .and_then(|boxed| (&mut **boxed as &mut (dyn Any + 'static)).downcast_mut())
    }

    /// Remove a type from this `Extensions`.
    ///
    /// If a extension of this type existed, it will be returned.
    pub fn remove<T: 'static>(&mut self) -> Option<T> {
        self.map.remove(&TypeId::of::<T>()).and_then(|boxed| {
            (boxed as Box<dyn Any + 'static>)
                .downcast()
                .ok()
                .map(|boxed| *boxed)
        })
    }

    /// Clear the `Extensions` of all inserted extensions.
    #[inline]
    pub fn clear(&mut self) {
        self.map.clear();
    }
}

impl fmt::Debug for Extensions {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Extensions").finish()
    }
}

#[test]
fn test_extensions() {
    #[derive(Debug, PartialEq)]
    struct MyType(i32);

    let mut extensions = Extensions::new();

    extensions.insert(5i32);
    extensions.insert(MyType(10));

    assert_eq!(extensions.get(), Some(&5i32));
    assert_eq!(extensions.get_mut(), Some(&mut 5i32));

    assert_eq!(extensions.remove::<i32>(), Some(5i32));
    assert!(extensions.get::<i32>().is_none());

    assert_eq!(extensions.get::<bool>(), None);
    assert_eq!(extensions.get(), Some(&MyType(10)));
}
<commit_msg>Extensions module improvement and tests. (#1297)<commit_after>use std::any::{Any, TypeId};
use std::fmt;

use fxhash::FxHashMap;

#[derive(Default)]
/// A type map of request extensions.
pub struct Extensions {
    map: FxHashMap<TypeId, Box<dyn Any>>,
}

impl Extensions {
    /// Create an empty `Extensions`.
    #[inline]
    pub fn new() -> Extensions {
        Extensions {
            map: FxHashMap::default(),
        }
    }

    /// Insert a type into this `Extensions`.
    ///
    /// If a extension of this type already existed, it will
    /// be returned.
    pub fn insert<T: 'static>(&mut self, val: T) {
        self.map.insert(TypeId::of::<T>(), Box::new(val));
    }

    /// Check if container contains entry
    pub fn contains<T: 'static>(&self) -> bool {
        self.map.contains_key(&TypeId::of::<T>())
    }

    /// Get a reference to a type previously inserted on this `Extensions`.
    pub fn get<T: 'static>(&self) -> Option<&T> {
        self.map
            .get(&TypeId::of::<T>())
            .and_then(|boxed| boxed.downcast_ref())
    }

    /// Get a mutable reference to a type previously inserted on this `Extensions`.
    pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
        self.map
            .get_mut(&TypeId::of::<T>())
            .and_then(|boxed| boxed.downcast_mut())
    }

    /// Remove a type from this `Extensions`.
    ///
    /// If a extension of this type existed, it will be returned.
    pub fn remove<T: 'static>(&mut self) -> Option<T> {
        self.map
            .remove(&TypeId::of::<T>())
            .and_then(|boxed| boxed.downcast().ok().map(|boxed| *boxed))
    }

    /// Clear the `Extensions` of all inserted extensions.
    #[inline]
    pub fn clear(&mut self) {
        self.map.clear();
    }
}

impl fmt::Debug for Extensions {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Extensions").finish()
    }
}

#[test]
fn test_remove() {
    let mut map = Extensions::new();

    map.insert::<i8>(123);
    assert!(map.get::<i8>().is_some());

    map.remove::<i8>();
    assert!(map.get::<i8>().is_none());
}

#[test]
fn test_clear() {
    let mut map = Extensions::new();

    map.insert::<i8>(8);
    map.insert::<i16>(16);
    map.insert::<i32>(32);

    assert!(map.contains::<i8>());
    assert!(map.contains::<i16>());
    assert!(map.contains::<i32>());

    map.clear();

    assert!(!map.contains::<i8>());
    assert!(!map.contains::<i16>());
    assert!(!map.contains::<i32>());

    map.insert::<i8>(10);
    assert_eq!(*map.get::<i8>().unwrap(), 10);
}

#[test]
fn test_integers() {
    let mut map = Extensions::new();

    map.insert::<i8>(8);
    map.insert::<i16>(16);
    map.insert::<i32>(32);
    map.insert::<i64>(64);
    map.insert::<i128>(128);
    map.insert::<u8>(8);
    map.insert::<u16>(16);
    map.insert::<u32>(32);
    map.insert::<u64>(64);
    map.insert::<u128>(128);
    assert!(map.get::<i8>().is_some());
    assert!(map.get::<i16>().is_some());
    assert!(map.get::<i32>().is_some());
    assert!(map.get::<i64>().is_some());
    assert!(map.get::<i128>().is_some());
    assert!(map.get::<u8>().is_some());
    assert!(map.get::<u16>().is_some());
    assert!(map.get::<u32>().is_some());
    assert!(map.get::<u64>().is_some());
    assert!(map.get::<u128>().is_some());
}

#[test]
fn test_composition() {
    struct Magi<T>(pub T);

    struct Madoka {
        pub god: bool,
    }

    struct Homura {
        pub attempts: usize,
    }

    struct Mami {
        pub guns: usize,
    }

    let mut map = Extensions::new();

    map.insert(Magi(Madoka { god: false }));
    map.insert(Magi(Homura { attempts: 0 }));
    map.insert(Magi(Mami { guns: 999 }));

    assert!(!map.get::<Magi<Madoka>>().unwrap().0.god);
    assert_eq!(0, map.get::<Magi<Homura>>().unwrap().0.attempts);
    assert_eq!(999, map.get::<Magi<Mami>>().unwrap().0.guns);
}

#[test]
fn test_extensions() {
    #[derive(Debug, PartialEq)]
    struct MyType(i32);

    let mut extensions = Extensions::new();

    extensions.insert(5i32);
    extensions.insert(MyType(10));

    assert_eq!(extensions.get(), Some(&5i32));
    assert_eq!(extensions.get_mut(), Some(&mut 5i32));

    assert_eq!(extensions.remove::<i32>(), Some(5i32));
    assert!(extensions.get::<i32>().is_none());

    assert_eq!(extensions.get::<bool>(), None);
    assert_eq!(extensions.get(), Some(&MyType(10)));
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! A linked-list implementation using `RawLink`s.
use super::rawlink::RawLink;

use core::marker::PhantomData;
use core::ptr::Unique;
#[cfg(test)] mod test;

pub unsafe trait OwnedRef<T> {
    unsafe fn from_raw(ptr: *mut T) -> Self;
    unsafe fn take(self);
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;
}

pub trait Node: Sized {
    fn next(&self) -> &RawLink<Self>;
    fn prev(&self) -> &RawLink<Self>;

    fn next_mut(&mut self) -> &mut RawLink<Self>;
    fn prev_mut(&mut self) -> &mut RawLink<Self>;
}

pub struct List<T, N>
where T: OwnedRef<N>
    , N: Node {
    head: RawLink<N>
  , tail: RawLink<N>
  , _ty_marker: PhantomData<T>
  , length: usize
 }

 // impl<T> Node for List<T>
 // where T: OwnedRef
 //     , T: Node {
 //
 //    fn next(&self) -> &RawLink<Self> { &self.head }
 //    fn prev(&self) -> &RawLink<Self> { &self.tail }
 //
 //    fn next_mut(&mut self) -> &mut RawLink<Self> { self.head }
 //    fn prev_mut(&mut self) -> &mut RawLink<Self> { self.tail }
 // }
impl<T, N> List<T, N>
where T: OwnedRef<N>
    , N: Node {

    pub const fn new() -> Self {
        List { head: RawLink::none()
             , tail: RawLink::none()
             , _ty_marker: PhantomData
             , length: 0 }
    }

    #[inline] pub fn len(&self) -> usize {
        self.length
    }

    pub fn front(&self) -> Option<&N> {
        unsafe { self.head.resolve() }
    }

    pub fn back(&self) -> Option<&N> {
        unsafe { self.tail.resolve() }
    }

    pub fn front_mut(&mut self) -> Option<&mut N> {
        unsafe { self.head.resolve_mut() }
    }

    pub fn back_mut(&mut self) -> Option<&mut N> {
        unsafe { self.tail.resolve_mut() }
    }

    pub fn is_empty(&self) -> bool {
        self.head.is_none()
    }

    pub fn push_front(&mut self, mut item: T) {
        unsafe {
            match self.head.resolve_mut() {
                None => {
                    // If this node's head is empty, set the pushed item's
                    // links to None, and make this node's tail point to the
                    // pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::none();
                    self.tail = RawLink::some(item.get_mut());
                }
              , Some(head) => {
                    // If this node is not empty, set the pushed item's tail
                    // to point at the head node, and make the head node's tail
                    // point to the pushed item
                    *item.get_mut().next_mut() = RawLink::some(head);
                    *item.get_mut().prev_mut() = RawLink::none();
                    *head.prev_mut() = RawLink::some(item.get_mut());
                }
            }
            // then, set this node's head pointer to point to the pushed item
            self.head = RawLink::some(item.get_mut());
            item.take();
            self.length += 1;
        }
    }

    pub fn push_back(&mut self, mut item: T) {
        unsafe {
            match self.tail.resolve_mut() {
                None => {
                    // If this node's tail is empty, set the pushed item's
                    // links to  None, and make this node's head point to the
                    // pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::none();
                    self.head = RawLink::some(item.get_mut());
                }
              , Some(tail) => {
                    // If this node is not empty, set the pushed item's head
                    // to point at the tail node, and make the tail node's head
                    // point to the pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::some(tail);
                    *tail.next_mut() = RawLink::some(item.get_mut());
                }
            }
            // then, set this node's head pointer to point to the pushed item
            self.tail = RawLink::some(item.get_mut());
            item.take();
            self.length += 1;
        }
    }

    pub fn pop_front(&mut self) -> Option<T> {
        unsafe {
            self.head.take().resolve_mut()
                .map(|head| {
                    // mem::swap( &mut self.head
                    //          , head.next_mut().resolve_mut()
                    //                .map(|next| next.prev_mut())
                    //                .unwrap_or(&mut RawLink::none()) );
                    match head.next_mut().resolve_mut() {
                        None => self.tail = RawLink::none()
                      , Some(next) => {
                            *next.prev_mut() = RawLink::none();
                            self.head = RawLink::some(next);
                        }
                    }
                    self.length -= 1;
                    T::from_raw(head)
                })
        }
    }

    pub fn pop_back(&mut self) -> Option<T> {
        unsafe {
            self.tail.take().resolve_mut()
                .map(|tail| {
                    match tail.prev_mut().resolve_mut() {
                        None => self.head = RawLink::none()
                      , Some(prev) => {
                            *prev.next_mut() = RawLink::none();
                            self.tail = RawLink::some(prev);
                        }
                    }
                    self.length -= 1;
                    T::from_raw(tail)
                })
        }
    }

    pub fn peek_front(&self) -> Option<&N> {
        unsafe { self.tail.resolve() }
    }
}

pub struct ListCursor<'a, T, N>
where T: OwnedRef<N>
    , T: 'a
    , N: Node
    , N: 'a {
        list: &'a mut List<T, N>
      , current: RawLink<N>
}

impl<'a, T, N> ListCursor<'a, T, N>
where T: OwnedRef<N>
    , T: 'a
    , N: Node
    , N: 'a {

    pub fn next(&mut self) -> Option<&mut N> {
        unsafe {
            match self.current.take().resolve_mut() {
                None => self.list.head.resolve_mut()
                            .and_then(|head| {
                                self.current = RawLink::some(head);
                                self.current.resolve_mut()
                            })
              , Some(thing) => {
                    self.current = match thing.next_mut().resolve_mut() {
                        None => RawLink::none()
                      , Some(other_thing) => RawLink::some(other_thing)
                    };
                    self.current.resolve_mut()
                }
            }
        }
    }

    pub fn peek_next(&mut self) -> Option<&mut N> {
        unsafe {
            self.current.resolve_mut()
                .map_or( self.list.front_mut()
                       , |next| next.next_mut().resolve_mut())
        }
    }

}

// impl<'a, T, N> Iterator for ListCursor<'a, T, N>
// where T: OwnedRef<N>
//     , T: 'a
//     , N: Node
//     , N: 'a {
//     type Item = &'a mut N;
//
//     fn next<'b: 'a>(&'b mut self) -> Option<&'a mut N> {
//         self.next()
//     }
// }

//
// unsafe impl<T> OwnedRef for Unique<T> where T: Node {
//
//     #[inline]
//     fn take(self) {}
//
//     unsafe fn from_raw(ptr: *mut T) -> Self {
//         Unique::new(ptr)
//     }
// }
//
// unsafe impl<'a, T> OwnedRef<T> for &'a mut T {
//     #
//     #[inline] unsafe fn from_raw(raw: *mut T) -> &'a mut T {
//         &mut *raw
//     }
//
//     #[inline] unsafe fn take(self) {
//         forget(self);
//     }
// }
//

unsafe impl<T> OwnedRef<T> for Unique<T>  {
    #[inline]
    fn get(&self) -> &T { unsafe { self.get() } }

    #[inline]
    fn get_mut(&mut self) -> &mut T { unsafe { self.get_mut() } }

    #[inline]
    unsafe fn take(self) {}

    unsafe fn from_raw(ptr: *mut T) -> Self {
        Unique::new(ptr)
    }
}

#[cfg(any(test, feature = "use-std"))]
unsafe impl<T> OwnedRef<T> for ::std::boxed::Box<T> {

    fn get(&self) -> &T { &**self }
    fn get_mut(&mut self) -> &mut T { &mut **self }

    #[inline] unsafe fn take(self) {
        ::std::boxed::Box::into_raw(self);
    }

    unsafe fn from_raw(ptr: *mut T) -> Self {
        ::std::boxed::Box::from_raw(ptr)
    }
}
<commit_msg>[intrusive] First pass on List::Cursor.remove()<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! A linked-list implementation using `RawLink`s.
use super::rawlink::RawLink;

use core::marker::PhantomData;
use core::ptr::Unique;
#[cfg(test)] mod test;

pub unsafe trait OwnedRef<T> {
    unsafe fn from_raw(ptr: *mut T) -> Self;
    unsafe fn take(self);
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;
}

pub trait Node: Sized {
    fn next(&self) -> &RawLink<Self>;
    fn prev(&self) -> &RawLink<Self>;

    fn next_mut(&mut self) -> &mut RawLink<Self>;
    fn prev_mut(&mut self) -> &mut RawLink<Self>;
}

pub struct List<T, N>
where T: OwnedRef<N>
    , N: Node {
    head: RawLink<N>
  , tail: RawLink<N>
  , _ty_marker: PhantomData<T>
  , length: usize
 }

 // impl<T> Node for List<T>
 // where T: OwnedRef
 //     , T: Node {
 //
 //    fn next(&self) -> &RawLink<Self> { &self.head }
 //    fn prev(&self) -> &RawLink<Self> { &self.tail }
 //
 //    fn next_mut(&mut self) -> &mut RawLink<Self> { self.head }
 //    fn prev_mut(&mut self) -> &mut RawLink<Self> { self.tail }
 // }
impl<T, N> List<T, N>
where T: OwnedRef<N>
    , N: Node {

    pub const fn new() -> Self {
        List { head: RawLink::none()
             , tail: RawLink::none()
             , _ty_marker: PhantomData
             , length: 0 }
    }

    #[inline] pub fn len(&self) -> usize {
        self.length
    }

    #[inline] pub fn front(&self) -> Option<&N> {
        unsafe { self.head.resolve() }
    }

    #[inline] pub fn back(&self) -> Option<&N> {
        unsafe { self.tail.resolve() }
    }

    #[inline] pub fn front_mut(&mut self) -> Option<&mut N> {
        unsafe { self.head.resolve_mut() }
    }

    #[inline] pub fn back_mut(&mut self) -> Option<&mut N> {
        unsafe { self.tail.resolve_mut() }
    }

    #[inline] pub fn is_empty(&self) -> bool {
        self.head.is_none()
    }

    pub fn push_front(&mut self, mut item: T) {
        unsafe {
            match self.head.resolve_mut() {
                None => {
                    // If this node's head is empty, set the pushed item's
                    // links to None, and make this node's tail point to the
                    // pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::none();
                    self.tail = RawLink::some(item.get_mut());
                }
              , Some(head) => {
                    // If this node is not empty, set the pushed item's tail
                    // to point at the head node, and make the head node's tail
                    // point to the pushed item
                    *item.get_mut().next_mut() = RawLink::some(head);
                    *item.get_mut().prev_mut() = RawLink::none();
                    *head.prev_mut() = RawLink::some(item.get_mut());
                }
            }
            // then, set this node's head pointer to point to the pushed item
            self.head = RawLink::some(item.get_mut());
            item.take();
            self.length += 1;
        }
    }

    pub fn push_back(&mut self, mut item: T) {
        unsafe {
            match self.tail.resolve_mut() {
                None => {
                    // If this node's tail is empty, set the pushed item's
                    // links to  None, and make this node's head point to the
                    // pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::none();
                    self.head = RawLink::some(item.get_mut());
                }
              , Some(tail) => {
                    // If this node is not empty, set the pushed item's head
                    // to point at the tail node, and make the tail node's head
                    // point to the pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::some(tail);
                    *tail.next_mut() = RawLink::some(item.get_mut());
                }
            }
            // then, set this node's head pointer to point to the pushed item
            self.tail = RawLink::some(item.get_mut());
            item.take();
            self.length += 1;
        }
    }

    pub fn pop_front(&mut self) -> Option<T> {
        unsafe {
            self.head.take().resolve_mut()
                .map(|head| {
                    // mem::swap( &mut self.head
                    //          , head.next_mut().resolve_mut()
                    //                .map(|next| next.prev_mut())
                    //                .unwrap_or(&mut RawLink::none()) );
                    match head.next_mut().resolve_mut() {
                        None => self.tail = RawLink::none()
                      , Some(next) => {
                            *next.prev_mut() = RawLink::none();
                            self.head = RawLink::some(next);
                        }
                    }
                    self.length -= 1;
                    T::from_raw(head)
                })
        }
    }

    pub fn pop_back(&mut self) -> Option<T> {
        unsafe {
            self.tail.take().resolve_mut()
                .map(|tail| {
                    match tail.prev_mut().resolve_mut() {
                        None => self.head = RawLink::none()
                      , Some(prev) => {
                            *prev.next_mut() = RawLink::none();
                            self.tail = RawLink::some(prev);
                        }
                    }
                    self.length -= 1;
                    T::from_raw(tail)
                })
        }
    }

    pub fn peek_front(&self) -> Option<&N> {
        unsafe { self.tail.resolve() }
    }
}

pub struct ListCursor<'a, T, N>
where T: OwnedRef<N>
    , T: 'a
    , N: Node
    , N: 'a {
        list: &'a mut List<T, N>
      , current: RawLink<N>
}

impl<'a, T, N> ListCursor<'a, T, N>
where T: OwnedRef<N>
    , T: 'a
    , N: Node
    , N: 'a {

    pub fn next(&mut self) -> Option<&mut N> {
        unsafe {
            match self.current.take().resolve_mut() {
                None => self.list.head.resolve_mut()
                            .and_then(|head| {
                                self.current = RawLink::some(head);
                                self.current.resolve_mut()
                            })
              , Some(thing) => {
                    self.current = match thing.next_mut().resolve_mut() {
                        None => RawLink::none()
                      , Some(other_thing) => RawLink::some(other_thing)
                    };
                    self.current.resolve_mut()
                }
            }
        }
    }

    pub fn peek_next(&mut self) -> Option<&mut N> {
        unsafe {
            self.current.resolve_mut()
                .map_or( self.list.front_mut()
                       , |next| next.next_mut().resolve_mut())
        }
    }

    pub fn remove(&mut self) -> Option<T> {
        unsafe {
            match self.current.resolve_mut() {
                None    => self.list.pop_front()
              , Some(c) =>
                    c.next_mut().take().resolve_mut()
                     .map(|p| {
                        match p.next_mut().resolve_mut() {
                            None => self.list.tail = RawLink::some(c)
                          , Some(n) => {
                                *n.prev_mut() = RawLink::some(c);
                                *c.next_mut() = RawLink::some(n);
                            }
                        }
                        T::from_raw(p)
                    })
            }
        }
    }

}

// impl<'a, T, N> Iterator for ListCursor<'a, T, N>
// where T: OwnedRef<N>
//     , T: 'a
//     , N: Node
//     , N: 'a {
//     type Item = &'a mut N;
//
//     fn next<'b: 'a>(&'b mut self) -> Option<&'a mut N> {
//         self.next()
//     }
// }

//
// unsafe impl<T> OwnedRef for Unique<T> where T: Node {
//
//     #[inline]
//     fn take(self) {}
//
//     unsafe fn from_raw(ptr: *mut T) -> Self {
//         Unique::new(ptr)
//     }
// }
//
// unsafe impl<'a, T> OwnedRef<T> for &'a mut T {
//     #
//     #[inline] unsafe fn from_raw(raw: *mut T) -> &'a mut T {
//         &mut *raw
//     }
//
//     #[inline] unsafe fn take(self) {
//         forget(self);
//     }
// }
//

unsafe impl<T> OwnedRef<T> for Unique<T>  {
    #[inline]
    fn get(&self) -> &T { unsafe { self.get() } }

    #[inline]
    fn get_mut(&mut self) -> &mut T { unsafe { self.get_mut() } }

    #[inline]
    unsafe fn take(self) {}

    unsafe fn from_raw(ptr: *mut T) -> Self {
        Unique::new(ptr)
    }
}

#[cfg(any(test, feature = "use-std"))]
unsafe impl<T> OwnedRef<T> for ::std::boxed::Box<T> {

    fn get(&self) -> &T { &**self }
    fn get_mut(&mut self) -> &mut T { &mut **self }

    #[inline] unsafe fn take(self) {
        ::std::boxed::Box::into_raw(self);
    }

    unsafe fn from_raw(ptr: *mut T) -> Self {
        ::std::boxed::Box::from_raw(ptr)
    }
}
<|endoftext|>