<commit_before>#![feature(rustc_private, never_type, decl_macro)]
#![allow(intra_doc_link_resolution_failure)]

extern crate flate2;
extern crate rustc;
extern crate rustc_allocator;
extern crate rustc_codegen_ssa;
extern crate rustc_codegen_utils;
extern crate rustc_data_structures;
extern crate rustc_fs_util;
extern crate rustc_incremental;
extern crate rustc_mir;
extern crate rustc_target;
extern crate syntax;

use std::any::Any;
use std::sync::mpsc;

use rustc::dep_graph::DepGraph;
use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc::session::config::OutputFilenames;
use rustc::ty::query::Providers;
use rustc::util::common::ErrorReported;
use rustc_codegen_utils::codegen_backend::CodegenBackend;

use cranelift::codegen::settings;

use crate::constant::ConstantCx;
use crate::prelude::*;

mod abi;
mod allocator;
mod analyze;
mod archive;
mod base;
mod common;
mod constant;
mod debuginfo;
mod driver;
mod intrinsics;
mod linkage;
mod main_shim;
mod metadata;
mod pretty_clif;
mod trap;
mod unimpl;
mod unsize;
mod value_and_place;
mod vtable;

mod prelude {
    pub use std::any::Any;
    pub use std::collections::{HashMap, HashSet};
    pub use std::convert::TryInto;

    pub use syntax::ast::{FloatTy, IntTy, UintTy};
    pub use syntax::source_map::{Pos, Span, DUMMY_SP};

    pub use rustc::bug;
    pub use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
    pub use rustc::mir::{self, interpret::AllocId, mono::MonoItem, *};
    pub use rustc::session::{
        config::{CrateType, Lto},
        Session,
    };
    pub use rustc::ty::layout::{self, Abi, LayoutOf, Scalar, Size, TyLayout, VariantIdx};
    pub use rustc::ty::{
        self, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt,
        TypeAndMut, TypeFoldable,
    };
    pub use rustc_data_structures::{
        fx::{FxHashMap, FxHashSet},
        indexed_vec::Idx,
        sync::Lrc,
    };
    pub use rustc_mir::monomorphize::collector;

    pub use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
    pub use rustc_codegen_ssa::traits::*;
    pub use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleKind};

    pub use cranelift::codegen::ir::{
        condcodes::IntCC, function::Function, ExternalName, FuncRef, Inst, SourceLoc, StackSlot,
    };
    pub use cranelift::codegen::isa::CallConv;
    pub use cranelift::codegen::Context;
    pub use cranelift::prelude::*;
    pub use cranelift_module::{
        self, Backend, DataContext, DataId, FuncId, FuncOrDataId, Linkage, Module,
    };

    pub use crate::abi::*;
    pub use crate::base::{trans_operand, trans_place};
    pub use crate::common::*;
    pub use crate::debuginfo::{DebugContext, FunctionDebugContext};
    pub use crate::trap::*;
    pub use crate::unimpl::{unimpl, with_unimpl_span};
    pub use crate::value_and_place::{CValue, CPlace};
    pub use crate::{Caches, CodegenCx};

    pub struct PrintOnPanic<F: Fn() -> String>(pub F);
    impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
        fn drop(&mut self) {
            if ::std::thread::panicking() {
                println!("{}", (self.0)());
            }
        }
    }
}

pub struct Caches<'tcx> {
    pub context: Context,
    pub vtables: HashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
}

impl Default for Caches<'_> {
    fn default() -> Self {
        Caches {
            context: Context::new(),
            vtables: HashMap::new(),
        }
    }
}

pub struct CodegenCx<'clif, 'tcx, B: Backend + 'static> {
    tcx: TyCtxt<'tcx>,
    module: &'clif mut Module<B>,
    ccx: ConstantCx,
    caches: Caches<'tcx>,
    debug_context: Option<&'clif mut DebugContext<'tcx>>,
}

impl<'clif, 'tcx, B: Backend + 'static> CodegenCx<'clif, 'tcx, B> {
    fn new(
        tcx: TyCtxt<'tcx>,
        module: &'clif mut Module<B>,
        debug_context: Option<&'clif mut DebugContext<'tcx>>,
    ) -> Self {
        CodegenCx {
            tcx,
            module,
            ccx: ConstantCx::default(),
            caches: Caches::default(),
            debug_context,
        }
    }

    fn finalize(self) {
        self.ccx.finalize(self.tcx, self.module);
    }
}

struct CraneliftCodegenBackend;

impl CodegenBackend for CraneliftCodegenBackend {
    fn init(&self, _sess: &Session) {}

    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
        Box::new(crate::metadata::CraneliftMetadataLoader)
    }

    fn provide(&self, providers: &mut Providers) {
        rustc_codegen_utils::symbol_names::provide(providers);
        rustc_codegen_ssa::back::symbol_export::provide(providers);

        providers.target_features_whitelist = |tcx, _cnum| tcx.arena.alloc(FxHashMap::default());
    }
    fn provide_extern(&self, providers: &mut Providers) {
        rustc_codegen_ssa::back::symbol_export::provide_extern(providers);
    }

    fn codegen_crate<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
        metadata: EncodedMetadata,
        need_metadata_module: bool,
        _rx: mpsc::Receiver<Box<dyn Any + Send>>,
    ) -> Box<dyn Any> {
        driver::codegen_crate(tcx, metadata, need_metadata_module)
    }

    fn join_codegen_and_link(
        &self,
        res: Box<dyn Any>,
        sess: &Session,
        _dep_graph: &DepGraph,
        outputs: &OutputFilenames,
    ) -> Result<(), ErrorReported> {
        use rustc_codegen_ssa::back::link::link_binary;

        let codegen_results = *res
            .downcast::<CodegenResults>()
            .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");

        let target_cpu = ::target_lexicon::HOST.to_string();
        link_binary::<crate::archive::ArArchiveBuilder<'_>>(
            sess,
            &codegen_results,
            outputs,
            &codegen_results.crate_name.as_str(),
            &target_cpu,
        );

        Ok(())
    }
}

fn target_triple(sess: &Session) -> target_lexicon::Triple {
    let mut target = &*sess.target.target.llvm_target;

    // FIXME add support for x86_64-apple-macosx10.7.0 to target-lexicon
    if target.starts_with("x86_64-apple-macosx") {
        target = "x86_64-apple-darwin";
    }

    target.parse().unwrap()
}

fn build_isa(sess: &Session) -> Box<dyn isa::TargetIsa + 'static> {
    let mut flags_builder = settings::builder();
    flags_builder.enable("is_pic").unwrap();
    flags_builder.set("probestack_enabled", "false").unwrap(); // ___cranelift_probestack is not provided
        flags_builder.set("enable_verifier", if cfg!(debug_assertions) {
        "true"
    } else {
        "false"
    }).unwrap();

    // FIXME enable again when https://github.com/CraneStation/cranelift/issues/664 is fixed
    /*
    use rustc::session::config::OptLevel;
    match sess.opts.optimize {
        OptLevel::No => {
            flags_builder.set("opt_level", "fastest").unwrap();
        }
        OptLevel::Less | OptLevel::Default => {}
        OptLevel::Aggressive => {
            flags_builder.set("opt_level", "best").unwrap();
        }
        OptLevel::Size | OptLevel::SizeMin => {
            sess.warn("Optimizing for size is not supported. Just ignoring the request");
        }
    }*/

    let target_triple = target_triple(sess);
    let flags = settings::Flags::new(flags_builder);
    cranelift::codegen::isa::lookup(target_triple)
        .unwrap()
        .finish(flags)
}

/// This is the entrypoint for a hot plugged rustc_codegen_cranelift
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
    Box::new(CraneliftCodegenBackend)
}
<commit_msg>Rustup<commit_after>#![feature(rustc_private, never_type, decl_macro)]
#![allow(intra_doc_link_resolution_failure)]

extern crate flate2;
extern crate rustc;
extern crate rustc_allocator;
extern crate rustc_codegen_ssa;
extern crate rustc_codegen_utils;
extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_fs_util;
extern crate rustc_incremental;
extern crate rustc_mir;
extern crate rustc_target;
extern crate syntax;

use std::any::Any;
use std::sync::mpsc;

use rustc::dep_graph::DepGraph;
use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc::session::config::OutputFilenames;
use rustc::ty::query::Providers;
use rustc::util::common::ErrorReported;
use rustc_codegen_utils::codegen_backend::CodegenBackend;

use cranelift::codegen::settings;

use crate::constant::ConstantCx;
use crate::prelude::*;

mod abi;
mod allocator;
mod analyze;
mod archive;
mod base;
mod common;
mod constant;
mod debuginfo;
mod driver;
mod intrinsics;
mod linkage;
mod main_shim;
mod metadata;
mod pretty_clif;
mod trap;
mod unimpl;
mod unsize;
mod value_and_place;
mod vtable;

mod prelude {
    pub use std::any::Any;
    pub use std::collections::{HashMap, HashSet};
    pub use std::convert::TryInto;

    pub use syntax::ast::{FloatTy, IntTy, UintTy};
    pub use syntax::source_map::{Pos, Span, DUMMY_SP};

    pub use rustc::bug;
    pub use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
    pub use rustc::mir::{self, interpret::AllocId, mono::MonoItem, *};
    pub use rustc::session::{
        config::{CrateType, Lto},
        Session,
    };
    pub use rustc::ty::layout::{self, Abi, LayoutOf, Scalar, Size, TyLayout, VariantIdx};
    pub use rustc::ty::{
        self, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt,
        TypeAndMut, TypeFoldable,
    };
    pub use rustc_data_structures::{
        fx::{FxHashMap, FxHashSet},
        indexed_vec::Idx,
        sync::Lrc,
    };
    pub use rustc_mir::monomorphize::collector;

    pub use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
    pub use rustc_codegen_ssa::traits::*;
    pub use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleKind};

    pub use cranelift::codegen::ir::{
        condcodes::IntCC, function::Function, ExternalName, FuncRef, Inst, SourceLoc, StackSlot,
    };
    pub use cranelift::codegen::isa::CallConv;
    pub use cranelift::codegen::Context;
    pub use cranelift::prelude::*;
    pub use cranelift_module::{
        self, Backend, DataContext, DataId, FuncId, FuncOrDataId, Linkage, Module,
    };

    pub use crate::abi::*;
    pub use crate::base::{trans_operand, trans_place};
    pub use crate::common::*;
    pub use crate::debuginfo::{DebugContext, FunctionDebugContext};
    pub use crate::trap::*;
    pub use crate::unimpl::{unimpl, with_unimpl_span};
    pub use crate::value_and_place::{CValue, CPlace};
    pub use crate::{Caches, CodegenCx};

    pub struct PrintOnPanic<F: Fn() -> String>(pub F);
    impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
        fn drop(&mut self) {
            if ::std::thread::panicking() {
                println!("{}", (self.0)());
            }
        }
    }
}

pub struct Caches<'tcx> {
    pub context: Context,
    pub vtables: HashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
}

impl Default for Caches<'_> {
    fn default() -> Self {
        Caches {
            context: Context::new(),
            vtables: HashMap::new(),
        }
    }
}

