1use crate::{Capability, CapabilityBound};
6use derivative::Derivative;
7use fuchsia_sync::{Mutex, MutexGuard};
8use std::borrow::Borrow;
9use std::collections::BTreeMap;
10use std::collections::btree_map::Entry;
11use std::sync::Arc;
12
13#[cfg(target_os = "fuchsia")]
14use fuchsia_async as fasync;
15
16pub type Key = cm_types::Name;
17pub type BorrowedKey = cm_types::BorrowedName;
18
19#[derive(Debug, Clone)]
21pub struct Dictionary {
22 inner: Arc<Mutex<DictInner>>,
23}
24
25#[derive(Derivative)]
26#[derivative(Debug)]
27pub(crate) struct DictInner {
28 pub(crate) entries: HybridMap,
30
31 #[derivative(Debug = "ignore")]
34 #[allow(dead_code)]
36 pub(crate) not_found: Option<Box<dyn Fn(&str) -> () + 'static + Send + Sync>>,
37
38 #[cfg(target_os = "fuchsia")]
42 #[derivative(Debug = "ignore")]
43 task_group: Option<fasync::Scope>,
44
45 #[derivative(Debug = "ignore")]
47 update_notifiers: UpdateNotifiers,
48}
49
50impl CapabilityBound for Dictionary {
51 fn debug_typename() -> &'static str {
52 "Dictionary"
53 }
54}
55
56impl Drop for DictInner {
57 fn drop(&mut self) {
58 let entries = std::mem::replace(&mut self.entries, HybridMap::default());
62 for (key, _) in entries.into_iter() {
63 self.update_notifiers.update(EntryUpdate::Remove(&key))
64 }
65 }
66}
67
68#[derive(Debug, Copy, Clone)]
70pub enum EntryUpdate<'a> {
71 Add(&'a BorrowedKey, &'a Capability),
72 Remove(&'a BorrowedKey),
73 Idle,
74}
75
76pub enum UpdateNotifierRetention {
79 Retain,
80 Drop_,
81}
82
83pub type UpdateNotifierFn =
88 Box<dyn for<'a> FnMut(EntryUpdate<'a>) -> UpdateNotifierRetention + Sync + Send>;
89
90impl Default for Dictionary {
91 fn default() -> Self {
92 Self {
93 inner: Arc::new(Mutex::new(DictInner {
94 entries: HybridMap::default(),
95 not_found: None,
96 #[cfg(target_os = "fuchsia")]
97 task_group: None,
98 update_notifiers: UpdateNotifiers::default(),
99 })),
100 }
101 }
102}
103
104impl Dictionary {
105 pub fn new() -> Self {
107 Self::default()
108 }
109
110 pub fn new_with_not_found(not_found: impl Fn(&str) -> () + 'static + Send + Sync) -> Self {
113 Self {
114 inner: Arc::new(Mutex::new(DictInner {
115 entries: HybridMap::default(),
116 not_found: Some(Box::new(not_found)),
117 #[cfg(target_os = "fuchsia")]
118 task_group: None,
119 update_notifiers: UpdateNotifiers::default(),
120 })),
121 }
122 }
123
124 pub(crate) fn lock(&self) -> MutexGuard<'_, DictInner> {
125 self.inner.lock()
126 }
127
128 pub fn register_update_notifier(&self, mut notifier_fn: UpdateNotifierFn) {
138 let mut guard = self.lock();
139 for (key, value) in guard.entries.iter() {
140 if let UpdateNotifierRetention::Drop_ = (notifier_fn)(EntryUpdate::Add(key, value)) {
141 return;
143 }
144 }
145 if let UpdateNotifierRetention::Retain = (notifier_fn)(EntryUpdate::Idle) {
146 guard.update_notifiers.0.push(notifier_fn);
147 }
148 }
149
150 pub fn insert(&self, key: Key, capability: Capability) -> Option<Capability> {
153 let DictInner { entries, update_notifiers, .. } = &mut *self.lock();
154 entries.insert(key, capability, update_notifiers)
155 }
156
157 pub fn append(&self, other: &Dictionary) -> Result<(), ()> {
158 let DictInner { entries, update_notifiers, .. } = &mut *self.lock();
159 let other = other.lock();
160 entries.append(&other.entries, update_notifiers)
161 }
162
163 pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<Capability>
166 where
167 Key: Borrow<Q> + Ord,
168 Q: Ord,
169 {
170 self.lock().entries.get(key)
171 }
172
173 pub fn get_or_insert(&self, key: &Key, default: impl FnOnce() -> Capability) -> Capability {
176 let DictInner { entries, update_notifiers, .. } = &mut *self.lock();
177 match entries.get(key) {
178 Some(v) => v,
179 None => {
180 let v = (default)();
181 entries.insert(key.clone(), v.clone(), update_notifiers);
182 v
183 }
184 }
185 }
186
187 pub fn remove(&self, key: &BorrowedKey) -> Option<Capability> {
190 let DictInner { entries, update_notifiers, .. } = &mut *self.lock();
191 entries.remove(key, update_notifiers)
192 }
193
194 pub fn enumerate(&self) -> impl Iterator<Item = (Key, Capability)> + use<> {
196 self.lock()
197 .entries
198 .iter()
199 .map(|(k, v)| (k.clone(), v.clone()))
200 .collect::<Vec<_>>()
201 .into_iter()
202 }
203
204 pub fn snapshot_keys_as_strings(&self) -> Vec<String> {
206 let guard = self.lock();
207 match &guard.entries {
208 HybridMap::Vec(vec) => vec.iter().map(|(k, _)| k.to_string()).collect(),
209 HybridMap::Map(map) => map.keys().map(|k| k.to_string()).collect(),
210 }
211 }
212
213 pub fn is_empty(&self) -> bool {
215 self.lock().entries.is_empty()
216 }
217
218 pub fn drain(&self) -> impl Iterator<Item = (Key, Capability)> + use<> {
220 let DictInner { entries, update_notifiers, .. } = &mut *self.lock();
221 let entries = std::mem::replace(entries, HybridMap::default());
222 for (key, _) in entries.iter() {
223 update_notifiers.update(EntryUpdate::Remove(&key))
224 }
225 entries.into_iter()
226 }
227
228 pub fn shallow_copy(&self) -> Self {
233 let copy = Self::new();
234 {
235 let DictInner { entries, .. } = &*self.lock();
236 let mut copy = copy.lock();
237 copy.entries = entries.shallow_copy();
238 }
239 copy
240 }
241
242 #[allow(dead_code)]
245 pub(crate) fn not_found(&self, entry: &str) {
246 if let Some(not_found_handler) = &self.lock().not_found {
247 not_found_handler(entry);
248 }
249 }
250}
251
252impl DictInner {
253 #[cfg(target_os = "fuchsia")]
254 pub(crate) fn tasks(&mut self) -> &mut fasync::Scope {
255 self.task_group.get_or_insert_with(|| fasync::Scope::new())
256 }
257}
258
259pub(crate) const HYBRID_SWITCH_INSERTION_LEN: usize = 11;
260pub(crate) const HYBRID_SWITCH_REMOVAL_LEN: usize = 5;
261
262#[derive(Debug)]
276pub(crate) enum HybridMap {
277 Vec(Vec<(Key, Capability)>),
278 Map(BTreeMap<Key, Capability>),
279}
280
281impl Default for HybridMap {
282 fn default() -> Self {
283 Self::Vec(Vec::default())
284 }
285}
286
287impl HybridMap {
288 pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<Capability>
289 where
290 Key: Borrow<Q> + Ord,
291 Q: Ord,
292 {
293 match self {
294 Self::Vec(vec) => match Self::sorted_vec_index_of(vec, key) {
295 Ok(index) => Some(vec[index].1.clone()),
296 Err(_) => None,
297 },
298 Self::Map(map) => match map.get(key) {
299 Some(capability) => Some(capability.clone()),
300 None => None,
301 },
302 }
303 }
304
305 pub fn insert(
306 &mut self,
307 key: Key,
308 mut capability: Capability,
309 update_notifiers: &mut UpdateNotifiers,
310 ) -> Option<Capability> {
311 match self {
312 Self::Vec(vec) => match Self::sorted_vec_index_of(vec, &key) {
313 Ok(index) => {
314 update_notifiers.update(EntryUpdate::Remove(&key));
315 update_notifiers.update(EntryUpdate::Add(&key, &capability));
316 std::mem::swap(&mut capability, &mut vec[index].1);
317 Some(capability)
318 }
319 Err(index) => {
320 update_notifiers.update(EntryUpdate::Add(&key, &capability));
321 if vec.len() + 1 >= HYBRID_SWITCH_INSERTION_LEN {
322 self.switch_to_map();
323 let Self::Map(map) = self else { unreachable!() };
324 map.insert(key, capability);
325 None
326 } else {
327 vec.reserve_exact(1);
328 vec.insert(index, (key, capability));
329 None
330 }
331 }
332 },
333 Self::Map(map) => match map.entry(key) {
334 Entry::Occupied(mut occupied) => {
335 update_notifiers.update(EntryUpdate::Remove(occupied.key()));
336 update_notifiers.update(EntryUpdate::Add(occupied.key(), &capability));
337 Some(occupied.insert(capability))
338 }
339 Entry::Vacant(vacant) => {
340 update_notifiers.update(EntryUpdate::Add(vacant.key(), &capability));
341 vacant.insert(capability);
342 None
343 }
344 },
345 }
346 }
347
348 pub fn remove(
349 &mut self,
350 key: &BorrowedKey,
351 update_notifiers: &mut UpdateNotifiers,
352 ) -> Option<Capability> {
353 let result = match self {
354 Self::Vec(vec) => match Self::sorted_vec_index_of(vec, key) {
355 Ok(index) => {
356 update_notifiers.update(EntryUpdate::Remove(key));
357 Some(vec.remove(index).1)
358 }
359 Err(_) => None,
360 },
361 Self::Map(map) => {
362 let result = map.remove(key);
363 if result.is_some() {
364 update_notifiers.update(EntryUpdate::Remove(key));
365 if self.len() <= HYBRID_SWITCH_REMOVAL_LEN {
366 self.switch_to_vec();
367 }
368 }
369 result
370 }
371 };
372 result
373 }
374
375 pub fn append(
376 &mut self,
377 other: &Self,
378 update_notifiers: &mut UpdateNotifiers,
379 ) -> Result<(), ()> {
380 if other.is_empty() {
381 return Ok(());
383 }
384
385 for (k, _) in other.iter() {
387 let contains_key = match self {
388 Self::Vec(vec) => matches!(Self::sorted_vec_index_of(vec, k), Ok(_)),
389 Self::Map(map) => map.contains_key(k),
390 };
391 if contains_key {
392 return Err(());
393 }
394 }
395
396 if self.len() + other.len() >= HYBRID_SWITCH_INSERTION_LEN {
397 self.switch_to_map();
399 } else if let Self::Vec(vec) = self {
400 vec.reserve(other.len());
403 }
404 for (k, v) in other.iter() {
405 self.insert(k.clone(), v.clone(), update_notifiers);
406 }
407 Ok(())
408 }
409
410 pub fn shallow_copy(&self) -> Self {
411 match self {
412 Self::Vec(vec) => {
413 let mut new_vec = Vec::with_capacity(vec.len());
414 for (key, value) in vec.iter() {
415 new_vec.push((key.clone(), value.clone()));
416 }
417 HybridMap::Vec(new_vec)
418 }
419 Self::Map(map) => {
420 let mut new_map = BTreeMap::new();
421 for (key, value) in map.iter() {
422 new_map.insert(key.clone(), value.clone());
423 }
424 HybridMap::Map(new_map)
425 }
426 }
427 }
428
429 pub fn len(&self) -> usize {
430 match self {
431 Self::Map(map) => map.len(),
432 Self::Vec(vec) => vec.len(),
433 }
434 }
435
436 pub fn is_empty(&self) -> bool {
437 match self {
438 Self::Map(map) => map.is_empty(),
439 Self::Vec(vec) => vec.is_empty(),
440 }
441 }
442
443 pub fn iter(&self) -> impl Iterator<Item = (&Key, &Capability)> {
444 match self {
445 Self::Vec(vec) => itertools::Either::Left(vec.iter().map(|kv| (&kv.0, &kv.1))),
446 Self::Map(map) => itertools::Either::Right(map.iter()),
447 }
448 }
449
450 pub fn into_iter(self) -> impl Iterator<Item = (Key, Capability)> {
451 match self {
452 Self::Vec(vec) => itertools::Either::Left(vec.into_iter()),
453 Self::Map(map) => itertools::Either::Right(map.into_iter()),
454 }
455 }
456
457 fn switch_to_map(&mut self) {
458 match self {
459 Self::Map(_) => {}
460 Self::Vec(vec) => {
461 let vec = std::mem::replace(vec, Vec::new());
462 let map = BTreeMap::from_iter(vec.into_iter());
463 *self = Self::Map(map);
464 }
465 }
466 }
467
468 fn switch_to_vec(&mut self) {
469 match self {
470 Self::Vec(_) => {}
471 Self::Map(map) => {
472 let map = std::mem::replace(map, Default::default());
473 let vec = Vec::from_iter(map.into_iter());
474 *self = Self::Vec(vec);
475 }
476 }
477 }
478
479 #[inline]
480 fn sorted_vec_index_of<Q: ?Sized>(vec: &Vec<(Key, Capability)>, key: &Q) -> Result<usize, usize>
481 where
482 Key: Borrow<Q> + Ord,
483 Q: Ord,
484 {
485 vec.binary_search_by(|probe| probe.0.borrow().cmp(&key))
486 }
487}
488
489#[derive(Default)]
490pub(crate) struct UpdateNotifiers(Vec<UpdateNotifierFn>);
491
492impl UpdateNotifiers {
493 fn update<'a>(&'a mut self, update: EntryUpdate<'a>) {
494 self.0.retain_mut(|notifier_fn| match (notifier_fn)(update) {
495 UpdateNotifierRetention::Retain => true,
496 UpdateNotifierRetention::Drop_ => false,
497 });
498 }
499}
500
501