defmt_parser/
display_hint.rs1use std::str::FromStr;
2
3#[derive(Clone, Debug, Eq, PartialEq)]
5pub enum DisplayHint {
6 NoHint {
7 zero_pad: usize,
8 },
9 Hexadecimal {
11 alternate: bool,
12 uppercase: bool,
13 zero_pad: usize,
14 },
15 Octal {
17 alternate: bool,
18 zero_pad: usize,
19 },
20 Binary {
22 alternate: bool,
23 zero_pad: usize,
24 },
25 Ascii,
27 Debug,
29 Seconds(TimePrecision),
31 Time(TimePrecision),
33 ISO8601(TimePrecision),
35 Bitflags {
38 name: String,
39 package: String,
40 disambiguator: String,
41 crate_name: Option<String>,
42 },
43 Unknown(String),
45}
46
47impl DisplayHint {
48 pub(crate) fn parse(mut s: &str) -> Option<Self> {
50 const BITFLAGS_HINT_START: &str = "__internal_bitflags_";
51
52 let alternate = if let Some(rest) = s.strip_prefix('#') {
55 s = rest;
56 true
57 } else {
58 false
59 };
60
61 let zero_pad = if let Some(rest) = s.strip_prefix('0') {
62 let (rest, columns) = parse_integer::<usize>(rest)?;
63 s = rest;
64 columns
65 } else {
66 0 };
68
69 if let Some(stripped) = s.strip_prefix(BITFLAGS_HINT_START) {
70 let parts = stripped.split('@').collect::<Vec<_>>();
71 if parts.len() < 3 || parts.len() > 4 {
72 return Some(DisplayHint::Unknown(s.into()));
73 }
74 return Some(DisplayHint::Bitflags {
75 name: parts[0].into(),
76 package: parts[1].into(),
77 disambiguator: parts[2].into(),
78 crate_name: parts.get(3).map(|&s| s.to_string()),
80 });
81 }
82
83 Some(match s {
84 "" => DisplayHint::NoHint { zero_pad },
85 "us" => DisplayHint::Seconds(TimePrecision::Micros),
86 "ms" => DisplayHint::Seconds(TimePrecision::Millis),
87 "tus" => DisplayHint::Time(TimePrecision::Micros),
88 "tms" => DisplayHint::Time(TimePrecision::Millis),
89 "ts" => DisplayHint::Time(TimePrecision::Seconds),
90 "a" => DisplayHint::Ascii,
91 "b" => DisplayHint::Binary {
92 alternate,
93 zero_pad,
94 },
95 "o" => DisplayHint::Octal {
96 alternate,
97 zero_pad,
98 },
99 "x" => DisplayHint::Hexadecimal {
100 alternate,
101 uppercase: false,
102 zero_pad,
103 },
104 "X" => DisplayHint::Hexadecimal {
105 alternate,
106 uppercase: true,
107 zero_pad,
108 },
109 "iso8601ms" => DisplayHint::ISO8601(TimePrecision::Millis),
110 "iso8601s" => DisplayHint::ISO8601(TimePrecision::Seconds),
111 "?" => DisplayHint::Debug,
112 _ => return None,
113 })
114 }
115}
116
117#[derive(Clone, Debug, Eq, PartialEq)]
119pub enum TimePrecision {
120 Micros,
121 Millis,
122 Seconds,
123}
124
125fn parse_integer<T: FromStr>(s: &str) -> Option<(&str, T)> {
130 let start_digits = s
131 .as_bytes()
132 .iter()
133 .copied()
134 .take_while(|b| b.is_ascii_digit())
135 .count();
136 let num = s[..start_digits].parse().ok()?;
137 Some((&s[start_digits..], num))
138}