pub struct CodegenCx<'clif, 'tcx, B: Backend + 'static> {
    tcx: TyCtxt<'tcx>,
    module: &'clif mut Module<B>,
    ccx: ConstantCx,
    caches: Caches<'tcx>,
    debug_context: Option<&'clif mut DebugContext<'tcx>>,
}

impl<'clif, 'tcx, B: Backend + 'static> CodegenCx<'clif, 'tcx, B> {
    fn new(
        tcx: TyCtxt<'tcx>,
        module: &'clif mut Module<B>,
        debug_context: Option<&'clif mut DebugContext<'tcx>>,
    ) -> Self {
        CodegenCx {
            tcx,
            module,
            ccx: ConstantCx::default(),
            caches: Caches::default(),
            debug_context,
        }
    }

    fn finalize(self) {
        self.ccx.finalize(self.tcx, self.module);
    }
}

struct CraneliftCodegenBackend;

impl CodegenBackend for CraneliftCodegenBackend {
    fn init(&self, _sess: &Session) {}

    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
        Box::new(crate::metadata::CraneliftMetadataLoader)
    }

    fn provide(&self, providers: &mut Providers) {
        rustc_codegen_utils::symbol_names::provide(providers);
        rustc_codegen_ssa::back::symbol_export::provide(providers);

        providers.target_features_whitelist = |tcx, _cnum| tcx.arena.alloc(FxHashMap::default());
    }
    fn provide_extern(&self, providers: &mut Providers) {
        rustc_codegen_ssa::back::symbol_export::provide_extern(providers);
    }

    fn codegen_crate<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
        metadata: EncodedMetadata,
        need_metadata_module: bool,
        _rx: mpsc::Receiver<Box<dyn Any + Send>>,
    ) -> Box<dyn Any> {
        driver::codegen_crate(tcx, metadata, need_metadata_module)
    }

    fn join_codegen_and_link(
        &self,
        res: Box<dyn Any>,
        sess: &Session,
        _dep_graph: &DepGraph,
        outputs: &OutputFilenames,
    ) -> Result<(), ErrorReported> {
        use rustc_codegen_ssa::back::link::link_binary;

        let codegen_results = *res
            .downcast::<CodegenResults>()
            .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");

        let target_cpu = ::target_lexicon::HOST.to_string();
        link_binary::<crate::archive::ArArchiveBuilder<'_>>(
            sess,
            &codegen_results,
            outputs,
            &codegen_results.crate_name.as_str(),
            &target_cpu,
        );

        Ok(())
    }
}

fn target_triple(sess: &Session) -> target_lexicon::Triple {
    let mut target = &*sess.target.target.llvm_target;

    // FIXME add support for x86_64-apple-macosx10.7.0 to target-lexicon
    if target.starts_with("x86_64-apple-macosx") {
        target = "x86_64-apple-darwin";
    }

    target.parse().unwrap()
}

fn build_isa(sess: &Session) -> Box<dyn isa::TargetIsa + 'static> {
    let mut flags_builder = settings::builder();
    flags_builder.enable("is_pic").unwrap();
    flags_builder.set("probestack_enabled", "false").unwrap(); // ___cranelift_probestack is not provided
        flags_builder.set("enable_verifier", if cfg!(debug_assertions) {
        "true"
    } else {
        "false"
    }).unwrap();

    // FIXME enable again when https://github.com/CraneStation/cranelift/issues/664 is fixed
    /*
    use rustc::session::config::OptLevel;
    match sess.opts.optimize {
        OptLevel::No => {
            flags_builder.set("opt_level", "fastest").unwrap();
        }
        OptLevel::Less | OptLevel::Default => {}
        OptLevel::Aggressive => {
            flags_builder.set("opt_level", "best").unwrap();
        }
        OptLevel::Size | OptLevel::SizeMin => {
            sess.warn("Optimizing for size is not supported. Just ignoring the request");
        }
    }*/

    let target_triple = target_triple(sess);
    let flags = settings::Flags::new(flags_builder);
    cranelift::codegen::isa::lookup(target_triple)
        .unwrap()
        .finish(flags)
}

/// This is the entrypoint for a hot plugged rustc_codegen_cranelift
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
    Box::new(CraneliftCodegenBackend)
}
<|endoftext|>


<commit_before>//! # Type safety for the weary netlink user
//!
//! ## Rationale
//!
//! The `libc` crate currently provides an interface for sockets but
//! the constants to configure the socket to do anything useful in netlink
//! are not included in the crate because they live in `/usr/include/linux/netlink.h` and friends.
//! As a result, doing anything with netlink in Rust is currently a bit of a headache.
//!
//! This crate aims to define the necessary constants and wrap them in types to both take
//! advantage of the Rust type system and also avoid the need to pop open `.h` files
//! to find the information necessary to construct netlink messages.
//!
//! ## Notes
//!
//! This crate is currently under heavy development.
//!
//! The `cc` crate is a build dependency to provide as much of a natively cross distribution
//! approach as possible regarding `#define`s in C. It is used to compile a C file that includes
//! the appropriate headers and exports them to the corresponding `stdint.h` types in C.

#![deny(missing_docs)]

extern crate libc;
extern crate byteorder;

/// C constants defined as types
pub mod ffi;
/// Wrapper for `libc` sockets
pub mod socket;
/// Top-level netlink header
pub mod nlhdr;
/// Genetlink (generic netlink) header and attribute helpers
pub mod genlhdr;
/// Error module
pub mod err;

use std::io::{Cursor,Read,Write};
use std::mem;

use byteorder::{NativeEndian,ReadBytesExt,WriteBytesExt};

use ffi::alignto;
use err::{SerError,DeError};

/// Struct representing the necessary state to serialize an object
pub struct NlSerState(Cursor<Vec<u8>>, Option<usize>);

impl NlSerState {
    /// Create new serialization state object
    pub fn new() -> Self {
        NlSerState(Cursor::new(Vec::new()), None)
    }

    /// Store length of payload for later use
    pub fn set_usize(&mut self, sz: usize) {
        self.1 = Some(sz);
    }

    /// Get length of payload
    pub fn get_usize(&mut self) -> Option<usize> {
        self.1.take()
    }

    /// Get buffer with serialized representation of consumed struct
    pub fn into_inner(self) -> Vec<u8> {
        self.0.into_inner()
    }
}

/// Struct representing the necessary state to deserialize an object
pub struct NlDeState<'a>(Cursor<&'a [u8]>, Option<usize>);

impl<'a> NlDeState<'a> {
    /// Create new deserialization state object
    pub fn new(s: &'a [u8]) -> Self {
        NlDeState(Cursor::new(s), None)
    }

    /// Store length of payload for later use
    pub fn set_usize(&mut self, sz: usize) {
        self.1 = Some(sz);
    }

    /// Get length of payload
    pub fn get_usize(&mut self) -> Option<usize> {
        self.1.take()
    }
}

/// Trait defining basic actions required for netlink communication
pub trait Nl: Sized + Default {
    /// Serialization method
    fn serialize(&mut self, &mut NlSerState) -> Result<(), SerError>;
    /// Deserialization method
    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError>;
    /// The size of the binary representation of a struct - not aligned to word size
    fn size(&self) -> usize;
    /// The size of the binary representation of a struct - aligned to word size
    fn asize(&self) -> usize {
        alignto(self.size())
    }
}

impl Nl for u8 {
    fn serialize(&mut self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_u8(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_u8()))
    }

    fn size(&self) -> usize {
        mem::size_of::<u8>()
    }
}

impl Nl for u16 {
    fn serialize(&mut self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_u16::<NativeEndian>(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_u16::<NativeEndian>()))
    }

    fn size(&self) -> usize {
        mem::size_of::<u16>()
    }
}

impl Nl for u32 {
    fn serialize(&mut self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_u32::<NativeEndian>(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_u32::<NativeEndian>()))
    }

    fn size(&self) -> usize {
        mem::size_of::<u32>()
    }
}

impl Nl for Vec<u8> {
    fn serialize(&mut self, state: &mut NlSerState) -> Result<(), SerError> {
        let len = state.get_usize().unwrap_or(self.len());
        let num_bytes = state.0.write(&self)?;
        if len - num_bytes > 0 {
            let padding = vec![0; len - num_bytes];
            state.0.write(&padding)?;
        }
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        let input = state.get_usize().unwrap_or(state.0.get_ref().len());
        let mut v = vec![0; input];
        let num_bytes = state.0.by_ref().take(input as u64).read(&mut v)?;
        if input > num_bytes {
            v.truncate(num_bytes);
        }
        Ok(v)
    }

    fn size(&self) -> usize {
        self.len()
    }
}

impl Nl for String {
    fn serialize(&mut self, state: &mut NlSerState) -> Result<(), SerError> {
        self.push('\0');
        let len = state.get_usize().unwrap_or(self.len());
        let num_bytes = state.0.write(self.as_bytes())?;
        if len - num_bytes > 0 {
            let padding = vec![0; len - num_bytes];
            state.0.write(&padding)?;
        }
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        let input = state.get_usize().unwrap_or(state.0.get_ref().len());
        let mut v = vec![0; input];
        let num_bytes = state.0.by_ref().take(input as u64).read(&mut v)?;
        if input > num_bytes {
            v.truncate(num_bytes);
        }
        v = v.into_iter().filter(|b| *b != 0).collect();
        let string = String::from_utf8(v)?;
        Ok(string)
    }

    fn size(&self) -> usize {
        self.len()
    }
}

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

    #[test]
    fn test_nl_u8() {
        let mut v: u8 = 5;
        let s: &[u8; 1] = &[5];
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(s, state.into_inner().as_slice());

        let s: &[u8; 1] = &[5];
        let mut state = NlDeState::new(s);
        let v = u8::deserialize(&mut state).unwrap();
        assert_eq!(v, 5)
    }

    #[test]
    fn test_nl_u16() {
        let mut v: u16 = 6000;
        let s: &mut [u8] = &mut [0; 2];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u16::<NativeEndian>(6000).unwrap();
        }
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(s, state.into_inner().as_slice());

        let s: &mut [u8] = &mut [0; 2];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u16::<NativeEndian>(6000).unwrap();
        }
        let mut state = NlDeState::new(&*s);
        let v = u16::deserialize(&mut state).unwrap();
        assert_eq!(v, 6000)
    }

    #[test]
    fn test_nl_u32() {
        let mut v: u32 = 600000;
        let s: &mut [u8] = &mut [0; 4];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u32::<NativeEndian>(600000).unwrap();
        }
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(s, state.into_inner().as_slice());

        let s: &mut [u8] = &mut [0; 4];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u32::<NativeEndian>(600000).unwrap();
        }
        let mut state = NlDeState::new(&*s);
        let v = u32::deserialize(&mut state).unwrap();
        assert_eq!(v, 600000)
    }

    #[test]
    fn test_nl_vec() {
        let mut v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(vec![1, 2, 3, 4, 5, 6, 7, 8, 9], state.into_inner().as_slice());

        let s = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0];
        let mut state = NlDeState::new(s);
        state.set_usize(s.len() as usize);
        let v = Vec::<u8>::deserialize(&mut state).unwrap();
        assert_eq!(v, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0])
    }

    #[test]
    fn test_nl_string() {
        let mut s = "AAAAA".to_string();
        let mut state = NlSerState::new();
        s.serialize(&mut state).unwrap();
        assert_eq!(vec![65, 65, 65, 65, 65, 0], state.into_inner().as_slice());

        let s = &[65, 65, 65, 65, 65, 65, 65, 0, 0, 0, 0];
        let mut state = NlDeState::new(s);
        state.set_usize(s.len() as usize);
        let string = String::deserialize(&mut state).unwrap();
        assert_eq!(string, "AAAAAAA".to_string())
    }
}
<commit_msg>Better null byte handling for C-style strings<commit_after>//! # Type safety for the weary netlink user
//!
//! ## Rationale
//!
//! The `libc` crate currently provides an interface for sockets but
//! the constants to configure the socket to do anything useful in netlink
//! are not included in the crate because they live in `/usr/include/linux/netlink.h` and friends.
//! As a result, doing anything with netlink in Rust is currently a bit of a headache.
//!
//! This crate aims to define the necessary constants and wrap them in types to both take
//! advantage of the Rust type system and also avoid the need to pop open `.h` files
//! to find the information necessary to construct netlink messages.
//!
//! ## Notes
//!
//! This crate is currently under heavy development.
//!
//! The `cc` crate is a build dependency to provide as much of a natively cross distribution
//! approach as possible regarding `#define`s in C. It is used to compile a C file that includes
//! the appropriate headers and exports them to the corresponding `stdint.h` types in C.

