firedbg_protocol/
value.rs

1//! The representation of Rust Value along with serde and pretty-print facilities
2
3use 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")]
20/// A representation of Rust Value
21pub enum RValue {
22    /// Aka `()`
23    Unit,
24    Prim(PValue),
25    Bytes {
26        typename: String,
27        value: Vec<u8>,
28    },
29    /// This includes a simple `&v`, as well as `Box` and `*const`
30    Ref {
31        typename: RefType,
32        addr: RefAddr,
33        value: Box<RValue>,
34    },
35    /// &dyn or Box<dyn>
36    DynRef {
37        typename: String,
38        addr: RefAddr,
39        vtable: RefAddr,
40        value: Box<RValue>,
41    },
42    /// Rc or Arc
43    RefCounted {
44        typename: RefCountedType,
45        addr: RefAddr,
46        strong: u64,
47        weak: u64,
48        value: Box<RValue>,
49    },
50    /// Rc<dyn> or Arc<dyn>
51    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)]
101/// Reference Type
102pub enum RefType {
103    Box,
104    #[strum(serialize = "ref")]
105    /// Reference
106    Ref,
107    #[strum(serialize = "ptr")]
108    /// Pointer
109    Ptr,
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, EnumString)]
113/// Reference-counted Smart Pointers
114pub enum RefCountedType {
115    Rc,
116    Arc,
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, EnumString)]
120/// Type of String
121pub enum StringType {
122    #[strum(serialize = "&str")]
123    /// String Literal
124    StrLit,
125    /// Owned String
126    String,
127}
128
129#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, EnumString)]
130#[strum(serialize_all = "lowercase")]
131/// Type of Array
132pub enum ArrayType {
133    /// Array
134    Arr,
135    /// Vector
136    Vec,
137    Slice,
138}
139
140#[derive(Debug, Copy, Clone, PartialEq, Eq)]
141/// Reference Address
142pub enum RefAddr {
143    Addr(Addr),
144    Redacted,
145}
146
147#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
148/// Memory Address. Assumed to be 8 bytes.
149pub 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")]
155/// Primitive Value
156pub 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    /// Most code assumes memory address to be 64 bits
171    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)]
183/// Aka Rust's complex enums, e.g. `Result`, `Option`.
184///
185/// The surface syntax of C-style and complex enums may look similar, but the underlying implementation is very different.
186/// If you "tweak" a enum from `enum { A }` to `enum { A(u8) }`, everything changes.
187pub 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    /// Pretty print `RValue` in a Rust-like syntax. Using `{:#}` would expand to multiple lines.
282    ///
283    /// Similar to `std::fmt::Debug`, but the goal is to make the format string almost-compile.
284    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                    // no bracket
353                } 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
517/// A wrapper type only for implementing `Display`.
518pub 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    /// # Panics
745    /// Panic if self is not of `Result` variant, or variant is not "Ok" or "Err".
746    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        // to_ne_bytes (endianness)
835        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}