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 69 70 71 72 73 74 75 76 77 78
use std::any::Any; use std::ffi::{CStr, CString}; use std::marker::PhantomData; use std::mem; use std::os::raw::c_char; use std::str; use objc::{Encode, Encoding}; use objc::runtime::Class; use objc_id::Id; use {INSCopying, INSObject}; pub trait INSValue : INSObject { type Value: 'static + Copy + Encode; fn value(&self) -> Self::Value { assert!(Self::Value::encode() == self.encoding()); unsafe { let mut value = mem::uninitialized::<Self::Value>(); let _: () = msg_send![self, getValue:&mut value]; value } } fn encoding(&self) -> Encoding { unsafe { let result: *const c_char = msg_send![self, objCType]; let s = CStr::from_ptr(result); let s = str::from_utf8(s.to_bytes()).unwrap(); Encoding::from_str(s) } } fn from_value(value: Self::Value) -> Id<Self> { let cls = Self::class(); let encoding = CString::new(Self::Value::encode().as_str()).unwrap(); unsafe { let obj: *mut Self = msg_send![cls, alloc]; let obj: *mut Self = msg_send![obj, initWithBytes:&value objCType:encoding.as_ptr()]; Id::from_retained_ptr(obj) } } } pub struct NSValue<T> { value: PhantomData<T>, } object_impl!(NSValue<T>); impl<T> INSObject for NSValue<T> where T: Any { fn class() -> &'static Class { Class::get("NSValue").unwrap() } } impl<T> INSValue for NSValue<T> where T: Any + Copy + Encode { type Value = T; } impl<T> INSCopying for NSValue<T> where T: Any { type Output = NSValue<T>; } #[cfg(test)] mod tests { use objc::Encode; use {INSValue, NSValue}; #[test] fn test_value() { let val = NSValue::from_value(13u32); assert!(val.value() == 13); assert!(u32::encode() == val.encoding()); } }