use alloc::vec::Vec;
use core::mem;
use core::ptr::copy_nonoverlapping;
use eventheader::FieldEncoding;
use eventheader::FieldFormat;
use eventheader::Opcode;
use eventheader::_internal;
use eventheader::_internal::EventDataDescriptor;
use eventheader::_internal::EventHeader;
use eventheader::_internal::HeaderFlags;
use crate::provider::EventSet;
#[allow(unused_imports)] use crate::Provider;
pub trait ValueField: Copy {}
impl ValueField for bool {}
impl ValueField for char {}
impl ValueField for f32 {}
impl ValueField for f64 {}
impl ValueField for i8 {}
impl ValueField for i16 {}
impl ValueField for i32 {}
impl ValueField for i64 {}
impl ValueField for isize {}
impl ValueField for u8 {}
impl ValueField for u16 {}
impl ValueField for u32 {}
impl ValueField for u64 {}
impl ValueField for usize {}
impl ValueField for [u8; 1] {}
impl ValueField for [u8; 2] {}
impl ValueField for [u8; 4] {}
impl ValueField for [u8; 8] {}
impl ValueField for [u8; 16] {}
pub trait StringField: ValueField + Default + Eq {}
impl StringField for char {}
impl StringField for i8 {}
impl StringField for i16 {}
impl StringField for i32 {}
impl StringField for u8 {}
impl StringField for u16 {}
impl StringField for u32 {}
pub trait BinaryField: ValueField + Default + Eq {}
impl BinaryField for i8 {}
impl BinaryField for u8 {}
trait ValueFieldEncoding: ValueField {
const VALUE_ENCODING: FieldEncoding = match mem::size_of::<Self>() {
1 => FieldEncoding::Value8,
2 => FieldEncoding::Value16,
4 => FieldEncoding::Value32,
8 => FieldEncoding::Value64,
16 => FieldEncoding::Value128,
_ => panic!(),
};
}
impl<T: ValueField> ValueFieldEncoding for T {}
trait StringFieldEncoding: StringField {
const STRING_ENCODING: FieldEncoding = match mem::size_of::<Self>() {
1 => FieldEncoding::StringLength16Char8,
2 => FieldEncoding::StringLength16Char16,
4 => FieldEncoding::StringLength16Char32,
_ => panic!(),
};
const ZSTRING_ENCODING: FieldEncoding = match mem::size_of::<Self>() {
1 => FieldEncoding::ZStringChar8,
2 => FieldEncoding::ZStringChar16,
4 => FieldEncoding::ZStringChar32,
_ => panic!(),
};
}
impl<T: StringField> StringFieldEncoding for T {}
trait BinaryFieldEncoding: BinaryField {
const BINARY_ENCODING: FieldEncoding = match mem::size_of::<Self>() {
1 => FieldEncoding::BinaryLength16Char8,
_ => panic!(),
};
}
impl<T: BinaryField> BinaryFieldEncoding for T {}
#[derive(Debug)]
pub struct EventBuilder {
meta: Vec<u8>,
data: Vec<u8>,
flags: HeaderFlags,
version: u8,
id: u16,
tag: u16,
opcode: Opcode,
}
impl EventBuilder {
pub fn new() -> EventBuilder {
return Self::new_with_capacity(256, 256);
}
pub fn new_with_capacity(meta_capacity: u16, data_capacity: u16) -> EventBuilder {
let mut b = EventBuilder {
meta: Vec::with_capacity(if meta_capacity < 4 {
4
} else {
meta_capacity as usize
}),
data: Vec::with_capacity(data_capacity as usize),
flags: HeaderFlags::DefaultWithExtension,
version: 0,
id: 0,
tag: 0,
opcode: Opcode::Info,
};
b.meta.resize(1, 0); return b;
}
pub fn reset(&mut self, name: &str, event_tag: u16) -> &mut Self {
debug_assert!(!name.contains('\0'), "event name must not contain '\\0'");
self.meta.clear();
self.data.clear();
self.flags = HeaderFlags::DefaultWithExtension;
self.version = 0;
self.id = 0;
self.tag = event_tag;
self.opcode = Opcode::Info;
self.meta.extend_from_slice(name.as_bytes());
self.meta.push(0);
return self;
}
pub fn write(
&self,
event_set: &EventSet,
activity_id: Option<&[u8; 16]>,
related_id: Option<&[u8; 16]>,
) -> i32 {
debug_assert!(related_id.is_none() || activity_id.is_some());
return if self.meta.len() + self.data.len() > 65535 - (52 + 16) {
34 } else {
_internal::write_eventheader(
event_set.state(),
&EventHeader {
flags: self.flags,
version: self.version,
id: self.id,
tag: self.tag,
opcode: self.opcode,
level: event_set.level(),
},
activity_id,
related_id,
self.meta.len() as u16,
&mut [
EventDataDescriptor::zero(),
EventDataDescriptor::from_bytes(&self.meta),
EventDataDescriptor::from_bytes(&self.data),
],
)
};
}
pub fn id_version(&mut self, id: u16, version: u8) -> &mut Self {
self.id = id;
self.version = version;
return self;
}
pub fn opcode(&mut self, opcode: Opcode) -> &mut Self {
self.opcode = opcode;
return self;
}
pub fn add_struct(
&mut self,
field_name: &str,
struct_field_count: u8,
field_tag: u16,
) -> &mut Self {
let masked_field_count = struct_field_count & FieldFormat::ValueMask;
debug_assert_eq!(
masked_field_count, struct_field_count,
"struct_field_count must be less than 128"
);
assert!(masked_field_count != 0, "struct_field_count must not be 0");
return self.raw_add_meta(
field_name,
FieldEncoding::Struct.as_int(),
masked_field_count,
field_tag,
);
}
pub fn add_struct_with_bookmark(
&mut self,
field_name: &str,
initial_struct_field_count: u8,
field_tag: u16,
field_count_bookmark: &mut usize,
) -> &mut Self {
let masked_field_count = initial_struct_field_count & FieldFormat::ValueMask;
debug_assert_eq!(
masked_field_count, initial_struct_field_count,
"initial_struct_field_count must be less than 128"
);
assert!(
masked_field_count != 0,
"initial_struct_field_count must not be 0"
);
self.raw_add_meta(
field_name,
FieldEncoding::Struct.as_int(),
masked_field_count,
field_tag,
);
*field_count_bookmark = if field_tag == 0 {
self.meta.len() - 1
} else {
self.meta.len() - 3
};
return self;
}
pub fn set_struct_field_count(
&mut self,
field_count_bookmark: usize,
updated_struct_field_count: u8,
) -> &mut Self {
let masked_field_count = updated_struct_field_count & FieldFormat::ValueMask;
debug_assert_eq!(
masked_field_count, updated_struct_field_count,
"updated_struct_field_count must be less than 128"
);
assert!(
masked_field_count != 0,
"updated_struct_field_count must not be 0"
);
self.meta[field_count_bookmark] =
(self.meta[field_count_bookmark] & 0x80) | masked_field_count;
return self;
}
pub fn add_value<V: ValueField>(
&mut self,
field_name: &str,
field_value: V,
format: FieldFormat,
field_tag: u16,
) -> &mut Self {
return self
.raw_add_meta_scalar(field_name, V::VALUE_ENCODING, format, field_tag)
.raw_add_data_value(&field_value);
}
pub fn add_value_sequence<'a, V: 'a + ValueField>(
&mut self,
field_name: &str,
field_values: impl IntoIterator<Item = &'a V>,
format: FieldFormat,
field_tag: u16,
) -> &mut Self {
return self
.raw_add_meta_vcount(field_name, V::VALUE_ENCODING, format, field_tag)
.raw_add_data_range(field_values, |this, value| {
this.raw_add_data_value(value);
});
}
pub fn add_str<V: StringField>(
&mut self,
field_name: &str,
field_value: impl AsRef<[V]>,
format: FieldFormat,
field_tag: u16,
) -> &mut Self {
return self
.raw_add_meta_scalar(field_name, V::STRING_ENCODING, format, field_tag)
.raw_add_data_counted(field_value.as_ref());
}
pub fn add_str_sequence<I: IntoIterator, V: StringField>(
&mut self,
field_name: &str,
field_values: I,
format: FieldFormat,
field_tag: u16,
) -> &mut Self
where
I::Item: AsRef<[V]>,
{
return self
.raw_add_meta_vcount(field_name, V::STRING_ENCODING, format, field_tag)
.raw_add_data_range(field_values, |this, value| {
this.raw_add_data_counted(value.as_ref());
});
}
pub fn add_cstr<V: StringField>(
&mut self,
field_name: &str,
field_value: impl AsRef<[V]>,
format: FieldFormat,
field_tag: u16,
) -> &mut Self {
return self
.raw_add_meta_scalar(field_name, V::ZSTRING_ENCODING, format, field_tag)
.raw_add_data_cstr(field_value.as_ref());
}
pub fn add_cstr_sequence<I: IntoIterator, V: StringField>(
&mut self,
field_name: &str,
field_values: I,
format: FieldFormat,
field_tag: u16,
) -> &mut Self
where
I::Item: AsRef<[V]>,
{
return self
.raw_add_meta_vcount(field_name, V::ZSTRING_ENCODING, format, field_tag)
.raw_add_data_range(field_values, |this, value| {
this.raw_add_data_cstr(value.as_ref());
});
}
pub fn add_binary<V: BinaryField>(
&mut self,
field_name: &str,
field_value: impl AsRef<[V]>,
format: FieldFormat,
field_tag: u16,
) -> &mut Self {
return self
.raw_add_meta_scalar(field_name, V::BINARY_ENCODING, format, field_tag)
.raw_add_data_counted(field_value.as_ref());
}
pub fn add_binary_sequence<I: IntoIterator, V: BinaryField>(
&mut self,
field_name: &str,
field_values: I,
format: FieldFormat,
field_tag: u16,
) -> &mut Self
where
I::Item: AsRef<[V]>,
{
return self
.raw_add_meta_vcount(field_name, V::BINARY_ENCODING, format, field_tag)
.raw_add_data_range(field_values, |this, value| {
this.raw_add_data_counted(value.as_ref());
});
}
pub fn raw_add_meta_scalar(
&mut self,
field_name: &str,
encoding: FieldEncoding,
format: FieldFormat,
field_tag: u16,
) -> &mut Self {
debug_assert_eq!(
encoding.as_int() & FieldEncoding::FlagMask,
0,
"encoding must not include any flags"
);
return self.raw_add_meta(field_name, encoding.as_int(), format.as_int(), field_tag);
}
pub fn raw_add_meta_vcount(
&mut self,
field_name: &str,
encoding: FieldEncoding,
format: FieldFormat,
field_tag: u16,
) -> &mut Self {
debug_assert_eq!(
encoding.as_int() & FieldEncoding::FlagMask,
0,
"encoding must not include any flags"
);
return self.raw_add_meta(
field_name,
encoding.as_int() | FieldEncoding::VArrayFlag,
format.as_int(),
field_tag,
);
}
pub fn raw_add_data_value<T: Copy>(&mut self, value: &T) -> &mut Self {
let value_size = mem::size_of::<T>();
let old_data_size = self.data.len();
self.data.reserve(value_size);
unsafe {
copy_nonoverlapping(
value as *const T as *const u8,
self.data.as_mut_ptr().add(old_data_size),
value_size,
);
self.data.set_len(old_data_size + value_size);
}
return self;
}
pub fn raw_add_data_slice<T: Copy>(&mut self, value: &[T]) -> &mut Self {
let value_size = mem::size_of_val(value);
let old_data_size = self.data.len();
self.data.reserve(value_size);
unsafe {
copy_nonoverlapping(
value.as_ptr() as *const u8,
self.data.as_mut_ptr().add(old_data_size),
value_size,
);
self.data.set_len(old_data_size + value_size);
}
return self;
}
fn raw_add_meta(
&mut self,
field_name: &str,
encoding: u8,
format: u8,
field_tag: u16,
) -> &mut Self {
debug_assert!(
!field_name.contains('\0'),
"field_name must not contain '\\0'"
);
self.meta.reserve(field_name.len() + 7);
self.meta.extend_from_slice(field_name.as_bytes());
self.meta.push(0);
if field_tag != 0 {
self.meta.push(0x80 | encoding);
self.meta.push(0x80 | format);
self.meta.extend_from_slice(&field_tag.to_ne_bytes());
} else if format != 0 {
self.meta.push(0x80 | encoding);
self.meta.push(format);
} else {
self.meta.push(encoding);
}
return self;
}
fn raw_add_data_cstr<T: Copy + Default + Eq>(&mut self, value: &[T]) -> &mut Self {
let zero = T::default();
let mut nul_pos = 0;
while nul_pos != value.len() {
if value[nul_pos] == zero {
return self.raw_add_data_slice(&value[0..nul_pos + 1]);
}
nul_pos += 1;
}
return self.raw_add_data_slice(value).raw_add_data_value(&zero);
}
fn raw_add_data_counted<T: Copy>(&mut self, value: &[T]) -> &mut Self {
if value.len() > 65535 {
return self
.raw_add_data_value(&65535)
.raw_add_data_slice(&value[0..65535]);
} else {
return self
.raw_add_data_value(&(value.len() as u16))
.raw_add_data_slice(value);
}
}
fn raw_add_data_range<T: IntoIterator>(
&mut self,
field_values: T,
add_data: impl Fn(&mut Self, T::Item),
) -> &mut Self {
let mut count = 0u16;
let old_data_size = self.data.len();
self.raw_add_data_value(&count);
for value in field_values {
if count == u16::MAX {
break;
}
count += 1;
add_data(self, value);
}
self.data[old_data_size..old_data_size + 2].copy_from_slice(&count.to_ne_bytes());
return self;
}
}
impl Default for EventBuilder {
fn default() -> Self {
return Self::new();
}
}