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