<commit_before>#![feature(untagged_unions)]

#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

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

use std::ffi::CStr;
use std::marker::PhantomData;
use std::os::raw::c_char;
use std::ptr;

/// Represents a Result from the capstone engine.
pub type CsResult<T> = Result<T, cs_err>;

type CsOptionValue = Option<usize>;

/// A utlity for configuring the Capstone engine.
pub struct Builder {
    arch: cs_arch,
    mode: cs_mode,
    syntax: CsOptionValue,
    detail: CsOptionValue,
    skipdata: CsOptionValue,
    skipdata_config: Option<cs_opt_skipdata>,
}

impl Builder {
    /// Returns a new `Builder` for the given `arch` and `mode`.
    pub fn new(arch: cs_arch, mode: cs_mode) -> Builder {
        Builder {
            arch: arch,
            mode: mode,
            syntax: None,
            detail: None,
            skipdata: None,
            skipdata_config: None,
        }
    }

    /// Create the Capstone engine with the configured options.
    pub fn build(self) -> CsResult<Capstone> {
        let engine = Capstone::new(self.arch, self.mode)?;

        if let Some(opt) = self.syntax {
            engine.option(CS_OPT_SYNTAX, opt)?;
        }

        if let Some(opt) = self.detail {
            engine.option(CS_OPT_DETAIL, opt)?;
        }

        if let Some(opt) = self.skipdata {
            engine.option(CS_OPT_SKIPDATA, opt)?;
        }

        if let Some(opt) = self.skipdata_config {
            if self.skipdata.is_none() || self.skipdata.unwrap() != CS_OPT_ON as _ {
                engine.option(CS_OPT_SKIPDATA, CS_OPT_ON as _)?;
            }

            engine.option(CS_OPT_SKIPDATA_SETUP, &opt as *const _ as _)?;
        }

        Ok(engine)
    }

    /// Set the syntax for the engine.
    pub fn syntax(mut self, syntax: cs_opt_value) -> Builder {
        self.syntax = Some(syntax as _);
        self
    }

    /// Set whether detail mode should be on.
    pub fn detail(mut self, detail: cs_opt_value) -> Builder {
        self.detail = Some(detail as _);
        self
    }

    /// Whether data encountered in code should be skipped.
    pub fn skipdata(mut self, doit: cs_opt_value) -> Builder {
        self.skipdata = Some(doit as _);
        self
    }

    /// Setup configuration for skipdata.
    /// Userdata will always be a nullptr for now.
    pub fn skipdata_config(mut self,
                           mnemonic: Option<&'static str>,
                           callback: cs_skipdata_cb_t)
                           -> Builder {
        self.skipdata_config = Some(cs_opt_skipdata {
                                        mnemonic: mnemonic.unwrap_or(".byte").as_ptr() as _,
                                        callback: callback,
                                        user_data: ptr::null_mut(),
                                    });
        self
    }
}

/// An instance of `Capstone` represents an instance of the capstone engine.
pub struct Capstone {
    handle: csh,
}

impl Capstone {
    /// `new` returns a new instance of the capstone engine with the given
    /// `arch`itecture and `mode` used.
    pub fn new(arch: cs_arch, mode: cs_mode) -> CsResult<Capstone> {
        let mut handle = 0;
        let err = unsafe { cs_open(arch, mode, &mut handle) };
        if err != CS_ERR_OK {
            Err(err)
        } else {
            Ok(Capstone { handle: handle })
        }
    }

    /// `disasm` disassembles the given `code` at the given `address`.
    /// It disassembles `count` instructions. If `count` is 0, then as many
    /// instructions as possible are disassembled.
    pub fn disasm(&self, code: &[u8], address: u64, count: usize) -> CsResult<Instructions> {
        let mut instructions: *mut cs_insn = ptr::null_mut();
        let count = unsafe {
            cs_disasm(self.handle,
                      code.as_ptr(),
                      code.len(),
                      address,
                      count,
                      &mut instructions)
        };

        if count == 0 {
            let err = unsafe { cs_errno(self.handle) };
            debug_assert_ne!(err, CS_ERR_OK);
            Err(err)
        } else {
            Ok(Instructions::from_raw(instructions, count))
        }
    }

    /// `disasm_all` disassembles as many instructions as possible in the given `code`
    /// at the given `address`.
    pub fn disasm_all(&self, code: &[u8], address: u64) -> CsResult<Instructions> {
        self.disasm(code, address, 0)
    }

    /// `error` returns the current error as a String.
    /// This may return `None`, if there is no error, or the conversion to a String failed.
    pub fn error(&self) -> Option<String> {
        let err = unsafe { cs_errno(self.handle) };
        if err != CS_ERR_OK {
            to_string(unsafe { cs_strerror(err) })
        } else {
            None
        }
    }

    /// Returns the name of the given group.
    pub fn group_name(&self, group_id: u32) -> Option<String> {
        to_string(unsafe { cs_group_name(self.handle, group_id) })
    }

    /// Returns whether the given instruction belongs to the given group.
    pub fn insn_group(&self, insn: &cs_insn, group_id: u32) -> bool {
        unsafe { cs_insn_group(self.handle, insn, group_id) }
    }

    /// Returns the name of the given instruction.
    pub fn insn_name(&self, insn_id: u32) -> Option<String> {
        to_string(unsafe { cs_insn_name(self.handle, insn_id) })
    }

    /// `option` sets the given option `type_` to the given `value`.
    pub fn option(&self, type_: cs_opt_type, value: usize) -> CsResult<()> {
        let err = unsafe { cs_option(self.handle, type_, value) };
        if err != CS_ERR_OK { Err(err) } else { Ok(()) }
    }

    /// Returns the name of the given register.
    pub fn reg_name(&self, reg_id: u32) -> Option<String> {
        to_string(unsafe { cs_reg_name(self.handle, reg_id) })
    }

    /// Returns whether the given register is read by the given instruction.
    pub fn reg_read(&self, insn: &cs_insn, reg_id: u32) -> bool {
        unsafe { cs_reg_read(self.handle, insn, reg_id) }
    }

    /// Returns whether the given register is written by the given instruction.
    pub fn reg_write(&self, insn: &cs_insn, reg_id: u32) -> bool {
        unsafe { cs_reg_write(self.handle, insn, reg_id) }
    }
}

impl Drop for Capstone {
    fn drop(&mut self) {
        let err = unsafe { cs_close(&mut self.handle) };
        if err != CS_ERR_OK {
            panic!("Error while calling cs_close: {:?}", err)
        }
    }
}

/// `Instructions` represents a number of disassembled instructions.
pub struct Instructions {
    instructions: *mut cs_insn,
    count: usize,
}

impl Instructions {
    fn from_raw(p: *mut cs_insn, count: usize) -> Instructions {
        Instructions {
            instructions: p,
            count: count,
        }
    }

    /// Returns true if there are no instructions.
    /// This actually will never be true but clippy wants there to be a `is_empty` method
    /// when there is a `len` method.
    pub fn is_empty(&self) -> bool {
        self.count == 0
    }

    /// Returns an `PointerIter` to iterate over all the instructions.
    pub fn iter(&self) -> PointerIter<cs_insn> {
        PointerIter::new(self.instructions, self.count)
    }

    /// Returns the number of instructions owned by this struct.
    pub fn len(&self) -> usize {
        self.count
    }
}

impl Drop for Instructions {
    fn drop(&mut self) {
        unsafe { cs_free(self.instructions, self.count) }
    }
}

/// Returns whether the requested feature is supported.
/// `query` can be one of the `CS_ARCH_`* values or `CS_ARCH_ALL` + 1 to check the diet mode.
pub fn support(query: cs_arch) -> bool {
    unsafe { cs_support(query as _) }
}

/// Returns the major version, minor version and the combined version.
pub fn version() -> (i32, i32, u32) {
    let mut major = 0;
    let mut minor = 0;
    (major, minor, unsafe { cs_version(&mut major, &mut minor) })
}

/// `PointerIter` iterates over an array of things that are
/// pointed to by an pointer.
pub struct PointerIter<'a, T: 'a> {
    ptr: *const T,
    count: usize,
    current: usize,
    lifetime: PhantomData<&'a T>,
}

impl<'a, T: 'a> PointerIter<'a, T> {
    pub fn new(ptr: *const T, count: usize) -> Self {
        PointerIter {
            ptr: ptr,
            count: count,
            current: 0,
            lifetime: PhantomData,
        }
    }
}

impl<'a, T: 'a> Iterator for PointerIter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        if self.current >= self.count {
            None
        } else {
            let object = unsafe { &*self.ptr.offset(self.current as _) };
            self.current += 1;
            Some(object)
        }
    }
}

impl cs_arm {
    pub fn operand_iter(&self) -> PointerIter<cs_arm_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_arm64 {
    pub fn operand_iter(&self) -> PointerIter<cs_arm64_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_mips {
    pub fn operand_iter(&self) -> PointerIter<cs_mips_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_ppc {
    pub fn operand_iter(&self) -> PointerIter<cs_ppc_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_sparc {
    pub fn operand_iter(&self) -> PointerIter<cs_sparc_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_sysz {
    pub fn operand_iter(&self) -> PointerIter<cs_sysz_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_x86 {
    pub fn operand_iter(&self) -> PointerIter<cs_x86_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_xcore {
    pub fn operand_iter(&self) -> PointerIter<cs_xcore_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_detail {
    /// Returns a reference to the `x86` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_x86(&self) -> &cs_x86 {
        unsafe { &self.__bindgen_anon_1.x86 }
    }

    /// Returns a reference to the `arm64` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_arm64(&self) -> &cs_arm64 {
        unsafe { &self.__bindgen_anon_1.arm64 }
    }

    /// Returns a reference to the `arm` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_arm(&self) -> &cs_arm {
        unsafe { &self.__bindgen_anon_1.arm }
    }

    /// Returns a reference to the `mips` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_mips(&self) -> &cs_mips {
        unsafe { &self.__bindgen_anon_1.mips }
    }

    /// Returns a reference to the `ppc` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_ppc(&self) -> &cs_ppc {
        unsafe { &self.__bindgen_anon_1.ppc }
    }

    /// Returns a reference to the `sparc` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_sparc(&self) -> &cs_sparc {
        unsafe { &self.__bindgen_anon_1.sparc }
    }

    /// Returns a reference to the `sysz` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_sysz(&self) -> &cs_sysz {
        unsafe { &self.__bindgen_anon_1.sysz }
    }

    /// Returns a reference to the `xcore` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_xcore(&self) -> &cs_xcore {
        unsafe { &self.__bindgen_anon_1.xcore }
    }

    /// Returns an iterator over the registers read by this instruction.
    pub fn regs_read_iter(&self) -> PointerIter<u8> {
        PointerIter::new(self.regs_read.as_ptr(), self.regs_read_count as _)
    }

    /// Returns an iterator over the registers written to by this instruction.
    pub fn regs_write_iter(&self) -> PointerIter<u8> {
        PointerIter::new(self.regs_write.as_ptr(), self.regs_write_count as _)
    }

