objc_foundation/
dictionary.rs1use std::cmp::min;
2use std::marker::PhantomData;
3use std::ops::Index;
4use std::ptr;
5
6use objc::runtime::Class;
7use objc_id::{Id, Owned, Ownership, ShareId};
8
9use {
10 INSArray, INSFastEnumeration, INSCopying, INSObject,
11 NSArray, NSSharedArray, NSEnumerator,
12};
13
14unsafe fn from_refs<D, T>(keys: &[&T], vals: &[&D::Value]) -> Id<D>
15 where D: INSDictionary, T: INSCopying<Output=D::Key> {
16 let cls = D::class();
17 let count = min(keys.len(), vals.len());
18 let obj: *mut D = msg_send![cls, alloc];
19 let obj: *mut D = msg_send![obj, initWithObjects:vals.as_ptr()
20 forKeys:keys.as_ptr()
21 count:count];
22 Id::from_retained_ptr(obj)
23}
24
25pub trait INSDictionary : INSObject {
26 type Key: INSObject;
27 type Value: INSObject;
28 type Own: Ownership;
29
30 fn count(&self) -> usize {
31 unsafe {
32 msg_send![self, count]
33 }
34 }
35
36 fn object_for(&self, key: &Self::Key) -> Option<&Self::Value> {
37 unsafe {
38 let obj: *mut Self::Value = msg_send![self, objectForKey:key];
39 if obj.is_null() { None } else { Some(&*obj) }
40 }
41 }
42
43 fn keys(&self) -> Vec<&Self::Key> {
44 let len = self.count();
45 let mut keys = Vec::with_capacity(len);
46 unsafe {
47 let _: () = msg_send![self, getObjects:ptr::null_mut::<Self::Value>()
48 andKeys:keys.as_mut_ptr()];
49 keys.set_len(len);
50 }
51 keys
52 }
53
54 fn values(&self) -> Vec<&Self::Value> {
55 let len = self.count();
56 let mut vals = Vec::with_capacity(len);
57 unsafe {
58 let _: () = msg_send![self, getObjects:vals.as_mut_ptr()
59 andKeys:ptr::null_mut::<Self::Key>()];
60 vals.set_len(len);
61 }
62 vals
63 }
64
65 fn keys_and_objects(&self) -> (Vec<&Self::Key>, Vec<&Self::Value>) {
66 let len = self.count();
67 let mut keys = Vec::with_capacity(len);
68 let mut objs = Vec::with_capacity(len);
69 unsafe {
70 let _: () = msg_send![self, getObjects:objs.as_mut_ptr()
71 andKeys:keys.as_mut_ptr()];
72 keys.set_len(len);
73 objs.set_len(len);
74 }
75 (keys, objs)
76 }
77
78 fn key_enumerator(&self) -> NSEnumerator<Self::Key> {
79 unsafe {
80 let result = msg_send![self, keyEnumerator];
81 NSEnumerator::from_ptr(result)
82 }
83 }
84
85 fn object_enumerator(&self) -> NSEnumerator<Self::Value> {
86 unsafe {
87 let result = msg_send![self, objectEnumerator];
88 NSEnumerator::from_ptr(result)
89 }
90 }
91
92 fn keys_array(&self) -> Id<NSSharedArray<Self::Key>> {
93 unsafe {
94 let keys: *mut NSSharedArray<Self::Key> = msg_send![self, allKeys];
95 Id::from_ptr(keys)
96 }
97 }
98
99 fn from_keys_and_objects<T>(keys: &[&T],
100 vals: Vec<Id<Self::Value, Self::Own>>) -> Id<Self>
101 where T: INSCopying<Output=Self::Key> {
102 let vals_refs: Vec<&Self::Value> = vals.iter().map(|obj| &**obj).collect();
103 unsafe {
104 from_refs(keys, &vals_refs)
105 }
106 }
107
108 fn into_values_array(dict: Id<Self>) -> Id<NSArray<Self::Value, Self::Own>> {
109 unsafe {
110 let vals = msg_send![dict, allValues];
111 Id::from_ptr(vals)
112 }
113 }
114}
115
116pub struct NSDictionary<K, V> {
117 key: PhantomData<ShareId<K>>,
118 obj: PhantomData<Id<V>>,
119}
120
121object_impl!(NSDictionary<K, V>);
122
123impl<K, V> INSObject for NSDictionary<K, V> where K: INSObject, V: INSObject {
124 fn class() -> &'static Class {
125 Class::get("NSDictionary").unwrap()
126 }
127}
128
129impl<K, V> INSDictionary for NSDictionary<K, V>
130 where K: INSObject, V: INSObject {
131 type Key = K;
132 type Value = V;
133 type Own = Owned;
134}
135
136impl<K, V> INSFastEnumeration for NSDictionary<K, V>
137 where K: INSObject, V: INSObject {
138 type Item = K;
139}
140
141impl<'a, K, V> Index<&'a K> for NSDictionary<K, V> where K: INSObject, V: INSObject {
142 type Output = V;
143
144 fn index(&self, index: &K) -> &V {
145 self.object_for(index).unwrap()
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use objc_id::Id;
152 use {INSArray, INSObject, INSString, NSObject, NSString};
153 use super::{INSDictionary, NSDictionary};
154
155 fn sample_dict(key: &str) -> Id<NSDictionary<NSString, NSObject>> {
156 let string = NSString::from_str(key);
157 let obj = NSObject::new();
158 NSDictionary::from_keys_and_objects(&[&*string], vec![obj])
159 }
160
161 #[test]
162 fn test_count() {
163 let dict = sample_dict("abcd");
164 assert!(dict.count() == 1);
165 }
166
167 #[test]
168 fn test_object_for() {
169 let dict = sample_dict("abcd");
170
171 let string = NSString::from_str("abcd");
172 assert!(dict.object_for(&string).is_some());
173
174 let string = NSString::from_str("abcde");
175 assert!(dict.object_for(&string).is_none());
176 }
177
178 #[test]
179 fn test_keys() {
180 let dict = sample_dict("abcd");
181 let keys = dict.keys();
182
183 assert!(keys.len() == 1);
184 assert!(keys[0].as_str() == "abcd");
185 }
186
187 #[test]
188 fn test_values() {
189 let dict = sample_dict("abcd");
190 let vals = dict.values();
191
192 assert!(vals.len() == 1);
193 }
194
195 #[test]
196 fn test_keys_and_objects() {
197 let dict = sample_dict("abcd");
198 let (keys, objs) = dict.keys_and_objects();
199
200 assert!(keys.len() == 1);
201 assert!(objs.len() == 1);
202 assert!(keys[0].as_str() == "abcd");
203 assert!(objs[0] == dict.object_for(keys[0]).unwrap());
204 }
205
206 #[test]
207 fn test_key_enumerator() {
208 let dict = sample_dict("abcd");
209 assert!(dict.key_enumerator().count() == 1);
210 assert!(dict.key_enumerator().next().unwrap().as_str() == "abcd");
211 }
212
213 #[test]
214 fn test_object_enumerator() {
215 let dict = sample_dict("abcd");
216 assert!(dict.object_enumerator().count() == 1);
217 }
218
219 #[test]
220 fn test_arrays() {
221 let dict = sample_dict("abcd");
222
223 let keys = dict.keys_array();
224 assert!(keys.count() == 1);
225 assert!(keys.object_at(0).as_str() == "abcd");
226
227 let objs = INSDictionary::into_values_array(dict);
228 assert!(objs.count() == 1);
229 }
230}