netcfg/network/
token_map.rs1use fuchsia_async as fasync;
8use futures::lock::{Mutex, MutexGuard};
9use futures::FutureExt as _;
10use std::collections::HashMap;
11use std::future::Future;
12use std::sync::Arc;
13use zx::AsHandleRef;
14
15pub(crate) struct TokenMap<Data> {
19 entries: Arc<Mutex<HashMap<zx::Koid, TokenMapEntry<Data>>>>,
22}
23
24impl<Data> Default for TokenMap<Data> {
25 fn default() -> Self {
26 Self { entries: Arc::new(Mutex::new(Default::default())) }
27 }
28}
29
30#[derive(Default)]
34pub(crate) struct TokenMapEntry<Data> {
35 data: Data,
36
37 #[expect(dead_code)]
38 task: Option<fasync::Task<()>>,
41}
42
43impl<Data> TokenMap<Data> {
44 async fn insert(
45 &self,
46 data: Data,
47 koid: zx::Koid,
48 fut: impl Future<Output = ()> + Send + 'static,
49 ) where
50 Data: Send + 'static,
51 {
52 let mut entries = self.entries.lock().await;
53 let task = fasync::Task::spawn({
54 let entries = Arc::downgrade(&self.entries);
55 async move {
56 fut.await;
57 if let Some(entries) = entries.upgrade() {
58 let _: Option<_> = entries.lock().await.remove(&koid);
59 }
60 }
61 });
62 let existing = entries.insert(koid, TokenMapEntry { data, task: Some(task) });
63 assert!(existing.is_none());
64 }
65
66 pub async fn insert_data(&self, data: Data) -> fidl::EventPair
69 where
70 Data: Send + 'static,
71 {
72 let (watcher, token) = zx::EventPair::create();
73 self.insert(
74 data,
75 token.get_koid().expect("unable to fetch koid for event_pair"),
76 fasync::OnSignals::new(watcher, zx::Signals::OBJECT_PEER_CLOSED).map(|_| ()),
77 )
78 .await;
79 token
80 }
81
82 pub async fn get<Handle: AsHandleRef>(&self, handle_ref: Handle) -> Option<MapData<'_, Data>> {
88 let koid = handle_ref.get_koid().expect("unable to fetch koid for provided handle");
89 let data = self.entries.lock().await;
90 MapData::new(data, koid)
91 }
92}
93
94pub(crate) struct MapData<'a, Data> {
98 data: MutexGuard<'a, HashMap<zx::Koid, TokenMapEntry<Data>>>,
99 koid: zx::Koid,
100}
101
102impl<'a, Data> MapData<'a, Data> {
103 fn new(
106 data: MutexGuard<'a, HashMap<zx::Koid, TokenMapEntry<Data>>>,
107 koid: zx::Koid,
108 ) -> Option<Self> {
109 if data.contains_key(&koid) {
110 Some(MapData { data, koid })
111 } else {
112 None
113 }
114 }
115}
116
117impl<Data> std::ops::Deref for MapData<'_, Data> {
119 type Target = Data;
120
121 fn deref(&self) -> &Self::Target {
122 &self.data.get(&self.koid).expect("entry must exist").data
123 }
124}
125
126impl<Data> std::ops::DerefMut for MapData<'_, Data> {
128 fn deref_mut(&mut self) -> &mut Self::Target {
129 &mut self.data.get_mut(&self.koid).expect("entry must exist").data
130 }
131}