1#![doc = include_str!("../README.md")]
4
5use std::hash::{Hash, Hasher};
6
7#[repr(C)]
8#[derive(Default, Eq, PartialEq, Copy, Clone)]
9pub struct Guid {
10 pub data1: u32,
11 pub data2: u16,
12 pub data3: u16,
13 pub data4: [u8; 8],
14}
15
16impl Hash for Guid {
17 fn hash<H: Hasher>(
18 &self,
19 state: &mut H) {
20 state.write_u32(self.data1);
21 state.write_u16(self.data2);
22 state.write_u16(self.data3);
23 }
24}
25
26impl Guid {
27 pub const fn from_u128(uuid: u128) -> Self {
28 Self {
29 data1: (uuid >> 96) as u32,
30 data2: (uuid >> 80 & 0xffff) as u16,
31 data3: (uuid >> 64 & 0xffff) as u16,
32 data4: (uuid as u64).to_be_bytes()
33 }
34 }
35
36 pub fn to_bytes(&self) -> [u8; 16] {
37 unsafe { std::mem::transmute(*self) }
38 }
39
40 pub fn v5_from_name(namespace: &[u8], name: &[u8]) -> Self {
51 use sha1::{Sha1, Digest};
52
53 let mut hasher = Sha1::new();
54 hasher.update(namespace);
55 hasher.update(name);
56 let result = hasher.finalize();
57
58 let a = u32::from_ne_bytes([result[0], result[1], result[2], result[3]]);
59 let b = u16::from_ne_bytes([result[4], result[5]]);
60 let mut c = u16::from_ne_bytes([result[6], result[7]]);
61
62 c = (c & 0x0FFF) | 0x5000;
64
65 Self {
66 data1: a,
67 data2: b,
68 data3: c,
69 data4: [
70 result[8], result[9], result[10], result[11],
71 result[12], result[13], result[14], result[15],
72 ],
73 }
74 }
75}
76
77pub mod event;
78pub mod sharing;
79pub mod helpers;
80pub mod intern;
81pub mod os;
82
83mod ruwind;
84
85pub mod unwind {
88 pub use crate::ruwind::{ModuleKey, UnwindType};
89 pub use crate::ruwind::elf::ElfLoadHeader;
90}
91
92#[cfg(any(doc, target_os = "linux"))]
93pub mod tracefs;
94#[cfg(any(doc, target_os = "linux"))]
95pub mod procfs;
96#[cfg(any(doc, target_os = "linux"))]
97pub mod perf_event;
98#[cfg(any(doc, target_os = "linux"))]
99pub mod openat;
100#[cfg(any(doc, target_os = "linux"))]
101pub mod user_events;
102
103#[cfg(any(doc, target_os = "windows"))]
104pub mod etw;
105
106#[cfg(feature = "scripting")]
107pub mod scripting;
108
109pub use sharing::{Writable, ReadOnly};
110
111pub mod pathbuf_ext;
112pub use pathbuf_ext::{PathBufInteger};
113
114pub type IOResult<T> = std::io::Result<T>;
115pub type IOError = std::io::Error;
116
117const fn page_size_to_mask(page_size: u64) -> u64 {
118 !((page_size - 1) as u64)
119}
120
121pub fn io_error(message: &str) -> IOError {
122 IOError::new(
123 std::io::ErrorKind::Other,
124 message)
125}
126
127#[cfg(test)]
128mod tests {
129 use super::Guid;
130
131 const NS: &[u8] = b"one_collect test namespace";
132
133 #[test]
134 fn v5_from_name_is_deterministic() {
135 assert_eq!(
136 Guid::v5_from_name(NS, b"record-trace").to_bytes(),
137 Guid::v5_from_name(NS, b"record-trace").to_bytes());
138 }
139
140 #[test]
141 fn v5_from_name_distinct_names_distinct_guids() {
142 assert_ne!(
143 Guid::v5_from_name(NS, b"session-a").to_bytes(),
144 Guid::v5_from_name(NS, b"session-b").to_bytes());
145 }
146
147 #[test]
148 fn v5_from_name_distinct_namespaces_distinct_guids() {
149 assert_ne!(
150 Guid::v5_from_name(b"namespace-a", b"same-name").to_bytes(),
151 Guid::v5_from_name(b"namespace-b", b"same-name").to_bytes());
152 }
153
154 #[test]
155 fn v5_from_name_sets_version_nibble_to_5() {
156 let guid = Guid::v5_from_name(NS, b"record-trace");
157 assert_eq!(guid.data3 & 0xF000, 0x5000);
158 }
159}
160