    /// Returns an iterator over the groups this instruction belongs to.
    pub fn groups_iter(&self) -> PointerIter<u8> {
        PointerIter::new(self.groups.as_ptr(), self.groups_count as _)
    }
}

impl cs_insn {
    pub fn get_mnemonic(&self) -> Option<String> {
        to_string(self.mnemonic.as_ptr())
    }

    pub fn get_op_str(&self) -> Option<String> {
        to_string(self.op_str.as_ptr())
    }
}

use std::fmt;
impl fmt::Debug for cs_insn {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("cs_insn")
            .field("id", &self.id)
            .field("address", &self.address)
            .field("size", &self.size)
            .field("bytes", &self.bytes)
            .field("mnemonic", &self.mnemonic)
            .field("detail", &self.detail)
            .finish()
    }
}

fn to_string(p: *const c_char) -> Option<String> {
    if p.is_null() {
        None
    } else {
        Some(unsafe { CStr::from_ptr(p) }.to_string_lossy().into_owned())
    }
}
<commit_msg>Always return Instructions, even when `count` is 0.<commit_after>#![feature(untagged_unions)]

#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

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

use std::ffi::CStr;
use std::marker::PhantomData;
use std::os::raw::c_char;
use std::ptr;

/// Represents a Result from the capstone engine.
pub type CsResult<T> = Result<T, cs_err>;

type CsOptionValue = Option<usize>;

/// A utlity for configuring the Capstone engine.
pub struct Builder {
    arch: cs_arch,
    mode: cs_mode,
    syntax: CsOptionValue,
    detail: CsOptionValue,
    skipdata: CsOptionValue,
    skipdata_config: Option<cs_opt_skipdata>,
}

impl Builder {
    /// Returns a new `Builder` for the given `arch` and `mode`.
    pub fn new(arch: cs_arch, mode: cs_mode) -> Builder {
        Builder {
            arch: arch,
            mode: mode,
            syntax: None,
            detail: None,
            skipdata: None,
            skipdata_config: None,
        }
    }

    /// Create the Capstone engine with the configured options.
    pub fn build(self) -> CsResult<Capstone> {
        let engine = Capstone::new(self.arch, self.mode)?;

        if let Some(opt) = self.syntax {
            engine.option(CS_OPT_SYNTAX, opt)?;
        }

        if let Some(opt) = self.detail {
            engine.option(CS_OPT_DETAIL, opt)?;
        }

        if let Some(opt) = self.skipdata {
            engine.option(CS_OPT_SKIPDATA, opt)?;
        }

        if let Some(opt) = self.skipdata_config {
            if self.skipdata.is_none() || self.skipdata.unwrap() != CS_OPT_ON as _ {
                engine.option(CS_OPT_SKIPDATA, CS_OPT_ON as _)?;
            }

            engine.option(CS_OPT_SKIPDATA_SETUP, &opt as *const _ as _)?;
        }

        Ok(engine)
    }

    /// Set the syntax for the engine.
    pub fn syntax(mut self, syntax: cs_opt_value) -> Builder {
        self.syntax = Some(syntax as _);
        self
    }

    /// Set whether detail mode should be on.
    pub fn detail(mut self, detail: cs_opt_value) -> Builder {
        self.detail = Some(detail as _);
        self
    }

    /// Whether data encountered in code should be skipped.
    pub fn skipdata(mut self, doit: cs_opt_value) -> Builder {
        self.skipdata = Some(doit as _);
        self
    }

    /// Setup configuration for skipdata.
    /// Userdata will always be a nullptr for now.
    pub fn skipdata_config(mut self,
                           mnemonic: Option<&'static str>,
                           callback: cs_skipdata_cb_t)
                           -> Builder {
        self.skipdata_config = Some(cs_opt_skipdata {
                                        mnemonic: mnemonic.unwrap_or(".byte").as_ptr() as _,
                                        callback: callback,
                                        user_data: ptr::null_mut(),
                                    });
        self
    }
}

/// An instance of `Capstone` represents an instance of the capstone engine.
pub struct Capstone {
    handle: csh,
}

impl Capstone {
    /// `new` returns a new instance of the capstone engine with the given
    /// `arch`itecture and `mode` used.
    pub fn new(arch: cs_arch, mode: cs_mode) -> CsResult<Capstone> {
        let mut handle = 0;
        let err = unsafe { cs_open(arch, mode, &mut handle) };
        if err != CS_ERR_OK {
            Err(err)
        } else {
            Ok(Capstone { handle: handle })
        }
    }

    /// `disasm` disassembles the given `code` at the given `address`.
    /// It disassembles `count` instructions. If `count` is 0, then as many
    /// instructions as possible are disassembled.
    pub fn disasm(&self, code: &[u8], address: u64, count: usize) -> Instructions {
        let mut instructions: *mut cs_insn = ptr::null_mut();
        let count = unsafe {
            cs_disasm(self.handle,
                      code.as_ptr(),
                      code.len(),
                      address,
                      count,
                      &mut instructions)
        };

        Instructions::from_raw(instructions, count)
    }

    /// `disasm_all` disassembles as many instructions as possible in the given `code`
    /// at the given `address`.
    pub fn disasm_all(&self, code: &[u8], address: u64) -> Instructions {
        self.disasm(code, address, 0)
    }

    /// `error` returns the current error as a String.
    /// This may return `None`, if there is no error, or the conversion to a String failed.
    pub fn error(&self) -> Option<String> {
        let err = unsafe { cs_errno(self.handle) };
        if err != CS_ERR_OK {
            to_string(unsafe { cs_strerror(err) })
        } else {
            None
        }
    }

    /// Returns the name of the given group.
    pub fn group_name(&self, group_id: u32) -> Option<String> {
        to_string(unsafe { cs_group_name(self.handle, group_id) })
    }

    /// Returns whether the given instruction belongs to the given group.
    pub fn insn_group(&self, insn: &cs_insn, group_id: u32) -> bool {
        unsafe { cs_insn_group(self.handle, insn, group_id) }
    }

    /// Returns the name of the given instruction.
    pub fn insn_name(&self, insn_id: u32) -> Option<String> {
        to_string(unsafe { cs_insn_name(self.handle, insn_id) })
    }

    /// `option` sets the given option `type_` to the given `value`.
    pub fn option(&self, type_: cs_opt_type, value: usize) -> CsResult<()> {
        let err = unsafe { cs_option(self.handle, type_, value) };
        if err != CS_ERR_OK { Err(err) } else { Ok(()) }
    }

    /// Returns the name of the given register.
    pub fn reg_name(&self, reg_id: u32) -> Option<String> {
        to_string(unsafe { cs_reg_name(self.handle, reg_id) })
    }

    /// Returns whether the given register is read by the given instruction.
    pub fn reg_read(&self, insn: &cs_insn, reg_id: u32) -> bool {
        unsafe { cs_reg_read(self.handle, insn, reg_id) }
    }

    /// Returns whether the given register is written by the given instruction.
    pub fn reg_write(&self, insn: &cs_insn, reg_id: u32) -> bool {
        unsafe { cs_reg_write(self.handle, insn, reg_id) }
    }
}

impl Drop for Capstone {
    fn drop(&mut self) {
        let err = unsafe { cs_close(&mut self.handle) };
        if err != CS_ERR_OK {
            panic!("Error while calling cs_close: {:?}", err)
        }
    }
}

/// `Instructions` represents a number of disassembled instructions.
pub struct Instructions {
    instructions: *mut cs_insn,
    count: usize,
}

impl Instructions {
    fn from_raw(p: *mut cs_insn, count: usize) -> Instructions {
        Instructions {
            instructions: p,
            count: count,
        }
    }

    /// Returns true if there are no instructions.
    /// This actually will never be true but clippy wants there to be a `is_empty` method
    /// when there is a `len` method.
    pub fn is_empty(&self) -> bool {
        self.count == 0
    }

    /// Returns an `PointerIter` to iterate over all the instructions.
    pub fn iter(&self) -> PointerIter<cs_insn> {
        PointerIter::new(self.instructions, self.count)
    }

    /// Returns the number of instructions owned by this struct.
    pub fn len(&self) -> usize {
        self.count
    }
}

impl Drop for Instructions {
    fn drop(&mut self) {
        unsafe { cs_free(self.instructions, self.count) }
    }
}

/// Returns whether the requested feature is supported.
/// `query` can be one of the `CS_ARCH_`* values or `CS_ARCH_ALL` + 1 to check the diet mode.
pub fn support(query: cs_arch) -> bool {
    unsafe { cs_support(query as _) }
}

/// Returns the major version, minor version and the combined version.
pub fn version() -> (i32, i32, u32) {
    let mut major = 0;
    let mut minor = 0;
    (major, minor, unsafe { cs_version(&mut major, &mut minor) })
}

/// `PointerIter` iterates over an array of things that are
/// pointed to by an pointer.
pub struct PointerIter<'a, T: 'a> {
    ptr: *const T,
    count: usize,
    current: usize,
    lifetime: PhantomData<&'a T>,
}

impl<'a, T: 'a> PointerIter<'a, T> {
    pub fn new(ptr: *const T, count: usize) -> Self {
        PointerIter {
            ptr: ptr,
            count: count,
            current: 0,
            lifetime: PhantomData,
        }
    }
}

impl<'a, T: 'a> Iterator for PointerIter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        if self.current >= self.count {
            None
        } else {
            let object = unsafe { &*self.ptr.offset(self.current as _) };
            self.current += 1;
            Some(object)
        }
    }
}

impl cs_arm {
    pub fn operand_iter(&self) -> PointerIter<cs_arm_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_arm64 {
    pub fn operand_iter(&self) -> PointerIter<cs_arm64_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_mips {
    pub fn operand_iter(&self) -> PointerIter<cs_mips_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_ppc {
    pub fn operand_iter(&self) -> PointerIter<cs_ppc_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_sparc {
    pub fn operand_iter(&self) -> PointerIter<cs_sparc_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_sysz {
    pub fn operand_iter(&self) -> PointerIter<cs_sysz_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_x86 {
    pub fn operand_iter(&self) -> PointerIter<cs_x86_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_xcore {
    pub fn operand_iter(&self) -> PointerIter<cs_xcore_op> {
        PointerIter::new(self.operands.as_ptr(), self.op_count as _)
    }
}

impl cs_detail {
    /// Returns a reference to the `x86` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_x86(&self) -> &cs_x86 {
        unsafe { &self.__bindgen_anon_1.x86 }
    }

    /// Returns a reference to the `arm64` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_arm64(&self) -> &cs_arm64 {
        unsafe { &self.__bindgen_anon_1.arm64 }
    }

    /// Returns a reference to the `arm` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_arm(&self) -> &cs_arm {
        unsafe { &self.__bindgen_anon_1.arm }
    }

    /// Returns a reference to the `mips` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_mips(&self) -> &cs_mips {
        unsafe { &self.__bindgen_anon_1.mips }
    }

    /// Returns a reference to the `ppc` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_ppc(&self) -> &cs_ppc {
        unsafe { &self.__bindgen_anon_1.ppc }
    }

    /// Returns a reference to the `sparc` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_sparc(&self) -> &cs_sparc {
        unsafe { &self.__bindgen_anon_1.sparc }
    }

    /// Returns a reference to the `sysz` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_sysz(&self) -> &cs_sysz {
        unsafe { &self.__bindgen_anon_1.sysz }
    }

