@ -1,6 +1,6 @@
#![ no_std ]
#![ no_std ]
use core ::{ mem , num , ptr } ;
use core ::num ;
use num_enum ::IntoPrimitive ;
use num_enum ::IntoPrimitive ;
@ -86,7 +86,7 @@ pub trait UpperMacFormatter {}
impl UpperMacFormatter for [ u8 ; 6 ] { }
impl UpperMacFormatter for [ u8 ; 6 ] { }
#[ repr(u8) ]
#[ repr(u8) ]
#[ derive(Copy, Clone, Debug )]
#[ derive(Copy, Clone, Debug , IntoPrimitive )]
pub enum RecordField {
pub enum RecordField {
Target = 1 ,
Target = 1 ,
Level ,
Level ,
@ -99,7 +99,7 @@ pub enum RecordField {
/// Types which are supported by aya-log and can be safely sent from eBPF
/// Types which are supported by aya-log and can be safely sent from eBPF
/// programs to userspace.
/// programs to userspace.
#[ repr(u8) ]
#[ repr(u8) ]
#[ derive(Copy, Clone, Debug )]
#[ derive(Copy, Clone, Debug , IntoPrimitive )]
pub enum Argument {
pub enum Argument {
DisplayHint ,
DisplayHint ,
@ -147,53 +147,24 @@ pub enum DisplayHint {
UpperMac ,
UpperMac ,
}
}
struct TagLenValue < T , V > {
pub ( crate ) fn write ( tag : u8 , value : & [ u8 ] , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
pub tag : T ,
pub value : V ,
}
impl < T , V > TagLenValue < T , V >
where
V : IntoIterator < Item = u8 > ,
< V as IntoIterator > ::IntoIter : ExactSizeIterator ,
{
pub ( crate ) fn write ( self , mut buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
// 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
let wire_len : LogValueLength = value
. len ( )
. len ( )
. try_into ( )
. try_into ( )
. map_err ( | num ::TryFromIntError { .. } | ( ) ) ? ;
. map_err ( | num ::TryFromIntError { .. } | ( ) ) ? ;
let size = mem ::size_of_val ( & tag ) + mem ::size_of_val ( & wire_len ) + len ;
let mut size = 0 ;
if size > buf . len ( ) {
macro_rules! copy_from_slice {
return Err ( ( ) ) ;
( $value :expr ) = > { {
let buf = buf . get_mut ( size .. ) . ok_or ( ( ) ) ? ;
let buf = buf . get_mut ( .. $value . len ( ) ) . ok_or ( ( ) ) ? ;
buf . copy_from_slice ( $value ) ;
size + = $value . len ( ) ;
} } ;
}
}
copy_from_slice ! ( & [ tag ] ) ;
let tag_size = mem ::size_of_val ( & tag ) ;
copy_from_slice ! ( & wire_len . to_ne_bytes ( ) ) ;
unsafe { ptr ::write_unaligned ( buf . as_mut_ptr ( ) as * mut _ , tag ) } ;
copy_from_slice ! ( value ) ;
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 ) .. ] ;
buf . iter_mut ( ) . zip ( value ) . for_each ( | ( dst , src ) | {
* dst = src ;
} ) ;
Ok ( size )
Ok ( size )
}
}
impl < T , V > TagLenValue < T , V > {
#[ inline(always) ]
pub ( crate ) fn new ( tag : T , value : V ) -> TagLenValue < T , V > {
TagLenValue { tag , value }
}
}
}
pub trait WriteToBuf {
pub trait WriteToBuf {
@ -205,7 +176,7 @@ macro_rules! impl_write_to_buf {
( $type :ident , $arg_type :expr ) = > {
( $type :ident , $arg_type :expr ) = > {
impl WriteToBuf for $type {
impl WriteToBuf for $type {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
TagLenValue::new ( $arg_type , self . to_ne_bytes ( ) ) . write ( buf )
write( $arg_type . into ( ) , & self . to_ne_bytes ( ) , buf )
}
}
}
}
} ;
} ;
@ -228,45 +199,45 @@ impl_write_to_buf!(f64, Argument::F64);
impl WriteToBuf for [ u8 ; 16 ] {
impl WriteToBuf for [ u8 ; 16 ] {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
TagLenValue::new ( Argument ::ArrU8Len16 , self ) . write ( buf )
write( Argument ::ArrU8Len16 . into ( ) , & self , buf )
}
}
}
}
impl WriteToBuf for [ u16 ; 8 ] {
impl WriteToBuf for [ u16 ; 8 ] {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
let bytes = unsafe { core ::mem ::transmute ::< _ , [ u8 ; 16 ] > ( self ) } ;
let bytes = unsafe { core ::mem ::transmute ::< _ , [ u8 ; 16 ] > ( self ) } ;
TagLenValue::new ( Argument ::ArrU16Len8 , bytes ) . write ( buf )
write( Argument ::ArrU16Len8 . into ( ) , & bytes , buf )
}
}
}
}
impl WriteToBuf for [ u8 ; 6 ] {
impl WriteToBuf for [ u8 ; 6 ] {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
TagLenValue::new ( Argument ::ArrU8Len6 , self ) . write ( buf )
write( Argument ::ArrU8Len6 . into ( ) , & self , buf )
}
}
}
}
impl WriteToBuf for & [ u8 ] {
impl WriteToBuf for & [ u8 ] {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
TagLenValue::new ( Argument ::Bytes , self . iter ( ) . copied ( ) ) . write ( buf )
write( Argument ::Bytes . into ( ) , self , buf )
}
}
}
}
impl WriteToBuf for & str {
impl WriteToBuf for & str {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
TagLenValue::new ( Argument ::Str , self . as_bytes ( ) . iter ( ) . copied ( ) ) . write ( buf )
write( Argument ::Str . into ( ) , self . as_bytes ( ) , buf )
}
}
}
}
impl WriteToBuf for DisplayHint {
impl WriteToBuf for DisplayHint {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
fn write ( self , buf : & mut [ u8 ] ) -> Result < usize , ( ) > {
let v : u8 = self . into ( ) ;
let v : u8 = self . into ( ) ;
TagLenValue::new ( Argument ::DisplayHint , v . to_ne_bytes ( ) ). write ( buf )
write ( Argument ::DisplayHint .into ( ) , & v . to_ne_bytes ( ) , buf )
}
}
}
}
#[ allow(clippy::result_unit_err) ]
#[ allow(clippy::result_unit_err) ]
#[ doc(hidden) ]
#[ doc(hidden) ]
#[ inline(always) ]
#[ inline(always) ] // This function takes too many arguments to not be inlined.
pub fn write_record_header (
pub fn write_record_header (
buf : & mut [ u8 ] ,
buf : & mut [ u8 ] ,
target : & str ,
target : & str ,
@ -278,16 +249,18 @@ pub fn write_record_header(
) -> Result < usize , ( ) > {
) -> Result < usize , ( ) > {
let level : u8 = level . into ( ) ;
let level : u8 = level . into ( ) ;
let mut size = 0 ;
let mut size = 0 ;
size + = TagLenValue ::new ( RecordField ::Target , target . as_bytes ( ) . iter ( ) . copied ( ) )
macro_rules! write {
. write ( & mut buf [ size .. ] ) ? ;
( $tag :expr , $value :expr ) = > { {
size + = TagLenValue ::new ( RecordField ::Level , level . to_ne_bytes ( ) ) . write ( & mut buf [ size .. ] ) ? ;
let buf = buf . get_mut ( size .. ) . ok_or ( ( ) ) ? ;
size + = TagLenValue ::new ( RecordField ::Module , module . as_bytes ( ) . iter ( ) . copied ( ) )
size + = write ( $tag . into ( ) , $value , buf ) ? ;
. write ( & mut buf [ size .. ] ) ? ;
} } ;
size + = TagLenValue ::new ( RecordField ::File , file . as_bytes ( ) . iter ( ) . copied ( ) )
}
. write ( & mut buf [ size .. ] ) ? ;
write! ( RecordField ::Target , target . as_bytes ( ) ) ;
size + = TagLenValue ::new ( RecordField ::Line , line . to_ne_bytes ( ) ) . write ( & mut buf [ size .. ] ) ? ;
write! ( RecordField ::Level , & level . to_ne_bytes ( ) ) ;
size + =
write! ( RecordField ::Module , module . as_bytes ( ) ) ;
TagLenValue ::new ( RecordField ::NumArgs , num_args . to_ne_bytes ( ) ) . write ( & mut buf [ size .. ] ) ? ;
write! ( RecordField ::File , file . as_bytes ( ) ) ;
write! ( RecordField ::Line , & line . to_ne_bytes ( ) ) ;
write! ( RecordField ::NumArgs , & num_args . to_ne_bytes ( ) ) ;
Ok ( size )
Ok ( size )
}
}