Skip to content

Instantly share code, notes, and snippets.

@Nercury
Created October 30, 2014 20:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nercury/ccc99ec11f49043c14ed to your computer and use it in GitHub Desktop.
Save Nercury/ccc99ec11f49043c14ed to your computer and use it in GitHub Desktop.
MaybeValue example
use std::mem;
use std::intrinsics::TypeId;
// Val
struct Val {
value: i32
}
impl Val {
fn new(value: i32) -> Val {
println!("create {}", value);
Val { value: value }
}
}
impl Drop for Val {
fn drop(&mut self) {
println!("destroyed {}", self.value);
}
}
// MaybeValue
struct MaybeValue {
ptr: *mut u8,
type_id: TypeId,
destroy: |*mut u8|:'static + Send -> (),
}
impl MaybeValue {
fn new<T: 'static>(value: T) -> MaybeValue {
MaybeValue {
ptr: unsafe { mem::transmute(box value) },
type_id: TypeId::of::<T>(),
destroy: |ptr| {
unsafe { mem::transmute::<*mut u8, Box<T>>(ptr) };
}
}
}
fn rob<T: 'static>(&mut self) -> Option<T> {
match self.ptr.is_null() {
true => None, // When ptr is null return None
false => match TypeId::of::<T>() == self.type_id {
true => { // When types match
// Transmute into returned value and set internal pointer to null,
// so we avoid owning same value in several places.
let result: Box<T> = unsafe { mem::transmute(self.ptr) };
self.ptr = std::ptr::null_mut();
Some(*result) // Unbox and return Some
},
false => None, // When types do not match return None
},
}
}
}
impl Drop for MaybeValue {
fn drop(&mut self) {
match self.ptr.is_null() {
true => (),
false => (self.destroy)(self.ptr),
}
}
}
fn main() {
let mut maybe = MaybeValue::new(Val::new(333));
let result = maybe.rob::<Val>();
match result {
Some(val) => println!("Has robed value {}", val.value),
None => println!("No robing!")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment