/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::collections::HashMap; use base::id::{BrowsingContextId, PipelineId, WebViewId}; #[derive(Debug, Default)] pub(crate) struct IdMap { pub(crate) browser_ids: HashMap, pub(crate) browsing_context_ids: HashMap, pub(crate) outer_window_ids: HashMap, } impl IdMap { pub(crate) fn browser_id(&mut self, webview_id: WebViewId) -> DevtoolsBrowserId { let len = self .browser_ids .len() .checked_add(1) .expect("WebViewId count overflow") .try_into() .expect("DevtoolsBrowserId overflow"); DevtoolsBrowserId(*self.browser_ids.entry(webview_id).or_insert(len)) } pub(crate) fn browsing_context_id( &mut self, browsing_context_id: BrowsingContextId, ) -> DevtoolsBrowsingContextId { let len = self .browsing_context_ids .len() .checked_add(1) .expect("BrowsingContextId count overflow") .try_into() .expect("DevtoolsBrowsingContextId overflow"); DevtoolsBrowsingContextId( *self .browsing_context_ids .entry(browsing_context_id) .or_insert(len), ) } pub(crate) fn outer_window_id(&mut self, pipeline_id: PipelineId) -> DevtoolsOuterWindowId { let len = self .outer_window_ids .len() .checked_add(1) .expect("PipelineId count overflow") .try_into() .expect("DevtoolsOuterWindowId overflow"); DevtoolsOuterWindowId(*self.outer_window_ids.entry(pipeline_id).or_insert(len)) } } #[derive(Clone, Copy, Debug, PartialEq)] pub(crate) struct DevtoolsBrowserId(u32); #[derive(Clone, Copy, Debug, PartialEq)] pub(crate) struct DevtoolsBrowsingContextId(u32); #[derive(Clone, Copy, Debug, PartialEq)] pub(crate) struct DevtoolsOuterWindowId(u32); impl DevtoolsBrowserId { pub(crate) fn value(&self) -> u32 { self.0 } } impl DevtoolsBrowsingContextId { pub(crate) fn value(&self) -> u32 { self.0 } } impl DevtoolsOuterWindowId { pub(crate) fn value(&self) -> u32 { self.0 } } #[test] pub(crate) fn test_id_map() { use std::thread; use base::id::{PipelineNamespace, PipelineNamespaceId}; use crossbeam_channel::unbounded; macro_rules! test_sequential_id_assignment { ($id_type:ident, $new_id_function:expr, $map_id_function:expr) => { let (sender, receiver) = unbounded(); let sender1 = sender.clone(); let sender2 = sender.clone(); let sender3 = sender.clone(); let threads = [ thread::spawn(move || { PipelineNamespace::install(PipelineNamespaceId(1)); sender1.send($new_id_function()).expect("Send failed"); sender1.send($new_id_function()).expect("Send failed"); sender1.send($new_id_function()).expect("Send failed"); }), thread::spawn(move || { PipelineNamespace::install(PipelineNamespaceId(2)); sender2.send($new_id_function()).expect("Send failed"); sender2.send($new_id_function()).expect("Send failed"); sender2.send($new_id_function()).expect("Send failed"); }), thread::spawn(move || { PipelineNamespace::install(PipelineNamespaceId(3)); sender3.send($new_id_function()).expect("Send failed"); sender3.send($new_id_function()).expect("Send failed"); sender3.send($new_id_function()).expect("Send failed"); }), ]; for thread in threads { thread.join().expect("Thread join failed"); } let mut id_map = IdMap::default(); assert_eq!( $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")), $id_type(1) ); assert_eq!( $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")), $id_type(2) ); assert_eq!( $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")), $id_type(3) ); assert_eq!( $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")), $id_type(4) ); assert_eq!( $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")), $id_type(5) ); assert_eq!( $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")), $id_type(6) ); assert_eq!( $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")), $id_type(7) ); assert_eq!( $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")), $id_type(8) ); assert_eq!( $map_id_function(&mut id_map, receiver.recv().expect("Recv failed")), $id_type(9) ); }; } test_sequential_id_assignment!( DevtoolsBrowserId, || WebViewId::new(), |id_map: &mut IdMap, id| id_map.browser_id(id) ); test_sequential_id_assignment!( DevtoolsBrowsingContextId, || BrowsingContextId::new(), |id_map: &mut IdMap, id| id_map.browsing_context_id(id) ); test_sequential_id_assignment!( DevtoolsOuterWindowId, || PipelineId::new(), |id_map: &mut IdMap, id| id_map.outer_window_id(id) ); }