    /// Returns a reference to the `xcore` field of the union.
    /// It is the responsibility of the caller to ensure that the field may be used.
    pub fn get_xcore(&self) -> &cs_xcore {
        unsafe { &self.__bindgen_anon_1.xcore }
    }

    /// Returns an iterator over the registers read by this instruction.
    pub fn regs_read_iter(&self) -> PointerIter<u8> {
        PointerIter::new(self.regs_read.as_ptr(), self.regs_read_count as _)
    }

    /// Returns an iterator over the registers written to by this instruction.
    pub fn regs_write_iter(&self) -> PointerIter<u8> {
        PointerIter::new(self.regs_write.as_ptr(), self.regs_write_count as _)
    }

    /// Returns an iterator over the groups this instruction belongs to.
    pub fn groups_iter(&self) -> PointerIter<u8> {
        PointerIter::new(self.groups.as_ptr(), self.groups_count as _)
    }
}

impl cs_insn {
    pub fn get_mnemonic(&self) -> Option<String> {
        to_string(self.mnemonic.as_ptr())
    }

    pub fn get_op_str(&self) -> Option<String> {
        to_string(self.op_str.as_ptr())
    }
}

use std::fmt;
impl fmt::Debug for cs_insn {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("cs_insn")
            .field("id", &self.id)
            .field("address", &self.address)
            .field("size", &self.size)
            .field("bytes", &self.bytes)
            .field("mnemonic", &self.mnemonic)
            .field("detail", &self.detail)
            .finish()
    }
}

fn to_string(p: *const c_char) -> Option<String> {
    if p.is_null() {
        None
    } else {
        Some(unsafe { CStr::from_ptr(p) }.to_string_lossy().into_owned())
    }
}
<|endoftext|>


<commit_before>extern crate hyper;

mod message;
mod user;
mod client;

use std::env;
use client::TwitchClient;

macro_rules! get_arg {
	($e:expr) => (env::args().nth($e).unwrap_or(String::from("")));
}

#[cfg(test)]
mod tests {

	#[test]
	fn it_works() {

		let client: TwitchClient;
		let user: String;
		let pass: String;
		let channel: String;
		let logging: bool;

		for (index, arg) in env::args().iter().enumerate() {
			if index == 0 { continue; }

			match arg {
				"-u" => user = get_arg!(index + 1),
				"-p" => pass = get_arg!(index + 1),
				"-c" => channel = get_arg!(index + 1),
				"-l" => logging = true,
			}
		}

		// TODO: check to see if user and pass are matched, if not, panic

		client = TwitchClient {
			user: user,
			auth: pass,
			default_channel: channel,
			logging: logging
		};
	}
}
<commit_msg>Added basic match loop for chat events. Instead of storing functions to call as events later, we're going to match an event from a queue against an event type.<commit_after>extern crate hyper;

mod message;
mod user;
mod client;

macro_rules! get_arg {
	($e:expr) => (env::args().nth($e).unwrap_or(String::from("")));
}

#[cfg(test)]
mod tests {

	use std::env;
	use client::TwitchClient;
	use client::Event;

	#[test]
	fn it_works() {

		let client: TwitchClient;
		let mut user = String::from("");
		let mut pass = String::from("");
		let mut channel = String::from("");
		let mut logging = false;

		for (index, arg) in env::args().enumerate() {
			if index == 0 { continue; }

			match arg.as_ref() {
				"-u" => user = get_arg!(index + 1),
				"-p" => pass = get_arg!(index + 1),
				"-c" => channel = get_arg!(index + 1),
				"-l" => logging = true,
				_ => panic!("Unexpected argument passed: {}", arg),
			}
		}

		client = TwitchClient {
			user: user,
			auth: pass,
			default_channel: channel,
			logging: logging
		};

		client.connect();

		loop {
			match client.recv_event() {
				Ok(Event::MessageReceived(m)) => {

				}
				Err(err) => println!("Error {:?}", err),
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate env_logger;
extern crate getopts;
extern crate time;
extern crate glutin;
extern crate gfx;
extern crate gfx_device_gl;
#[cfg(target_os = "windows")]
extern crate gfx_device_dx11;
extern crate gfx_window_glutin;
//extern crate gfx_window_glfw;
#[cfg(target_os = "windows")]
extern crate gfx_window_dxgi;

pub mod shade;

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

pub struct Init<R: gfx::Resources> {
    pub backend: shade::Backend,
    pub color: gfx::handle::RenderTargetView<R, ColorFormat>,
    pub depth: gfx::handle::DepthStencilView<R, DepthFormat>,
    pub aspect_ratio: f32,
}

pub enum Backend {
    OpenGL2,
    Direct3D11 {
        pix_mode: bool,
    },
}

pub struct Config {
    //pub backend: Backend,
    pub size: (u16, u16),
}

pub const DEFAULT_CONFIG: Config = Config {
    //backend: Backend::OpenGL2,
    size: (800, 520),
};

struct Harness {
    start: f64,
    num_frames: f64,
}

impl Harness {
    fn new() -> Harness {
        Harness {
            start: time::precise_time_s(),
            num_frames: 0.0,
        }
    }
    fn bump(&mut self) {
        self.num_frames += 1.0;
    }
}

impl Drop for Harness {
    fn drop(&mut self) {
        let time_end = time::precise_time_s();
        println!("Avg frame time: {} ms",
            (time_end - self.start) * 1000.0 / self.num_frames
        );
    }
}

pub trait ApplicationBase<R: gfx::Resources, C: gfx::CommandBuffer<R>> {
    fn new<F>(F, gfx::Encoder<R, C>, Init<R>) -> Self where
        F: gfx::Factory<R>;
    fn render<D>(&mut self, &mut D) where
        D: gfx::Device<Resources=R, CommandBuffer=C>;
}

pub trait Application<R: gfx::Resources>: Sized {
    fn new<F: gfx::Factory<R>>(F, Init<R>) -> Self;
    fn render<C: gfx::CommandBuffer<R>>(&mut self, &mut gfx::Encoder<R, C>);
    #[cfg(target_os = "windows")]
    fn launch_default(name: &str) where WrapD3D11<Self>: ApplicationD3D11 {
        WrapD3D11::<Self>::launch(name, DEFAULT_CONFIG);
    }
    #[cfg(not(target_os = "windows"))]
    fn launch_default(name: &str) where WrapGL2<Self>: ApplicationGL {
        WrapGL2::<Self>::launch(name, DEFAULT_CONFIG);
    }
}

pub struct Wrap<R: gfx::Resources, C: gfx::CommandBuffer<R>, A>{
    encoder: gfx::Encoder<R, C>,
    app: A,
}

#[cfg(target_os = "windows")]
pub type D3D11CommandBuffer = gfx_device_dx11::CommandBuffer<gfx_device_dx11::DeferredContext>;
#[cfg(target_os = "windows")]
pub type D3D11CommandBufferFake = gfx_device_dx11::CommandBuffer<gfx_device_dx11::CommandList>;
#[cfg(target_os = "windows")]
pub type WrapD3D11<A> = Wrap<gfx_device_dx11::Resources, D3D11CommandBuffer, A>;
pub type WrapGL2<A> = Wrap<gfx_device_gl::Resources, gfx_device_gl::CommandBuffer, A>;

impl<R, C, A> ApplicationBase<R, C> for Wrap<R, C, A> where
    R: gfx::Resources,
    C: gfx::CommandBuffer<R>,
    A: Application<R>
{
    fn new<F>(factory: F, encoder: gfx::Encoder<R, C>, init: Init<R>) -> Self where
        F: gfx::Factory<R>
    {
        Wrap {
            encoder: encoder,
            app: A::new(factory, init),
        }
    }

    fn render<D>(&mut self, device: &mut D) where
        D: gfx::Device<Resources=R, CommandBuffer=C>
    {
        self.app.render(&mut self.encoder);
        self.encoder.flush(device);
    }
}

pub trait ApplicationGL {
    fn launch(&str, Config);
}

#[cfg(target_os = "windows")]
pub trait ApplicationD3D11 {
    fn launch(&str, Config);
}

impl<A> ApplicationGL for A where
    A: ApplicationBase<gfx_device_gl::Resources,
                       gfx_device_gl::CommandBuffer>
{
    fn launch(title: &str, config: Config) {
        use gfx::traits::Device;

        env_logger::init().unwrap();
        let builder = glutin::WindowBuilder::new()
            .with_title(title.to_string())
            .with_dimensions(config.size.0 as u32, config.size.1 as u32)
            .with_vsync();
        let (window, mut device, mut factory, main_color, main_depth) =
            gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder);
        let (width, height) = window.get_inner_size().unwrap();
        let combuf = factory.create_command_buffer();
        let shade_lang = device.get_info().shading_language;

        let mut app = Self::new(factory, combuf.into(), Init {
            backend: if shade_lang.is_embedded {
                shade::Backend::GlslEs(shade_lang)
            } else {
                shade::Backend::Glsl(shade_lang)
            },
            color: main_color,
            depth: main_depth,
            aspect_ratio: width as f32 / height as f32,
        });

        let mut harness = Harness::new();
        'main: loop {
            // quit when Esc is pressed.
            for event in window.poll_events() {
                match event {
                    glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) |
                    glutin::Event::Closed => break 'main,
                    _ => {},
                }
            }
            // draw a frame
            app.render(&mut device);
            window.swap_buffers().unwrap();
            device.cleanup();
            harness.bump()
        }
    }
}

#[cfg(target_os = "windows")]
impl<
    A: ApplicationBase<gfx_device_dx11::Resources, D3D11CommandBuffer>
> ApplicationD3D11 for A {
    fn launch(title: &str, config: Config) {
        use gfx::traits::{Device, Factory};

        env_logger::init().unwrap();
        let (window, device, mut factory, main_color) =
            gfx_window_dxgi::init::<ColorFormat>(title, config.size.0, config.size.1)
            .unwrap();
        let main_depth = factory.create_depth_stencil_view_only(
            window.size.0, window.size.1).unwrap();

        //let combuf = factory.create_command_buffer();
        let combuf = factory.create_command_buffer_native();

        let mut app = Self::new(factory, combuf.into(), Init {
            backend: shade::Backend::Hlsl(device.get_shader_model()),
            color: main_color,
            depth: main_depth,
            aspect_ratio: window.size.0 as f32 / window.size.1 as f32,
        });

        let mut device: gfx_device_dx11::Deferred = device.into();

        let mut harness = Harness::new();
        while window.dispatch() {
            app.render(&mut device);
            window.swap_buffers(1);
            device.cleanup();
            harness.bump();
        }
    }
}
<commit_msg>[gl] Added ES version fork for the app launcher<commit_after>// Copyright 2016 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate env_logger;
extern crate getopts;
extern crate time;
extern crate glutin;
extern crate gfx;
extern crate gfx_device_gl;
#[cfg(target_os = "windows")]
extern crate gfx_device_dx11;
extern crate gfx_window_glutin;
//extern crate gfx_window_glfw;
#[cfg(target_os = "windows")]
extern crate gfx_window_dxgi;

pub mod shade;

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

pub struct Init<R: gfx::Resources> {
    pub backend: shade::Backend,
    pub color: gfx::handle::RenderTargetView<R, ColorFormat>,
    pub depth: gfx::handle::DepthStencilView<R, DepthFormat>,
    pub aspect_ratio: f32,
}

pub enum Backend {
    OpenGL2,
    Direct3D11 {
        pix_mode: bool,
    },
}

pub struct Config {
    //pub backend: Backend,
    pub size: (u16, u16),
}

pub const DEFAULT_CONFIG: Config = Config {
    //backend: Backend::OpenGL2,
    size: (800, 520),
};

struct Harness {
    start: f64,
    num_frames: f64,
}

impl Harness {
    fn new() -> Harness {
        Harness {
            start: time::precise_time_s(),
            num_frames: 0.0,
        }
    }
    fn bump(&mut self) {
        self.num_frames += 1.0;
    }
}

impl Drop for Harness {
    fn drop(&mut self) {
        let time_end = time::precise_time_s();
        println!("Avg frame time: {} ms",
            (time_end - self.start) * 1000.0 / self.num_frames
        );
    }
}

pub trait ApplicationBase<R: gfx::Resources, C: gfx::CommandBuffer<R>> {
    fn new<F>(F, gfx::Encoder<R, C>, Init<R>) -> Self where
        F: gfx::Factory<R>;
    fn render<D>(&mut self, &mut D) where
        D: gfx::Device<Resources=R, CommandBuffer=C>;
}

pub trait Application<R: gfx::Resources>: Sized {
    fn new<F: gfx::Factory<R>>(F, Init<R>) -> Self;
    fn render<C: gfx::CommandBuffer<R>>(&mut self, &mut gfx::Encoder<R, C>);
    #[cfg(target_os = "windows")]
    fn launch_default(name: &str) where WrapD3D11<Self>: ApplicationD3D11 {
        WrapD3D11::<Self>::launch(name, DEFAULT_CONFIG);
    }
    #[cfg(not(target_os = "windows"))]
    fn launch_default(name: &str) where WrapGL2<Self>: ApplicationGL {
        WrapGL2::<Self>::launch(name, DEFAULT_CONFIG);
    }
}

pub struct Wrap<R: gfx::Resources, C: gfx::CommandBuffer<R>, A>{
    encoder: gfx::Encoder<R, C>,
    app: A,
}

#[cfg(target_os = "windows")]
pub type D3D11CommandBuffer = gfx_device_dx11::CommandBuffer<gfx_device_dx11::DeferredContext>;
#[cfg(target_os = "windows")]
pub type D3D11CommandBufferFake = gfx_device_dx11::CommandBuffer<gfx_device_dx11::CommandList>;
#[cfg(target_os = "windows")]
pub type WrapD3D11<A> = Wrap<gfx_device_dx11::Resources, D3D11CommandBuffer, A>;
pub type WrapGL2<A> = Wrap<gfx_device_gl::Resources, gfx_device_gl::CommandBuffer, A>;

impl<R, C, A> ApplicationBase<R, C> for Wrap<R, C, A> where
    R: gfx::Resources,
    C: gfx::CommandBuffer<R>,
    A: Application<R>
{
    fn new<F>(factory: F, encoder: gfx::Encoder<R, C>, init: Init<R>) -> Self where
        F: gfx::Factory<R>
    {
        Wrap {
            encoder: encoder,
            app: A::new(factory, init),
        }
    }

    fn render<D>(&mut self, device: &mut D) where
        D: gfx::Device<Resources=R, CommandBuffer=C>
    {
        self.app.render(&mut self.encoder);
        self.encoder.flush(device);
    }
}

pub trait ApplicationGL {
    fn launch(&str, Config);
}

#[cfg(target_os = "windows")]
pub trait ApplicationD3D11 {
    fn launch(&str, Config);
}

impl<A> ApplicationGL for A where
    A: ApplicationBase<gfx_device_gl::Resources,
                       gfx_device_gl::CommandBuffer>
{
    fn launch(title: &str, config: Config) {
        use gfx::traits::Device;

        env_logger::init().unwrap();
        let gl_version = glutin::GlRequest::GlThenGles {
            opengl_version: (3, 2), //TODO: try more versions
            opengles_version: (2, 0),
        };
        let builder = glutin::WindowBuilder::new()
            .with_title(title.to_string())
            .with_dimensions(config.size.0 as u32, config.size.1 as u32)
            .with_gl(gl_version)
            .with_vsync();
        let (window, mut device, mut factory, main_color, main_depth) =
            gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder);
        let (width, height) = window.get_inner_size().unwrap();
        let combuf = factory.create_command_buffer();
        let shade_lang = device.get_info().shading_language;

        let mut app = Self::new(factory, combuf.into(), Init {
            backend: if shade_lang.is_embedded {
                shade::Backend::GlslEs(shade_lang)
            } else {
                shade::Backend::Glsl(shade_lang)
            },
            color: main_color,
            depth: main_depth,
            aspect_ratio: width as f32 / height as f32,
        });

        let mut harness = Harness::new();
        'main: loop {
            // quit when Esc is pressed.
            for event in window.poll_events() {
                match event {
                    glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) |
                    glutin::Event::Closed => break 'main,
                    _ => {},
                }
            }
            // draw a frame
            app.render(&mut device);
            window.swap_buffers().unwrap();
            device.cleanup();
            harness.bump()
        }
    }
}