#![deny(missing_docs)]

extern crate libc;
extern crate byteorder;

/// C constants defined as types
pub mod ffi;
/// Wrapper for `libc` sockets
pub mod socket;
/// Top-level netlink header
pub mod nlhdr;
/// Genetlink (generic netlink) header and attribute helpers
pub mod genlhdr;
/// Error module
pub mod err;

use std::io::{Cursor,Read,Write};
use std::mem;

use byteorder::{NativeEndian,ReadBytesExt,WriteBytesExt};

use ffi::alignto;
use err::{SerError,DeError};

/// Struct representing the necessary state to serialize an object
pub struct NlSerState(Cursor<Vec<u8>>, Option<usize>);

impl NlSerState {
    /// Create new serialization state object
    pub fn new() -> Self {
        NlSerState(Cursor::new(Vec::new()), None)
    }

    /// Store length of payload for later use
    pub fn set_usize(&mut self, sz: usize) {
        self.1 = Some(sz);
    }

    /// Get length of payload
    pub fn get_usize(&mut self) -> Option<usize> {
        self.1.take()
    }

    /// Get buffer with serialized representation of consumed struct
    pub fn into_inner(self) -> Vec<u8> {
        self.0.into_inner()
    }
}

/// Struct representing the necessary state to deserialize an object
pub struct NlDeState<'a>(Cursor<&'a [u8]>, Option<usize>);

impl<'a> NlDeState<'a> {
    /// Create new deserialization state object
    pub fn new(s: &'a [u8]) -> Self {
        NlDeState(Cursor::new(s), None)
    }

    /// Store length of payload for later use
    pub fn set_usize(&mut self, sz: usize) {
        self.1 = Some(sz);
    }

    /// Get length of payload
    pub fn get_usize(&mut self) -> Option<usize> {
        self.1.take()
    }
}

/// Trait defining basic actions required for netlink communication
pub trait Nl: Sized + Default {
    /// Serialization method
    fn serialize(&mut self, &mut NlSerState) -> Result<(), SerError>;
    /// Deserialization method
    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError>;
    /// The size of the binary representation of a struct - not aligned to word size
    fn size(&self) -> usize;
    /// The size of the binary representation of a struct - aligned to word size
    fn asize(&self) -> usize {
        alignto(self.size())
    }
}

impl Nl for u8 {
    fn serialize(&mut self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_u8(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_u8()))
    }

    fn size(&self) -> usize {
        mem::size_of::<u8>()
    }
}

impl Nl for u16 {
    fn serialize(&mut self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_u16::<NativeEndian>(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_u16::<NativeEndian>()))
    }

    fn size(&self) -> usize {
        mem::size_of::<u16>()
    }
}

impl Nl for u32 {
    fn serialize(&mut self, state: &mut NlSerState) -> Result<(), SerError> {
        try!(state.0.write_u32::<NativeEndian>(*self));
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        Ok(try!(state.0.read_u32::<NativeEndian>()))
    }

    fn size(&self) -> usize {
        mem::size_of::<u32>()
    }
}

impl Nl for Vec<u8> {
    fn serialize(&mut self, state: &mut NlSerState) -> Result<(), SerError> {
        let len = state.get_usize().unwrap_or(self.len());
        let num_bytes = state.0.write(&self)?;
        if len - num_bytes > 0 {
            let padding = vec![0; len - num_bytes];
            state.0.write(&padding)?;
        }
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        let input = state.get_usize().unwrap_or(state.0.get_ref().len());
        let mut v = vec![0; input];
        let num_bytes = state.0.by_ref().take(input as u64).read(&mut v)?;
        if input > num_bytes {
            v.truncate(num_bytes);
        }
        Ok(v)
    }

    fn size(&self) -> usize {
        self.len()
    }
}

impl Nl for String {
    fn serialize(&mut self, state: &mut NlSerState) -> Result<(), SerError> {
        self.push('\0');
        let len = state.get_usize().unwrap_or(self.len());
        let num_bytes = state.0.write(self.as_bytes())?;
        if len - num_bytes > 0 {
            let padding = vec![0; len - num_bytes];
            state.0.write(&padding)?;
        }
        Ok(())
    }

    fn deserialize(state: &mut NlDeState) -> Result<Self, DeError> {
        let input = state.get_usize().unwrap_or(state.0.get_ref().len());
        let mut v = vec![0; input];
        let num_bytes = state.0.by_ref().take(input as u64).read(&mut v)?;
        if input > num_bytes {
            v.truncate(num_bytes);
        }
        let pos = v.iter().position(|b| *b == 0);
        if let Some(p) = pos {
            v.truncate(p);
        }
        let string = String::from_utf8(v)?;
        Ok(string)
    }

    fn size(&self) -> usize {
        self.len()
    }
}

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

    #[test]
    fn test_nl_u8() {
        let mut v: u8 = 5;
        let s: &[u8; 1] = &[5];
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(s, state.into_inner().as_slice());

        let s: &[u8; 1] = &[5];
        let mut state = NlDeState::new(s);
        let v = u8::deserialize(&mut state).unwrap();
        assert_eq!(v, 5)
    }

    #[test]
    fn test_nl_u16() {
        let mut v: u16 = 6000;
        let s: &mut [u8] = &mut [0; 2];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u16::<NativeEndian>(6000).unwrap();
        }
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(s, state.into_inner().as_slice());

        let s: &mut [u8] = &mut [0; 2];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u16::<NativeEndian>(6000).unwrap();
        }
        let mut state = NlDeState::new(&*s);
        let v = u16::deserialize(&mut state).unwrap();
        assert_eq!(v, 6000)
    }

    #[test]
    fn test_nl_u32() {
        let mut v: u32 = 600000;
        let s: &mut [u8] = &mut [0; 4];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u32::<NativeEndian>(600000).unwrap();
        }
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(s, state.into_inner().as_slice());

        let s: &mut [u8] = &mut [0; 4];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u32::<NativeEndian>(600000).unwrap();
        }
        let mut state = NlDeState::new(&*s);
        let v = u32::deserialize(&mut state).unwrap();
        assert_eq!(v, 600000)
    }

    #[test]
    fn test_nl_vec() {
        let mut v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        let mut state = NlSerState::new();
        v.serialize(&mut state).unwrap();
        assert_eq!(vec![1, 2, 3, 4, 5, 6, 7, 8, 9], state.into_inner().as_slice());

        let s = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0];
        let mut state = NlDeState::new(s);
        state.set_usize(s.len() as usize);
        let v = Vec::<u8>::deserialize(&mut state).unwrap();
        assert_eq!(v, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0])
    }

    #[test]
    fn test_nl_string() {
        let mut s = "AAAAA".to_string();
        let mut state = NlSerState::new();
        s.serialize(&mut state).unwrap();
        assert_eq!(vec![65, 65, 65, 65, 65, 0], state.into_inner().as_slice());

        let s = &[65, 65, 65, 65, 65, 65, 65, 0, 0, 0, 0];
        let mut state = NlDeState::new(s);
        state.set_usize(s.len() as usize);
        let string = String::deserialize(&mut state).unwrap();
        assert_eq!(string, "AAAAAAA".to_string())
    }
}
<|endoftext|>


<commit_before>//! Core I/O traits and combinators when working with Tokio.
//!
//! A description of the high-level I/O combinators can be [found online] in
//! addition to a description of the [low level details].
//!
//! [found online]: https://tokio.rs/docs/getting-started/core/
//! [low level details]: https://tokio.rs/docs/going-deeper/core-low-level/

#![deny(missing_docs)]
#![doc(html_root_url = "https://docs.rs/tokio-io/0.1")]

#[macro_use]
extern crate log;
extern crate futures;

use std::io;

use futures::{BoxFuture, Async};
use futures::stream::BoxStream;

/// A convenience typedef around a `Future` whose error component is `io::Error`
pub type IoFuture<T> = BoxFuture<T, io::Error>;

/// A convenience typedef around a `Stream` whose error component is `io::Error`
pub type IoStream<T> = BoxStream<T, io::Error>;

/// A convenience macro for working with `io::Result<T>` from the `Read` and
/// `Write` traits.
///
/// This macro takes `io::Result<T>` as input, and returns `T` as the output. If
/// the input type is of the `Err` variant, then `Poll::NotReady` is returned if
/// it indicates `WouldBlock` or otherwise `Err` is returned.
#[macro_export]
macro_rules! try_nb {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => {
            return Ok(::futures::Async::NotReady)
        }
        Err(e) => return Err(e.into()),
    })
}

mod copy;
mod flush;
mod frame;
mod lines;
mod read;
mod read_exact;
mod read_to_end;
mod read_until;
mod split;
mod window;
mod write_all;
pub use self::copy::{copy, Copy};
pub use self::flush::{flush, Flush};
pub use self::frame::{EasyBuf, EasyBufMut, Framed, Codec};
pub use self::lines::{lines, Lines};
pub use self::read::{read, Read};
pub use self::read_exact::{read_exact, ReadExact};
pub use self::read_to_end::{read_to_end, ReadToEnd};
pub use self::read_until::{read_until, ReadUntil};
pub use self::split::{ReadHalf, WriteHalf};
pub use self::window::Window;
pub use self::write_all::{write_all, WriteAll};

