From 9a1a720a74fd458b4865e1139dd2f4ca84994ef2 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 19 Apr 2023 13:36:34 -0400 Subject: [PATCH] aya-log-common: generalize TagLenValue This allows logging values backed by generators. --- aya-log-common/src/lib.rs | 93 +++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/aya-log-common/src/lib.rs b/aya-log-common/src/lib.rs index 9b85c65e..80bab66a 100644 --- a/aya-log-common/src/lib.rs +++ b/aya-log-common/src/lib.rs @@ -1,6 +1,6 @@ #![no_std] -use core::{mem, num, ptr, slice}; +use core::{mem, num, ptr}; use num_enum::IntoPrimitive; @@ -98,58 +98,65 @@ pub enum DisplayHint { UpperMac, } -struct TagLenValue<'a, T> { - tag: T, - value: &'a [u8], +struct TagLenValue { + pub tag: T, + pub value: V, } -impl<'a, T> TagLenValue<'a, T> +impl TagLenValue where - T: Copy, + V: IntoIterator, + ::IntoIter: ExactSizeIterator, { - #[inline(always)] - pub(crate) fn new(tag: T, value: &'a [u8]) -> TagLenValue<'a, T> { - TagLenValue { tag, value } - } - - pub(crate) fn write(&self, mut buf: &mut [u8]) -> Result { + pub(crate) fn write(self, mut buf: &mut [u8]) -> Result { // Break the abstraction to please the verifier. if buf.len() > LOG_BUF_CAPACITY { buf = &mut buf[..LOG_BUF_CAPACITY]; } let Self { tag, value } = self; + let value = value.into_iter(); let len = value.len(); let wire_len: LogValueLength = value .len() .try_into() .map_err(|num::TryFromIntError { .. }| ())?; - let size = mem::size_of_val(tag) + mem::size_of_val(&wire_len) + len; + let size = mem::size_of_val(&tag) + mem::size_of_val(&wire_len) + len; if size > buf.len() { return Err(()); } - unsafe { ptr::write_unaligned(buf.as_mut_ptr() as *mut _, *tag) }; - buf = &mut buf[mem::size_of_val(tag)..]; + let tag_size = mem::size_of_val(&tag); + unsafe { ptr::write_unaligned(buf.as_mut_ptr() as *mut _, tag) }; + buf = &mut buf[tag_size..]; unsafe { ptr::write_unaligned(buf.as_mut_ptr() as *mut _, wire_len) }; buf = &mut buf[mem::size_of_val(&wire_len)..]; - unsafe { ptr::copy_nonoverlapping(value.as_ptr(), buf.as_mut_ptr(), len) }; + buf.iter_mut().zip(value).for_each(|(dst, src)| { + *dst = src; + }); Ok(size) } } +impl TagLenValue { + #[inline(always)] + pub(crate) fn new(tag: T, value: V) -> TagLenValue { + TagLenValue { tag, value } + } +} + pub trait WriteToBuf { #[allow(clippy::result_unit_err)] - fn write(&self, buf: &mut [u8]) -> Result; + fn write(self, buf: &mut [u8]) -> Result; } macro_rules! impl_write_to_buf { ($type:ident, $arg_type:expr) => { impl WriteToBuf for $type { - fn write(&self, buf: &mut [u8]) -> Result { - TagLenValue::::new($arg_type, &self.to_ne_bytes()).write(buf) + fn write(self, buf: &mut [u8]) -> Result { + TagLenValue::new($arg_type, self.to_ne_bytes()).write(buf) } } }; @@ -171,35 +178,34 @@ impl_write_to_buf!(f32, Argument::F32); impl_write_to_buf!(f64, Argument::F64); impl WriteToBuf for [u8; 16] { - fn write(&self, buf: &mut [u8]) -> Result { - TagLenValue::::new(Argument::ArrU8Len16, self).write(buf) + fn write(self, buf: &mut [u8]) -> Result { + TagLenValue::new(Argument::ArrU8Len16, self).write(buf) } } impl WriteToBuf for [u16; 8] { - fn write(&self, buf: &mut [u8]) -> Result { - let ptr = self.as_ptr().cast::(); - let bytes = unsafe { slice::from_raw_parts(ptr, 16) }; - TagLenValue::::new(Argument::ArrU16Len8, bytes).write(buf) + fn write(self, buf: &mut [u8]) -> Result { + let bytes = unsafe { core::mem::transmute::<_, [u8; 16]>(self) }; + TagLenValue::new(Argument::ArrU16Len8, bytes).write(buf) } } impl WriteToBuf for [u8; 6] { - fn write(&self, buf: &mut [u8]) -> Result { - TagLenValue::::new(Argument::ArrU8Len6, self).write(buf) + fn write(self, buf: &mut [u8]) -> Result { + TagLenValue::new(Argument::ArrU8Len6, self).write(buf) } } -impl WriteToBuf for str { - fn write(&self, buf: &mut [u8]) -> Result { - TagLenValue::::new(Argument::Str, self.as_bytes()).write(buf) +impl WriteToBuf for &str { + fn write(self, buf: &mut [u8]) -> Result { + TagLenValue::new(Argument::Str, self.as_bytes().iter().copied()).write(buf) } } impl WriteToBuf for DisplayHint { - fn write(&self, buf: &mut [u8]) -> Result { - let v: u8 = (*self).into(); - TagLenValue::::new(Argument::DisplayHint, &v.to_ne_bytes()).write(buf) + fn write(self, buf: &mut [u8]) -> Result { + let v: u8 = self.into(); + TagLenValue::new(Argument::DisplayHint, v.to_ne_bytes()).write(buf) } } @@ -217,17 +223,16 @@ pub fn write_record_header( ) -> Result { let level: u8 = level.into(); let mut size = 0; - for attr in [ - TagLenValue::::new(RecordField::Target, target.as_bytes()), - TagLenValue::::new(RecordField::Level, &level.to_ne_bytes()), - TagLenValue::::new(RecordField::Module, module.as_bytes()), - TagLenValue::::new(RecordField::File, file.as_bytes()), - TagLenValue::::new(RecordField::Line, &line.to_ne_bytes()), - TagLenValue::::new(RecordField::NumArgs, &num_args.to_ne_bytes()), - ] { - size += attr.write(&mut buf[size..])?; - } - + size += TagLenValue::new(RecordField::Target, target.as_bytes().iter().copied()) + .write(&mut buf[size..])?; + size += TagLenValue::new(RecordField::Level, level.to_ne_bytes()).write(&mut buf[size..])?; + size += TagLenValue::new(RecordField::Module, module.as_bytes().iter().copied()) + .write(&mut buf[size..])?; + size += TagLenValue::new(RecordField::File, file.as_bytes().iter().copied()) + .write(&mut buf[size..])?; + size += TagLenValue::new(RecordField::Line, line.to_ne_bytes()).write(&mut buf[size..])?; + size += + TagLenValue::new(RecordField::NumArgs, num_args.to_ne_bytes()).write(&mut buf[size..])?; Ok(size) }