#[cfg(target_os = "windows")]
impl<
    A: ApplicationBase<gfx_device_dx11::Resources, D3D11CommandBuffer>
> ApplicationD3D11 for A {
    fn launch(title: &str, config: Config) {
        use gfx::traits::{Device, Factory};

        env_logger::init().unwrap();
        let (window, device, mut factory, main_color) =
            gfx_window_dxgi::init::<ColorFormat>(title, config.size.0, config.size.1)
            .unwrap();
        let main_depth = factory.create_depth_stencil_view_only(
            window.size.0, window.size.1).unwrap();

        //let combuf = factory.create_command_buffer();
        let combuf = factory.create_command_buffer_native();

        let mut app = Self::new(factory, combuf.into(), Init {
            backend: shade::Backend::Hlsl(device.get_shader_model()),
            color: main_color,
            depth: main_depth,
            aspect_ratio: window.size.0 as f32 / window.size.1 as f32,
        });

        let mut device: gfx_device_dx11::Deferred = device.into();

        let mut harness = Harness::new();
        while window.dispatch() {
            app.render(&mut device);
            window.swap_buffers(1);
            device.cleanup();
            harness.bump();
        }
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs,trivial_casts,trivial_numeric_casts,
        missing_debug_implementations, missing_copy_implementations,
        unsafe_code,unstable_features,unused_import_braces,unused_qualifications)
]

// Copyright 2015-2016 Daniel P. Clark & array_tool Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! Array Tool
//!
//! Array Tool is a collection of powerful methods for working with collections.

/// Array Tool provides many useful methods for vectors
pub mod vec {

  /// Several different methods for getting, or evaluating, uniqueness.
  pub trait Uniq {
    /// `uniq` returns a vector of unique values within itself as compared to
    /// the other vector which is provided as a input parameter.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Uniq;
    ///
    /// vec![1,2,3,4,5,6].uniq( vec![1,2,5,7,9] );
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![3,4,6]
    /// ```
    fn uniq(&self, other: Self) -> Self;

    /// `unique` removes duplicates from within the vector and returns Self.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Uniq;
    ///
    /// vec![1,2,1,3,2,3,4,5,6].unique();
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![1,2,3,4,5,6]
    /// ```
    fn unique(&self) -> Self;
    /// `is_unique` returns boolean value on whether all values within
    /// Self are unique.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Uniq;
    ///
    /// vec![1,2,1,3,4,3,4,5,6].is_unique();
    /// ```
    ///
    /// # Output
    /// ```text
    /// false
    /// ```
    fn is_unique(&self) -> bool;
  }

  impl<T: Clone + PartialEq> Uniq for Vec<T> {
    fn uniq(&self, other: Vec<T>) -> Vec<T> {
      let mut out = self.unique();
      for x in other.unique() {
        for y in (0..out.len()).rev() {
          if x == out[y] {
            out.remove(y);
          }
        }
      }
      out
    }
    fn unique(&self) -> Vec<T> {
      let mut a = self.clone();
      for x in (0..a.len()).rev() {
        for y in (x+1..a.len()).rev() {
          if a[x] == a[y] {
            a.remove(y);
          }
        }
      }
      a
    }
    fn is_unique(&self) -> bool {
      let mut a = true;
      for x in 0..self.len() {
        for y in x+1..self.len() {
          if self[x] == self[y] {
            a = false;
            break;
          }
        }
      }
      a
    }
  }

  /// Removes, or Adds, the first element of self.
  pub trait Shift<T> {
    /// Removes and returns the first item from the vector
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Shift;
    ///
    /// let mut x = vec![0,1,2,3];
    /// assert_eq!(x.shift(), 0);
    /// assert_eq!(x, vec![1,2,3]);
    /// ```
    fn shift(&mut self) -> T;
    /// Insert item at the beginning of the vector.  No return value.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Shift;
    ///
    /// let mut x = vec![1,2,3];
    /// x.unshift(0);
    /// assert_eq!(x, vec![0,1,2,3]);
    /// ```
    fn unshift(&mut self, other: T);
  }
  impl<T: PartialEq> Shift<T> for Vec<T> {
    fn shift(&mut self) -> T {
      self.remove(0)
    }
    fn unshift(&mut self, other: T) {
      &self.insert(0, other);
    }
  }

  /// Set Intersection — Returns a new array containing elements common to the two arrays,
  /// excluding any duplicates. The order is preserved from the original array.
  pub trait Intersect {
    /// # Example
    /// ```
    /// use array_tool::vec::Intersect;
    ///
    /// vec![1,1,3,5].intersect(vec![1,2,3]);
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![1,3]
    /// ```
    fn intersect(&self, Self) -> Self;
  }
  impl<T: PartialEq + Clone> Intersect for Vec<T> {
    fn intersect(&self, other: Vec<T>) -> Vec<T> {
      let mut out = vec![];
      let a = self.unique();
      let length = other.len();
      for x in a {
        for y in 0..length {
          if x == other[y] {
            out.push(x);
            break;
          }
        }
      }
      out
    }
  }

  /// Join vector of ToString capable things to a String with given delimiter.
  pub trait Join {
    /// # Example
    /// ```
    /// use array_tool::vec::Join;
    ///
    /// vec![1,2,3].join(",");
    /// ```
    ///
    /// # Output
    /// ```text
    /// "1,2,3"
    /// ```
    fn join(&self, joiner: &'static str) -> String;
  }
  impl<T: ToString> Join for Vec<T> {
    fn join(&self, joiner: &'static str) -> String {
      let mut out = String::from("");
      for x in 0..self.len() {
        out.push_str(&self[x].to_string());
        if x < self.len()-1 {
          out.push_str(&joiner)
        }
      }
      out
    }
  }