/// A trait for readable objects which operated in an asynchronous and
/// futures-aware fashion.
///
/// This trait inherits from `io::Read` and indicates as a marker that an I/O
/// object is **nonblocking**, meaning that it will return an error instead of
/// blocking when bytes are read. Specifically this means that the `read`
/// function for traits that implement this type can have a few return values:
///
/// * `Ok(n)` means that `n` bytes of data was immediately read and placed into
///   the output buffer, where `n` == 0 implies that EOF has been reached.
/// * `Err(e) if e.kind() == ErrorKind::WouldBlock` means that no data was read
///   into the buffer provided. The I/O object is not currently readable but may
///   become readable in the future. Most importantly, **the current future's
///   task is scheduled to get unparked when the object is readable**. This
///   means that like `Future::poll` you'll receive a notification when the I/O
///   object is readable again.
/// * `Err(e)` for other errors are standard I/O errors coming from the
///   underlying object.
///
/// This trait importantly means that the `read` method only works in the
/// context of a future's task. The object may panic if used outside of a task.
pub trait AsyncRead: io::Read {
    /// Tests to see if this I/O object may be readable.
    ///
    /// This method returns an `Async<()>` indicating whether the object
    /// **might** be readable. It is possible that even if this method returns
    /// `Async::Ready` that a call to `read` would return a `WouldBlock` error.
    ///
    /// There is a default implementation for this function which always
    /// indicates that an I/O object is readable, but objects which can
    /// implement a finer grained version of this are recommended to do so.
    ///
    /// If this function returns `Async::NotReady` then the current future's
    /// task is arranged to receive a notification when it might not return
    /// `NotReady`.
    ///
    /// # Panics
    ///
    /// This method is likely to panic if called from outside the context of a
    /// future's task.
    fn poll_read(&mut self) -> Async<()> {
        Async::Ready(())
    }

    /// Provides a `Stream` and `Sink` interface for reading and writing to this
    /// `Io` object, using `Decode` and `Encode` to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the `Codec`
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both `Stream` and
    /// `Sink`; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling `split` on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    fn framed<C: Codec>(self, codec: C) -> Framed<Self, C>
        where Self: AsyncWrite + Sized,
    {
        frame::framed(self, codec)
    }

    /// Helper method for splitting this read/write object into two halves.
    ///
    /// The two halves returned implement the `Read` and `Write` traits,
    /// respectively.
    fn split(self) -> (ReadHalf<Self>, WriteHalf<Self>)
        where Self: AsyncWrite + Sized,
    {
        split::split(self)
    }
}

/// A trait for writable objects which operated in an asynchronous and
/// futures-aware fashion.
///
/// This trait inherits from `io::Write` and indicates as a marker that an I/O
/// object is **nonblocking**, meaning that it will return an error instead of
/// blocking when bytes are written. Specifically this means that the `write`
/// function for traits that implement this type can have a few return values:
///
/// * `Ok(n)` means that `n` bytes of data was immediately written .
/// * `Err(e) if e.kind() == ErrorKind::WouldBlock` means that no data was
///   written from the buffer provided. The I/O object is not currently
///   writable but may become writable in the future. Most importantly, **the
///   current future's task is scheduled to get unparked when the object is
///   readable**. This means that like `Future::poll` you'll receive a
///   notification when the I/O object is writable again.
/// * `Err(e)` for other errors are standard I/O errors coming from the
///   underlying object.
///
/// This trait importantly means that the `write` method only works in the
/// context of a future's task. The object may panic if used outside of a task.
pub trait AsyncWrite: io::Write {
    /// Tests to see if this I/O object may be writable.
    ///
    /// This method returns an `Async<()>` indicating whether the object
    /// **might** be writable. It is possible that even if this method returns
    /// `Async::Ready` that a call to `write` would return a `WouldBlock` error.
    ///
    /// There is a default implementation for this function which always
    /// indicates that an I/O object is writable, but objects which can
    /// implement a finer grained version of this are recommended to do so.
    ///
    /// If this function returns `Async::NotReady` then the current future's
    /// task is arranged to receive a notification when it might not return
    /// `NotReady`.
    ///
    /// # Panics
    ///
    /// This method is likely to panic if called from outside the context of a
    /// future's task.
    fn poll_write(&mut self) -> Async<()> {
        Async::Ready(())
    }
}

impl AsyncRead for io::Repeat {}
impl AsyncWrite for io::Sink {}
impl<T: AsyncRead> AsyncRead for io::Take<T> {}
<commit_msg>Add object-safe impls of Async{Read,Write}<commit_after>//! Core I/O traits and combinators when working with Tokio.
//!
//! A description of the high-level I/O combinators can be [found online] in
//! addition to a description of the [low level details].
//!
//! [found online]: https://tokio.rs/docs/getting-started/core/
//! [low level details]: https://tokio.rs/docs/going-deeper/core-low-level/

#![deny(missing_docs)]
#![doc(html_root_url = "https://docs.rs/tokio-io/0.1")]

#[macro_use]
extern crate log;
extern crate futures;

use std::io;

use futures::{BoxFuture, Async};
use futures::stream::BoxStream;

/// A convenience typedef around a `Future` whose error component is `io::Error`
pub type IoFuture<T> = BoxFuture<T, io::Error>;

/// A convenience typedef around a `Stream` whose error component is `io::Error`
pub type IoStream<T> = BoxStream<T, io::Error>;

/// A convenience macro for working with `io::Result<T>` from the `Read` and
/// `Write` traits.
///
/// This macro takes `io::Result<T>` as input, and returns `T` as the output. If
/// the input type is of the `Err` variant, then `Poll::NotReady` is returned if
/// it indicates `WouldBlock` or otherwise `Err` is returned.
#[macro_export]
macro_rules! try_nb {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => {
            return Ok(::futures::Async::NotReady)
        }
        Err(e) => return Err(e.into()),
    })
}

mod copy;
mod flush;
mod frame;
mod lines;
mod read;
mod read_exact;
mod read_to_end;
mod read_until;
mod split;
mod window;
mod write_all;
pub use self::copy::{copy, Copy};
pub use self::flush::{flush, Flush};
pub use self::frame::{EasyBuf, EasyBufMut, Framed, Codec};
pub use self::lines::{lines, Lines};
pub use self::read::{read, Read};
pub use self::read_exact::{read_exact, ReadExact};
pub use self::read_to_end::{read_to_end, ReadToEnd};
pub use self::read_until::{read_until, ReadUntil};
pub use self::split::{ReadHalf, WriteHalf};
pub use self::window::Window;
pub use self::write_all::{write_all, WriteAll};

/// A trait for readable objects which operated in an asynchronous and
/// futures-aware fashion.
///
/// This trait inherits from `io::Read` and indicates as a marker that an I/O
/// object is **nonblocking**, meaning that it will return an error instead of
/// blocking when bytes are read. Specifically this means that the `read`
/// function for traits that implement this type can have a few return values:
///
/// * `Ok(n)` means that `n` bytes of data was immediately read and placed into
///   the output buffer, where `n` == 0 implies that EOF has been reached.
/// * `Err(e) if e.kind() == ErrorKind::WouldBlock` means that no data was read
///   into the buffer provided. The I/O object is not currently readable but may
///   become readable in the future. Most importantly, **the current future's
///   task is scheduled to get unparked when the object is readable**. This
///   means that like `Future::poll` you'll receive a notification when the I/O
///   object is readable again.
/// * `Err(e)` for other errors are standard I/O errors coming from the
///   underlying object.
///
/// This trait importantly means that the `read` method only works in the
/// context of a future's task. The object may panic if used outside of a task.
pub trait AsyncRead: io::Read {
    /// Tests to see if this I/O object may be readable.
    ///
    /// This method returns an `Async<()>` indicating whether the object
    /// **might** be readable. It is possible that even if this method returns
    /// `Async::Ready` that a call to `read` would return a `WouldBlock` error.
    ///
    /// There is a default implementation for this function which always
    /// indicates that an I/O object is readable, but objects which can
    /// implement a finer grained version of this are recommended to do so.
    ///
    /// If this function returns `Async::NotReady` then the current future's
    /// task is arranged to receive a notification when it might not return
    /// `NotReady`.
    ///
    /// # Panics
    ///
    /// This method is likely to panic if called from outside the context of a
    /// future's task.
    fn poll_read(&mut self) -> Async<()> {
        Async::Ready(())
    }

    /// Provides a `Stream` and `Sink` interface for reading and writing to this
    /// `Io` object, using `Decode` and `Encode` to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the `Codec`
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both `Stream` and
    /// `Sink`; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling `split` on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    fn framed<C: Codec>(self, codec: C) -> Framed<Self, C>
        where Self: AsyncWrite + Sized,
    {
        frame::framed(self, codec)
    }

    /// Helper method for splitting this read/write object into two halves.
    ///
    /// The two halves returned implement the `Read` and `Write` traits,
    /// respectively.
    fn split(self) -> (ReadHalf<Self>, WriteHalf<Self>)
        where Self: AsyncWrite + Sized,
    {
        split::split(self)
    }
}

impl<T: ?Sized + AsyncRead> AsyncRead for Box<T> {
    fn poll_read(&mut self) -> Async<()> {
        (**self).poll_read()
    }
}
impl<'a, T: ?Sized + AsyncRead> AsyncRead for &'a mut T {
    fn poll_read(&mut self) -> Async<()> {
        (**self).poll_read()
    }
}

/// A trait for writable objects which operated in an asynchronous and
/// futures-aware fashion.
///
/// This trait inherits from `io::Write` and indicates as a marker that an I/O
/// object is **nonblocking**, meaning that it will return an error instead of
/// blocking when bytes are written. Specifically this means that the `write`
/// function for traits that implement this type can have a few return values:
///
/// * `Ok(n)` means that `n` bytes of data was immediately written .
/// * `Err(e) if e.kind() == ErrorKind::WouldBlock` means that no data was
///   written from the buffer provided. The I/O object is not currently
///   writable but may become writable in the future. Most importantly, **the
///   current future's task is scheduled to get unparked when the object is
///   readable**. This means that like `Future::poll` you'll receive a
///   notification when the I/O object is writable again.
/// * `Err(e)` for other errors are standard I/O errors coming from the
///   underlying object.
///
/// This trait importantly means that the `write` method only works in the
/// context of a future's task. The object may panic if used outside of a task.
pub trait AsyncWrite: io::Write {
    /// Tests to see if this I/O object may be writable.
    ///
    /// This method returns an `Async<()>` indicating whether the object
    /// **might** be writable. It is possible that even if this method returns
    /// `Async::Ready` that a call to `write` would return a `WouldBlock` error.
    ///
    /// There is a default implementation for this function which always
    /// indicates that an I/O object is writable, but objects which can
    /// implement a finer grained version of this are recommended to do so.
    ///
    /// If this function returns `Async::NotReady` then the current future's
    /// task is arranged to receive a notification when it might not return
    /// `NotReady`.
    ///
    /// # Panics
    ///
    /// This method is likely to panic if called from outside the context of a
    /// future's task.
    fn poll_write(&mut self) -> Async<()> {
        Async::Ready(())
    }
}

impl<T: ?Sized + AsyncWrite> AsyncWrite for Box<T> {
    fn poll_write(&mut self) -> Async<()> {
        (**self).poll_write()
    }
}
impl<'a, T: ?Sized + AsyncWrite> AsyncWrite for &'a mut T {
    fn poll_write(&mut self) -> Async<()> {
        (**self).poll_write()
    }
}

impl AsyncRead for io::Repeat {}
impl AsyncWrite for io::Sink {}
impl<T: AsyncRead> AsyncRead for io::Take<T> {}
<|endoftext|>


