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