#![doc = include_str!("../README.md")]
use std::hash::{Hash, Hasher};
#[repr(C)]
#[derive(Default, Eq, PartialEq, Copy, Clone)]
pub struct Guid {
pub data1: u32,
pub data2: u16,
pub data3: u16,
pub data4: [u8; 8],
}
impl Hash for Guid {
fn hash<H: Hasher>(
&self,
state: &mut H) {
state.write_u32(self.data1);
state.write_u16(self.data2);
state.write_u16(self.data3);
}
}
impl Guid {
pub const fn from_u128(uuid: u128) -> Self {
Self {
data1: (uuid >> 96) as u32,
data2: (uuid >> 80 & 0xffff) as u16,
data3: (uuid >> 64 & 0xffff) as u16,
data4: (uuid as u64).to_be_bytes()
}
}
pub fn to_bytes(&self) -> [u8; 16] {
unsafe { std::mem::transmute(*self) }
}
pub fn v5_from_name(namespace: &[u8], name: &[u8]) -> Self {
use sha1::{Sha1, Digest};
let mut hasher = Sha1::new();
hasher.update(namespace);
hasher.update(name);
let result = hasher.finalize();
let a = u32::from_ne_bytes([result[0], result[1], result[2], result[3]]);
let b = u16::from_ne_bytes([result[4], result[5]]);
let mut c = u16::from_ne_bytes([result[6], result[7]]);
c = (c & 0x0FFF) | 0x5000;
Self {
data1: a,
data2: b,
data3: c,
data4: [
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15],
],
}
}
}
pub mod event;
pub mod sharing;
pub mod helpers;
pub mod intern;
pub mod os;
mod ruwind;
pub mod unwind {
pub use crate::ruwind::{ModuleKey, UnwindType};
pub use crate::ruwind::elf::ElfLoadHeader;
}
#[cfg(any(doc, target_os = "linux"))]
pub mod tracefs;
#[cfg(any(doc, target_os = "linux"))]
pub mod procfs;
#[cfg(any(doc, target_os = "linux"))]
pub mod perf_event;
#[cfg(any(doc, target_os = "linux"))]
pub mod openat;
#[cfg(any(doc, target_os = "linux"))]
pub mod user_events;
#[cfg(any(doc, target_os = "windows"))]
pub mod etw;
#[cfg(feature = "scripting")]
pub mod scripting;
pub use sharing::{Writable, ReadOnly};
pub mod pathbuf_ext;
pub use pathbuf_ext::{PathBufInteger};
pub type IOResult<T> = std::io::Result<T>;
pub type IOError = std::io::Error;
const fn page_size_to_mask(page_size: u64) -> u64 {
!((page_size - 1) as u64)
}
pub fn io_error(message: &str) -> IOError {
IOError::new(
std::io::ErrorKind::Other,
message)
}
#[cfg(test)]
mod tests {
use super::Guid;
const NS: &[u8] = b"one_collect test namespace";
#[test]
fn v5_from_name_is_deterministic() {
assert_eq!(
Guid::v5_from_name(NS, b"record-trace").to_bytes(),
Guid::v5_from_name(NS, b"record-trace").to_bytes());
}
#[test]
fn v5_from_name_distinct_names_distinct_guids() {
assert_ne!(
Guid::v5_from_name(NS, b"session-a").to_bytes(),
Guid::v5_from_name(NS, b"session-b").to_bytes());
}
#[test]
fn v5_from_name_distinct_namespaces_distinct_guids() {
assert_ne!(
Guid::v5_from_name(b"namespace-a", b"same-name").to_bytes(),
Guid::v5_from_name(b"namespace-b", b"same-name").to_bytes());
}
#[test]
fn v5_from_name_sets_version_nibble_to_5() {
let guid = Guid::v5_from_name(NS, b"record-trace");
assert_eq!(guid.data3 & 0xF000, 0x5000);
}
}