1use crate::{util::impl_serde_with_str, IndexMap};
4use serde::{Deserialize, Serialize};
5use std::{
6 fmt::{Debug, Display},
7 str::FromStr,
8};
9use strum::{Display, EnumString};
10
11pub const STD_HASH_MAP: &str = "std::collections::hash::map::HashMap<";
12pub const STD_HASH_SET: &str = "std::collections::hash::set::HashSet<";
13pub const STD_HASH_STATE: &str = ", std::collections::hash::map::RandomState>";
14pub const CORE_REF_CELL: &str = "core::cell::RefCell<";
15pub const STD_MUTEX: &str = "std::sync::mutex::Mutex<";
16pub const STD_RWLOCK: &str = "std::sync::rwlock::RwLock<";
17
18#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
19#[serde(tag = "type")]
20pub enum RValue {
22 Unit,
24 Prim(PValue),
25 Bytes {
26 typename: String,
27 value: Vec<u8>,
28 },
29 Ref {
31 typename: RefType,
32 addr: RefAddr,
33 value: Box<RValue>,
34 },
35 DynRef {
37 typename: String,
38 addr: RefAddr,
39 vtable: RefAddr,
40 value: Box<RValue>,
41 },
42 RefCounted {
44 typename: RefCountedType,
45 addr: RefAddr,
46 strong: u64,
47 weak: u64,
48 value: Box<RValue>,
49 },
50 DynRefCounted {
52 typename: String,
53 addr: RefAddr,
54 strong: u64,
55 weak: u64,
56 vtable: RefAddr,
57 value: Box<RValue>,
58 },
59 UnresolvedRef {
60 addr: RefAddr,
61 },
62 Struct {
63 typename: String,
64 fields: IndexMap<String, RValue>,
65 },
66 Tuple {
67 typename: String,
68 items: Vec<RValue>,
69 },
70 Enum {
71 typename: String,
72 variant: String,
73 },
74 String {
75 typename: StringType,
76 value: String,
77 },
78 Union {
79 typeinfo: UnionType,
80 variant: String,
81 fields: IndexMap<String, RValue>,
82 },
83 Option {
84 typename: String,
85 variant: String,
86 value: Option<Box<RValue>>,
87 },
88 Result {
89 typename: String,
90 variant: String,
91 value: Box<RValue>,
92 },
93 Array {
94 typename: ArrayType,
95 data: Vec<RValue>,
96 },
97 Opaque,
98}
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, EnumString)]
101pub enum RefType {
103 Box,
104 #[strum(serialize = "ref")]
105 Ref,
107 #[strum(serialize = "ptr")]
108 Ptr,
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, EnumString)]
113pub enum RefCountedType {
115 Rc,
116 Arc,
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, EnumString)]
120pub enum StringType {
122 #[strum(serialize = "&str")]
123 StrLit,
125 String,
127}
128
129#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, EnumString)]
130#[strum(serialize_all = "lowercase")]
131pub enum ArrayType {
133 Arr,
135 Vec,
137 Slice,
138}
139
140#[derive(Debug, Copy, Clone, PartialEq, Eq)]
141pub enum RefAddr {
143 Addr(Addr),
144 Redacted,
145}
146
147#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
148pub struct Addr([u8; 8]);
150
151#[rustfmt::skip]
152#[allow(non_camel_case_types)]
153#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
154#[serde(tag = "typename", content = "value")]
155pub enum PValue {
157 bool(bool),
158 char(char),
159 u8(u8),
160 i8(i8),
161 u16(u16),
162 i16(i16),
163 u32(u32),
164 i32(i32),
165 #[serde(serialize_with = "serialize_as_str", deserialize_with = "deserialize_from_str")]
166 u64(u64),
167 #[serde(serialize_with = "serialize_as_str", deserialize_with = "deserialize_from_str")]
168 i64(i64),
169 #[serde(serialize_with = "serialize_as_str", deserialize_with = "deserialize_from_str")]
170 usize(u64),
172 #[serde(serialize_with = "serialize_as_str", deserialize_with = "deserialize_from_str")]
173 isize(i64),
174 #[serde(serialize_with = "serialize_as_str", deserialize_with = "deserialize_from_str")]
175 u128(u128),
176 #[serde(serialize_with = "serialize_as_str", deserialize_with = "deserialize_from_str")]
177 i128(i128),
178 f32(f32),
179 f64(f64),
180}
181
182#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
183pub struct UnionType {
188 pub name: String,
189 pub variants: Vec<String>,
190}
191
192impl RValue {
193 pub fn redact_addr(&mut self) {
194 match self {
195 Self::Unit => (),
196 Self::Prim(_) => (),
197 Self::Bytes { .. } => (),
198 Self::Ref { addr, value, .. } => {
199 *addr = RefAddr::Redacted;
200 value.redact_addr();
201 }
202 Self::DynRef {
203 addr,
204 vtable,
205 value,
206 ..
207 } => {
208 *addr = RefAddr::Redacted;
209 *vtable = RefAddr::Redacted;
210 value.redact_addr();
211 }
212 Self::RefCounted { addr, value, .. } => {
213 *addr = RefAddr::Redacted;
214 value.redact_addr();
215 }
216 Self::DynRefCounted {
217 addr,
218 vtable,
219 value,
220 ..
221 } => {
222 *addr = RefAddr::Redacted;
223 *vtable = RefAddr::Redacted;
224 value.redact_addr();
225 }
226 Self::UnresolvedRef { addr } => {
227 *addr = RefAddr::Redacted;
228 }
229 Self::Struct { fields, .. } => {
230 for value in fields.values_mut() {
231 value.redact_addr();
232 }
233 }
234 Self::Tuple { items, .. } => {
235 for value in items.iter_mut() {
236 value.redact_addr();
237 }
238 }
239 Self::Enum { .. } => (),
240 Self::String { .. } => (),
241 Self::Union { fields, .. } => {
242 for value in fields.values_mut() {
243 value.redact_addr();
244 }
245 }
246 Self::Option { value, .. } => {
247 if let Some(value) = value {
248 value.redact_addr();
249 }
250 }
251 Self::Result { value, .. } => {
252 value.redact_addr();
253 }
254 Self::Array { data, .. } => {
255 for value in data.iter_mut() {
256 value.redact_addr();
257 }
258 }
259 Self::Opaque => (),
260 }
261 }
262
263 pub fn prim(&self) -> Option<PValue> {
264 if let Self::Prim(value) = self {
265 Some(*value)
266 } else {
267 None
268 }
269 }
270
271 pub fn struct_field(&self, field: &str) -> Option<&RValue> {
272 if let Self::Struct { fields, .. } = self {
273 fields.get(field)
274 } else {
275 None
276 }
277 }
278}
279
280impl Display for RValue {
281 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
285 let pretty = f.alternate();
286 let width = f.width().unwrap_or_default();
287 match self {
288 Self::Unit => write!(f, "()")?,
289 Self::Prim(v) => {
290 if pretty {
291 write!(f, "{:#}", v)?
292 } else {
293 write!(f, "{}", v)?
294 }
295 }
296 Self::Bytes { typename, value } => {
297 if typename.starts_with('&') {
298 write!(f, "&")?;
299 }
300 write!(f, "[")?;
301 for (i, b) in value.iter().enumerate() {
302 write!(
303 f,
304 "0x{b:02x}{}",
305 if i < value.len() - 1 { ", " } else { "" }
306 )?;
307 }
308 write!(f, "]")?;
309 }
310 Self::Ref {
311 typename, value, ..
312 } => {
313 let b = match *typename {
314 RefType::Ref => {
315 write!(f, "&")?;
316 ""
317 }
318 RefType::Ptr => {
319 write!(f, "*")?;
320 ""
321 }
322 RefType::Box => {
323 write!(f, "alloc::boxed::Box::new(")?;
324 ")"
325 }
326 };
327 if pretty {
328 write!(f, "{value:#width$}", width = width)?;
329 } else {
330 write!(f, "{value}")?;
331 }
332 write!(f, "{}", b)?;
333 }
334 Self::DynRef {
335 typename, value, ..
336 } => {
337 if typename.starts_with("&dyn ") {
338 write!(f, "{} ", typename)?;
339 } else {
340 write!(
341 f,
342 "{}::new(",
343 typename.replacen("alloc::boxed::Box<", "alloc::boxed::Box::<", 1)
344 )?;
345 }
346 if pretty {
347 write!(f, "{value:#width$}", width = width)?;
348 } else {
349 write!(f, "{value}")?;
350 }
351 if typename.starts_with("&dyn ") {
352 } else {
354 write!(f, ")")?;
355 }
356 }
357 Self::RefCounted {
358 typename, value, ..
359 } => {
360 write!(
361 f,
362 "{}::new(",
363 match typename {
364 RefCountedType::Rc => "alloc::rc::Rc",
365 RefCountedType::Arc => "alloc::sync::Arc",
366 }
367 )?;
368 if pretty {
369 write!(f, "{value:#width$}", width = width)?;
370 } else {
371 write!(f, "{value}")?;
372 }
373 write!(f, ")")?;
374 }
375 Self::DynRefCounted {
376 typename, value, ..
377 } => {
378 write!(
379 f,
380 "{}::new(",
381 typename
382 .replacen("alloc::rc::Rc<", "alloc::rc::Rc::<", 1)
383 .replacen("alloc::sync::Arc<", "alloc::sync::Arc::<", 1)
384 )?;
385 if pretty {
386 write!(f, "{value:#width$}", width = width)?;
387 } else {
388 write!(f, "{value}")?;
389 }
390 write!(f, ")")?;
391 }
392 Self::UnresolvedRef { .. } => {
393 write!(f, "&()")?;
394 }
395 Self::Struct { typename, fields } => {
396 if fields.is_empty() {
397 return write!(f, "{} {{ }}", typename);
398 }
399 let is_tuple = fields.keys().next().map(|s| s.as_str()).unwrap_or_default() == "0";
400 if is_tuple {
401 write!(f, "{}(", typename)?;
402 for (i, (_, value)) in fields.iter().enumerate() {
403 write!(
404 f,
405 "{}{}",
406 value,
407 if i < fields.len() - 1 { ", " } else { "" }
408 )?;
409 }
410 return write!(f, ")");
411 }
412 if (typename.starts_with(STD_HASH_MAP) || typename.starts_with(STD_HASH_SET))
413 && typename.ends_with(STD_HASH_STATE)
414 && (fields.contains_key("items") && fields.contains_key("len"))
415 {
416 print_hashmap(f, typename, fields, width, pretty)?;
417 } else {
418 write!(f, "{}", typename)?;
419 print_struct(f, typename, fields, width, pretty)?;
420 }
421 }
422 Self::Tuple { items, .. } => {
423 write!(f, "(")?;
424 for (i, item) in items.iter().enumerate() {
425 write!(f, "{}{}", item, if i < items.len() - 1 { ", " } else { "" })?;
426 }
427 write!(f, ")")?;
428 }
429 Self::Enum { typename, variant } => write!(f, "{}::{}", typename, variant)?,
430 Self::String { typename, value } => {
431 if typename == &StringType::StrLit {
432 write!(f, "{:?}", value)?;
433 } else {
434 write!(f, "String::from({:?})", value)?;
435 }
436 }
437 Self::Union {
438 typeinfo,
439 variant,
440 fields,
441 } => {
442 let typename = typeinfo.name.replacen('<', "::<", 1);
443 write!(f, "{}::{}", typename, variant)?;
444 if !fields.is_empty() {
445 let is_tuple = fields.keys().next().unwrap() == "0";
446 if is_tuple {
447 write!(f, "(")?;
448 for (i, (_, value)) in fields.iter().enumerate() {
449 write!(
450 f,
451 "{}{}",
452 value,
453 if i < fields.len() - 1 { ", " } else { "" }
454 )?;
455 }
456 write!(f, ")")?;
457 } else if fields.is_empty() {
458 write!(f, " {{ }}")?;
459 } else {
460 print_struct(f, &typename, fields, width, pretty)?;
461 }
462 }
463 }
464 Self::Option {
465 typename,
466 variant,
467 value,
468 } => {
469 write!(
470 f,
471 "{}::{}",
472 typename.replacen("core::option::Option<", "core::option::Option::<", 1),
473 variant,
474 )?;
475 if let Some(value) = value {
476 write!(f, "(")?;
477 if pretty {
478 write!(f, "{value:#width$}", width = width)?;
479 } else {
480 write!(f, "{value}")?;
481 }
482 write!(f, ")")?;
483 }
484 }
485 Self::Result {
486 typename,
487 variant,
488 value,
489 } => {
490 write!(
491 f,
492 "{}::{}(",
493 typename.replacen("core::result::Result<", "core::result::Result::<", 1),
494 variant
495 )?;
496 if pretty {
497 write!(f, "{value:#width$}", width = width)?;
498 } else {
499 write!(f, "{value}")?;
500 }
501 write!(f, ")")?;
502 }
503 Self::Array { typename, data } => {
504 match *typename {
505 ArrayType::Arr => (),
506 ArrayType::Vec => write!(f, "vec!")?,
507 ArrayType::Slice => write!(f, "&")?,
508 }
509 print_arr_items(f, data, width, pretty)?;
510 }
511 Self::Opaque => write!(f, "(?)")?,
512 }
513 Ok(())
514 }
515}
516
517pub struct ArgumentList<'a>(pub &'a [(String, RValue)]);
519
520impl<'a> Display for ArgumentList<'a> {
521 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
522 let pretty = f.alternate();
523 for (name, value) in self.0.iter() {
524 write!(f, "{name}: ")?;
525 if pretty {
526 write!(f, "{value:#}")?;
527 } else {
528 write!(f, "{value}")?;
529 }
530 }
531 Ok(())
532 }
533}
534
535fn print_struct(
536 f: &mut std::fmt::Formatter<'_>,
537 typename: &str,
538 fields: &IndexMap<String, RValue>,
539 width: usize,
540 pretty: bool,
541) -> std::fmt::Result {
542 if (typename.starts_with(CORE_REF_CELL) && fields.contains_key("value"))
543 || (typename.starts_with(STD_MUTEX) && fields.contains_key("data"))
544 || (typename.starts_with(STD_RWLOCK) && fields.contains_key("data"))
545 {
546 let mut value = fields
547 .get(if typename.starts_with(CORE_REF_CELL) {
548 "value"
549 } else {
550 "data"
551 })
552 .unwrap();
553 match value {
554 RValue::Struct { fields, .. } => {
555 if let Some(v) = fields.get("value") {
556 value = v;
557 }
558 }
559 _ => (),
560 }
561 write!(f, "::new(")?;
562 if pretty {
563 write!(f, "{}", value)?;
564 } else {
565 write!(f, "{:#width$}", value, width = width)?;
566 }
567 write!(f, ")")?;
568 return Ok(());
569 }
570
571 let nl = if pretty { '\n' } else { ' ' };
572 let indent = if pretty {
573 String::from_utf8(vec![b' '; (width + 1) * 4]).unwrap()
574 } else {
575 String::new()
576 };
577 write!(f, " {{{}", nl)?;
578 for (i, (attr, value)) in fields.iter().enumerate() {
579 if pretty {
580 write!(
581 f,
582 "{}{}: {:#width$}{}{}",
583 indent,
584 attr,
585 value,
586 ",",
587 nl,
588 width = (width + 1)
589 )?;
590 } else {
591 write!(
592 f,
593 "{}: {}{}",
594 attr,
595 value,
596 if i < fields.len() - 1 { ", " } else { " " }
597 )?;
598 }
599 }
600 if pretty {
601 write!(f, "{}", String::from_utf8(vec![b' '; width * 4]).unwrap())?;
602 }
603 write!(f, "}}")?;
604 Ok(())
605}
606
607fn print_hashmap(
608 f: &mut std::fmt::Formatter<'_>,
609 typename: &str,
610 fields: &IndexMap<String, RValue>,
611 width: usize,
612 pretty: bool,
613) -> std::fmt::Result {
614 let items = match fields.get("items").unwrap() {
615 RValue::Array { data, .. } => data,
616 _ => {
617 write!(f, "{}", typename)?;
618 return print_struct(f, typename, fields, width, pretty);
619 }
620 };
621
622 let nl = if pretty { "\n" } else { "" };
623 let indent = if pretty {
624 String::from_utf8(vec![b' '; width * 4]).unwrap()
625 } else {
626 String::new()
627 };
628 write!(f, "{}[{}", indent, nl)?;
629 for (i, value) in items.iter().enumerate() {
630 if pretty {
631 write!(
632 f,
633 " {}{:#width$}{}{}",
634 indent,
635 value,
636 ",",
637 nl,
638 width = (width + 1)
639 )?;
640 } else {
641 write!(
642 f,
643 "{}{}",
644 value,
645 if i < items.len() - 1 { ", " } else { "" }
646 )?;
647 }
648 }
649 write!(f, "{}]{}", indent, nl)?;
650 write!(f, ".into_iter(){}", nl)?;
651 write!(f, ".collect::<{}>()", typename.replace(STD_HASH_STATE, ">"))?;
652 Ok(())
653}
654
655fn print_arr_items(
656 f: &mut std::fmt::Formatter<'_>,
657 data: &[RValue],
658 width: usize,
659 pretty: bool,
660) -> std::fmt::Result {
661 write!(f, "[")?;
662 if data.is_empty() {
663 write!(f, "]")?;
664 return Ok(());
665 }
666 let indent = if pretty {
667 write!(f, "\n")?;
668 String::from_utf8(vec![b' '; (width + 1) * 4]).unwrap()
669 } else {
670 String::new()
671 };
672 for (i, item) in data.iter().enumerate() {
673 if pretty {
674 write!(f, "{}{:#width$},\n", indent, item, width = (width + 1))?;
675 } else {
676 write!(f, "{}{}", item, if i < data.len() - 1 { ", " } else { "" })?;
677 }
678 }
679 if pretty {
680 write!(f, "{}", String::from_utf8(vec![b' '; width * 4]).unwrap())?;
681 }
682 write!(f, "]")?;
683 Ok(())
684}
685
686impl RValue {
687 pub fn typename(&self) -> String {
688 match self {
689 Self::Unit => "()".to_owned(),
690 Self::Prim(v) => v.typename().to_owned(),
691 Self::Bytes { typename, .. } => typename.to_owned(),
692 Self::Ref {
693 typename, value, ..
694 } => match *typename {
695 RefType::Ref => {
696 format!("&{}", value.typename())
697 }
698 RefType::Ptr => {
699 format!("*{}", value.typename())
700 }
701 ty => {
702 format!("{}<{}>", ty, value.typename())
703 }
704 },
705 Self::DynRef { typename, .. } => typename.to_owned(),
706 Self::RefCounted {
707 typename, value, ..
708 } => {
709 format!("{}<{}>", typename, value.typename())
710 }
711 Self::DynRefCounted { typename, .. } => typename.to_owned(),
712 Self::UnresolvedRef { .. } => "&()".to_owned(),
713 Self::Struct { typename, .. } => typename.to_owned(),
714 Self::Tuple { typename, .. } => typename.to_owned(),
715 Self::Enum { typename, .. } => typename.to_owned(),
716 Self::String { typename, .. } => typename.to_string(),
717 Self::Union { typeinfo, .. } => typeinfo.name.to_owned(),
718 Self::Option { typename, .. } => typename.to_owned(),
719 Self::Result { typename, .. } => typename.to_owned(),
720 Self::Array { typename, data } => {
721 let vtype = if data.is_empty() {
722 "(?)".to_owned()
723 } else {
724 data[0].typename()
725 };
726 match *typename {
727 ArrayType::Arr => format!("[{}]", vtype),
728 ArrayType::Vec => format!("Vec<{}>", vtype),
729 ArrayType::Slice => format!("&[{}]", vtype),
730 }
731 }
732 Self::Opaque => "(?)".to_owned(),
733 }
734 }
735
736 pub fn is_struct(&self) -> bool {
737 matches!(self, Self::Struct { .. })
738 }
739
740 pub fn is_result(&self) -> bool {
741 matches!(self, Self::Result { .. })
742 }
743
744 pub fn result_variant(&self) -> Result<(), ()> {
747 match self {
748 Self::Result { variant, .. } => match variant.as_str() {
749 "Ok" => Ok(()),
750 "Err" => Err(()),
751 e => panic!("Unexpected variant {e}"),
752 },
753 _ => panic!("Not Result"),
754 }
755 }
756}
757
758impl Display for PValue {
759 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
760 let s = if f.alternate() { "_" } else { "" };
761 match self {
762 Self::bool(v) => write!(f, "{v:?}"),
763 Self::char(v) => write!(f, "'{v}'"),
764 Self::u8(v) => write!(f, "{v}{s}u8"),
765 Self::i8(v) => write!(f, "{v}{s}i8"),
766 Self::u16(v) => write!(f, "{v}{s}u16"),
767 Self::i16(v) => write!(f, "{v}{s}i16"),
768 Self::u32(v) => write!(f, "{v}{s}u32"),
769 Self::i32(v) => write!(f, "{v}{s}i32"),
770 Self::u64(v) => write!(f, "{v}{s}u64"),
771 Self::i64(v) => write!(f, "{v}{s}i64"),
772 Self::usize(v) => write!(f, "{v}{s}usize"),
773 Self::isize(v) => write!(f, "{v}{s}isize"),
774 Self::u128(v) => write!(f, "{v}{s}u128"),
775 Self::i128(v) => write!(f, "{v}{s}i128"),
776 Self::f32(v) => write!(f, "{v}{s}f32"),
777 Self::f64(v) => write!(f, "{v}{s}f64"),
778 }
779 }
780}
781
782impl PValue {
783 pub fn typename(&self) -> &'static str {
784 match self {
785 Self::bool(..) => "bool",
786 Self::char(..) => "char",
787 Self::u8(..) => "u8",
788 Self::i8(..) => "i8",
789 Self::u16(..) => "u16",
790 Self::i16(..) => "i16",
791 Self::u32(..) => "u32",
792 Self::i32(..) => "i32",
793 Self::u64(..) => "u64",
794 Self::i64(..) => "i64",
795 Self::usize(..) => "usize",
796 Self::isize(..) => "isize",
797 Self::u128(..) => "u128",
798 Self::i128(..) => "i128",
799 Self::f32(..) => "f32",
800 Self::f64(..) => "f64",
801 }
802 }
803}
804
805impl Addr {
806 pub fn new(b: &[u8]) -> Self {
807 match b.len() {
808 4 => Self([0, 0, 0, 0, b[0], b[1], b[2], b[3]]),
809 8 => Self([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]),
810 _ => panic!("Not an address: {b:?}"),
811 }
812 }
813
814 pub fn to_bytes(&self) -> Vec<u8> {
815 self.0.to_vec()
816 }
817}
818
819impl From<u64> for Addr {
820 fn from(v: u64) -> Self {
821 Self::new(&v.to_ne_bytes())
822 }
823}
824
825impl Debug for Addr {
826 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
827 <Self as Display>::fmt(self, f)
828 }
829}
830
831impl Display for Addr {
832 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
833 write!(f, "0x")?;
834 for b in self.0.iter().rev() {
836 write!(f, "{:02x}", b)?;
837 }
838 Ok(())
839 }
840}
841
842impl FromStr for Addr {
843 type Err = &'static str;
844
845 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
846 let mut addr = [0u8; 8];
847 let bytes = s.as_bytes();
848 if bytes.len() != 18 {
849 return Err("Not 8 bytes?");
850 }
851 let mut i = 2;
852 while i < 18 {
853 let str = std::str::from_utf8(&bytes[i..i + 2]).unwrap();
854 let b = u8::from_str_radix(str, 16).map_err(|_| "Invalid byte")?;
855 addr[7 - (i - 2) / 2] = b;
856 i += 2;
857 }
858 Ok(Addr(addr))
859 }
860}
861
862impl Display for RefAddr {
863 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
864 match self {
865 Self::Redacted => write!(f, "<redacted>"),
866 Self::Addr(addr) => write!(f, "{addr}"),
867 }
868 }
869}
870
871impl FromStr for RefAddr {
872 type Err = &'static str;
873
874 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
875 if s == "<redacted>" {
876 Ok(Self::Redacted)
877 } else {
878 Ok(Self::Addr(s.parse()?))
879 }
880 }
881}
882
883impl_serde_with_str!(RefAddr);
884impl_serde_with_str!(RefType);
885impl_serde_with_str!(RefCountedType);
886impl_serde_with_str!(StringType);
887impl_serde_with_str!(ArrayType);
888
889fn serialize_as_str<S, T>(v: &T, serializer: S) -> Result<S::Ok, S::Error>
890where
891 S: serde::Serializer,
892 T: std::fmt::Display,
893{
894 serializer.serialize_str(&v.to_string())
895}
896
897fn deserialize_from_str<'de, D, T>(deserializer: D) -> Result<T, D::Error>
898where
899 D: serde::Deserializer<'de>,
900 T: FromStr,
901 <T as FromStr>::Err: Display,
902{
903 let s = <&str>::deserialize(deserializer)?;
904 s.parse().map_err(serde::de::Error::custom)
905}
906
907#[cfg(test)]
908mod test {
909 use super::*;
910
911 #[test]
912 fn test_serde_addr() {
913 let addr = Addr([0x12, 0x34, 0x56, 0x78, 0xab, 0xcd, 0xef, 0x00]);
914 let ref_addr = RefAddr::Addr(addr);
915 assert_eq!(addr.to_string().as_str(), "0x00efcdab78563412");
916 assert_eq!(ref_addr.to_string().as_str(), "0x00efcdab78563412");
917 assert_eq!(addr, "0x00efcdab78563412".parse().unwrap());
918 assert_eq!(ref_addr, "0x00efcdab78563412".parse().unwrap());
919 assert_eq!(RefAddr::Redacted, "<redacted>".parse().unwrap());
920 }
921}