1use crate::{MapHandle, URID};
8use std::collections::HashMap;
9use std::ffi::{CStr, CString};
10use std::marker::PhantomPinned;
11use std::os::raw::*;
12
13pub struct DebugMap {
18 storage: HashMap<CString, URID>,
19 feature: crate::Map,
20 _pin: PhantomPinned,
21}
22
23extern "C" fn mapping_fn(handle: MapHandle, uri: *const c_char) -> URID {
24 let map = unsafe { (handle as *mut HashMap<CString, URID>).as_mut() }.unwrap();
25 let uri = unsafe { CStr::from_ptr(uri) }.to_owned();
26
27 if !map.contains_key(&uri) {
28 let biggest_urid = map.values().map(|urid: &URID| -> URID { *urid }).max();
29 let new_urid = match biggest_urid {
30 Some(urid) => urid + 1,
31 None => 0,
32 };
33 map.insert(uri.clone(), new_urid);
34 }
35
36 map[&uri]
37}
38
39impl DebugMap {
40 pub fn new() -> Box<Self> {
42 let mut debug_map = Box::new(Self {
43 storage: HashMap::new(),
44 feature: crate::Map {
45 handle: std::ptr::null_mut(),
46 map: mapping_fn,
47 },
48 _pin: PhantomPinned,
49 });
50 debug_map.feature.handle =
51 &mut debug_map.storage as *mut HashMap<CString, URID> as *mut c_void;
52 debug_map
53 }
54
55 pub fn get_map_ref(&self) -> &crate::Map {
57 &self.feature
58 }
59
60 pub fn get_map_mut(&mut self) -> &mut crate::Map {
62 &mut self.feature
63 }
64
65 pub unsafe fn create_cached_map(&mut self) -> crate::CachedMap {
75 let faked_map: &'static mut crate::Map =
76 (self.get_map_mut() as *mut crate::Map).as_mut().unwrap();
77 crate::CachedMap::new(faked_map)
78 }
79}
80#[cfg(test)]
81mod test {
82 use crate::debug::*;
83
84 const GITHUB_URI: &[u8] = b"https://github.com\0";
85 const GITLAB_URI: &[u8] = b"https://gitlab.com\0";
86
87 #[test]
88 fn test_mapping() {
89 let mut debug_map = DebugMap::new();
90 let map = debug_map.get_map_mut();
91
92 let github_urid = map.map(CStr::from_bytes_with_nul(GITHUB_URI).unwrap());
93 let gitlab_urid = map.map(CStr::from_bytes_with_nul(GITLAB_URI).unwrap());
94
95 assert_ne!(github_urid, gitlab_urid);
96 }
97
98 #[test]
99 fn test_cached_mapping() {
100 let mut debug_map = DebugMap::new();
101 let mut cached_map = unsafe { debug_map.create_cached_map() };
102
103 let github_urid = cached_map.map(CStr::from_bytes_with_nul(GITHUB_URI).unwrap());
104 let gitlab_urid = cached_map.map(CStr::from_bytes_with_nul(GITLAB_URI).unwrap());
105
106 assert_ne!(github_urid, gitlab_urid);
107 }
108}