  /// Expand and duplicate the vectors content `times` the integer given
  pub trait Times {
    /// # Example
    /// ```
    /// use array_tool::vec::Times;
    ///
    /// vec![1,2,3].times(3);
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![1,2,3,1,2,3,1,2,3]
    /// ```
    fn times(&self, qty: i32) -> Self;
  }
  impl<T: Clone> Times for Vec<T> {
    /// Expand and duplicate the vectors content `times` the integer given
    fn times(&self, qty: i32) -> Vec<T> {
      let mut out = vec![self[0].clone();self.len()*(qty as usize)];
      let mut cycle = self.iter().cycle();
      for x in 0..self.len()*(qty as usize) {
        out[x] = cycle.next().unwrap().clone();
      }
      out
    }
  }

  /// Create a `union` between two vectors.
  /// Returns a new vector by joining with other, excluding any duplicates and preserving
  /// the order from the original vector.
  pub trait Union {
    /// # Example
    /// ```
    /// use array_tool::vec::Union;
    ///
    /// vec!["a","b","c"].union(vec!["c","d","a"]);
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![ "a", "b", "c", "d" ]
    /// ```
    fn union(&self, other: Self) -> Self;
  }
  impl<T: PartialEq + Clone> Union for Vec<T> {
    fn union(&self, other: Vec<T>) -> Vec<T> {
      let mut stack = self.clone();
      for x in other { // don't use append method as it's destructive
        stack.push(x)
      }
      stack.unique()
    }
  }
}

/// Get `uniques` from two vectors
///
/// # Example
/// ```
/// use array_tool::uniques;
///
/// uniques(vec![1,2,3,4,5], vec![2,5,6,7,8]);
/// ```
///
/// # Output
/// ```text
/// vec![vec![1,3,4], vec![6,7,8]]
/// ```
pub fn uniques<T: PartialEq + Clone>(a: Vec<T>, b: Vec<T>) -> Vec<Vec<T>> {
  use self::vec::Uniq;
  vec![a.uniq(b.clone()), b.uniq(a)]
}

<commit_msg>More documentation for core. [ci skip]<commit_after>#![deny(missing_docs,trivial_casts,trivial_numeric_casts,
        missing_debug_implementations, missing_copy_implementations,
        unsafe_code,unstable_features,unused_import_braces,unused_qualifications)
]

// Copyright 2015-2016 Daniel P. Clark & array_tool Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! # Array Tool
//!
//! is a collection of powerful methods for working with collections.
//! Some of the most common methods you would use on Arrays made available
//! on Vectors. Polymorphic implementations for handling most of your use cases.
//!
//! In your rust files where you plan to use it put this at the top
//!
//! ```
//! extern crate array_tool;
//! ```
//!
//! And if you plan to use all of the Vector helper methods available:
//!
//! ```
//! use array_tool::vec::*;
//! ```

/// Array Tool provides many useful methods for vectors
pub mod vec {

  /// Several different methods for getting, or evaluating, uniqueness.
  pub trait Uniq {
    /// `uniq` returns a vector of unique values within itself as compared to
    /// the other vector which is provided as a input parameter.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Uniq;
    ///
    /// vec![1,2,3,4,5,6].uniq( vec![1,2,5,7,9] );
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![3,4,6]
    /// ```
    fn uniq(&self, other: Self) -> Self;

    /// `unique` removes duplicates from within the vector and returns Self.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Uniq;
    ///
    /// vec![1,2,1,3,2,3,4,5,6].unique();
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![1,2,3,4,5,6]
    /// ```
    fn unique(&self) -> Self;
    /// `is_unique` returns boolean value on whether all values within
    /// Self are unique.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Uniq;
    ///
    /// vec![1,2,1,3,4,3,4,5,6].is_unique();
    /// ```
    ///
    /// # Output
    /// ```text
    /// false
    /// ```
    fn is_unique(&self) -> bool;
  }

  impl<T: Clone + PartialEq> Uniq for Vec<T> {
    fn uniq(&self, other: Vec<T>) -> Vec<T> {
      let mut out = self.unique();
      for x in other.unique() {
        for y in (0..out.len()).rev() {
          if x == out[y] {
            out.remove(y);
          }
        }
      }
      out
    }
    fn unique(&self) -> Vec<T> {
      let mut a = self.clone();
      for x in (0..a.len()).rev() {
        for y in (x+1..a.len()).rev() {
          if a[x] == a[y] {
            a.remove(y);
          }
        }
      }
      a
    }
    fn is_unique(&self) -> bool {
      let mut a = true;
      for x in 0..self.len() {
        for y in x+1..self.len() {
          if self[x] == self[y] {
            a = false;
            break;
          }
        }
      }
      a
    }
  }

  /// Removes, or Adds, the first element of self.
  pub trait Shift<T> {
    /// Removes and returns the first item from the vector
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Shift;
    ///
    /// let mut x = vec![0,1,2,3];
    /// assert_eq!(x.shift(), 0);
    /// assert_eq!(x, vec![1,2,3]);
    /// ```
    fn shift(&mut self) -> T;
    /// Insert item at the beginning of the vector.  No return value.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Shift;
    ///
    /// let mut x = vec![1,2,3];
    /// x.unshift(0);
    /// assert_eq!(x, vec![0,1,2,3]);
    /// ```
    fn unshift(&mut self, other: T);
  }
  impl<T: PartialEq> Shift<T> for Vec<T> {
    fn shift(&mut self) -> T {
      self.remove(0)
    }
    fn unshift(&mut self, other: T) {
      &self.insert(0, other);
    }
  }

  /// Set Intersection — Returns a new array containing elements common to the two arrays,
  /// excluding any duplicates. The order is preserved from the original array.
  pub trait Intersect {
    /// # Example
    /// ```
    /// use array_tool::vec::Intersect;
    ///
    /// vec![1,1,3,5].intersect(vec![1,2,3]);
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![1,3]
    /// ```
    fn intersect(&self, Self) -> Self;
  }
  impl<T: PartialEq + Clone> Intersect for Vec<T> {
    fn intersect(&self, other: Vec<T>) -> Vec<T> {
      let mut out = vec![];
      let a = self.unique();
      let length = other.len();
      for x in a {
        for y in 0..length {
          if x == other[y] {
            out.push(x);
            break;
          }
        }
      }
      out
    }
  }

  /// Join vector of ToString capable things to a String with given delimiter.
  pub trait Join {
    /// # Example
    /// ```
    /// use array_tool::vec::Join;
    ///
    /// vec![1,2,3].join(",");
    /// ```
    ///
    /// # Output
    /// ```text
    /// "1,2,3"
    /// ```
    fn join(&self, joiner: &'static str) -> String;
  }
  impl<T: ToString> Join for Vec<T> {
    fn join(&self, joiner: &'static str) -> String {
      let mut out = String::from("");
      for x in 0..self.len() {
        out.push_str(&self[x].to_string());
        if x < self.len()-1 {
          out.push_str(&joiner)
        }
      }
      out
    }
  }

  /// Expand and duplicate the vectors content `times` the integer given
  pub trait Times {
    /// # Example
    /// ```
    /// use array_tool::vec::Times;
    ///
    /// vec![1,2,3].times(3);
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![1,2,3,1,2,3,1,2,3]
    /// ```
    fn times(&self, qty: i32) -> Self;
  }
  impl<T: Clone> Times for Vec<T> {
    /// Expand and duplicate the vectors content `times` the integer given
    fn times(&self, qty: i32) -> Vec<T> {
      let mut out = vec![self[0].clone();self.len()*(qty as usize)];
      let mut cycle = self.iter().cycle();
      for x in 0..self.len()*(qty as usize) {
        out[x] = cycle.next().unwrap().clone();
      }
      out
    }
  }

