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}