<commit_before>//! A fast, low-level IO library for Rust focusing on non-blocking APIs, event
//! notification, and other useful utilities for building high performance IO
//! apps.
//!
//! # Goals
//!
//! * Fast - minimal overhead over the equivalent OS facilities (epoll, kqueue, etc...)
//! * Zero allocations
//! * A scalable readiness-based API, similar to epoll on Linux
//! * Design to allow for stack allocated buffers when possible (avoid double buffering).
//! * Provide utilities such as a timers, a notification channel, buffer abstractions, and a slab.
//!
//! # Usage
//!
//! Using mio starts by creating an [EventLoop](struct.EventLoop.html), which
//! handles receiving events from the OS and dispatching them to a supplied
//! [Handler](handler/trait.Handler.html).
//!
//! # Example
//!
//! ```
//! use mio::*;
//! use mio::tcp::{TcpListener, TcpStream};
//!
//! // Setup some tokens to allow us to identify which event is
//! // for which socket.
//! const SERVER: Token = Token(0);
//! const CLIENT: Token = Token(1);
//!
//! let addr = "127.0.0.1:13265".parse().unwrap();
//!
//! // Setup the server socket
//! let server = TcpListener::bind(&addr).unwrap();
//!
//! // Create an poll instance
//! let poll = Poll::new().unwrap();
//!
//! // Start listening for incoming connections
//! poll.register(&server, SERVER, Ready::readable(),
//!               PollOpt::edge()).unwrap();
//!
//! // Setup the client socket
//! let sock = TcpStream::connect(&addr).unwrap();
//!
//! // Register the socket
//! poll.register(&sock, CLIENT, Ready::readable(),
//!               PollOpt::edge()).unwrap();
//!
//! // Create storage for events
//! let mut events = Events::with_capacity(1024);
//!
//! loop {
//!     poll.poll(&mut events, None).unwrap();
//!
//!     for event in events.iter() {
//!         match event.token() {
//!             SERVER => {
//!                 // Accept and drop the socket immediately, this will close
//!                 // the socket and notify the client of the EOF.
//!                 let _ = server.accept();
//!             }
//!             CLIENT => {
//!                 // The server just shuts down the socket, let's just exit
//!                 // from our event loop.
//!                 return;
//!             }
//!             _ => unreachable!(),
//!         }
//!     }
//! }
//!
//! ```

#![doc(html_root_url = "https://docs.rs/mio/0.6.1")]
#![crate_name = "mio"]
#![cfg_attr(unix, deny(warnings))]

extern crate lazycell;
extern crate net2;
extern crate slab;

#[cfg(unix)]
extern crate libc;

#[cfg(windows)]
extern crate miow;

#[cfg(windows)]
extern crate winapi;

#[cfg(windows)]
extern crate kernel32;

#[macro_use]
extern crate log;

#[cfg(test)]
extern crate env_logger;

mod event;
mod io;
mod iovec;
mod net;
mod poll;
mod sys;
mod token;

pub mod channel;
pub mod timer;

/// EventLoop and other deprecated types
pub mod deprecated;

pub use event::{
    PollOpt,
    Ready,
    Event,
};
pub use io::{
    Evented,
    would_block,
};
pub use iovec::IoVec;
pub use net::{
    tcp,
    udp,
};
pub use poll::{
    Poll,
    Events,
    EventsIter,
    Registration,
    SetReadiness,
};
pub use token::{
    Token,
};

#[cfg(unix)]
pub mod unix {
    //! Unix only extensions

    pub use sys::{
        EventedFd,
    };
}

/// Windows-only extensions to the mio crate.
///
/// Mio on windows is currently implemented with IOCP for a high-performance
/// implementation of asynchronous I/O. Mio then provides TCP and UDP as sample
/// bindings for the system to connect networking types to asynchronous I/O. On
/// Unix this scheme is then also extensible to all other file descriptors with
/// the `EventedFd` type, but on Windows no such analog is available. The
/// purpose of this module, however, is to similarly provide a mechanism for
/// foreign I/O types to get hooked up into the IOCP event loop.
///
/// This module provides two types for interfacing with a custom IOCP handle:
///
/// * `Binding` - this type is intended to govern binding with mio's `Poll`
///   type. Each I/O object should contain an instance of `Binding` that's
///   interfaced with for the implementation of the `Evented` trait. The
///   `register`, `reregister`, and `deregister` methods for the `Evented` trait
///   all have rough analogs with `Binding`.
///
///   Note that this type **does not handle readiness**. That is, this type does
///   not handle whether sockets are readable/writable/etc. It's intended that
///   IOCP types will internally manage this state with a `SetReadiness` type
///   from the `poll` module. The `SetReadiness` is typically lazily created on
///   the first time that `Evented::register` is called and then stored in the
///   I/O object.
///
///   Also note that for types which represent streams of bytes the mio
///   interface of *readiness* doesn't map directly to the Windows model of
///   *completion*. This means that types will have to perform internal
///   buffering to ensure that a readiness interface can be provided. For a
///   sample implementation see the TCP/UDP modules in mio itself.
///
/// * `Overlapped` - this type is intended to be used as the concreate instances
///   of the `OVERLAPPED` type that most win32 methods expect. It's crucial, for
///   safety, that all asynchronous operations are initiated with an instance of
///   `Overlapped` and not another instantiation of `OVERLAPPED`.
///
///   Mio's `Overlapped` type is created with a function pointer that receives
///   a `OVERLAPPED_ENTRY` type when called. This `OVERLAPPED_ENTRY` type is
///   defined in the `winapi` crate. Whenever a completion is posted to an IOCP
///   object the `OVERLAPPED` that was signaled will be interpreted as
///   `Overlapped` in the mio crate and this function pointer will be invoked.
///   Through this function pointer, and through the `OVERLAPPED` pointer,
///   implementations can handle management of I/O events.
///
/// When put together these two types enable custom Windows handles to be
/// registered with mio's event loops. The `Binding` type is used to associate
/// handles and the `Overlapped` type is used to execute I/O operations. When
/// the I/O operations are completed a custom function pointer is called which
/// typically modifies a `SetReadiness` set by `Evented` methods which will get
/// later hooked into the mio event loop.
#[cfg(windows)]
pub mod windows {

    pub use sys::{Overlapped, Binding};
}

// Conversion utilities
mod convert {
    use std::time::Duration;

    const NANOS_PER_MILLI: u32 = 1_000_000;
    const MILLIS_PER_SEC: u64 = 1_000;

    /// Convert a `Duration` to milliseconds, rounding up and saturating at
    /// `u64::MAX`.
    ///
    /// The saturating is fine because `u64::MAX` milliseconds are still many
    /// million years.
    pub fn millis(duration: Duration) -> u64 {
        // Round up.
        let millis = (duration.subsec_nanos() + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI;
        duration.as_secs().saturating_mul(MILLIS_PER_SEC).saturating_add(millis as u64)
    }
}
<commit_msg>Fix broken links and an outdated usage in mio's doc.<commit_after>//! A fast, low-level IO library for Rust focusing on non-blocking APIs, event
//! notification, and other useful utilities for building high performance IO
//! apps.
//!
//! # Goals
//!
//! * Fast - minimal overhead over the equivalent OS facilities (epoll, kqueue, etc...)
//! * Zero allocations
//! * A scalable readiness-based API, similar to epoll on Linux
//! * Design to allow for stack allocated buffers when possible (avoid double buffering).
//! * Provide utilities such as a timers, a notification channel, buffer abstractions, and a slab.
//!
//! # Usage
//!
//! Using mio starts by creating an [Poll](struct.Poll.html), which reads events from the OS and
//! put them into [Events](struct.Events.html). You can handle IO events from the OS with it.
//!
//! # Example
//!
//! ```
//! use mio::*;
//! use mio::tcp::{TcpListener, TcpStream};
//!
//! // Setup some tokens to allow us to identify which event is
//! // for which socket.
//! const SERVER: Token = Token(0);
//! const CLIENT: Token = Token(1);
//!
//! let addr = "127.0.0.1:13265".parse().unwrap();
//!
//! // Setup the server socket
//! let server = TcpListener::bind(&addr).unwrap();
//!
//! // Create an poll instance
//! let poll = Poll::new().unwrap();
//!
//! // Start listening for incoming connections
//! poll.register(&server, SERVER, Ready::readable(),
//!               PollOpt::edge()).unwrap();
//!
//! // Setup the client socket
//! let sock = TcpStream::connect(&addr).unwrap();
//!
//! // Register the socket
//! poll.register(&sock, CLIENT, Ready::readable(),
//!               PollOpt::edge()).unwrap();
//!
//! // Create storage for events
//! let mut events = Events::with_capacity(1024);
//!
//! loop {
//!     poll.poll(&mut events, None).unwrap();
//!
//!     for event in events.iter() {
//!         match event.token() {
//!             SERVER => {
//!                 // Accept and drop the socket immediately, this will close
//!                 // the socket and notify the client of the EOF.
//!                 let _ = server.accept();
//!             }
//!             CLIENT => {
//!                 // The server just shuts down the socket, let's just exit
//!                 // from our event loop.
//!                 return;
//!             }
//!             _ => unreachable!(),
//!         }
//!     }
//! }
//!
//! ```

#![doc(html_root_url = "https://docs.rs/mio/0.6.1")]
#![crate_name = "mio"]
#![cfg_attr(unix, deny(warnings))]

extern crate lazycell;
extern crate net2;
extern crate slab;

#[cfg(unix)]
extern crate libc;

#[cfg(windows)]
extern crate miow;

#[cfg(windows)]
extern crate winapi;

#[cfg(windows)]
extern crate kernel32;

#[macro_use]
extern crate log;

#[cfg(test)]
extern crate env_logger;

mod event;
mod io;
mod iovec;
mod net;
mod poll;
mod sys;
mod token;

pub mod channel;
pub mod timer;

/// EventLoop and other deprecated types
pub mod deprecated;

pub use event::{
    PollOpt,
    Ready,
    Event,
};
pub use io::{
    Evented,
    would_block,
};
pub use iovec::IoVec;
pub use net::{
    tcp,
    udp,
};
pub use poll::{
    Poll,
    Events,
    EventsIter,
    Registration,
    SetReadiness,
};
pub use token::{
    Token,
};

#[cfg(unix)]
pub mod unix {
    //! Unix only extensions

