1use std::fmt;
12use std::sync::Arc;
13
14use crate::{expr, Expr, ExprKind, Normal, Number};
15
16fn wxf_display(f: &mut fmt::Formatter, expr: &Expr, indent: Option<usize>) -> fmt::Result {
20 use base64::Engine;
21 match wolfram_serialize::to_wxf(expr, None) {
22 Ok(bytes) => {
23 let b64 = base64::engine::general_purpose::STANDARD.encode(&bytes);
24 let e = expr!(::BinaryDeserialize[::ByteArray[(b64)]]);
25 fmt_kind(f, e.kind(), indent)
26 },
27 Err(_) => write!(f, "Failure[\"BinarySerializeError\"]"),
28 }
29}
30
31fn is_compound(kind: &ExprKind) -> bool {
34 matches!(kind, ExprKind::Normal(_) | ExprKind::Association(_))
35}
36
37fn is_nested(kind: &ExprKind) -> bool {
42 match kind {
43 ExprKind::Normal(n) => n.contents.iter().any(|e| is_compound(e.kind())),
44 ExprKind::Association(a) => a.iter().any(|e| is_compound(e.value.kind())),
45 _ => false,
46 }
47}
48
49fn child_indent(indent: Option<usize>, breaks: bool) -> Option<usize> {
53 if breaks {
54 indent.map(|d| d + 1)
55 } else {
56 indent
57 }
58}
59
60fn fmt_seq<F>(
65 f: &mut fmt::Formatter,
66 indent: Option<usize>,
67 open: &str,
68 close: &str,
69 len: usize,
70 brk: bool,
71 mut item: F,
72) -> fmt::Result
73where
74 F: FnMut(&mut fmt::Formatter, usize) -> fmt::Result,
75{
76 let depth = indent.unwrap_or(0);
77 f.write_str(open)?;
78 for i in 0..len {
79 if brk {
80 write!(f, "\n{}", " ".repeat(depth + 1))?;
81 } else if i > 0 {
82 f.write_str(", ")?;
83 }
84 item(f, i)?;
85 if brk && i + 1 < len {
86 f.write_str(",")?;
87 }
88 }
89 if brk {
90 write!(f, "\n{}", " ".repeat(depth))?;
91 }
92 f.write_str(close)
93}
94
95fn fmt_normal(f: &mut fmt::Formatter, n: &Normal, indent: Option<usize>) -> fmt::Result {
101 let ExprKind::Symbol(sym) = n.head.kind() else {
102 return fmt_call(f, n, indent);
103 };
104 match sym.as_str() {
105 "System`List" | "List" => fmt_list(f, n, indent),
106 "System`Rule" | "Rule" => fmt_infix(f, n, indent, "->"),
107 "System`RuleDelayed" | "RuleDelayed" => fmt_infix(f, n, indent, ":>"),
108 "System`Set" | "Set" => fmt_infix(f, n, indent, "="),
109 "System`Slot" | "Slot" => fmt_slot(f, n, indent, "#"),
110 "System`SlotSequence" | "SlotSequence" => fmt_slot(f, n, indent, "##"),
111 _ => fmt_call(f, n, indent),
112 }
113}
114
115fn fmt_delimited(
117 f: &mut fmt::Formatter,
118 n: &Normal,
119 indent: Option<usize>,
120 open: &str,
121 close: &str,
122) -> fmt::Result {
123 let brk = indent.is_some() && n.contents.iter().any(|e| is_nested(e.kind()));
124 let inner = child_indent(indent, brk);
125 fmt_seq(f, indent, open, close, n.contents.len(), brk, |f, i| {
126 fmt_kind(f, n.contents[i].kind(), inner)
127 })
128}
129
130fn fmt_call(f: &mut fmt::Formatter, n: &Normal, indent: Option<usize>) -> fmt::Result {
132 fmt_delimited(f, n, indent, &format!("{}[", n.head), "]")
133}
134
135fn fmt_list(f: &mut fmt::Formatter, n: &Normal, indent: Option<usize>) -> fmt::Result {
137 fmt_delimited(f, n, indent, "{", "}")
138}
139
140fn fmt_infix(
143 f: &mut fmt::Formatter,
144 n: &Normal,
145 indent: Option<usize>,
146 op: &str,
147) -> fmt::Result {
148 if n.contents.len() != 2 {
149 return fmt_call(f, n, indent);
150 }
151 fmt_kind(f, n.contents[0].kind(), indent)?;
152 write!(f, " {op} ")?;
153 fmt_kind(f, n.contents[1].kind(), indent)
154}
155
156fn fmt_slot(
161 f: &mut fmt::Formatter,
162 n: &Normal,
163 indent: Option<usize>,
164 prefix: &str,
165) -> fmt::Result {
166 match n.contents.as_slice() {
167 [arg] => match arg.kind() {
168 ExprKind::String(name) => {
169 f.write_str(prefix)?;
170 f.write_str(name)
171 },
172 kind @ ExprKind::Integer(_) => {
173 f.write_str(prefix)?;
174 fmt_kind(f, kind, indent)
175 },
176 _ => fmt_call(f, n, indent),
177 },
178 _ => fmt_call(f, n, indent),
179 }
180}
181
182fn fmt_kind(f: &mut fmt::Formatter, kind: &ExprKind, indent: Option<usize>) -> fmt::Result {
187 match kind {
188 ExprKind::Normal(n) => fmt_normal(f, n, indent),
189 ExprKind::Association(a) => {
190 let brk = indent.is_some() && a.iter().any(|e| is_nested(e.value.kind()));
191 let inner = child_indent(indent, brk);
192 fmt_seq(f, indent, "<|", "|>", a.len(), brk, |f, i| {
193 let entry = &a[i];
194 let arrow = if entry.delayed { ":>" } else { "->" };
195 write!(f, "{} {arrow} ", entry.key)?;
196 fmt_kind(f, entry.value.kind(), inner)
197 })
198 },
199 ExprKind::Integer(int) => write!(f, "{int}"),
200 ExprKind::Real(real) => write!(f, "{:?}", **real),
203 ExprKind::String(string) => write!(f, "{string:?}"),
206 ExprKind::Symbol(symbol) => write!(f, "{symbol}"),
207 ExprKind::ByteArray(ba) => {
208 use base64::Engine;
209 let b64 = base64::engine::general_purpose::STANDARD.encode(ba.as_slice());
210 fmt_kind(f, expr!(::ByteArray[(b64)]).kind(), indent)
211 },
212 ExprKind::NumericArray(arr) => {
213 let expr = Expr {
214 inner: Arc::new(ExprKind::NumericArray(arr.clone())),
215 };
216 wxf_display(f, &expr, indent)
217 },
218 ExprKind::PackedArray(arr) => {
219 let expr = Expr {
220 inner: Arc::new(ExprKind::PackedArray(arr.clone())),
221 };
222 wxf_display(f, &expr, indent)
223 },
224 ExprKind::BigInteger(n) => write!(f, "{}", n.as_str()),
225 ExprKind::BigReal(r) => write!(f, "{}", r.as_str()),
226 }
227}
228
229impl fmt::Display for Expr {
230 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
231 fmt_kind(f, self.kind(), None)
232 }
233}
234
235impl fmt::Display for ExprKind {
236 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
237 fmt_kind(f, self, None)
238 }
239}
240
241impl fmt::Debug for ExprKind {
242 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243 fmt_kind(f, self, Some(0))
244 }
245}
246
247impl fmt::Display for Normal {
248 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
249 fmt_normal(f, self, None)
250 }
251}
252
253impl fmt::Display for Number {
254 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
255 fmt_kind(f, &ExprKind::from(*self), None)
256 }
257}