1use crate::error::ParseWarning;
6use crate::fxt_builder::{FxtBuilder, SerializeError};
7use crate::session::ResolveCtx;
8use crate::string::StringRef;
9use crate::{ParseError, ParseResult, trace_header};
10use flyweights::FlyStr;
11use nom::Parser;
12use nom::number::complete::{le_f64, le_i64, le_u64};
13
14#[derive(Clone, Debug, PartialEq)]
15pub struct Arg {
16 pub name: FlyStr,
17 pub value: ArgValue,
18}
19
20impl Arg {
21 pub(crate) fn resolve_n(ctx: &mut ResolveCtx, raw: Vec<RawArg<'_>>) -> Vec<Self> {
22 raw.into_iter().filter_map(|a| Self::resolve(ctx, a)).collect()
23 }
24
25 fn resolve(ctx: &mut ResolveCtx, raw: RawArg<'_>) -> Option<Self> {
26 let name = ctx.resolve_str(raw.name);
27 if let Some(value) = ArgValue::resolve(ctx, raw.value) {
28 Some(Self { name, value })
29 } else {
30 ctx.add_warning(ParseWarning::SkippingArgWithUnknownType { name });
31 None
32 }
33 }
34}
35
36#[derive(Debug, PartialEq, Clone)]
37pub struct RawArg<'a> {
38 pub name: StringRef<'a>,
39 pub value: RawArgValue<'a>,
40}
41
42impl<'a> RawArg<'a> {
43 pub(crate) fn parse_n(count: u8, buf: &'a [u8]) -> ParseResult<'a, Vec<Self>> {
44 nom::multi::count(Self::parse, count as usize).parse(buf)
45 }
46
47 pub(crate) fn parse(buf: &'a [u8]) -> ParseResult<'a, Self> {
48 use nom::combinator::map;
49
50 let (buf, base_header) = BaseArgHeader::parse(buf)?;
51 let (rem, payload) = base_header.take_payload(buf)?;
52 let (payload, name) = StringRef::parse(base_header.name_ref(), payload)?;
53
54 let arg_ty = base_header.raw_type();
55 let (empty, value) = match arg_ty {
56 NULL_ARG_TYPE => Ok((payload, RawArgValue::Null)),
57 BOOL_ARG_TYPE => {
58 let header = BoolHeader::new(base_header.0).map_err(nom::Err::Failure)?;
59 Ok((payload, RawArgValue::Boolean(header.value() != 0)))
60 }
61 I32_ARG_TYPE => {
62 let header = I32Header::new(base_header.0).map_err(nom::Err::Failure)?;
63 Ok((payload, RawArgValue::Signed32(header.value())))
64 }
65 U32_ARG_TYPE => {
66 let header = U32Header::new(base_header.0).map_err(nom::Err::Failure)?;
67 Ok((payload, RawArgValue::Unsigned32(header.value())))
68 }
69 I64_ARG_TYPE => map(le_i64, |i| RawArgValue::Signed64(i)).parse(payload),
70 U64_ARG_TYPE => map(le_u64, |u| RawArgValue::Unsigned64(u)).parse(payload),
71 F64_ARG_TYPE => map(le_f64, |f| RawArgValue::Double(f)).parse(payload),
72 STR_ARG_TYPE => {
73 let header = StringHeader::new(base_header.0).map_err(nom::Err::Failure)?;
74 map(move |b| StringRef::parse(header.value_ref(), b), |s| RawArgValue::String(s))
75 .parse(payload)
76 }
77 PTR_ARG_TYPE => map(le_u64, |p| RawArgValue::Pointer(p)).parse(payload),
78 KOBJ_ARG_TYPE => map(le_u64, |k| RawArgValue::KernelObj(k)).parse(payload),
79 BLOB_ARG_TYPE => {
80 let header = BlobHeader::new(base_header.0).map_err(nom::Err::Failure)?;
81 Ok((&[][..], RawArgValue::Blob(&payload[..header.blob_size() as usize])))
82 }
83 unknown => Ok((&[][..], RawArgValue::Unknown { raw_type: unknown, bytes: payload })),
84 }?;
85
86 if empty.is_empty() {
87 Ok((rem, Self { name, value }))
88 } else {
89 Err(nom::Err::Failure(ParseError::InvalidSize))
90 }
91 }
92
93 pub(crate) fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
94 let arg_name_ref = match self.name {
95 StringRef::Index(id) => fxt_layout::StringRefHeader::indexed(id.into()).bits(),
96 StringRef::Inline(name) => {
97 fxt_layout::StringRefHeader::inline(name.len() as u16).bits()
98 }
99 StringRef::Empty => {
100 return Err(SerializeError::MissingArgName);
101 }
102 };
103
104 match &self.value {
105 RawArgValue::Null => {
106 let mut header = NullHeader::empty();
107 header.set_name_ref(arg_name_ref);
108 let mut builder = FxtBuilder::new(header);
109 if let StringRef::Inline(name_str) = self.name {
110 builder = builder.atom(name_str);
111 }
112 Ok(builder.build())
113 }
114 RawArgValue::Boolean(val) => {
115 let mut header = BoolHeader::empty();
116 header.set_name_ref(arg_name_ref);
117 header.set_value(*val as u8);
118 let mut builder = FxtBuilder::new(header);
119 if let StringRef::Inline(name_str) = self.name {
120 builder = builder.atom(name_str);
121 }
122 Ok(builder.build())
123 }
124 RawArgValue::Signed32(val) => {
125 let mut header = I32Header::empty();
126 header.set_name_ref(arg_name_ref);
127 header.set_value(*val);
128 let mut builder = FxtBuilder::new(header);
129 if let StringRef::Inline(name_str) = self.name {
130 builder = builder.atom(name_str);
131 }
132 Ok(builder.build())
133 }
134 RawArgValue::Unsigned32(val) => {
135 let mut header = U32Header::empty();
136 header.set_name_ref(arg_name_ref);
137 header.set_value(*val);
138 let mut builder = FxtBuilder::new(header);
139 if let StringRef::Inline(name_str) = self.name {
140 builder = builder.atom(name_str);
141 }
142 Ok(builder.build())
143 }
144 RawArgValue::Signed64(val) => {
145 let mut header = I64Header::empty();
146 header.set_name_ref(arg_name_ref);
147 let mut builder = FxtBuilder::new(header);
148 if let StringRef::Inline(name_str) = self.name {
149 builder = builder.atom(name_str);
150 }
151 Ok(builder.atom(val.to_le_bytes()).build())
152 }
153 RawArgValue::Unsigned64(val) => {
154 let mut header = U64Header::empty();
155 header.set_name_ref(arg_name_ref);
156 let mut builder = FxtBuilder::new(header);
157 if let StringRef::Inline(name_str) = self.name {
158 builder = builder.atom(name_str);
159 }
160 Ok(builder.atom(val.to_le_bytes()).build())
161 }
162 RawArgValue::Double(val) => {
163 let mut header = F64Header::empty();
164 header.set_name_ref(arg_name_ref);
165 let mut builder = FxtBuilder::new(header);
166 if let StringRef::Inline(name_str) = self.name {
167 builder = builder.atom(name_str);
168 }
169 Ok(builder.atom(val.to_le_bytes()).build())
170 }
171 RawArgValue::String(str_val) => {
172 let mut header = StringHeader::empty();
173 header.set_name_ref(arg_name_ref);
174 header.set_value_ref(match str_val {
175 StringRef::Index(id) => {
176 fxt_layout::StringRefHeader::indexed((*id).into()).bits()
177 }
178 StringRef::Inline(val) => {
179 fxt_layout::StringRefHeader::inline(val.len() as u16).bits()
180 }
181 StringRef::Empty => 0u16,
182 });
183 let mut builder = FxtBuilder::new(header);
184 if let StringRef::Inline(name_str) = self.name {
185 builder = builder.atom(name_str);
186 }
187 if let StringRef::Inline(value_str) = str_val {
188 builder = builder.atom(value_str);
189 }
190 Ok(builder.build())
191 }
192 RawArgValue::Pointer(val) => {
193 let mut header = PtrHeader::empty();
194 header.set_name_ref(arg_name_ref);
195 let mut builder = FxtBuilder::new(header);
196 if let StringRef::Inline(name_str) = self.name {
197 builder = builder.atom(name_str);
198 }
199 Ok(builder.atom(val.to_le_bytes()).build())
200 }
201 RawArgValue::KernelObj(val) => {
202 let mut header = KobjHeader::empty();
203 header.set_name_ref(arg_name_ref);
204 let mut builder = FxtBuilder::new(header);
205 if let StringRef::Inline(name_str) = self.name {
206 builder = builder.atom(name_str);
207 }
208 Ok(builder.atom(val.to_le_bytes()).build())
209 }
210 RawArgValue::Blob(val) => {
211 let mut header = BlobHeader::empty();
212 header.set_name_ref(arg_name_ref);
213 header.set_blob_size(val.len() as u32);
214 let mut builder = FxtBuilder::new(header);
215 if let StringRef::Inline(name_str) = self.name {
216 builder = builder.atom(name_str);
217 }
218 builder = builder.atom(val);
219 Ok(builder.build())
220 }
221 RawArgValue::Unknown { raw_type, bytes } => {
222 let mut header = BaseArgHeader::empty();
223 header.set_raw_type(*raw_type);
224 let mut builder = FxtBuilder::new(header);
225 if let StringRef::Inline(name_str) = self.name {
226 builder = builder.atom(name_str);
227 }
228 Ok(builder.atom(bytes).build())
229 }
230 }
231 }
232}
233
234#[derive(Clone, Debug, PartialEq)]
235pub enum ArgValue {
236 Null,
237 Boolean(bool),
238 Signed32(i32),
239 Unsigned32(u32),
240 Signed64(i64),
241 Unsigned64(u64),
242 Double(f64),
243 String(FlyStr),
244 Pointer(u64),
245 KernelObj(u64),
246 Blob(Vec<u8>),
247}
248
249impl ArgValue {
250 pub fn is_null(&self) -> bool {
251 matches!(self, Self::Null)
252 }
253
254 pub fn boolean(&self) -> Option<bool> {
255 match self {
256 Self::Boolean(b) => Some(*b),
257 _ => None,
258 }
259 }
260
261 pub fn signed_32(&self) -> Option<i32> {
262 match self {
263 Self::Signed32(n) => Some(*n),
264 _ => None,
265 }
266 }
267
268 pub fn unsigned_32(&self) -> Option<u32> {
269 match self {
270 Self::Unsigned32(n) => Some(*n),
271 _ => None,
272 }
273 }
274
275 pub fn signed_64(&self) -> Option<i64> {
276 match self {
277 Self::Signed64(n) => Some(*n),
278 _ => None,
279 }
280 }
281
282 pub fn unsigned_64(&self) -> Option<u64> {
283 match self {
284 Self::Unsigned64(n) => Some(*n),
285 _ => None,
286 }
287 }
288
289 pub fn double(&self) -> Option<f64> {
290 match self {
291 Self::Double(n) => Some(*n),
292 _ => None,
293 }
294 }
295
296 pub fn string(&self) -> Option<&str> {
297 match self {
298 Self::String(s) => Some(s.as_str()),
299 _ => None,
300 }
301 }
302
303 pub fn pointer(&self) -> Option<u64> {
304 match self {
305 Self::Pointer(p) => Some(*p),
306 _ => None,
307 }
308 }
309
310 pub fn kernel_obj(&self) -> Option<u64> {
311 match self {
312 Self::KernelObj(k) => Some(*k),
313 _ => None,
314 }
315 }
316
317 pub fn blob(&self) -> Option<&[u8]> {
318 match self {
319 Self::Blob(b) => Some(b),
320 _ => None,
321 }
322 }
323
324 fn resolve(ctx: &mut ResolveCtx, raw: RawArgValue<'_>) -> Option<Self> {
325 Some(match raw {
326 RawArgValue::Null => ArgValue::Null,
327 RawArgValue::Boolean(b) => ArgValue::Boolean(b),
328 RawArgValue::Signed32(s) => ArgValue::Signed32(s),
329 RawArgValue::Unsigned32(u) => ArgValue::Unsigned32(u),
330 RawArgValue::Signed64(s) => ArgValue::Signed64(s),
331 RawArgValue::Unsigned64(u) => ArgValue::Unsigned64(u),
332 RawArgValue::Double(f) => ArgValue::Double(f),
333 RawArgValue::String(s) => ArgValue::String(ctx.resolve_str(s)),
334 RawArgValue::Pointer(p) => ArgValue::Pointer(p),
335 RawArgValue::KernelObj(k) => ArgValue::KernelObj(k),
336 RawArgValue::Blob(b) => ArgValue::Blob(b.to_vec()),
337 RawArgValue::Unknown { .. } => {
338 return None;
339 }
340 })
341 }
342}
343
344impl std::fmt::Display for ArgValue {
345 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
346 match self {
347 ArgValue::Null => write!(f, "null"),
348 ArgValue::Boolean(v) => write!(f, "{v}"),
349 ArgValue::Signed32(v) => write!(f, "{v}"),
350 ArgValue::Unsigned32(v) => write!(f, "{v}"),
351 ArgValue::Signed64(v) => write!(f, "{v}"),
352 ArgValue::Unsigned64(v) => write!(f, "{v}"),
353 ArgValue::Double(v) => write!(f, "{v}"),
354 ArgValue::String(v) => write!(f, "{v}"),
355 ArgValue::Pointer(v) => write!(f, "{v:#016x}"),
356 ArgValue::KernelObj(v) => write!(f, "{v}"),
357 ArgValue::Blob(v) => write!(f, "{v:02X?}"),
358 }
359 }
360}
361
362#[derive(Clone, Debug, PartialEq)]
363pub enum RawArgValue<'a> {
364 Null,
365 Boolean(bool),
366 Signed32(i32),
367 Unsigned32(u32),
368 Signed64(i64),
369 Unsigned64(u64),
370 Double(f64),
371 String(StringRef<'a>),
372 Pointer(u64),
373 KernelObj(u64),
374 Blob(&'a [u8]),
375 Unknown { raw_type: u8, bytes: &'a [u8] },
376}
377
378macro_rules! arg_header {
379 ($name:ident $(($arg_ty:expr))? { $($record_specific:tt)* }) => {
380 trace_header! {
381 $name $(($arg_ty))? {
382 $($record_specific)*
383 u16, name_ref: 16, 31;
384 }
385 }
386 };
387}
388
389pub(crate) const NULL_ARG_TYPE: u8 = 0;
390pub(crate) const I32_ARG_TYPE: u8 = 1;
391pub(crate) const U32_ARG_TYPE: u8 = 2;
392pub(crate) const I64_ARG_TYPE: u8 = 3;
393pub(crate) const U64_ARG_TYPE: u8 = 4;
394pub(crate) const F64_ARG_TYPE: u8 = 5;
395pub(crate) const STR_ARG_TYPE: u8 = 6;
396pub(crate) const PTR_ARG_TYPE: u8 = 7;
397pub(crate) const KOBJ_ARG_TYPE: u8 = 8;
398pub(crate) const BOOL_ARG_TYPE: u8 = 9;
399pub(crate) const BLOB_ARG_TYPE: u8 = 10;
400
401arg_header! {
403 BaseArgHeader {}
404}
405
406arg_header! {
407 NullHeader (NULL_ARG_TYPE) {}
408}
409
410arg_header! {
411 I32Header (I32_ARG_TYPE) {
412 i32, value: 32, 63;
413 }
414}
415
416arg_header! {
417 U32Header (U32_ARG_TYPE) {
418 u32, value: 32, 63;
419 }
420}
421
422arg_header! {
423 I64Header (I64_ARG_TYPE) {}
424}
425
426arg_header! {
427 U64Header (U64_ARG_TYPE) {}
428}
429
430arg_header! {
431 F64Header (F64_ARG_TYPE) {}
432}
433
434arg_header! {
435 StringHeader (STR_ARG_TYPE) {
436 u16, value_ref: 32, 47;
437 }
438}
439
440arg_header! {
441 PtrHeader (PTR_ARG_TYPE) {}
442}
443
444arg_header! {
445 KobjHeader (KOBJ_ARG_TYPE) {}
446}
447
448arg_header! {
449 BoolHeader (BOOL_ARG_TYPE) {
450 u8, value: 32, 32;
451 }
452}
453
454arg_header! {
455 BlobHeader (BLOB_ARG_TYPE) {
456 u32, blob_size: 32, 63;
457 }
458}
459
460#[cfg(test)]
461mod tests {
462 use super::*;
463 use std::num::NonZeroU16;
464
465 #[test]
466 fn null_arg_name_index() {
467 let mut header = BaseArgHeader::empty();
468 header.set_name_ref(10);
469
470 let arg_record_bytes = FxtBuilder::new(header).build();
471 let raw_arg_record = RawArg {
472 name: StringRef::Index(NonZeroU16::new(10).unwrap()),
473 value: RawArgValue::Null,
474 };
475
476 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
477 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
478 }
479 #[test]
480 fn null_arg_name_inline() {
481 let name = "hello";
482 let mut header = BaseArgHeader::empty();
483 header.set_name_ref(fxt_layout::StringRefHeader::inline(name.len() as u16).bits());
484
485 let arg_record_bytes = FxtBuilder::new(header).atom(name).build();
486 let raw_arg_record = RawArg { name: StringRef::Inline("hello"), value: RawArgValue::Null };
487
488 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
489 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
490 }
491
492 #[test]
493 fn i32_arg_name_index() {
494 let mut header = I32Header::empty();
495 header.set_name_ref(10);
496 header.set_value(-19);
497
498 let arg_record_bytes = FxtBuilder::new(header).build();
499 let raw_arg_record = RawArg {
500 name: StringRef::Index(NonZeroU16::new(10).unwrap()),
501 value: RawArgValue::Signed32(-19),
502 };
503
504 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
505 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
506 }
507
508 #[test]
509 fn i32_arg_name_inline() {
510 let name = "hello";
511 let mut header = I32Header::empty();
512 header.set_name_ref(fxt_layout::StringRefHeader::inline(name.len() as u16).bits());
513 header.set_value(-19);
514
515 let arg_record_bytes = FxtBuilder::new(header).atom(name).build();
516 let raw_arg_record =
517 RawArg { name: StringRef::Inline("hello"), value: RawArgValue::Signed32(-19) };
518
519 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
520 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
521 }
522
523 #[test]
524 fn u32_arg_name_index() {
525 let mut header = U32Header::empty();
526 header.set_name_ref(10);
527 header.set_value(23);
528
529 let arg_record_bytes = FxtBuilder::new(header).build();
530 let raw_arg_record = RawArg {
531 name: StringRef::Index(NonZeroU16::new(10).unwrap()),
532 value: RawArgValue::Unsigned32(23),
533 };
534
535 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
536 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
537 }
538
539 #[test]
540 fn u32_arg_name_inline() {
541 let name = "hello";
542 let mut header = U32Header::empty();
543 header.set_name_ref(fxt_layout::StringRefHeader::inline(name.len() as u16).bits());
544 header.set_value(23);
545
546 let arg_record_bytes = FxtBuilder::new(header).atom(name).build();
547 let raw_arg_record =
548 RawArg { name: StringRef::Inline("hello"), value: RawArgValue::Unsigned32(23) };
549
550 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
551 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
552 }
553
554 #[test]
555 fn i64_arg_name_index() {
556 let mut header = BaseArgHeader::empty();
557 header.set_name_ref(10);
558 header.set_raw_type(I64_ARG_TYPE);
559
560 let arg_record_bytes = FxtBuilder::new(header).atom((-79i64).to_le_bytes()).build();
561 let raw_arg_record = RawArg {
562 name: StringRef::Index(NonZeroU16::new(10).unwrap()),
563 value: RawArgValue::Signed64(-79),
564 };
565
566 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
567 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
568 }
569
570 #[test]
571 fn i64_arg_name_inline() {
572 let name = "hello";
573 let mut header = BaseArgHeader::empty();
574 header.set_name_ref(fxt_layout::StringRefHeader::inline(name.len() as u16).bits());
575 header.set_raw_type(I64_ARG_TYPE);
576
577 let arg_record_bytes =
578 FxtBuilder::new(header).atom(name).atom((-845i64).to_le_bytes()).build();
579 let raw_arg_record =
580 RawArg { name: StringRef::Inline("hello"), value: RawArgValue::Signed64(-845) };
581
582 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
583 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
584 }
585
586 #[test]
587 fn u64_arg_name_index() {
588 let mut header = BaseArgHeader::empty();
589 header.set_name_ref(10);
590 header.set_raw_type(U64_ARG_TYPE);
591
592 let arg_record_bytes = FxtBuilder::new(header).atom(1024u64.to_le_bytes()).build();
593 let raw_arg_record = RawArg {
594 name: StringRef::Index(NonZeroU16::new(10).unwrap()),
595 value: RawArgValue::Unsigned64(1024),
596 };
597
598 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
599 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
600 }
601
602 #[test]
603 fn u64_arg_name_inline() {
604 let name = "hello";
605 let mut header = BaseArgHeader::empty();
606 header.set_name_ref(fxt_layout::StringRefHeader::inline(name.len() as u16).bits());
607 header.set_raw_type(U64_ARG_TYPE);
608
609 let arg_record_bytes =
610 FxtBuilder::new(header).atom(name).atom(4096u64.to_le_bytes()).build();
611 let raw_arg_record =
612 RawArg { name: StringRef::Inline("hello"), value: RawArgValue::Unsigned64(4096) };
613
614 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
615 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
616 }
617
618 #[test]
619 fn f64_arg_name_index() {
620 let mut header = BaseArgHeader::empty();
621 header.set_name_ref(10);
622 header.set_raw_type(F64_ARG_TYPE);
623
624 let arg_record_bytes = FxtBuilder::new(header).atom(1007.893f64.to_le_bytes()).build();
625 let raw_arg_record = RawArg {
626 name: StringRef::Index(NonZeroU16::new(10).unwrap()),
627 value: RawArgValue::Double(1007.893),
628 };
629
630 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
631 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
632 }
633
634 #[test]
635 fn f64_arg_name_inline() {
636 let name = "hello";
637 let mut header = BaseArgHeader::empty();
638 header.set_name_ref(fxt_layout::StringRefHeader::inline(name.len() as u16).bits());
639 header.set_raw_type(F64_ARG_TYPE);
640
641 let arg_record_bytes =
642 FxtBuilder::new(header).atom(name).atom(23634.1231f64.to_le_bytes()).build();
643 let raw_arg_record =
644 RawArg { name: StringRef::Inline("hello"), value: RawArgValue::Double(23634.1231) };
645
646 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
647 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
648 }
649
650 #[test]
651 fn string_arg_name_index_value_index() {
652 let mut header = StringHeader::empty();
653 header.set_name_ref(10);
654 header.set_value_ref(11);
655
656 let arg_record_bytes = FxtBuilder::new(header).build();
657 let raw_arg_record = RawArg {
658 name: StringRef::Index(NonZeroU16::new(10).unwrap()),
659 value: RawArgValue::String(StringRef::Index(NonZeroU16::new(11).unwrap())),
660 };
661
662 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
663 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
664 }
665
666 #[test]
667 fn string_arg_name_index_value_inline() {
668 let value = "123-456-7890";
669 let mut header = StringHeader::empty();
670 header.set_name_ref(10);
671 header.set_value_ref(fxt_layout::StringRefHeader::inline(value.len() as u16).bits());
672
673 let arg_record_bytes = FxtBuilder::new(header).atom(value).build();
674 let raw_arg_record = RawArg {
675 name: StringRef::Index(NonZeroU16::new(10).unwrap()),
676 value: RawArgValue::String(StringRef::Inline(value)),
677 };
678
679 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
680 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
681 }
682
683 #[test]
684 fn string_arg_name_inline_value_index() {
685 let name = "hello";
686 let mut header = StringHeader::empty();
687 header.set_name_ref(fxt_layout::StringRefHeader::inline(name.len() as u16).bits());
688 header.set_value_ref(13);
689
690 let arg_record_bytes = FxtBuilder::new(header).atom(name).build();
691 let raw_arg_record = RawArg {
692 name: StringRef::Inline(name),
693 value: RawArgValue::String(StringRef::Index(NonZeroU16::new(13).unwrap())),
694 };
695
696 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
697 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
698 }
699
700 #[test]
701 fn string_arg_name_inline_value_inline() {
702 let name = "hello";
703 let value = "123-456-7890";
704 let mut header = StringHeader::empty();
705 header.set_name_ref(fxt_layout::StringRefHeader::inline(name.len() as u16).bits());
706 header.set_value_ref(fxt_layout::StringRefHeader::inline(value.len() as u16).bits());
707
708 let arg_record_bytes = FxtBuilder::new(header).atom(name).atom(value).build();
709 let raw_arg_record = RawArg {
710 name: StringRef::Inline(name),
711 value: RawArgValue::String(StringRef::Inline(value)),
712 };
713
714 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
715 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
716 }
717
718 #[test]
719 fn pointer_arg_name_index() {
720 let mut header = BaseArgHeader::empty();
721 header.set_name_ref(10);
722 header.set_raw_type(PTR_ARG_TYPE);
723
724 let arg_record_bytes = FxtBuilder::new(header).atom(256u64.to_le_bytes()).build();
725 let raw_arg_record = RawArg {
726 name: StringRef::Index(NonZeroU16::new(10).unwrap()),
727 value: RawArgValue::Pointer(256),
728 };
729
730 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
731 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
732 }
733
734 #[test]
735 fn pointer_arg_name_inline() {
736 let name = "hello";
737 let mut header = BaseArgHeader::empty();
738 header.set_name_ref(fxt_layout::StringRefHeader::inline(name.len() as u16).bits());
739 header.set_raw_type(PTR_ARG_TYPE);
740
741 let arg_record_bytes =
742 FxtBuilder::new(header).atom(name).atom(512u64.to_le_bytes()).build();
743 let raw_arg_record =
744 RawArg { name: StringRef::Inline("hello"), value: RawArgValue::Pointer(512) };
745
746 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
747 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
748 }
749
750 #[test]
751 fn koid_arg_name_index() {
752 let mut header = BaseArgHeader::empty();
753 header.set_name_ref(10);
754 header.set_raw_type(KOBJ_ARG_TYPE);
755
756 let arg_record_bytes = FxtBuilder::new(header).atom(17u64.to_le_bytes()).build();
757 let raw_arg_record = RawArg {
758 name: StringRef::Index(NonZeroU16::new(10).unwrap()),
759 value: RawArgValue::KernelObj(17),
760 };
761
762 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
763 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
764 }
765
766 #[test]
767 fn koid_arg_name_inline() {
768 let name = "hello";
769 let mut header = BaseArgHeader::empty();
770 header.set_name_ref(fxt_layout::StringRefHeader::inline(name.len() as u16).bits());
771 header.set_raw_type(KOBJ_ARG_TYPE);
772
773 let arg_record_bytes = FxtBuilder::new(header).atom(name).atom(21u64.to_le_bytes()).build();
774 let raw_arg_record =
775 RawArg { name: StringRef::Inline("hello"), value: RawArgValue::KernelObj(21) };
776
777 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
778 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
779 }
780
781 #[test]
782 fn bool_arg_name_index() {
783 let mut header = BoolHeader::empty();
784 header.set_name_ref(10);
785 header.set_value(true as u8);
786
787 let arg_record_bytes = FxtBuilder::new(header).build();
788 let raw_arg_record = RawArg {
789 name: StringRef::Index(NonZeroU16::new(10).unwrap()),
790 value: RawArgValue::Boolean(true),
791 };
792
793 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
794 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
795 }
796
797 #[test]
798 fn bool_arg_name_inline() {
799 let name = "hello";
800 let mut header = BoolHeader::empty();
801 header.set_name_ref(fxt_layout::StringRefHeader::inline(name.len() as u16).bits());
802 header.set_value(true as u8);
803
804 let arg_record_bytes = FxtBuilder::new(header).atom(name).build();
805 let raw_arg_record =
806 RawArg { name: StringRef::Inline("hello"), value: RawArgValue::Boolean(true) };
807
808 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
809 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
810 }
811
812 #[test]
813 fn blob_arg_name_index() {
814 let blob = b"the rain in spain falls mainly on the plain";
815 let mut header = BlobHeader::empty();
816 header.set_name_ref(10);
817 header.set_blob_size(blob.len() as u32);
818
819 let arg_record_bytes = FxtBuilder::new(header).atom(blob).build();
820 let raw_arg_record = RawArg {
821 name: StringRef::Index(NonZeroU16::new(10).unwrap()),
822 value: RawArgValue::Blob(blob),
823 };
824
825 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
826 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
827 }
828
829 #[test]
830 fn blob_arg_name_inline() {
831 let name: &str = "hello";
832 let blob = b"the rain in spain falls mainly on the plain";
833 let mut header = BlobHeader::empty();
834 header.set_name_ref(fxt_layout::StringRefHeader::inline(name.len() as u16).bits());
835 header.set_blob_size(blob.len() as u32);
836
837 let arg_record_bytes = FxtBuilder::new(header).atom(name).atom(blob).build();
838 let raw_arg_record =
839 RawArg { name: StringRef::Inline("hello"), value: RawArgValue::Blob(blob) };
840
841 assert_parses_to_arg!(arg_record_bytes, raw_arg_record);
842 assert_eq!(raw_arg_record.serialize().unwrap(), arg_record_bytes);
843 }
844}