use alloc::vec::Vec;
use core::fmt;
use core::pin::Pin;
use core::str::from_utf8;
use tracelogging::Guid;
use tracelogging::Level;
use tracelogging::ProviderEnableCallback;
use tracelogging::_internal::ProviderContext;
#[allow(unused_imports)] use crate::EventBuilder;
pub struct Provider {
pub(crate) context: ProviderContext,
pub(crate) meta: Vec<u8>, id: Guid,
callback_fn: Option<ProviderEnableCallback>,
callback_context: usize,
}
impl Provider {
pub fn current_thread_activity_id() -> Guid {
let mut activity_id = Guid::zero();
ProviderContext::activity_id_control(
1, &mut activity_id,
);
return activity_id;
}
pub fn set_current_thread_activity_id(value: &Guid) -> Guid {
let mut activity_id = *value;
ProviderContext::activity_id_control(
4, &mut activity_id,
);
return activity_id;
}
pub fn create_activity_id() -> Guid {
let mut activity_id = Guid::zero();
ProviderContext::activity_id_control(
3, &mut activity_id,
);
return activity_id;
}
pub fn guid_from_name(name: &str) -> Guid {
return Guid::from_name(name);
}
pub fn options() -> ProviderOptions {
return ProviderOptions::new();
}
pub fn new(name: &str, options: &ProviderOptions) -> Self {
return Self::new_with_id(name, options, &Guid::from_name(name));
}
pub fn new_with_id(name: &str, options: &ProviderOptions, id: &Guid) -> Self {
assert!(
name.len() < 32768,
"provider name.len() must be less than 32KB"
);
debug_assert!(!name.contains('\0'), "provider name must not contain '\\0'");
const GROUP_TRAIT_LEN: u16 = 2 + 1 + 16;
let name_len = name.len() as u16;
let traits_len = if options.group_id.is_some() {
GROUP_TRAIT_LEN
} else {
0
};
let meta_len = 2 + name_len + 1 + traits_len;
let mut meta = Vec::with_capacity(meta_len as usize);
meta.extend_from_slice(&meta_len.to_le_bytes());
meta.extend_from_slice(name.as_bytes());
meta.push(0);
if traits_len != 0 {
meta.extend_from_slice(&GROUP_TRAIT_LEN.to_le_bytes());
meta.push(1); meta.extend_from_slice(&options.group_id.unwrap().to_bytes_le());
}
debug_assert_eq!(
meta.len(),
meta_len as usize,
"Bug: Incorrect meta length reservation"
);
return Self {
context: ProviderContext::new(),
meta,
id: *id,
callback_fn: options.callback_fn,
callback_context: options.callback_context,
};
}
pub fn name(&self) -> &str {
let mut name_end = 2;
while self.meta[name_end] != 0 {
name_end += 1;
}
return from_utf8(&self.meta[2..name_end]).unwrap();
}
pub const fn id(&self) -> &Guid {
return &self.id;
}
#[inline(always)]
pub const fn enabled(&self, level: Level, keyword: u64) -> bool {
return self.context.enabled(level, keyword);
}
pub fn unregister(&self) -> u32 {
return self.context.unregister();
}
pub unsafe fn register(self: Pin<&Self>) -> u32 {
let result = unsafe { self
.context
.register(&self.id, self.callback_fn, self.callback_context) };
if result == 0 {
self.context.set_information(
2, &self.meta[..],
);
}
return result;
}
}
impl fmt::Debug for Provider {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
return write!(
f,
"Provider {{ name: \"{}\", id: {}, enabled: {}, reg_handle: {:x} }}",
self.name(),
from_utf8(&self.id.to_utf8_bytes()).unwrap(),
self.enabled(Level::LogAlways, 0),
self.context.reg_handle()
);
}
}
#[derive(Clone, Copy, Default)]
pub struct ProviderOptions {
group_id: Option<Guid>,
callback_fn: Option<ProviderEnableCallback>,
callback_context: usize,
}
impl ProviderOptions {
pub const fn new() -> Self {
return Self {
group_id: None,
callback_fn: None,
callback_context: 0,
};
}
pub fn group_id(&mut self, value: &Guid) -> &mut Self {
self.group_id = Some(*value);
return self;
}
pub fn callback(
&mut self,
callback_fn: ProviderEnableCallback,
callback_context: usize,
) -> &mut Self {
self.callback_fn = Some(callback_fn);
self.callback_context = callback_context;
return self;
}
}
impl fmt::Debug for ProviderOptions {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let callback_ptr = match self.callback_fn {
None => core::ptr::null(),
Some(p) => p as *const (),
};
return write!(
f,
"ProviderOptions {{ group_id: \"{:?}\", callback_fn: {:?}, callback_context: {:x} }}",
self.group_id, callback_ptr, self.callback_context
);
}
}