objc_foundation/
value.rs

1use std::any::Any;
2use std::ffi::{CStr, CString};
3use std::marker::PhantomData;
4use std::mem;
5use std::os::raw::c_char;
6use std::str;
7
8use objc::{Encode, Encoding};
9use objc::runtime::Class;
10use objc_id::Id;
11
12use {INSCopying, INSObject};
13
14pub trait INSValue : INSObject {
15    type Value: 'static + Copy + Encode;
16
17    fn value(&self) -> Self::Value {
18        assert!(Self::Value::encode() == self.encoding());
19        unsafe {
20            let mut value = mem::uninitialized::<Self::Value>();
21            let _: () = msg_send![self, getValue:&mut value];
22            value
23        }
24    }
25
26    fn encoding(&self) -> Encoding {
27        unsafe {
28            let result: *const c_char = msg_send![self, objCType];
29            let s = CStr::from_ptr(result);
30            let s = str::from_utf8(s.to_bytes()).unwrap();
31            Encoding::from_str(s)
32        }
33    }
34
35    fn from_value(value: Self::Value) -> Id<Self> {
36        let cls = Self::class();
37        let encoding = CString::new(Self::Value::encode().as_str()).unwrap();
38        unsafe {
39            let obj: *mut Self = msg_send![cls, alloc];
40            let obj: *mut Self = msg_send![obj, initWithBytes:&value
41                                                     objCType:encoding.as_ptr()];
42            Id::from_retained_ptr(obj)
43        }
44    }
45}
46
47pub struct NSValue<T> {
48    value: PhantomData<T>,
49}
50
51object_impl!(NSValue<T>);
52
53impl<T> INSObject for NSValue<T> where T: Any {
54    fn class() -> &'static Class {
55        Class::get("NSValue").unwrap()
56    }
57}
58
59impl<T> INSValue for NSValue<T> where T: Any + Copy + Encode {
60    type Value = T;
61}
62
63impl<T> INSCopying for NSValue<T> where T: Any {
64    type Output = NSValue<T>;
65}
66
67#[cfg(test)]
68mod tests {
69    use objc::Encode;
70    use {INSValue, NSValue};
71
72    #[test]
73    fn test_value() {
74        let val = NSValue::from_value(13u32);
75        assert!(val.value() == 13);
76        assert!(u32::encode() == val.encoding());
77    }
78}