1use std::fmt;
8
9use crate::{SimpleValue, Value};
10
11impl fmt::Display for Value {
12 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13 fmt::Debug::fmt(self, f)
14 }
15}
16
17impl fmt::Debug for Value {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 match self {
20 Self::SimpleValue(sv) => match *sv {
21 SimpleValue::FALSE => f.write_str("false"),
22 SimpleValue::TRUE => f.write_str("true"),
23 SimpleValue::NULL => f.write_str("null"),
24 other => write!(f, "simple({})", other.0),
25 },
26
27 Self::Unsigned(n) => write!(f, "{n}"),
28
29 Self::Negative(n) => write!(f, "{actual}", actual = -i128::from(*n) - 1),
30
31 Self::Float(float) => {
32 let value = float.to_f64();
33 if value.is_nan() {
34 use crate::float::Inner;
35 match float.0 {
36 Inner::F16(0x7e00) => f.write_str("NaN"), Inner::F16(bits) => write!(f, "float'{bits:04x}'"),
38 Inner::F32(bits) => write!(f, "float'{bits:08x}'"),
39 Inner::F64(bits) => write!(f, "float'{bits:016x}'"),
40 }
41 } else if value.is_infinite() {
42 if value.is_sign_positive() {
43 f.write_str("Infinity")
44 } else {
45 f.write_str("-Infinity")
46 }
47 } else {
48 format_ecmascript_float(f, value)
49 }
50 }
51
52 Self::ByteString(bytes) => {
53 f.write_str("h'")?;
54 for b in bytes {
55 write!(f, "{b:02x}")?;
56 }
57 f.write_str("'")
58 }
59
60 Self::TextString(s) => {
61 f.write_str("\"")?;
62 for c in s.chars() {
63 match c {
64 '"' => f.write_str("\\\"")?,
65 '\\' => f.write_str("\\\\")?,
66 '\u{08}' => f.write_str("\\b")?,
67 '\u{0C}' => f.write_str("\\f")?,
68 '\n' => f.write_str("\\n")?,
69 '\r' => f.write_str("\\r")?,
70 '\t' => f.write_str("\\t")?,
71 c if c.is_control() => write!(f, "\\u{:04x}", c as u32)?,
72 c => write!(f, "{c}")?,
73 }
74 }
75 f.write_str("\"")
76 }
77
78 Self::Array(items) => {
79 let mut list = f.debug_list();
80 for item in items {
81 list.entry(item);
82 }
83 list.finish()
84 }
85
86 Self::Map(map) => {
87 let mut m = f.debug_map();
88 for (key, value) in map {
89 m.entry(key, value);
90 }
91 m.finish()
92 }
93
94 Self::Tag(tag, content) => {
95 if self.data_type().is_integer() {
97 if let Ok(n) = self.to_u128() {
98 return write!(f, "{n}");
99 }
100 if let Ok(n) = self.to_i128() {
101 return write!(f, "{n}");
102 }
103 }
104
105 if f.alternate() {
106 write!(f, "{tag}({content:#?})")
107 } else {
108 write!(f, "{tag}({content:?})")
109 }
110 }
111 }
112 }
113}
114
115fn format_ecmascript_float(f: &mut fmt::Formatter<'_>, value: f64) -> fmt::Result {
119 if value == 0.0 {
120 return f.write_str(if value.is_sign_negative() { "-0.0" } else { "0.0" });
121 }
122
123 let sign = if value.is_sign_negative() { "-" } else { "" };
124 let scientific = format!("{:e}", value.abs());
125 let (mantissa, exponent) = scientific.split_once('e').unwrap();
126 let rust_exp: i32 = exponent.parse().unwrap();
127 let digits: String = mantissa.chars().filter(|c| *c != '.').collect();
128 let k = digits.len() as i32;
129 let e = rust_exp + 1;
130
131 f.write_str(sign)?;
132
133 if 0 < e && e <= 21 {
134 if e >= k {
135 f.write_str(&digits)?;
136 for _ in 0..(e - k) {
137 f.write_str("0")?;
138 }
139 f.write_str(".0")
140 } else {
141 let (int_part, frac_part) = digits.split_at(e as usize);
142 write!(f, "{int_part}.{frac_part}")
143 }
144 } else if -6 < e && e <= 0 {
145 f.write_str("0.")?;
146 for _ in 0..(-e) {
147 f.write_str("0")?;
148 }
149 f.write_str(&digits)
150 } else {
151 let exp_val = e - 1;
152 let (first, rest) = digits.split_at(1);
153 if rest.is_empty() {
154 write!(f, "{first}.0")?;
155 } else {
156 write!(f, "{first}.{rest}")?;
157 }
158 if exp_val >= 0 {
159 write!(f, "e+{exp_val}")
160 } else {
161 write!(f, "e{exp_val}")
162 }
163 }
164}