  /// Create a `union` between two vectors.
  /// Returns a new vector by joining with other, excluding any duplicates and preserving
  /// the order from the original vector.
  pub trait Union {
    /// # Example
    /// ```
    /// use array_tool::vec::Union;
    ///
    /// vec!["a","b","c"].union(vec!["c","d","a"]);
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![ "a", "b", "c", "d" ]
    /// ```
    fn union(&self, other: Self) -> Self;
  }
  impl<T: PartialEq + Clone> Union for Vec<T> {
    fn union(&self, other: Vec<T>) -> Vec<T> {
      let mut stack = self.clone();
      for x in other { // don't use append method as it's destructive
        stack.push(x)
      }
      stack.unique()
    }
  }
}

/// Get `uniques` from two vectors
///
/// # Example
/// ```
/// use array_tool::uniques;
///
/// uniques(vec![1,2,3,4,5], vec![2,5,6,7,8]);
/// ```
///
/// # Output
/// ```text
/// vec![vec![1,3,4], vec![6,7,8]]
/// ```
pub fn uniques<T: PartialEq + Clone>(a: Vec<T>, b: Vec<T>) -> Vec<Vec<T>> {
  use self::vec::Uniq;
  vec![a.uniq(b.clone()), b.uniq(a)]
}

<|endoftext|>


<commit_before>#![feature(zero_one)]
use std::iter::Iterator;
use std::num::{Zero, One};
use std::ops::{BitAnd, BitOr, Shr, Shl};

pub struct BiteratorLsb<T> {
    val: T,
    at_end: bool
}

impl<T> BiteratorLsb<T>
    where T : Sized+Eq+Shr<usize, Output=T>+Ord+BitAnd<T, Output=T>+Zero+One+Copy
{
    fn new(init: T) -> BiteratorLsb<T> {
        BiteratorLsb{val: init, at_end: false}
    }
}

impl<T> Iterator for BiteratorLsb<T>
    where T : Sized+Eq+Shr<usize, Output=T>+Ord+BitAnd<T, Output=T>+Zero+One+Copy
{
    type Item = bool;

    fn next(&mut self) -> Option<bool> {
        if self.at_end { return None; }

        let lsb = self.val & T::one();
        self.val = self.val >> 1usize;
        if self.val == T::zero() {
            self.at_end = true;
        }

        if lsb == T::zero() {
            Some(false)
        } else {
            Some(true)
        }
    }
}

pub fn build_from<T, I>(iter: &mut I, max: usize) -> T
    where I: Iterator<Item=bool>,
          T: Zero + One + BitOr<T, Output=T> + Shl<usize, Output=T>
{
    let mut val: T = T::zero();

    let mut i = 0;
    loop {
        if i >= max { break; }
        let bit = match iter.next() {
            Some(true)  => T::one(),
            Some(false) => T::zero(),
            None => break
        };
        val = val | (bit << i);
        i += 1;
    }

    return val;
}

#[test]
fn test_bitstream() {
    let v: Vec<_> = BiteratorLsb::new(12u64).collect();
    assert_eq!([false, false, true, true], &v[..]);

    let v: Vec<_> = BiteratorLsb::new(0b1110u8).collect();
    assert_eq!([false, true, true, true], &v[..]);

    let v: Vec<_> = BiteratorLsb::new(0b001110u8).collect();
    assert_eq!([false, true, true, true], &v[..]);
}

#[test]
fn test_build_from() {
    let num = 0b001110u8;
    let n = build_from(&mut BiteratorLsb::new(num), 8);
    assert_eq!(num, n);
}

#[test]
fn test_build_from_partial() {
    let mut iter = BiteratorLsb::new(0b1110u8);
    assert_eq!(0b0u8, build_from(&mut iter, 1));
    assert_eq!(0b11u8, build_from(&mut iter, 2));
    assert_eq!(0b1u8, build_from(&mut iter, 1));
}
<commit_msg>Make new public<commit_after>#![feature(zero_one)]
use std::iter::Iterator;
use std::num::{Zero, One};
use std::ops::{BitAnd, BitOr, Shr, Shl};

pub struct BiteratorLsb<T> {
    val: T,
    at_end: bool
}

impl<T> BiteratorLsb<T>
    where T : Sized+Eq+Shr<usize, Output=T>+Ord+BitAnd<T, Output=T>+Zero+One+Copy
{
    pub fn new(init: T) -> BiteratorLsb<T> {
        BiteratorLsb{val: init, at_end: false}
    }
}

impl<T> Iterator for BiteratorLsb<T>
    where T : Sized+Eq+Shr<usize, Output=T>+Ord+BitAnd<T, Output=T>+Zero+One+Copy
{
    type Item = bool;

    fn next(&mut self) -> Option<bool> {
        if self.at_end { return None; }

        let lsb = self.val & T::one();
        self.val = self.val >> 1usize;
        if self.val == T::zero() {
            self.at_end = true;
        }

        if lsb == T::zero() {
            Some(false)
        } else {
            Some(true)
        }
    }
}

pub fn build_from<T, I>(iter: &mut I, max: usize) -> T
    where I: Iterator<Item=bool>,
          T: Zero + One + BitOr<T, Output=T> + Shl<usize, Output=T>
{
    let mut val: T = T::zero();

    let mut i = 0;
    loop {
        if i >= max { break; }
        let bit = match iter.next() {
            Some(true)  => T::one(),
            Some(false) => T::zero(),
            None => break
        };
        val = val | (bit << i);
        i += 1;
    }

    return val;
}

#[test]
fn test_bitstream() {
    let v: Vec<_> = BiteratorLsb::new(12u64).collect();
    assert_eq!([false, false, true, true], &v[..]);

    let v: Vec<_> = BiteratorLsb::new(0b1110u8).collect();
    assert_eq!([false, true, true, true], &v[..]);

    let v: Vec<_> = BiteratorLsb::new(0b001110u8).collect();
    assert_eq!([false, true, true, true], &v[..]);
}

#[test]
fn test_build_from() {
    let num = 0b001110u8;
    let n = build_from(&mut BiteratorLsb::new(num), 8);
    assert_eq!(num, n);
}

#[test]
fn test_build_from_partial() {
    let mut iter = BiteratorLsb::new(0b1110u8);
    assert_eq!(0b0u8, build_from(&mut iter, 1));
    assert_eq!(0b11u8, build_from(&mut iter, 2));
    assert_eq!(0b1u8, build_from(&mut iter, 1));
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Abstraction of a thread pool for basic parallelism.

#![feature(unsafe_destructor)]

use std::mem;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread::{self, JoinGuard};

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Thunk<'a> = Box<FnBox + Send + 'a>;

struct Sentinel<'a> {
    jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
    active: bool
}

impl<'a> Sentinel<'a> {
    fn new(jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>) -> Sentinel<'a> {
        Sentinel {
            jobs: jobs,
            active: true
        }
    }

    // Cancel and destroy this sentinel.
    fn cancel(mut self) {
        self.active = false;
    }
}

#[unsafe_destructor]
impl<'a> Drop for Sentinel<'a> {
    fn drop(&mut self) {
        if self.active {
            spawn_in_pool(self.jobs.clone())
        }
    }
}

/// A thread pool used to execute functions in parallel.
///
/// Spawns `n` worker threads and replenishes the pool if any worker threads
/// panic.
///
/// # Example
///
/// ```rust
/// use threadpool::ThreadPool;
/// use std::sync::mpsc::channel;
///
/// let pool = ThreadPool::new(4);
///
/// let (tx, rx) = channel();
/// for i in 0..8 {
///     let tx = tx.clone();
///     pool.execute(move|| {
///         tx.send(i).unwrap();
///     });
/// }
///
/// assert_eq!(rx.iter().take(8).fold(0, |a, b| a + b), 28);
/// ```
pub struct ThreadPool {
    // How the threadpool communicates with subthreads.
    //
    // This is the only such Sender, so when it is dropped all subthreads will
    // quit.
    jobs: Sender<Thunk<'static>>
}

impl ThreadPool {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: usize) -> ThreadPool {
        assert!(threads >= 1);

        let (tx, rx) = channel::<Thunk<'static>>();
        let rx = Arc::new(Mutex::new(rx));

        // Threadpool threads
        for _ in 0..threads {
            spawn_in_pool(rx.clone());
        }

        ThreadPool { jobs: tx }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F : FnOnce() + Send + 'static
    {
        self.jobs.send(Box::new(move || job())).unwrap();
    }
}

fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk<'static>>>>) {
    thread::spawn(move || {
        // Will spawn a new thread on panic unless it is cancelled.
        let sentinel = Sentinel::new(&jobs);

        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The Threadpool was dropped.
                Err(..) => break
            }
        }

        sentinel.cancel();
    });
}

/// A scoped thread pool used to execute functions in parallel.
///
/// `ScopedPool` is different from `ThreadPool` in that:
///
/// * When dropped, it propagates panics that occur in the worker threads.
/// * It doesn't require the `'static` bound on the functions that are executed.
/// * Worker threads are joined when the `ScopedPool` is dropped.
///
/// # Example
///
/// ```rust
/// use threadpool::ScopedPool;
///
/// let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
///
/// // We need an extra scope to shorten the lifetime of the pool
/// {
///     let pool = ScopedPool::new(4);
///     for x in &mut numbers[..] {
///         pool.execute(move|| {
///             *x += 1;
///         });
///     }
/// }
///
/// assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
/// ```
pub struct ScopedPool<'pool> {
    sender: Option<Sender<Thunk<'pool>>>,
    _guards: Vec<JoinGuard<'pool, ()>>
}

impl<'pool> ScopedPool<'pool> {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: u32) -> ScopedPool<'pool> {
        assert!(threads >= 1);

        let (sender, receiver) = channel();
        let receiver = Arc::new(Mutex::new(receiver));

        let mut guards = Vec::with_capacity(threads as usize);
        for _ in 0..threads {
            guards.push(spawn_scoped_in_pool(receiver.clone()));
        }

        ScopedPool { sender: Some(sender), _guards: guards }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F: FnOnce() + Send + 'pool
    {
        self.sender.as_ref().unwrap().send(Box::new(job)).unwrap();
    }
}

#[unsafe_destructor]
impl<'a> Drop for ScopedPool<'a> {
    fn drop(&mut self) {
        // We need to ensure that the sender is dropped before the JoinGuards
        // Otherwise the threads will be joined and wait forever in the loop
        mem::replace(&mut self.sender, None);
    }
}

fn spawn_scoped_in_pool<'a>(jobs: Arc<Mutex<Receiver<Thunk<'a>>>>) -> JoinGuard<'a, ()>
{
    thread::scoped(move || {
        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The pool was dropped.
                Err(..) => break
            }
        }
    })
}

#[cfg(test)]
mod test {
    use super::ThreadPool;
    use std::sync::mpsc::channel;
    use std::sync::{Arc, Barrier};

    const TEST_TASKS: usize = 4;

    #[test]
    fn test_works() {
        let pool = ThreadPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    #[should_fail]
    fn test_zero_tasks_panic() {
        ThreadPool::new(0);
    }

    #[test]
    fn test_recovery_from_subtask_panic() {
        let pool = ThreadPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }

        // Ensure new threads were spawned to compensate.
        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() {

        let pool = ThreadPool::new(TEST_TASKS);
        let waiter = Arc::new(Barrier::new(TEST_TASKS + 1));

        // Panic all the existing threads in a bit.
        for _ in 0..TEST_TASKS {
            let waiter = waiter.clone();
            pool.execute(move|| {
                waiter.wait();
                panic!();
            });
        }

        drop(pool);

        // Kick off the failure.
        waiter.wait();
    }
}

#[cfg(test)]
mod test_scoped {
    use super::ScopedPool;
    use std::sync::mpsc::channel;

    const TEST_TASKS: u32 = 4;

    #[test]
    fn test_works_1() {
        let pool = ScopedPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS as usize).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_works_2() {
        let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        {
            let pool = ScopedPool::new(TEST_TASKS);
            for x in numbers.iter_mut() {
                pool.execute(move || {
                    *x += 1;
                });
            }
        }
        assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
    }

    #[test]
    #[should_fail]
    fn test_zero_tasks_panic() {
        ScopedPool::new(0);
    }

    #[test]
    #[should_fail]
    fn test_panic_propagation() {
        let pool = ScopedPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }
    }
}
<commit_msg>Fix for rust-lang/rust#23752<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Abstraction of a thread pool for basic parallelism.

#![feature(unsafe_destructor)]

use std::mem;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread::{self, JoinGuard};

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Thunk<'a> = Box<FnBox + Send + 'a>;

struct Sentinel<'a> {
    jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
    active: bool
}

impl<'a> Sentinel<'a> {
    fn new(jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>) -> Sentinel<'a> {
        Sentinel {
            jobs: jobs,
            active: true
        }
    }

    // Cancel and destroy this sentinel.
    fn cancel(mut self) {
        self.active = false;
    }
}

#[unsafe_destructor]
impl<'a> Drop for Sentinel<'a> {
    fn drop(&mut self) {
        if self.active {
            spawn_in_pool(self.jobs.clone())
        }
    }
}

/// A thread pool used to execute functions in parallel.
///
/// Spawns `n` worker threads and replenishes the pool if any worker threads
/// panic.
///
/// # Example
///
/// ```rust
/// use threadpool::ThreadPool;
/// use std::sync::mpsc::channel;
///
/// let pool = ThreadPool::new(4);
///
/// let (tx, rx) = channel();
/// for i in 0..8 {
///     let tx = tx.clone();
///     pool.execute(move|| {
///         tx.send(i).unwrap();
///     });
/// }
///
/// assert_eq!(rx.iter().take(8).fold(0, |a, b| a + b), 28);
/// ```
pub struct ThreadPool {
    // How the threadpool communicates with subthreads.
    //
    // This is the only such Sender, so when it is dropped all subthreads will
    // quit.
    jobs: Sender<Thunk<'static>>
}

impl ThreadPool {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: usize) -> ThreadPool {
        assert!(threads >= 1);

        let (tx, rx) = channel::<Thunk<'static>>();
        let rx = Arc::new(Mutex::new(rx));

        // Threadpool threads
        for _ in 0..threads {
            spawn_in_pool(rx.clone());
        }

        ThreadPool { jobs: tx }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F : FnOnce() + Send + 'static
    {
        self.jobs.send(Box::new(move || job())).unwrap();
    }
}

fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk<'static>>>>) {
    thread::spawn(move || {
        // Will spawn a new thread on panic unless it is cancelled.
        let sentinel = Sentinel::new(&jobs);

        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The Threadpool was dropped.
                Err(..) => break
            }
        }

        sentinel.cancel();
    });
}

/// A scoped thread pool used to execute functions in parallel.
///
/// `ScopedPool` is different from `ThreadPool` in that:
///
/// * When dropped, it propagates panics that occur in the worker threads.
/// * It doesn't require the `'static` bound on the functions that are executed.
/// * Worker threads are joined when the `ScopedPool` is dropped.
///
/// # Example
///
/// ```rust
/// use threadpool::ScopedPool;
///
/// let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
///
/// // We need an extra scope to shorten the lifetime of the pool
/// {
///     let pool = ScopedPool::new(4);
///     for x in &mut numbers[..] {
///         pool.execute(move|| {
///             *x += 1;
///         });
///     }
/// }
///
/// assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
/// ```
pub struct ScopedPool<'pool> {
    sender: Option<Sender<Thunk<'pool>>>,
    _guards: Vec<JoinGuard<'pool, ()>>
}

impl<'pool> ScopedPool<'pool> {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: u32) -> ScopedPool<'pool> {
        assert!(threads >= 1);

        let (sender, receiver) = channel();
        let receiver = Arc::new(Mutex::new(receiver));

        let mut guards = Vec::with_capacity(threads as usize);
        for _ in 0..threads {
            guards.push(spawn_scoped_in_pool(receiver.clone()));
        }

        ScopedPool { sender: Some(sender), _guards: guards }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F: FnOnce() + Send + 'pool
    {
        self.sender.as_ref().unwrap().send(Box::new(job)).unwrap();
    }
}

#[unsafe_destructor]
impl<'a> Drop for ScopedPool<'a> {
    fn drop(&mut self) {
        // We need to ensure that the sender is dropped before the JoinGuards
        // Otherwise the threads will be joined and wait forever in the loop
        mem::replace(&mut self.sender, None);
    }
}

fn spawn_scoped_in_pool<'a>(jobs: Arc<Mutex<Receiver<Thunk<'a>>>>) -> JoinGuard<'a, ()>
{
    thread::scoped(move || {
        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The pool was dropped.
                Err(..) => break
            }
        }
    })
}

#[cfg(test)]
mod test {
    use super::ThreadPool;
    use std::sync::mpsc::channel;
    use std::sync::{Arc, Barrier};

    const TEST_TASKS: usize = 4;

    #[test]
    fn test_works() {
        let pool = ThreadPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    #[should_panic]
    fn test_zero_tasks_panic() {
        ThreadPool::new(0);
    }

    #[test]
    fn test_recovery_from_subtask_panic() {
        let pool = ThreadPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }

        // Ensure new threads were spawned to compensate.
        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() {

        let pool = ThreadPool::new(TEST_TASKS);
        let waiter = Arc::new(Barrier::new(TEST_TASKS + 1));

        // Panic all the existing threads in a bit.
        for _ in 0..TEST_TASKS {
            let waiter = waiter.clone();
            pool.execute(move|| {
                waiter.wait();
                panic!();
            });
        }

        drop(pool);

        // Kick off the failure.
        waiter.wait();
    }
}

#[cfg(test)]
mod test_scoped {
    use super::ScopedPool;
    use std::sync::mpsc::channel;

    const TEST_TASKS: u32 = 4;

    #[test]
    fn test_works_1() {
        let pool = ScopedPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS as usize).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_works_2() {
        let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        {
            let pool = ScopedPool::new(TEST_TASKS);
            for x in numbers.iter_mut() {
                pool.execute(move || {
                    *x += 1;
                });
            }
        }
        assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
    }

    #[test]
    #[should_panic]
    fn test_zero_tasks_panic() {
        ScopedPool::new(0);
    }

    #[test]
    #[should_panic]
    fn test_panic_propagation() {
        let pool = ScopedPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }
    }
}
<|endoftext|>


<commit_before>//! This crate provides a fast mpmc multicast queue.
//! It's based on the queue design from the LMAX Disruptor, with a few improvements:
//!
//!   * It acts as a futures stream/sink, so you can set up high-performance pipelines
//!
//!   * It can dynamically add/remove senders, and each stream can have multiple receivers
//!
//!   * It has fast runtime fallbacks for whenr there's a single consumer and/or a single producer
//!
//!   * It works on 32 bit systems without any performance or capability penalty
//!
//!   * In most cases, one can view data written directly into the queue without copying it
//!
//! In many cases, MultiQueue will be a good replacement for channels and it's broadcast
//! capabilities can replace more complex concurrency systems with a single queue.
//!
//! #Queue Model:
//! MultiQueue functions similarly to the LMAX Disruptor from a high level view.
//! There's an incoming FIFO data stream that is broadcast to a set of subscribers
//! as if there were multiple streams being written to.
//! There are two main differences:
//!   * MultiQueue transparently supports switching between single and multiple producers.
//!   * Each broadcast stream can be shared among multiple consumers.
//!
//! The last part makes the model a bit confusing, since there's a difference between a
//! stream of data and something consuming that stream. To make things worse, each consumer
//! may not actually see each value on the stream. Instead, multiple consumers may act on
//! a single stream each getting unique access to certain elements.
//!
//! A helpful mental model may be to think about this as if each stream was really just an mpmc
//! queue that was getting pushed to, and the MultiQueue structure just assembled a bunch
//! together behind the scenes. This isn't the case of course, but it's helpful for thinking.
//!
//! An diagram that represents a general use case of the queue where each consumer has unique
//! access to a stream is below - the # stand in for producers and @ stands in for the consumer of
//! each stream, each with a label. The lines are meant to show the data flow through the queue.
//!
//! ```text
//! -> #        @-1
//!     \      /
//!      -> -> -> @-2
//!     /      \
//! -> #        @-3
//! ```
//!
//! This is a pretty standard broadcast queue setup -
//! for each element sent in, it is seen on each stream by that's streams consumer.
//!
//!
//! However, in MultiQueue, each logical consumer might actually be demultiplexed
//! across many actual consumers, like below.
//!
//! ```text
//! -> #        @-1
//!     \      /
//!      -> -> -> @-2' (really @+@+@ each compete for a spot)
//!     /      \
//! -> #        @-3
//! ```
//!
//! If this diagram is redrawn with each of the producers sending in a
//! sequenced element (time goes left  to right):
//!
//! ```text
//! t=1|t=2|    t=3    | t=4|
//! 1 -> #              @-1 (1, 2)
//!       \            /
//!        -> 2 -> 1 -> -> @-2' (really @ (1) + @ (2) + @ (nothing yet))
//!       /            \
//! 2 -> #              @-3 (1, 2)
//!```
//!
//! If one imagines this as a webserver, the streams for @-1 and @-3 might be doing random
//! webservery work like some logging or metrics gathering and can handle
//! the workload completely on one core, @-2 is doing expensive work handling requests
//! and is split into multiple workers dealing with the data stream.
//!
//!
//! #Usage:
//! From the receiving side, this behaves quite similarly to a channel receiver.
//! The .recv function will block until data is available and then return the data.
//!
//! For senders, there is only .try_send (except for the futures sink, which can park),
//! This is due to performance and api reasons - you should handle backlog instead of just blocking.
//!
//! # Example: SPSC channel
//!
//! ```
//! extern crate multiqueue;
//!
//! use std::thread;
//!
//! let (send, recv) = multiqueue::multiqueue(10);
//!
//! let handle = thread::spawn(move || {
//!     for val in recv {
//!         println!("Got {}", val);
//!     }
//! });
//!
//! for i in 0..10 {
//!     send.try_send(i).unwrap();
//! }
//!
//! // Drop the sender to close the queue
//! drop(send);
//!
//! handle.join();
//!
//! // prints
//! // Got 0
//! // Got 1
//! // Got 2
//! // etc
//! ```
//!
//! # Example: SPSC broadcasting
//!
//! ```
//! extern crate multiqueue;
//!
//! use std::thread;
//!
//! let (send, recv) = multiqueue::multiqueue(4);
//! let mut handles = vec![];
//! for i in 0..2 { // or n
//!     let cur_recv = recv.add_stream();
//!     handles.push(thread::spawn(move || {
//!         for val in cur_recv {
//!             println!("Stream {} got {}", i, val);
//!         }
//!     }));
//! }
//!
//! // Take notice that I drop the reader - this removes it from
//! // the queue, meaning that the readers in the new threads
//! // won't get starved by the lack of progress from recv
//! recv.unsubscribe();
//!
//! for i in 0..10 {
//!     // Don't do this busy loop in real stuff unless you're really sure
//!     loop {
//!         if send.try_send(i).is_ok() {
//!             break;
//!         }
//!     }
//! }
//!
//! // Drop the sender to close the queue
//! drop(send);
//!
//! for t in handles {
//!     t.join();
//! }
//!
//! // prints along the lines of
//! // Stream 0 got 0
//! // Stream 0 got 1
//! // Stream 1 got 0
//! // Stream 0 got 2
//! // Stream 1 got 1
//! // etc
//!
//! ```
//!
//! //! # Example: SPMC broadcast
//! ```
//! extern crate multiqueue;
//!
//! use std::thread;
//!
//! let (send, recv) = multiqueue::multiqueue(4);
//!
//! let mut handles = vec![];
//!
//! for i in 0..2 { // or n
//!     let cur_recv = recv.add_stream();
//!     for j in 0..2 {
//!         let stream_consumer = cur_recv.clone();
//!         handles.push(thread::spawn(move || {
//!             for val in stream_consumer {
//!                 println!("Stream {} consumer {} got {}", i, j, val);
//!             }
//!         }));
//!     }
//!     // cur_recv is dropped here
//! }
//!
//! // Take notice that I drop the reader - this removes it from
//! // the queue, meaning that the readers in the new threads
//! // won't get starved by the lack of progress from recv
//! recv.unsubscribe();
//!
//! for i in 0..10 {
//!     // Don't do this busy loop in real stuff unless you're really sure
//!     loop {
//!         if send.try_send(i).is_ok() {
//!             break;
//!         }
//!     }
//! }
//! drop(send);
//!
//! for t in handles {
//!     t.join();
//! }
//!
//! // prints along the lines of
//! // Stream 0 consumer 1 got 2
//! // Stream 0 consumer 0 got 0
//! // Stream 1 consumer 0 got 0
//! // Stream 0 consumer 1 got 1
//! // Stream 1 consumer 1 got 1
//! // Stream 1 consumer 0 got 2
//! // etc
//!
//! // some join mechanics here
//! ```
//!
//! # Example: Usage menagerie
//!
//! ```
//! extern crate multiqueue;
//!
//! use std::thread;
//!
//! let (send, recv) = multiqueue::multiqueue(4);
//! let mut handles = vec![];
//!
//! // start like before
//! for i in 0..2 { // or n
//!     let cur_recv = recv.add_stream();
//!     for j in 0..2 {
//!         let stream_consumer = cur_recv.clone();
//!         handles.push(thread::spawn(move ||
//!             for val in stream_consumer {
//!                 println!("Stream {} consumer {} got {}", i, j, val);
//!             }
//!         ));
//!     }
//!     // cur_recv is dropped here
//! }
//!
//! // On this stream, since there's only one consumer,
//! // the receiver can be made into a SingleReceiver
//! // which can view items inline in the queue
//! let single_recv = recv.add_stream().into_single().unwrap();
//!
//! handles.push(thread::spawn(move ||
//!     for val in single_recv.iter_with(|item_ref| 10 * *item_ref) {
//!         println!("{}", val);
//!     }
//! ));
//!
//! // Same as above, except this time we just want to iterate until the receiver is empty
//! let single_recv_2 = recv.add_stream().into_single().unwrap();
//!
//! handles.push(thread::spawn(move ||
//!     for val in single_recv_2.partial_iter_with(|item_ref| 10 * *item_ref) {
//!         println!("{}", val);
//!     }
//! ));
//!
//! // Take notice that I drop the reader - this removes it from
//! // the queue, meaning that the readers in the new threads
//! // won't get starved by the lack of progress from recv
//! recv.unsubscribe();
//!
//! // Many senders to give all the receivers something
//! for _ in 0..3 {
//!     let cur_send = send.clone();
//!     handles.push(thread::spawn(move ||
//!         for i in 0..10 {
//!             loop {
//!                 if cur_send.try_send(i).is_ok() {
//!                     break;
//!                 }
//!             }
//!         }
//!     ));
//! }
//! drop(send);
//!
//! for t in handles {
//!    t.join();
//! }
//! ```

