2
2
3
3
use core:: {
4
4
net:: { IpAddr , Ipv4Addr , Ipv6Addr } ,
5
- num:: { NonZeroUsize , TryFromIntError } ,
5
+ num:: TryFromIntError ,
6
6
} ;
7
7
8
8
use num_enum:: IntoPrimitive ;
9
9
10
- pub const LOG_FIELDS : usize = 6 ;
11
-
12
10
pub type LogValueLength = u16 ;
13
11
14
12
#[ repr( u8 ) ]
@@ -93,8 +91,8 @@ impl UpperMacFormatter for [u8; 6] {}
93
91
94
92
#[ repr( u8 ) ]
95
93
#[ derive( Copy , Clone , Debug , IntoPrimitive ) ]
96
- pub enum RecordField {
97
- Target = 1 ,
94
+ pub enum RecordFieldKind {
95
+ Target ,
98
96
Level ,
99
97
Module ,
100
98
File ,
@@ -106,7 +104,7 @@ pub enum RecordField {
106
104
/// programs to userspace.
107
105
#[ repr( u8 ) ]
108
106
#[ derive( Copy , Clone , Debug , IntoPrimitive ) ]
109
- pub enum Argument {
107
+ pub enum ArgumentKind {
110
108
DisplayHint ,
111
109
112
110
I8 ,
@@ -158,172 +156,207 @@ pub enum DisplayHint {
158
156
UpperMac ,
159
157
}
160
158
161
- // Must be inlined, else the BPF backend emits:
162
- //
163
- // llvm: <unknown>:0:0: in function _ZN14aya_log_common5write17hc9ed05433e23a663E { i64, i64 } (i8, ptr, i64, ptr, i64): only integer returns supported
164
- #[ inline( always) ]
165
- pub ( crate ) fn write ( tag : u8 , value : & [ u8 ] , buf : & mut [ u8 ] ) -> Option < NonZeroUsize > {
166
- // TODO(https://github.com/rust-lang/rust-clippy/issues/14112): Remove this allowance when the
167
- // lint behaves more sensibly.
168
- #[ expect( clippy:: manual_ok_err) ]
169
- let wire_len: LogValueLength = match value. len ( ) . try_into ( ) {
170
- Ok ( wire_len) => Some ( wire_len) ,
171
- Err ( TryFromIntError { .. } ) => None ,
172
- } ?;
173
- let mut size = 0 ;
174
- for slice in [ & [ tag] [ ..] , & wire_len. to_ne_bytes ( ) [ ..] , value] {
175
- let buf = buf. get_mut ( size..) ?;
176
- let buf = buf. get_mut ( ..slice. len ( ) ) ?;
177
- buf. copy_from_slice ( slice) ;
178
- size += slice. len ( ) ;
179
- }
180
- NonZeroUsize :: new ( size)
181
- }
182
-
183
- pub trait WriteToBuf {
184
- fn write ( self , buf : & mut [ u8 ] ) -> Option < NonZeroUsize > ;
159
+ pub trait Argument {
160
+ fn as_argument ( & self ) -> ( ArgumentKind , impl AsRef < [ u8 ] > ) ;
185
161
}
186
162
187
- macro_rules! impl_write_to_buf {
188
- ( $type: ident, $arg_type: expr) => {
189
- impl WriteToBuf for $type {
190
- // This need not be inlined because the return value is Option<N> where N is
191
- // mem::size_of<$type>, which is a compile-time constant.
192
- #[ inline( never) ]
193
- fn write( self , buf: & mut [ u8 ] ) -> Option <NonZeroUsize > {
194
- write( $arg_type. into( ) , & self . to_ne_bytes( ) , buf)
163
+ macro_rules! impl_argument {
164
+ ( $self: ident, $arg_type: expr) => {
165
+ impl Argument for $self {
166
+ fn as_argument( & self ) -> ( ArgumentKind , impl AsRef <[ u8 ] >) {
167
+ ( $arg_type, self . to_ne_bytes( ) )
195
168
}
196
169
}
197
170
} ;
198
171
}
199
172
200
- impl_write_to_buf ! ( i8 , Argument :: I8 ) ;
201
- impl_write_to_buf ! ( i16 , Argument :: I16 ) ;
202
- impl_write_to_buf ! ( i32 , Argument :: I32 ) ;
203
- impl_write_to_buf ! ( i64 , Argument :: I64 ) ;
204
- impl_write_to_buf ! ( isize , Argument :: Isize ) ;
173
+ impl_argument ! ( i8 , ArgumentKind :: I8 ) ;
174
+ impl_argument ! ( i16 , ArgumentKind :: I16 ) ;
175
+ impl_argument ! ( i32 , ArgumentKind :: I32 ) ;
176
+ impl_argument ! ( i64 , ArgumentKind :: I64 ) ;
177
+ impl_argument ! ( isize , ArgumentKind :: Isize ) ;
178
+
179
+ impl_argument ! ( u8 , ArgumentKind :: U8 ) ;
180
+ impl_argument ! ( u16 , ArgumentKind :: U16 ) ;
181
+ impl_argument ! ( u32 , ArgumentKind :: U32 ) ;
182
+ impl_argument ! ( u64 , ArgumentKind :: U64 ) ;
183
+ impl_argument ! ( usize , ArgumentKind :: Usize ) ;
205
184
206
- impl_write_to_buf ! ( u8 , Argument :: U8 ) ;
207
- impl_write_to_buf ! ( u16 , Argument :: U16 ) ;
208
- impl_write_to_buf ! ( u32 , Argument :: U32 ) ;
209
- impl_write_to_buf ! ( u64 , Argument :: U64 ) ;
210
- impl_write_to_buf ! ( usize , Argument :: Usize ) ;
185
+ impl_argument ! ( f32 , ArgumentKind :: F32 ) ;
186
+ impl_argument ! ( f64 , ArgumentKind :: F64 ) ;
211
187
212
- impl_write_to_buf ! ( f32 , Argument :: F32 ) ;
213
- impl_write_to_buf ! ( f64 , Argument :: F64 ) ;
188
+ enum Either < L , R > {
189
+ Left ( L ) ,
190
+ Right ( R ) ,
191
+ }
214
192
215
- impl WriteToBuf for IpAddr {
216
- fn write ( self , buf : & mut [ u8 ] ) -> Option < NonZeroUsize > {
193
+ impl < L , R > AsRef < [ u8 ] > for Either < L , R >
194
+ where
195
+ L : AsRef < [ u8 ] > ,
196
+ R : AsRef < [ u8 ] > ,
197
+ {
198
+ fn as_ref ( & self ) -> & [ u8 ] {
217
199
match self {
218
- IpAddr :: V4 ( ipv4_addr ) => write ( Argument :: Ipv4Addr . into ( ) , & ipv4_addr . octets ( ) , buf ) ,
219
- IpAddr :: V6 ( ipv6_addr ) => write ( Argument :: Ipv6Addr . into ( ) , & ipv6_addr . octets ( ) , buf ) ,
200
+ Either :: Left ( l ) => l . as_ref ( ) ,
201
+ Either :: Right ( r ) => r . as_ref ( ) ,
220
202
}
221
203
}
222
204
}
223
205
224
- impl WriteToBuf for Ipv4Addr {
225
- fn write ( self , buf : & mut [ u8 ] ) -> Option < NonZeroUsize > {
226
- write ( Argument :: Ipv4Addr . into ( ) , & self . octets ( ) , buf)
206
+ impl Argument for IpAddr {
207
+ fn as_argument ( & self ) -> ( ArgumentKind , impl AsRef < [ u8 ] > ) {
208
+ match self {
209
+ IpAddr :: V4 ( ipv4_addr) => {
210
+ let ( kind, value) = ipv4_addr. as_argument ( ) ;
211
+ ( kind, Either :: Left ( value) )
212
+ }
213
+ IpAddr :: V6 ( ipv6_addr) => {
214
+ let ( kind, value) = ipv6_addr. as_argument ( ) ;
215
+ ( kind, Either :: Right ( value) )
216
+ }
217
+ }
227
218
}
228
219
}
229
220
230
- impl WriteToBuf for [ u8 ; 4 ] {
231
- // This need not be inlined because the return value is Option<N> where N is 16, which is a
232
- // compile-time constant.
233
- #[ inline( never) ]
234
- fn write ( self , buf : & mut [ u8 ] ) -> Option < NonZeroUsize > {
235
- write ( Argument :: ArrU8Len4 . into ( ) , & self , buf)
221
+ impl Argument for Ipv4Addr {
222
+ fn as_argument ( & self ) -> ( ArgumentKind , impl AsRef < [ u8 ] > ) {
223
+ ( ArgumentKind :: Ipv4Addr , self . octets ( ) )
236
224
}
237
225
}
238
226
239
- impl WriteToBuf for Ipv6Addr {
240
- fn write ( self , buf : & mut [ u8 ] ) -> Option < NonZeroUsize > {
241
- write ( Argument :: Ipv6Addr . into ( ) , & self . octets ( ) , buf )
227
+ impl Argument for [ u8 ; 4 ] {
228
+ fn as_argument ( & self ) -> ( ArgumentKind , impl AsRef < [ u8 ] > ) {
229
+ ( ArgumentKind :: ArrU8Len4 , self )
242
230
}
243
231
}
244
232
245
- impl WriteToBuf for [ u8 ; 16 ] {
246
- // This need not be inlined because the return value is Option<N> where N is 16, which is a
247
- // compile-time constant.
248
- #[ inline( never) ]
249
- fn write ( self , buf : & mut [ u8 ] ) -> Option < NonZeroUsize > {
250
- write ( Argument :: ArrU8Len16 . into ( ) , & self , buf)
233
+ impl Argument for Ipv6Addr {
234
+ fn as_argument ( & self ) -> ( ArgumentKind , impl AsRef < [ u8 ] > ) {
235
+ ( ArgumentKind :: Ipv6Addr , self . octets ( ) )
251
236
}
252
237
}
253
238
254
- impl WriteToBuf for [ u16 ; 8 ] {
255
- // This need not be inlined because the return value is Option<N> where N is 16, which is a
256
- // compile-time constant.
257
- #[ inline( never) ]
258
- fn write ( self , buf : & mut [ u8 ] ) -> Option < NonZeroUsize > {
259
- let bytes = unsafe { core:: mem:: transmute :: < [ u16 ; 8 ] , [ u8 ; 16 ] > ( self ) } ;
260
- write ( Argument :: ArrU16Len8 . into ( ) , & bytes, buf)
239
+ impl Argument for [ u8 ; 16 ] {
240
+ fn as_argument ( & self ) -> ( ArgumentKind , impl AsRef < [ u8 ] > ) {
241
+ ( ArgumentKind :: ArrU8Len16 , self )
261
242
}
262
243
}
263
244
264
- impl WriteToBuf for [ u8 ; 6 ] {
265
- // This need not be inlined because the return value is Option<N> where N is 6, which is a
266
- // compile-time constant.
267
- #[ inline( never) ]
268
- fn write ( self , buf : & mut [ u8 ] ) -> Option < NonZeroUsize > {
269
- write ( Argument :: ArrU8Len6 . into ( ) , & self , buf)
245
+ impl Argument for [ u16 ; 8 ] {
246
+ fn as_argument ( & self ) -> ( ArgumentKind , impl AsRef < [ u8 ] > ) {
247
+ let bytes = unsafe { core:: mem:: transmute :: < & [ u16 ; 8 ] , & [ u8 ; 16 ] > ( self ) } ;
248
+ ( ArgumentKind :: ArrU16Len8 , bytes)
270
249
}
271
250
}
272
251
273
- impl WriteToBuf for & [ u8 ] {
274
- // Must be inlined, else the BPF backend emits:
275
- //
276
- // llvm: <unknown>:0:0: in function _ZN63_$LT$$RF$$u5b$u8$u5d$$u20$as$u20$aya_log_common..WriteToBuf$GT$5write17h08f30a45f7b9f09dE { i64, i64 } (ptr, i64, ptr, i64): only integer returns supported
277
- #[ inline( always) ]
278
- fn write ( self , buf : & mut [ u8 ] ) -> Option < NonZeroUsize > {
279
- write ( Argument :: Bytes . into ( ) , self , buf)
252
+ impl Argument for [ u8 ; 6 ] {
253
+ fn as_argument ( & self ) -> ( ArgumentKind , impl AsRef < [ u8 ] > ) {
254
+ ( ArgumentKind :: ArrU8Len6 , self )
280
255
}
281
256
}
282
257
283
- impl WriteToBuf for & str {
284
- // Must be inlined, else the BPF backend emits:
285
- //
286
- // llvm: <unknown>:0:0: in function _ZN54_$LT$$RF$str$u20$as$u20$aya_log_common..WriteToBuf$GT$5write17h7e2d1ccaa758e2b5E { i64, i64 } (ptr, i64, ptr, i64): only integer returns supported
287
- #[ inline( always) ]
288
- fn write ( self , buf : & mut [ u8 ] ) -> Option < NonZeroUsize > {
289
- write ( Argument :: Str . into ( ) , self . as_bytes ( ) , buf)
258
+ impl Argument for & [ u8 ] {
259
+ fn as_argument ( & self ) -> ( ArgumentKind , impl AsRef < [ u8 ] > ) {
260
+ ( ArgumentKind :: Bytes , self )
290
261
}
291
262
}
292
263
293
- impl WriteToBuf for DisplayHint {
294
- // This need not be inlined because the return value is Option<N> where N is 1, which is a
295
- // compile-time constant.
296
- #[ inline( never) ]
297
- fn write ( self , buf : & mut [ u8 ] ) -> Option < NonZeroUsize > {
298
- let v: u8 = self . into ( ) ;
299
- write ( Argument :: DisplayHint . into ( ) , & v. to_ne_bytes ( ) , buf)
264
+ impl Argument for & str {
265
+ fn as_argument ( & self ) -> ( ArgumentKind , impl AsRef < [ u8 ] > ) {
266
+ ( ArgumentKind :: Str , self . as_bytes ( ) )
267
+ }
268
+ }
269
+
270
+ impl Argument for DisplayHint {
271
+ fn as_argument ( & self ) -> ( ArgumentKind , impl AsRef < [ u8 ] > ) {
272
+ let v: u8 = ( * self ) . into ( ) ;
273
+ ( ArgumentKind :: DisplayHint , v. to_ne_bytes ( ) )
274
+ }
275
+ }
276
+
277
+ fn wire_len ( value : & [ u8 ] ) -> Option < [ u8 ; 2 ] > {
278
+ match LogValueLength :: try_from ( value. len ( ) ) {
279
+ Ok ( wire_len) => Some ( wire_len. to_ne_bytes ( ) ) ,
280
+ Err ( TryFromIntError { .. } ) => None ,
281
+ }
282
+ }
283
+
284
+ #[ doc( hidden) ]
285
+ pub struct Field < T > ( [ u8 ; 1 ] , [ u8 ; 2 ] , T ) ;
286
+
287
+ impl < T : AsRef < [ u8 ] > > Field < T > {
288
+ pub fn new ( kind : impl Into < u8 > , value : T ) -> Option < Self > {
289
+ let wire_len = wire_len ( value. as_ref ( ) ) ?;
290
+ Some ( Self ( [ kind. into ( ) ] , wire_len, value) )
291
+ }
292
+
293
+ pub fn with_bytes ( & self , op : & mut impl FnMut ( & [ u8 ] ) -> Option < ( ) > ) -> Option < ( ) > {
294
+ let Self ( kind, wire_len, value) = self ;
295
+ op ( & kind[ ..] ) ?;
296
+ op ( & wire_len[ ..] ) ?;
297
+ op ( value. as_ref ( ) ) ?;
298
+ Some ( ( ) )
300
299
}
301
300
}
302
301
303
302
#[ doc( hidden) ]
304
- #[ inline( always) ] // This function takes too many arguments to not be inlined.
305
- pub fn write_record_header (
306
- buf : & mut [ u8 ] ,
307
- target : & str ,
308
- level : Level ,
309
- module : & str ,
310
- file : & str ,
311
- line : u32 ,
312
- num_args : usize ,
313
- ) -> Option < NonZeroUsize > {
314
- let level: u8 = level. into ( ) ;
315
- let mut size = 0 ;
316
- for ( tag, value) in [
317
- ( RecordField :: Target , target. as_bytes ( ) ) ,
318
- ( RecordField :: Level , & level. to_ne_bytes ( ) ) ,
319
- ( RecordField :: Module , module. as_bytes ( ) ) ,
320
- ( RecordField :: File , file. as_bytes ( ) ) ,
321
- ( RecordField :: Line , & line. to_ne_bytes ( ) ) ,
322
- ( RecordField :: NumArgs , & num_args. to_ne_bytes ( ) ) ,
323
- ] {
324
- let buf = buf. get_mut ( size..) ?;
325
- let len = write ( tag. into ( ) , value, buf) ?;
326
- size += len. get ( ) ;
303
+ pub struct Header < ' a > {
304
+ target : Field < & ' a [ u8 ] > ,
305
+ level : Field < [ u8 ; 1 ] > ,
306
+ module : Field < & ' a [ u8 ] > ,
307
+ file : Field < & ' a [ u8 ] > ,
308
+ line : Field < [ u8 ; 4 ] > ,
309
+ num_args : Field < [ u8 ; 4 ] > ,
310
+ }
311
+
312
+ impl < ' a > Header < ' a > {
313
+ pub fn new (
314
+ target : & ' a str ,
315
+ level : Level ,
316
+ module : & ' a str ,
317
+ file : & ' a str ,
318
+ line : u32 ,
319
+ num_args : u32 ,
320
+ ) -> Option < Self > {
321
+ let target = target. as_bytes ( ) ;
322
+ let level: u8 = level. into ( ) ;
323
+ let level = level. to_ne_bytes ( ) ;
324
+ let module = module. as_bytes ( ) ;
325
+ let file = file. as_bytes ( ) ;
326
+ let line = line. to_ne_bytes ( ) ;
327
+ let num_args = num_args. to_ne_bytes ( ) ;
328
+ let target = Field :: new ( RecordFieldKind :: Target , target) ?;
329
+ let level = Field :: new ( RecordFieldKind :: Level , level) ?;
330
+ let module = Field :: new ( RecordFieldKind :: Module , module) ?;
331
+ let file = Field :: new ( RecordFieldKind :: File , file) ?;
332
+ let line = Field :: new ( RecordFieldKind :: Line , line) ?;
333
+ let num_args = Field :: new ( RecordFieldKind :: NumArgs , num_args) ?;
334
+
335
+ Some ( Self {
336
+ target,
337
+ level,
338
+ module,
339
+ file,
340
+ line,
341
+ num_args,
342
+ } )
343
+ }
344
+
345
+ pub fn with_bytes ( & self , op : & mut impl FnMut ( & [ u8 ] ) -> Option < ( ) > ) -> Option < ( ) > {
346
+ let Self {
347
+ target,
348
+ level,
349
+ module,
350
+ file,
351
+ line,
352
+ num_args,
353
+ } = self ;
354
+ target. with_bytes ( op) ?;
355
+ level. with_bytes ( op) ?;
356
+ module. with_bytes ( op) ?;
357
+ file. with_bytes ( op) ?;
358
+ line. with_bytes ( op) ?;
359
+ num_args. with_bytes ( op) ?;
360
+ Some ( ( ) )
327
361
}
328
- NonZeroUsize :: new ( size)
329
362
}
0 commit comments