    pub use sys::{
        EventedFd,
    };
}

/// Windows-only extensions to the mio crate.
///
/// Mio on windows is currently implemented with IOCP for a high-performance
/// implementation of asynchronous I/O. Mio then provides TCP and UDP as sample
/// bindings for the system to connect networking types to asynchronous I/O. On
/// Unix this scheme is then also extensible to all other file descriptors with
/// the `EventedFd` type, but on Windows no such analog is available. The
/// purpose of this module, however, is to similarly provide a mechanism for
/// foreign I/O types to get hooked up into the IOCP event loop.
///
/// This module provides two types for interfacing with a custom IOCP handle:
///
/// * `Binding` - this type is intended to govern binding with mio's `Poll`
///   type. Each I/O object should contain an instance of `Binding` that's
///   interfaced with for the implementation of the `Evented` trait. The
///   `register`, `reregister`, and `deregister` methods for the `Evented` trait
///   all have rough analogs with `Binding`.
///
///   Note that this type **does not handle readiness**. That is, this type does
///   not handle whether sockets are readable/writable/etc. It's intended that
///   IOCP types will internally manage this state with a `SetReadiness` type
///   from the `poll` module. The `SetReadiness` is typically lazily created on
///   the first time that `Evented::register` is called and then stored in the
///   I/O object.
///
///   Also note that for types which represent streams of bytes the mio
///   interface of *readiness* doesn't map directly to the Windows model of
///   *completion*. This means that types will have to perform internal
///   buffering to ensure that a readiness interface can be provided. For a
///   sample implementation see the TCP/UDP modules in mio itself.
///
/// * `Overlapped` - this type is intended to be used as the concreate instances
///   of the `OVERLAPPED` type that most win32 methods expect. It's crucial, for
///   safety, that all asynchronous operations are initiated with an instance of
///   `Overlapped` and not another instantiation of `OVERLAPPED`.
///
///   Mio's `Overlapped` type is created with a function pointer that receives
///   a `OVERLAPPED_ENTRY` type when called. This `OVERLAPPED_ENTRY` type is
///   defined in the `winapi` crate. Whenever a completion is posted to an IOCP
///   object the `OVERLAPPED` that was signaled will be interpreted as
///   `Overlapped` in the mio crate and this function pointer will be invoked.
///   Through this function pointer, and through the `OVERLAPPED` pointer,
///   implementations can handle management of I/O events.
///
/// When put together these two types enable custom Windows handles to be
/// registered with mio's event loops. The `Binding` type is used to associate
/// handles and the `Overlapped` type is used to execute I/O operations. When
/// the I/O operations are completed a custom function pointer is called which
/// typically modifies a `SetReadiness` set by `Evented` methods which will get
/// later hooked into the mio event loop.
#[cfg(windows)]
pub mod windows {

    pub use sys::{Overlapped, Binding};
}

// Conversion utilities
mod convert {
    use std::time::Duration;

    const NANOS_PER_MILLI: u32 = 1_000_000;
    const MILLIS_PER_SEC: u64 = 1_000;

    /// Convert a `Duration` to milliseconds, rounding up and saturating at
    /// `u64::MAX`.
    ///
    /// The saturating is fine because `u64::MAX` milliseconds are still many
    /// million years.
    pub fn millis(duration: Duration) -> u64 {
        // Round up.
        let millis = (duration.subsec_nanos() + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI;
        duration.as_secs().saturating_mul(MILLIS_PER_SEC).saturating_add(millis as u64)
    }
}
<|endoftext|>


<commit_before>#![feature(unsafe_destructor)]
#![feature(core)]

use std::thread;
use std::iter::IntoIterator;

mod maps;

pub use maps::{unordered_map, UnorderedParMap, map, ParMap};

/// Execute `f` on each element of `iter`, in their own `scoped`
/// thread.
///
/// If `f` panics, so does `for_`. If this occurs, the number of
/// elements of `iter` that have had `f` called on them is
/// unspecified.
pub fn for_<I: IntoIterator, F>(iter: I, ref f: F)
    where I::Item: Send, F: Fn(I::Item) + Sync
{
    let _guards: Vec<_> = iter.into_iter().map(|elem| {
        thread::scoped(move || {
            f(elem)
        })
    }).collect();
}

/// Execute `f` on both `x` and `y`, in parallel, returning the
/// result.
///
/// This is the same (including panic semantics) as `(f(x), f(y))`, up
/// to ordering. It is designed to be used for divide-and-conquer
/// algorithms.
pub fn both<T, U, F>(x: T, y: T, ref f: F) -> (U, U)
    where T: Send,
          U: Send,
          F: Sync + Fn(T) -> U
{
    let guard = thread::scoped(move || f(y));
    let a = f(x);
    let b = guard.join();
    (a, b)
}
<commit_msg>Add a chunk of docs to the library description.<commit_after>//! Straight-forward functions and types for basic data parallel
//! operations.
//!
//! This library provides a few building blocks for operating on data
//! in parallel, particularly iterators. At the moment, it is not
//! designed to be robust or eek out every last drop of performance,
//! but rather explore some ways in which Rust's type system allows
//! for some fairly fancy things to be written with a guarantee of
//! safety, all without a garbage collector.
//!
//! The only dependency is `std` and there is no `unsafe` code at all,
//! all the parallelism is built directly from the functionality
//! provided by `std::thread` and `std::sync` and leverages their
//! correctness to automatically ensure correctness (at the memory
//! safety level).
//!
//! The core design is to simply allow for operations that could occur
//! on a single thread to execute on many, it is not intending to
//! serve as a hard boundary between threads; in particular, if
//! something (a `panic!`) would take down the main thread when run
//! sequentially, it will also take down the main thread (eventually)
//! when run using the functions in this library.
//!
//! On the point of performance and robust, there's no thread pooling,
//! and so everything essentially spawns a new thread for each
//! element, which is definitely suboptimal for many
//! reasons. Fortunately, not all is lost, the functionality is
//! designed to be as generic as possible, so the iterator functions
//! work with many many iterators, e.g. instead of executing a thread
//! on every element of a vector individually, a user can divide that
//! vector into disjoint sections and spread those across much fewer
//! threads (e.g. [the `chunks`
//! method](http://doc.rust-lang.org/nightly/std/slice/trait.SliceExt.html#tymethod.chunks)).
//!
//! Either way, **this is not recommended for general use**. At the
//! moment, it is too easy to get resource exhaustion, and crash the
//! application, and generally pays a much higher cost than necessary.
//!
//! # Example
//!
//! Initialise an array, in parallel.
//!
//! ```rust
//! let mut data = [0; 10];
//! simple_parallel::for_(data.iter_mut().enumerate(), |(i, elem)| {
//!     *elem = i as i32;
//! })
//! ```
//!
//! Transform each element of an ordered map in a fancy way, in
//! parallel, with `map` (`map` ensures the output order matches the
//! input order, unlike `unordered_map`),
//!
//! ```rust
//! use std::collections::BTreeMap;
//!
//! let mut map = BTreeMap::new();
//! map.insert('a', 1);
//! map.insert('x', 55);
//!
//! let f = |(&c, &elem): (&char, _)| {
//!     let mut x = elem  * c as i32;
//!     // ... something complicated and expensive ...
//!     return x as f64
//! };
//!
//! // (`IntoIterator` is used, so "direct" iteration like this is fine.)
//! let par_iter = simple_parallel::map(&map, &f);
//!
//! // the computation is executing on several threads in the
//! // background, so that elements are hopefully ready as soon as
//! // possible.
//!
//! for value in par_iter {
//!     println!("I computed {}", value);
//! }
//! ```
//!
//! Sum an arbitrarily long slice, in parallel, by summing subsections and adding
//! everything to a shared mutex, stored on the stack of the main
//! thread. (A parallel fold is currently missing, hence the mutex.)
//!
//! ```rust
//! use std::sync::Mutex;
//!
//! // limit the spew of thread spawning to something sensible
//! const NUM_CHUNKS: usize = 8;
//!
//! fn sum(x: &[f64]) -> f64 {
//!     // (round up)
//!     let elements_per_chunk = (x.len() + NUM_CHUNKS - 1) / NUM_CHUNKS;
//!
//!     let total = Mutex::new(0.0);
//!     simple_parallel::for_(x.chunks(elements_per_chunk), |chunk| {
//!         // sum up this little subsection
//!         let subsum = chunk.iter().fold(0.0, |a, b| a + *b);
//!         *total.lock().unwrap() += subsum;
//!     });
//!
//!     let answer = *total.lock().unwrap();
//!     answer
//! }
//! ```
//!
//! A sketch of a very simple recursive parallel merge-sort, using
//! `both` to handle the recursion. (A working implementation may
//! really need some temporary buffers to mangle the data, but the key
//! point is `both` naturally running things in parallel.)
//!
//! ```rust
//! /// Merges the two sorted runs `left` and `right`.
//! /// That is, after `merge(left, right)`,
//! ///
//! ///    left[0] <= left[1] <= ... <= left[last] <= right[0] <= ...
//! fn merge<T: Ord>(left: &mut [T], right: &mut [T]) {
//!     // magic (but non-parallel, so boring)
//! }
//!
//! fn parallel_merge_sort<T: Ord + Send>(x: &mut [T]) {
//!    // base case
//!    if x.len() <= 1 { return }
//!
//!    // get two disjoint halves of the `x`,
//!    let half = x.len() / 2;
//!    let (left, right) = x.split_at_mut(half);
//!    // and sort them recursively, in parallel
//!    simple_parallel::both(&mut *left, &mut *right, |v| parallel_merge_sort(v));
//!
//!    // now combine the two sorted halves
//!    merge(left, right)
//! }
//! ```
//!
//! The [`examples`
//! folder](https://github.com/huonw/simple_parallel/tree/master/examples)
//! contains more intricate example(s), such as a parallel fast
//! Fourier transform implementation (it really works, and the
//! parallelism does buy something... when tuned).
#![feature(unsafe_destructor)]
#![feature(core)]

use std::thread;
use std::iter::IntoIterator;

mod maps;

pub use maps::{unordered_map, UnorderedParMap, map, ParMap};

/// Execute `f` on each element of `iter`, in their own `scoped`
/// thread.
///
/// If `f` panics, so does `for_`. If this occurs, the number of
/// elements of `iter` that have had `f` called on them is
/// unspecified.
pub fn for_<I: IntoIterator, F>(iter: I, ref f: F)
    where I::Item: Send, F: Fn(I::Item) + Sync
{
    let _guards: Vec<_> = iter.into_iter().map(|elem| {
        thread::scoped(move || {
            f(elem)
        })
    }).collect();
}

/// Execute `f` on both `x` and `y`, in parallel, returning the
/// result.
///
/// This is the same (including panic semantics) as `(f(x), f(y))`, up
/// to ordering. It is designed to be used for divide-and-conquer
/// algorithms.
pub fn both<T, U, F>(x: T, y: T, ref f: F) -> (U, U)
    where T: Send,
          U: Send,
          F: Sync + Fn(T) -> U
{
    let guard = thread::scoped(move || f(y));
    let a = f(x);
    let b = guard.join();
    (a, b)
}
<|endoftext|>


<commit_before>// Copyright © 2014, Simonas Kazlauskas <rdrand@kazlauskas.me>
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without
// fee is hereby granted, provided that the above copyright notice and this permission notice
// appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
//! An implementation of random number generators based on `rdrand` and `rdseed` instructions.

#![no_std]
#![feature(slice_align_to)]

extern crate rand_core;

use rand_core::{RngCore, CryptoRng, Error, ErrorKind};
use core::slice;

const RETRY_LIMIT: u8 = 127;

#[cold]
#[inline(never)]
pub fn busy_loop_fail() -> ! {
    panic!("hardware generator failure");
}

/// A cryptographically secure statistically uniform, non-periodic and non-deterministic random bit
/// generator.
///
/// Note that this generator may be implemented using a deterministic algorithm that is reseeded
/// routinely from a non-deterministic entropy source to achieve the desirable properties.
///
/// This generator is a viable replacement to any generator, however, since nobody has audited
/// Intel or AMD hardware yet, the usual disclaimers as to their suitability apply.
///
/// It is much faster than `OsRng`, but is only supported on more recent Intel
/// (Ivy Bridge and later) and AMD (Ryzen and later) processors.
#[derive(Clone, Copy)]
pub struct RdRand(());

/// A cryptographically secure non-deterministic random bit generator.
///
/// This generator produces high-entropy output and is suited to seed other pseudo-random
/// generators.
///
/// This instruction currently is only available in Intel Broadwell (and later) and AMD Ryzen
/// processors.
///
/// This generator is not intended for general random number generation purposes and should be used
/// to seed other generators implementing [SeedableRng].
#[derive(Clone, Copy)]
pub struct RdSeed(());

impl CryptoRng for RdRand {}
impl CryptoRng for RdSeed {}

mod arch {
    #[cfg(target_arch = "x86_64")]
    pub use core::arch::x86_64::*;
    #[cfg(target_arch = "x86")]
    pub use core::arch::x86::*;

