Created
October 30, 2014 20:25
-
-
Save Nercury/ccc99ec11f49043c14ed to your computer and use it in GitHub Desktop.
MaybeValue example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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