mod alloc;
mod atomicsignal;
mod consume;
mod countedindex;
mod maybe_acquire;
mod memory;
mod multiqueue;
mod read_cursor;
pub mod wait;

pub use multiqueue::{multiqueue, multiqueue_with, Receiver, SingleReceiver, Sender,
                     FuturesReceiver, FuturesSender, futures_multiqueue};
<commit_msg>Fixed documentation issue<commit_after>//! This crate provides a fast mpmc multicast queue.
//! It's based on the queue design from the LMAX Disruptor, with a few improvements:
//!
//!   * It acts as a futures stream/sink, so you can set up high-performance pipelines
//!
//!   * It can dynamically add/remove senders, and each stream can have multiple receivers
//!
//!   * It has fast runtime fallbacks for whenr there's a single consumer and/or a single producer
//!
//!   * It works on 32 bit systems without any performance or capability penalty
//!
//!   * In most cases, one can view data written directly into the queue without copying it
//!
//! In many cases, MultiQueue will be a good replacement for channels and it's broadcast
//! capabilities can replace more complex concurrency systems with a single queue.
//!
//! #Queue Model:
//! MultiQueue functions similarly to the LMAX Disruptor from a high level view.
//! There's an incoming FIFO data stream that is broadcast to a set of subscribers
//! as if there were multiple streams being written to.
//! There are two main differences:
//!   * MultiQueue transparently supports switching between single and multiple producers.
//!   * Each broadcast stream can be shared among multiple consumers.
//!
//! The last part makes the model a bit confusing, since there's a difference between a
//! stream of data and something consuming that stream. To make things worse, each consumer
//! may not actually see each value on the stream. Instead, multiple consumers may act on
//! a single stream each getting unique access to certain elements.
//!
//! A helpful mental model may be to think about this as if each stream was really just an mpmc
//! queue that was getting pushed to, and the MultiQueue structure just assembled a bunch
//! together behind the scenes. This isn't the case of course, but it's helpful for thinking.
//!
//! An diagram that represents a general use case of the queue where each consumer has unique
//! access to a stream is below - the # stand in for producers and @ stands in for the consumer of
//! each stream, each with a label. The lines are meant to show the data flow through the queue.
//!
//! ```text
//! -> #        @-1
//!     \      /
//!      -> -> -> @-2
//!     /      \
//! -> #        @-3
//! ```
//!
//! This is a pretty standard broadcast queue setup -
//! for each element sent in, it is seen on each stream by that's streams consumer.
//!
//!
//! However, in MultiQueue, each logical consumer might actually be demultiplexed
//! across many actual consumers, like below.
//!
//! ```text
//! -> #        @-1
//!     \      /
//!      -> -> -> @-2' (really @+@+@ each compete for a spot)
//!     /      \
//! -> #        @-3
//! ```
//!
//! If this diagram is redrawn with each of the producers sending in a
//! sequenced element (time goes left  to right):
//!
//! ```text
//! t=1|t=2|    t=3    | t=4|
//! 1 -> #              @-1 (1, 2)
//!       \            /
//!        -> 2 -> 1 -> -> @-2' (really @ (1) + @ (2) + @ (nothing yet))
//!       /            \
//! 2 -> #              @-3 (1, 2)
//!```
//!
//! If one imagines this as a webserver, the streams for @-1 and @-3 might be doing random
//! webservery work like some logging or metrics gathering and can handle
//! the workload completely on one core, @-2 is doing expensive work handling requests
//! and is split into multiple workers dealing with the data stream.
//!
//!
//! #Usage:
//! From the receiving side, this behaves quite similarly to a channel receiver.
//! The .recv function will block until data is available and then return the data.
//!
//! For senders, there is only .try_send (except for the futures sink, which can park),
//! This is due to performance and api reasons - you should handle backlog instead of just blocking.
//!
//! # Example: SPSC channel
//!
//! ```
//! extern crate multiqueue;
//!
//! use std::thread;
//!
//! let (send, recv) = multiqueue::multiqueue(10);
//!
//! let handle = thread::spawn(move || {
//!     for val in recv {
//!         println!("Got {}", val);
//!     }
//! });
//!
//! for i in 0..10 {
//!     send.try_send(i).unwrap();
//! }
//!
//! // Drop the sender to close the queue
//! drop(send);
//!
//! handle.join();
//!
//! // prints
//! // Got 0
//! // Got 1
//! // Got 2
//! // etc
//! ```
//!
//! # Example: SPSC broadcasting
//!
//! ```
//! extern crate multiqueue;
//!
//! use std::thread;
//!
//! let (send, recv) = multiqueue::multiqueue(4);
//! let mut handles = vec![];
//! for i in 0..2 { // or n
//!     let cur_recv = recv.add_stream();
//!     handles.push(thread::spawn(move || {
//!         for val in cur_recv {
//!             println!("Stream {} got {}", i, val);
//!         }
//!     }));
//! }
//!
//! // Take notice that I drop the reader - this removes it from
//! // the queue, meaning that the readers in the new threads
//! // won't get starved by the lack of progress from recv
//! recv.unsubscribe();
//!
//! for i in 0..10 {
//!     // Don't do this busy loop in real stuff unless you're really sure
//!     loop {
//!         if send.try_send(i).is_ok() {
//!             break;
//!         }
//!     }
//! }
//!
//! // Drop the sender to close the queue
//! drop(send);
//!
//! for t in handles {
//!     t.join();
//! }
//!
//! // prints along the lines of
//! // Stream 0 got 0
//! // Stream 0 got 1
//! // Stream 1 got 0
//! // Stream 0 got 2
//! // Stream 1 got 1
//! // etc
//!
//! ```
//!
//! //! # Example: SPMC broadcast
//!
//! ```
//! extern crate multiqueue;
//!
//! use std::thread;
//!
//! let (send, recv) = multiqueue::multiqueue(4);
//!
//! let mut handles = vec![];
//!
//! for i in 0..2 { // or n
//!     let cur_recv = recv.add_stream();
//!     for j in 0..2 {
//!         let stream_consumer = cur_recv.clone();
//!         handles.push(thread::spawn(move || {
//!             for val in stream_consumer {
//!                 println!("Stream {} consumer {} got {}", i, j, val);
//!             }
//!         }));
//!     }
//!     // cur_recv is dropped here
//! }
//!
//! // Take notice that I drop the reader - this removes it from
//! // the queue, meaning that the readers in the new threads
//! // won't get starved by the lack of progress from recv
//! recv.unsubscribe();
//!
//! for i in 0..10 {
//!     // Don't do this busy loop in real stuff unless you're really sure
//!     loop {
//!         if send.try_send(i).is_ok() {
//!             break;
//!         }
//!     }
//! }
//! drop(send);
//!
//! for t in handles {
//!     t.join();
//! }
//!
//! // prints along the lines of
//! // Stream 0 consumer 1 got 2
//! // Stream 0 consumer 0 got 0
//! // Stream 1 consumer 0 got 0
//! // Stream 0 consumer 1 got 1
//! // Stream 1 consumer 1 got 1
//! // Stream 1 consumer 0 got 2
//! // etc
//!
//! // some join mechanics here
//! ```
//!
//! # Example: Usage menagerie
//!
//! ```
//! extern crate multiqueue;
//!
//! use std::thread;
//!
//! let (send, recv) = multiqueue::multiqueue(4);
//! let mut handles = vec![];
//!
//! // start like before
//! for i in 0..2 { // or n
//!     let cur_recv = recv.add_stream();
//!     for j in 0..2 {
//!         let stream_consumer = cur_recv.clone();
//!         handles.push(thread::spawn(move ||
//!             for val in stream_consumer {
//!                 println!("Stream {} consumer {} got {}", i, j, val);
//!             }
//!         ));
//!     }
//!     // cur_recv is dropped here
//! }
//!
//! // On this stream, since there's only one consumer,
//! // the receiver can be made into a SingleReceiver
//! // which can view items inline in the queue
//! let single_recv = recv.add_stream().into_single().unwrap();
//!
//! handles.push(thread::spawn(move ||
//!     for val in single_recv.iter_with(|item_ref| 10 * *item_ref) {
//!         println!("{}", val);
//!     }
//! ));
//!
//! // Same as above, except this time we just want to iterate until the receiver is empty
//! let single_recv_2 = recv.add_stream().into_single().unwrap();
//!
//! handles.push(thread::spawn(move ||
//!     for val in single_recv_2.partial_iter_with(|item_ref| 10 * *item_ref) {
//!         println!("{}", val);
//!     }
//! ));
//!
//! // Take notice that I drop the reader - this removes it from
//! // the queue, meaning that the readers in the new threads
//! // won't get starved by the lack of progress from recv
//! recv.unsubscribe();
//!
//! // Many senders to give all the receivers something
//! for _ in 0..3 {
//!     let cur_send = send.clone();
//!     handles.push(thread::spawn(move ||
//!         for i in 0..10 {
//!             loop {
//!                 if cur_send.try_send(i).is_ok() {
//!                     break;
//!                 }
//!             }
//!         }
//!     ));
//! }
//! drop(send);
//!
//! for t in handles {
//!    t.join();
//! }
//! ```

mod alloc;
mod atomicsignal;
mod consume;
mod countedindex;
mod maybe_acquire;
mod memory;
mod multiqueue;
mod read_cursor;
pub mod wait;

pub use multiqueue::{multiqueue, multiqueue_with, Receiver, SingleReceiver, Sender,
                     FuturesReceiver, FuturesSender, futures_multiqueue};
<|endoftext|>