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