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