1use base::id::{BrowsingContextId, PipelineId, WebViewId};
6use rustc_hash::FxHashMap;
7
8#[derive(Debug, Default)]
9pub(crate) struct IdMap {
10 pub(crate) browser_ids: FxHashMap<WebViewId, u32>,
11 pub(crate) browsing_context_ids: FxHashMap<BrowsingContextId, u32>,
12 pub(crate) outer_window_ids: FxHashMap<PipelineId, u32>,
13}
14
15impl IdMap {
16 pub(crate) fn browser_id(&mut self, webview_id: WebViewId) -> DevtoolsBrowserId {
17 let len = self
18 .browser_ids
19 .len()
20 .checked_add(1)
21 .expect("WebViewId count overflow")
22 .try_into()
23 .expect("DevtoolsBrowserId overflow");
24 DevtoolsBrowserId(*self.browser_ids.entry(webview_id).or_insert(len))
25 }
26 pub(crate) fn browsing_context_id(
27 &mut self,
28 browsing_context_id: BrowsingContextId,
29 ) -> DevtoolsBrowsingContextId {
30 let len = self
31 .browsing_context_ids
32 .len()
33 .checked_add(1)
34 .expect("BrowsingContextId count overflow")
35 .try_into()
36 .expect("DevtoolsBrowsingContextId overflow");
37 DevtoolsBrowsingContextId(
38 *self
39 .browsing_context_ids
40 .entry(browsing_context_id)
41 .or_insert(len),
42 )
43 }
44 pub(crate) fn outer_window_id(&mut self, pipeline_id: PipelineId) -> DevtoolsOuterWindowId {
45 let len = self
46 .outer_window_ids
47 .len()
48 .checked_add(1)
49 .expect("PipelineId count overflow")
50 .try_into()
51 .expect("DevtoolsOuterWindowId overflow");
52 DevtoolsOuterWindowId(*self.outer_window_ids.entry(pipeline_id).or_insert(len))
53 }
54}
55
56#[derive(Clone, Copy, Debug, PartialEq)]
57pub(crate) struct DevtoolsBrowserId(u32);
58
59#[derive(Clone, Copy, Debug, PartialEq)]
60pub(crate) struct DevtoolsBrowsingContextId(u32);
61
62#[derive(Clone, Copy, Debug, PartialEq)]
63pub(crate) struct DevtoolsOuterWindowId(u32);
64
65impl DevtoolsBrowserId {
66 pub(crate) fn value(&self) -> u32 {
67 self.0
68 }
69}
70
71impl DevtoolsBrowsingContextId {
72 pub(crate) fn value(&self) -> u32 {
73 self.0
74 }
75}
76
77impl DevtoolsOuterWindowId {
78 pub(crate) fn value(&self) -> u32 {
79 self.0
80 }
81}
82
83#[cfg(test)]
84mod test {
85 use super::*;
86
87 #[test]
88 pub(crate) fn test_id_map() {
89 use std::thread;
90
91 use base::id::{PipelineNamespace, PipelineNamespaceId};
92 use crossbeam_channel::unbounded;
93
94 macro_rules! test_sequential_id_assignment {
95 ($id_type:ident, $new_id_function:expr, $map_id_function:expr) => {
96 let (sender, receiver) = unbounded();
97 let sender1 = sender.clone();
98 let sender2 = sender.clone();
99 let sender3 = sender.clone();
100 let threads = [
101 thread::spawn(move || {
102 PipelineNamespace::install(PipelineNamespaceId(1));
103 sender1.send($new_id_function()).expect("Send failed");
104 sender1.send($new_id_function()).expect("Send failed");
105 sender1.send($new_id_function()).expect("Send failed");
106 }),
107 thread::spawn(move || {
108 PipelineNamespace::install(PipelineNamespaceId(2));
109 sender2.send($new_id_function()).expect("Send failed");
110 sender2.send($new_id_function()).expect("Send failed");
111 sender2.send($new_id_function()).expect("Send failed");
112 }),
113 thread::spawn(move || {
114 PipelineNamespace::install(PipelineNamespaceId(3));
115 sender3.send($new_id_function()).expect("Send failed");
116 sender3.send($new_id_function()).expect("Send failed");
117 sender3.send($new_id_function()).expect("Send failed");
118 }),
119 ];
120 for thread in threads {
121 thread.join().expect("Thread join failed");
122 }
123 let mut id_map = IdMap::default();
124 assert_eq!(
125 $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")),
126 $id_type(1)
127 );
128 assert_eq!(
129 $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")),
130 $id_type(2)
131 );
132 assert_eq!(
133 $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")),
134 $id_type(3)
135 );
136 assert_eq!(
137 $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")),
138 $id_type(4)
139 );
140 assert_eq!(
141 $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")),
142 $id_type(5)
143 );
144 assert_eq!(
145 $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")),
146 $id_type(6)
147 );
148 assert_eq!(
149 $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")),
150 $id_type(7)
151 );
152 assert_eq!(
153 $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")),
154 $id_type(8)
155 );
156 assert_eq!(
157 $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")),
158 $id_type(9)
159 );
160 };
161 }
162
163 test_sequential_id_assignment!(
164 DevtoolsBrowserId,
165 || WebViewId::new(base::id::TEST_PAINTER_ID),
166 |id_map: &mut IdMap, id| id_map.browser_id(id)
167 );
168 test_sequential_id_assignment!(
169 DevtoolsBrowsingContextId,
170 || BrowsingContextId::new(),
171 |id_map: &mut IdMap, id| id_map.browsing_context_id(id)
172 );
173 test_sequential_id_assignment!(
174 DevtoolsOuterWindowId,
175 || PipelineId::new(),
176 |id_map: &mut IdMap, id| id_map.outer_window_id(id)
177 );
178 }
179}