1 use std::cmp::min;
2 use std::marker::PhantomData;
3 use std::ops::Index;
4 use std::ptr;
5 
6 use objc::runtime::Class;
7 use objc_id::{Id, Owned, Ownership, ShareId};
8 
9 use {
10     INSArray, INSFastEnumeration, INSCopying, INSObject,
11     NSArray, NSSharedArray, NSEnumerator,
12 };
13 
14 unsafe 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];
from_ordering(order: Ordering) -> NSComparisonResult19     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 
25 pub trait INSDictionary : INSObject {
26     type Key: INSObject;
as_ordering(&self) -> Ordering27     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> {
from_range(range: Range<usize>) -> NSRange44         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()];
as_range(&self) -> Range<usize>49             keys.set_len(len);
50         }
51         keys
52     }
53 
from_refs<A>(refs: &[&A::Item]) -> Id<A> where A: INSArray54     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>) {
count(&self) -> usize66         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()];
object_at(&self, index: usize) -> &Self::Item72             keys.set_len(len);
73             objs.set_len(len);
74         }
75         (keys, objs)
76     }
77 
78     fn key_enumerator(&self) -> NSEnumerator<Self::Key> {
first_object(&self) -> Option<&Self::Item>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> {
last_object(&self) -> Option<&Self::Item>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>> {
object_enumerator(&self) -> NSEnumerator<Self::Item>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],
from_vec(vec: Vec<Id<Self::Item, Self::Own>>) -> Id<Self>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     }
objects_in_range(&self, range: Range<usize>) -> Vec<&Self::Item>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 
116 pub struct NSDictionary<K, V> {
to_vec(&self) -> Vec<&Self::Item>117     key: PhantomData<ShareId<K>>,
118     obj: PhantomData<Id<V>>,
119 }
120 
121 object_impl!(NSDictionary<K, V>);
122 
123 impl<K, V> INSObject for NSDictionary<K, V> where K: INSObject, V: INSObject {
124     fn class() -> &'static Class {
125         Class::get("NSDictionary").unwrap()
126     }
127 }
mut_object_at(&mut self, index: usize) -> &mut Self::Item where Self: INSArray<Own=Owned>128 
129 impl<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 
shared_object_at(&self, index: usize) -> ShareId<Self::Item> where Self: INSArray<Own=Shared>136 impl<K, V> INSFastEnumeration for NSDictionary<K, V>
137         where K: INSObject, V: INSObject {
138     type Item = K;
139 }
140 
141 impl<'a, K, V> Index<&'a K> for NSDictionary<K, V> where K: INSObject, V: INSObject {
142     type Output = V;
143 
from_slice(slice: &[ShareId<Self::Item>]) -> Id<Self> where Self: INSArray<Own=Shared>144     fn index(&self, index: &K) -> &V {
145         self.object_for(index).unwrap()
146     }
147 }
148 
149 #[cfg(test)]
150 mod tests {
151     use objc_id::Id;
to_shared_vec(&self) -> Vec<ShareId<Self::Item>> where Self: INSArray<Own=Shared>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]
class() -> &'static Class168     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     }
index(&self, index: usize) -> &T194 
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() {
insert_object_at(&mut self, index: usize, obj: Id<Self::Item, Self::Own>)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]
replace_object_at(&mut self, index: usize, obj: Id<Self::Item, Self::Own>) -> Id<Self::Item, Self::Own>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 
remove_object_at(&mut self, index: usize) -> Id<Self::Item, Self::Own>227         let objs = INSDictionary::into_values_array(dict);
228         assert!(objs.count() == 1);
229     }
230 }
231