1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
//! Support for storing dynamically-sized types on the stack //! //! The `StackDST` type provides a fixed size (7 word in the current version) buffer in which a trait object //! or array can be stored, without resorting to a heap allocation. //! //! # Examples //! ## An unboxed any //! As a quick example - The following wraps a 64-bit integer up in a StackDST using the Any trait. //! //! ```rust //! use std::any::Any; //! type StackDST<T> = stack_dst::Value<T>; //! //! let dst = StackDST::<Any>::new(1234u64).ok().expect("Integer did not fit in allocation"); //! println!("dst as u64 = {:?}", dst.downcast_ref::<u64>()); //! println!("dst as i8 = {:?}", dst.downcast_ref::<i8>()); //! ``` //! //! ## Stack-allocated closure! //! The following snippet shows how small (`'static`) closures can be returned using StackDST //! //! ```rust //! # fn main() { //! type StackDST<T> = stack_dst::Value<T>; //! //! fn make_closure(value: u64) -> StackDST<FnMut()->String> { //! StackDST::new(move || format!("Hello there! value={}", value)).ok().expect("Closure doesn't fit") //! } //! let mut closure = make_closure(666); //! assert_eq!( (&mut *closure)(), "Hello there! value=666" ); //! # } //! ``` #![feature(unsize)] // needed for Unsize #![cfg_attr(feature="no_std",no_std)] #![crate_type="lib"] #![crate_name="stack_dst"] #![deny(missing_docs)] use std::{mem,slice}; #[cfg(feature="no_std")] mod std { pub use core::{ops,mem,slice,marker,ptr}; } /// Trait used to represent the data buffer for StackDSTA. /// /// Typically you'll passs a [usize; N] array pub trait DataBuf: Copy+Default+AsMut<[usize]>+AsRef<[usize]> { } impl<T: Copy+Default+AsMut<[usize]>+AsRef<[usize]>> DataBuf for T { } pub use value::{ValueA,Value}; pub use stack::{StackA}; mod value; mod stack; /// Obtain mutable access to a pointer's words fn ptr_as_slice<T: ?Sized>(ptr: &mut *const T) -> &mut [usize] { assert!( mem::size_of::<&T>() % mem::size_of::<usize>() == 0 ); let words = mem::size_of::<&T>() / mem::size_of::<usize>(); // SAFE: Points to valid memory (a raw pointer) unsafe { slice::from_raw_parts_mut(ptr as *mut _ as *mut usize, words) } }