    #[cfg(target_arch = "x86")]
    pub(crate) unsafe fn _rdrand64_step(dest: &mut u64) -> i32 {
        let mut ret1: u32 = ::core::mem::uninitialized();
        let mut ret2: u32 = ::core::mem::uninitialized();
        if _rdrand32_step(&mut ret1) != 0 && _rdrand32_step(&mut ret2) != 0 {
            *dest = (ret1 as u64) << 32 | (ret2 as u64);
            1
        } else {
            0
        }
    }

    #[cfg(target_arch = "x86")]
    pub(crate) unsafe fn _rdseed64_step(dest: &mut u64) -> i32 {
        let mut ret1: u32 = ::core::mem::uninitialized();
        let mut ret2: u32 = ::core::mem::uninitialized();
        if _rdseed32_step(&mut ret1) != 0 && _rdseed32_step(&mut ret2) != 0 {
            *dest = (ret1 as u64) << 32 | (ret2 as u64);
            1
        } else {
            0
        }
    }
}

macro_rules! check_cpuid {
    ("rdrand") => { {
        const FLAG : u32 = 1 << 30;
        ::arch::__cpuid(1).ecx & FLAG == FLAG
    } };
    ("rdseed") => { {
        const FLAG : u32 = 1 << 18;
        ::arch::__cpuid(7).ebx & FLAG == FLAG
    } };
}

macro_rules! loop_rand {
    ($feat: tt, $el: ty, $step: path) => { {
        #[target_feature(enable = $feat)]
        unsafe fn imp() -> Option<$el> {
            let mut ret: $el = ::core::mem::uninitialized();
            for _ in 0..RETRY_LIMIT {
                if $step(&mut ret) != 0 {
                    return Some(ret);
                }
            }
            return None;
        }
        unsafe { imp() }
    } }
}

macro_rules! impl_rand {
    ($gen:ident, $feat:tt, $step16: path, $step32:path, $step64:path,
     maxstep = $maxstep:path, maxty = $maxty: ty, next = $trynext:ident) => {
        impl $gen {
            pub fn new() -> Result<Self, Error> {
                unsafe {
                    if cfg!(target_feature=$feat) || check_cpuid!($feat) {
                        Ok($gen(()))
                    } else {
                        Err(Error::new(rand_core::ErrorKind::Unavailable,
                                       "the instruction is not supported"))
                    }
                }
            }

            #[inline(always)]
            pub fn try_next_u16(&self) -> Option<u16> {
                loop_rand!($feat, u16, $step16)
            }

            #[inline(always)]
            pub fn try_next_u32(&self) -> Option<u32> {
                loop_rand!($feat, u32, $step32)
            }

            #[inline(always)]
            pub fn try_next_u64(&self) -> Option<u64> {
                loop_rand!($feat, u64, $step64)
            }
        }

        impl RngCore for $gen {
            #[inline(always)]
            fn next_u32(&mut self) -> u32 {
                if let Some(result) = self.try_next_u32() {
                    result
                } else {
                    busy_loop_fail()
                }
            }

            #[inline(always)]
            fn next_u64(&mut self) -> u64 {
                if let Some(result) = self.try_next_u64() {
                    result
                } else {
                    busy_loop_fail()
                }
            }

            #[inline(always)]
            fn fill_bytes(&mut self, dest: &mut [u8]) {
                if let Err(_) = self.try_fill_bytes(dest) {
                    busy_loop_fail()
                }
            }

            fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
                #[target_feature(enable = $feat)]
                unsafe fn imp_fast(dest: &mut [$maxty])
                -> Result<(), Error>
                {
                    'outer: for el in dest {
                        for _ in 0..RETRY_LIMIT {
                            if $maxstep(el) != 0 {
                                continue 'outer;
                            }
                        }
                        return Err(Error::new(ErrorKind::Unexpected, "hardware generator failure"));
                    }
                    Ok(())
                }

                unsafe fn imp_slow(this: &mut $gen, mut dest: &mut [u8],
                                   word: &mut $maxty, buffer: &mut &[u8])
                -> Result<(), Error> {
                    while !dest.is_empty() {
                        if buffer.is_empty() {
                            if let Some(w) = $gen::$trynext(&*this) {
                                *word = w;
                                *buffer = slice::from_raw_parts(&word as *const _ as *const u8,
                                                                ::core::mem::size_of::<$maxty>());
                            } else {
                                return Err(Error::new(ErrorKind::Unexpected,
                                                      "hardware generator failure"));
                            }
                        }
                        let len = dest.len().min(buffer.len());
                        let (copy_src, leftover) = buffer.split_at(len);
                        let (copy_dest, dest_leftover) = { dest }.split_at_mut(len);
                        *buffer = leftover;
                        dest = dest_leftover;
                        copy_dest.copy_from_slice(copy_src);
                    }
                    Ok(())
                }

                unsafe {
                    let destlen = dest.len();
                    if destlen > ::core::mem::size_of::<$maxty>() {
                            let (left, mid, right) = dest.align_to_mut();
                            let mut word = 0;
                            let mut buffer: &[u8] = &[];
                            imp_fast(mid)?;
                            imp_slow(self, left, &mut word, &mut buffer)?;
                            imp_slow(self, right, &mut word, &mut buffer)
                    } else {
                        let mut word = 0;
                        let mut buffer: &[u8] = &[];
                        imp_slow(self, dest, &mut word, &mut buffer)
                    }
                }
            }
        }
    }
}

#[cfg(target_arch = "x86_64")]
impl_rand!(RdRand, "rdrand",
           ::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step,
           maxstep = ::arch::_rdrand64_step, maxty = u64, next = try_next_u64);
#[cfg(target_arch = "x86_64")]
impl_rand!(RdSeed, "rdseed",
           ::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step,
           maxstep = ::arch::_rdseed64_step, maxty = u64, next = try_next_u64);
#[cfg(target_arch = "x86")]
impl_rand!(RdRand, "rdrand",
           ::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step,
           maxstep = ::arch::_rdrand32_step, maxty = u32, next = try_next_u32);
#[cfg(target_arch = "x86")]
impl_rand!(RdSeed, "rdseed",
           ::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step,
           maxstep = ::arch::_rdseed32_step, maxty = u32, next = try_next_u32);

#[test]
fn rdrand_works() {
    let _ = RdRand::new().map(|mut r| {
        r.next_u32();
        r.next_u64();
    });
}

#[test]
fn rdseed_works() {
    let _ = RdSeed::new().map(|mut r| {
        r.next_u32();
        r.next_u64();
    });
}
<commit_msg>Rework how try_fill_buffer works and docs<commit_after>// Copyright © 2014, Simonas Kazlauskas <rdrand@kazlauskas.me>
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without
// fee is hereby granted, provided that the above copyright notice and this permission notice
// appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
//! An implementation of random number generators based on `rdrand` and `rdseed` instructions.
//!
//! The random number generators provided by this crate are fairly slow (the latency for these
//! instructions is pretty high), but provide high quality random bits. Caveat is: neither AMD’s
//! nor Intel’s designs are public and therefore are not verifiable for lack of backdoors.
//!
//! Unless you know what you are doing, use the random number generators provided by the `rand`
//! crate (such as `OsRng`) instead.
//!
//! Here are a measurements for select processor architectures. Check [Agner’s instruction tables]
//! for up-to-date listings.
//!
//!

//!

//!     Architecture

//!     Latency (cycles)
//!     Maximum throughput (per core)
//!

//!

//!
//!     u16
//!     u32
//!     u64
//!
//!

//!

//!     AMD Ryzen
//!     ~1200

//!     ~1200
//!     ~2500
//!     ~12MB/s @ 3.7GHz

//!

//!

//!     Intel Skylake
//!     460

//!     460
//!     460

//!     ~72MB/s @ 4.2GHz
//!

//!

//!     Intel Haswell
//!     320
//!     320
//!     320
//!     ~110MB/s @ 4.4GHz
//!

//!

//!
//! [Agner’s instruction tables]: http://agner.org/optimize/

#![feature(slice_align_to)]
#![no_std]

extern crate rand_core;

use rand_core::{RngCore, CryptoRng, Error, ErrorKind};
use core::slice;

const RETRY_LIMIT: u8 = 127;

#[cold]
#[inline(never)]
pub fn busy_loop_fail() -> ! {
    panic!("hardware generator failure");
}

/// A cryptographically secure statistically uniform, non-periodic and non-deterministic random bit
/// generator.
///
/// Note that this generator may be implemented using a deterministic algorithm that is reseeded
/// routinely from a non-deterministic entropy source to achieve the desirable properties.
///
/// This generator is a viable replacement to any generator, however, since nobody has audited
/// Intel or AMD hardware yet, the usual disclaimers as to their suitability apply.
///
/// It is potentially faster than `OsRng`, but is only supported on more recent Intel (Ivy Bridge
/// and later) and AMD (Ryzen and later) processors.
#[derive(Clone, Copy)]
pub struct RdRand(());

/// A cryptographically secure non-deterministic random bit generator.
///
/// This generator produces high-entropy output and is suited to seed other pseudo-random
/// generators.
///
/// This instruction currently is only available in Intel Broadwell (and later) and AMD Ryzen
/// processors.
///
/// This generator is not intended for general random number generation purposes and should be used
/// to seed other generators implementing [SeedableRng].
#[derive(Clone, Copy)]
pub struct RdSeed(());

impl CryptoRng for RdRand {}
impl CryptoRng for RdSeed {}

mod arch {
    #[cfg(target_arch = "x86_64")]
    pub use core::arch::x86_64::*;
    #[cfg(target_arch = "x86")]
    pub use core::arch::x86::*;

    #[cfg(target_arch = "x86")]
    pub(crate) unsafe fn _rdrand64_step(dest: &mut u64) -> i32 {
        let mut ret1: u32 = ::core::mem::uninitialized();
        let mut ret2: u32 = ::core::mem::uninitialized();
        if _rdrand32_step(&mut ret1) != 0 && _rdrand32_step(&mut ret2) != 0 {
            *dest = (ret1 as u64) << 32 | (ret2 as u64);
            1
        } else {
            0
        }
    }

    #[cfg(target_arch = "x86")]
    pub(crate) unsafe fn _rdseed64_step(dest: &mut u64) -> i32 {
        let mut ret1: u32 = ::core::mem::uninitialized();
        let mut ret2: u32 = ::core::mem::uninitialized();
        if _rdseed32_step(&mut ret1) != 0 && _rdseed32_step(&mut ret2) != 0 {
            *dest = (ret1 as u64) << 32 | (ret2 as u64);
            1
        } else {
            0
        }
    }
}

macro_rules! check_cpuid {
    ("rdrand") => { {
        const FLAG : u32 = 1 << 30;
        ::arch::__cpuid(1).ecx & FLAG == FLAG
    } };
    ("rdseed") => { {
        const FLAG : u32 = 1 << 18;
        ::arch::__cpuid(7).ebx & FLAG == FLAG
    } };
}

macro_rules! loop_rand {
    ($el: ty, $step: path) => { {
        let mut idx = 0;
        loop {
            let mut el: $el = ::core::mem::uninitialized();
            if $step(&mut el) != 0 {
                break Some(el);
            } else if idx == RETRY_LIMIT {
                break None;
            }
            idx += 1;
        }
    } }
}

macro_rules! impl_rand {
    ($gen:ident, $feat:tt, $step16: path, $step32:path, $step64:path,
     maxstep = $maxstep:path, maxty = $maxty: ty) => {
        impl $gen {
            /// Create a new instance of the random number generator.
            ///
            /// This constructor checks whether the CPU the program is running on supports the
            /// instruction necessary for this generator to operate. If the instruction is not
            /// supported, an error is returned.
            pub fn new() -> Result<Self, Error> {
                unsafe {
                    if cfg!(target_feature=$feat) || check_cpuid!($feat) {
                        Ok($gen(()))
                    } else {
                        Err(Error::new(rand_core::ErrorKind::Unavailable,
                                       "the instruction is not supported"))
                    }
                }
            }

            /// Generate a single random `u16` value.
            ///
            /// The underlying instruction may fail for variety reasons (such as actual hardware
            /// failure or exhausted entropy), however the exact reason for the failure is not
            /// usually exposed.
            ///
            /// This method will retry calling the instruction a few times, however if all the
            /// attempts fail, it will return `None`.
            ///
            /// In case `None` is returned, the caller should assume that an non-recoverable
            /// hardware failure has occured and use another random number genrator instead.
            #[inline(always)]
            pub fn try_next_u16(&self) -> Option<u16> {
                #[target_feature(enable = $feat)]
                unsafe fn imp()
                -> Option<u16> {
                    loop_rand!(u16, $step16)
                }
                unsafe { imp() }
            }

            /// Generate a single random `u32` value.
            ///
            /// The underlying instruction may fail for variety reasons (such as actual hardware
            /// failure or exhausted entropy), however the exact reason for the failure is not
            /// usually exposed.
            ///
            /// This method will retry calling the instruction a few times, however if all the
            /// attempts fail, it will return `None`.
            ///
            /// In case `None` is returned, the caller should assume that an non-recoverable
            /// hardware failure has occured and use another random number genrator instead.
            #[inline(always)]
            pub fn try_next_u32(&self) -> Option<u32> {
                #[target_feature(enable = $feat)]
                unsafe fn imp()
                -> Option<u32> {
                    loop_rand!(u32, $step32)
                }
                unsafe { imp() }
            }

            /// Generate a single random `u64` value.
            ///
            /// The underlying instruction may fail for variety reasons (such as actual hardware
            /// failure or exhausted entropy), however the exact reason for the failure is not
            /// usually exposed.
            ///
            /// This method will retry calling the instruction a few times, however if all the
            /// attempts fail, it will return `None`.
            ///
            /// In case `None` is returned, the caller should assume that an non-recoverable
            /// hardware failure has occured and use another random number genrator instead.
            ///
            /// Note, that on 32-bit targets, there’s no underlying instruction to generate a
            /// 64-bit number, so it is emulated with the 32-bit version of the instruction.
            #[inline(always)]
            pub fn try_next_u64(&self) -> Option<u64> {
                #[target_feature(enable = $feat)]
                unsafe fn imp()
                -> Option<u64> {
                    loop_rand!(u64, $step64)
                }
                unsafe { imp() }
            }
        }

        impl RngCore for $gen {
            /// Generate a single random `u32` value.
            ///
            /// The underlying instruction may fail for variety reasons (such as actual hardware
            /// failure or exhausted entropy), however the exact reason for the failure is not
            /// usually exposed.
            ///
            /// # Panic
            ///
            /// This method will retry calling the instruction a few times, however if all the
            /// attempts fail, it will `panic`.
            ///
            /// In case `panic` occurs, the caller should assume that an non-recoverable
            /// hardware failure has occured and use another random number genrator instead.
            #[inline(always)]
            fn next_u32(&mut self) -> u32 {
                if let Some(result) = self.try_next_u32() {
                    result
                } else {
                    busy_loop_fail()
                }
            }

            /// Generate a single random `u64` value.
            ///
            /// The underlying instruction may fail for variety reasons (such as actual hardware
            /// failure or exhausted entropy), however the exact reason for the failure is not
            /// usually exposed.
            ///
            /// Note, that on 32-bit targets, there’s no underlying instruction to generate a
            /// 64-bit number, so it is emulated with the 32-bit version of the instruction.
            ///
            /// # Panic
            ///
            /// This method will retry calling the instruction a few times, however if all the
            /// attempts fail, it will `panic`.
            ///
            /// In case `panic` occurs, the caller should assume that an non-recoverable
            /// hardware failure has occured and use another random number genrator instead.
            #[inline(always)]
            fn next_u64(&mut self) -> u64 {
                if let Some(result) = self.try_next_u64() {
                    result
                } else {
                    busy_loop_fail()
                }
            }

            /// Fill a buffer `dest` with random data.
            ///
            /// See `try_fill_bytes` for a more extensive documentation.
            ///
            /// # Panic
            ///
            /// This method will panic any time `try_fill_bytes` would return an error.
            #[inline(always)]
            fn fill_bytes(&mut self, dest: &mut [u8]) {
                if let Err(_) = self.try_fill_bytes(dest) {
                    busy_loop_fail()
                }
            }

            /// Fill a buffer `dest` with random data.
            ///
            /// This method will use the most appropriate variant of the instruction available on
            /// the machine to achieve the greatest single-core throughput, however it has a
            /// slightly higher setup cost than the plain `next_u32` or `next_u64` methods.
            ///
            /// The underlying instruction may fail for variety reasons (such as actual hardware
            /// failure or exhausted entropy), however the exact reason for the failure is not
            /// usually exposed.
            ///
            /// This method will retry calling the instruction a few times, however if all the
            /// attempts fail, it will return an error.
            ///
            /// If an error is returned, the caller should assume that an non-recoverable hardware
            /// failure has occured and use another random number genrator instead.
            #[inline(always)]
            fn try_fill_bytes(&mut self, dest: &mut [u8])
            -> Result<(), Error> {
                #[target_feature(enable = $feat)]
                unsafe fn imp(dest: &mut [u8])
                -> Result<(), Error> {
                    unsafe fn imp_less_fast(mut dest: &mut [u8], word: &mut $maxty,
                                            buffer: &mut &[u8])
                    -> Result<(), Error> {
                        while !dest.is_empty() {
                            if buffer.is_empty() {
                                if let Some(w) = loop_rand!($maxty, $maxstep) {
                                    *word = w;
                                    *buffer = slice::from_raw_parts(
                                        word as *const _ as *const u8,
                                        ::core::mem::size_of::<$maxty>()
                                    );
                                } else {
                                    return Err(Error::new(ErrorKind::Unexpected,
                                                          "hardware generator failure"));
                                }
                            }

                            let len = dest.len().min(buffer.len());
                            let (copy_src, leftover) = buffer.split_at(len);
                            let (copy_dest, dest_leftover) = { dest }.split_at_mut(len);
                            *buffer = leftover;
                            dest = dest_leftover;
                            ::core::ptr::copy_nonoverlapping(
                                copy_src.as_ptr(), copy_dest.as_mut_ptr(), len
                            );
                        }
                        Ok(())
                    }

                    let destlen = dest.len();
                    if destlen > ::core::mem::size_of::<$maxty>() {
                            let (left, mid, right) = dest.align_to_mut();
                            let mut word = 0;
                            let mut buffer: &[u8] = &[];

                            for el in mid {
                                if let Some(val) = loop_rand!($maxty, $maxstep) {
                                    *el = val;
                                } else {
                                    return Err(Error::new(ErrorKind::Unexpected,
                                                          "hardware generator failure"));
                                }
                            }

                            imp_less_fast(left, &mut word, &mut buffer)?;
                            imp_less_fast(right, &mut word, &mut buffer)
                    } else {
                        let mut word = 0;
                        let mut buffer: &[u8] = &[];
                        imp_less_fast(dest, &mut word, &mut buffer)
                    }
                }
                unsafe { imp(dest) }
            }
        }
    }
}

#[cfg(target_arch = "x86_64")]
impl_rand!(RdRand, "rdrand",
           ::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step,
           maxstep = ::arch::_rdrand64_step, maxty = u64);
#[cfg(target_arch = "x86_64")]
impl_rand!(RdSeed, "rdseed",
           ::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step,
           maxstep = ::arch::_rdseed64_step, maxty = u64);
#[cfg(target_arch = "x86")]
impl_rand!(RdRand, "rdrand",
           ::arch::_rdrand16_step, ::arch::_rdrand32_step, ::arch::_rdrand64_step,
           maxstep = ::arch::_rdrand32_step, maxty = u32);
#[cfg(target_arch = "x86")]
impl_rand!(RdSeed, "rdseed",
           ::arch::_rdseed16_step, ::arch::_rdseed32_step, ::arch::_rdseed64_step,
           maxstep = ::arch::_rdseed32_step, maxty = u32);

#[test]
fn rdrand_works() {
    let _ = RdRand::new().map(|mut r| {
        r.next_u32();
        r.next_u64();
    });
}

#[test]
fn fill_fills_all_bytes() {
    let _ = RdRand::new().map(|mut r| {
        let mut peach = [0; 128];
        let mut banana = [0; 128];
        let mut start = 0;
        let mut end = 128;
        'outer: while start < end {
            banana = [0; 128];
            for _ in 0..512 {
                peach = [0; 128];
                r.fill_bytes(&mut peach[start..end]);
                for (b, p) in banana.iter_mut().zip(peach.iter()) {
                    *b = *b | *p;
                }
                if (&banana[start..end]).iter().all(|x| *x != 0) {
                    assert!(banana[..start].iter().all(|x| *x == 0), "all other values must be 0");
                    assert!(banana[end..].iter().all(|x| *x == 0), "all other values must be 0");
                    if start < 17 {
                        start += 1;
                    } else {
                        end -= 3;
                    }
                    continue 'outer;
                }
            }
            panic!("wow, we broke it? {} {} {:?}", start, end, &banana[..])
        }
    });
}

#[test]
fn rdseed_works() {
    let _ = RdSeed::new().map(|mut r| {
        r.next_u32();
        r.next_u64();
    });
}
<|endoftext|>