1use std::convert::TryFrom;
9
10use wolfram_serialize::Error;
11use wolfram_serialize::{
12 ExpressionEnum, FromWXF, NumericArrayEnum, PackedArrayEnum, Reader, ToWXF, Writer,
13 WxfReader, WxfStruct, WxfWriter,
14};
15
16use crate::{
17 ArrayBuf, Association, BigInteger, BigReal, Expr, ExprKind, NumericArray,
18 PackedArray, RuleEntry, Symbol,
19};
20
21impl ToWXF for Symbol {
26 fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
27 w.write_symbol(self.as_str())
28 }
29}
30
31impl ToWXF for NumericArray {
32 fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
33 w.write_numeric_array(
34 ArrayBuf::data_type(self),
35 ArrayBuf::dimensions(self),
36 ArrayBuf::as_bytes(self),
37 )
38 }
39}
40
41impl ToWXF for PackedArray {
42 fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
43 w.write_packed_array(
44 ArrayBuf::data_type(self),
45 ArrayBuf::dimensions(self),
46 ArrayBuf::as_bytes(self),
47 )
48 }
49}
50
51fn write_assoc<W: Writer>(a: &Association, w: &mut WxfWriter<W>) -> Result<(), Error> {
57 w.write_association(a.len())?;
58 for e in a.iter() {
59 w.write_rule(e.delayed)?;
60 e.key.to_wxf(w)?;
61 e.value.to_wxf(w)?;
62 }
63 Ok(())
64}
65
66impl ToWXF for BigInteger {
67 fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
68 w.write_big_integer(self.as_str())
69 }
70}
71
72impl ToWXF for BigReal {
73 fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
74 w.write_big_real(self.as_str())
75 }
76}
77
78impl ToWXF for Expr {
79 fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
80 match self.kind() {
81 ExprKind::Integer(n) => w.write_integer(*n),
82 ExprKind::Real(r) => w.write_real(**r),
83 ExprKind::String(t) => w.write_string(t.as_str()),
84 ExprKind::Symbol(sym) => w.write_symbol(sym.as_str()),
85 ExprKind::Normal(normal) => {
86 w.write_function(normal.elements().len())?;
87 normal.head().to_wxf(w)?;
88 for arg in normal.elements() {
89 arg.to_wxf(w)?;
90 }
91 Ok(())
92 },
93 ExprKind::ByteArray(b) => w.write_byte_array(b.as_slice()),
94 ExprKind::Association(a) => write_assoc(a, w),
95 ExprKind::NumericArray(arr) => w.write_numeric_array(
96 ArrayBuf::data_type(arr),
97 ArrayBuf::dimensions(arr),
98 ArrayBuf::as_bytes(arr),
99 ),
100 ExprKind::PackedArray(arr) => w.write_packed_array(
101 ArrayBuf::data_type(arr),
102 ArrayBuf::dimensions(arr),
103 ArrayBuf::as_bytes(arr),
104 ),
105 ExprKind::BigInteger(n) => w.write_big_integer(n.as_str()),
106 ExprKind::BigReal(r) => w.write_big_real(r.as_str()),
107 }
108 }
109}
110
111impl WxfStruct for Expr {}
122
123fn symbol_from_name(name: String) -> Symbol {
131 unsafe { Symbol::unchecked_new(name) }
134}
135
136fn numeric_array_from_parts(
137 dt: NumericArrayEnum,
138 dims: Vec<usize>,
139 bytes: Vec<u8>,
140) -> NumericArray {
141 NumericArray::new(dt, dims, bytes)
142}
143
144fn packed_array_from_parts(
145 dt: NumericArrayEnum,
146 dims: Vec<usize>,
147 bytes: Vec<u8>,
148) -> Result<PackedArray, Error> {
149 let pdt = PackedArrayEnum::try_from(dt).map_err(|_| {
150 Error::invalid(format!(
151 "PackedArray does not support element type {}",
152 dt.name()
153 ))
154 })?;
155 Ok(PackedArray::new(pdt, dims, bytes))
156}
157
158impl<'de> FromWXF<'de> for Symbol {
159 fn from_wxf_with_tag<R: Reader<'de>>(
160 r: &mut WxfReader<R>,
161 tok: ExpressionEnum,
162 ) -> Result<Self, Error> {
163 if tok != ExpressionEnum::Symbol {
164 return Err(Error::unexpected_token(&["Symbol"], tok));
165 }
166 Ok(symbol_from_name(r.read_symbol_name()?))
167 }
168}
169
170impl<'de> FromWXF<'de> for NumericArray {
171 fn from_wxf_with_tag<R: Reader<'de>>(
172 r: &mut WxfReader<R>,
173 tok: ExpressionEnum,
174 ) -> Result<Self, Error> {
175 if tok != ExpressionEnum::NumericArray {
176 return Err(Error::unexpected_token(&["NumericArray"], tok));
177 }
178 let (dt, dims, bytes) = r.read_numeric_array_parts()?;
179 Ok(numeric_array_from_parts(dt, dims, bytes))
180 }
181}
182
183impl<'de> FromWXF<'de> for PackedArray {
184 fn from_wxf_with_tag<R: Reader<'de>>(
185 r: &mut WxfReader<R>,
186 tok: ExpressionEnum,
187 ) -> Result<Self, Error> {
188 if tok != ExpressionEnum::PackedArray {
189 return Err(Error::unexpected_token(&["PackedArray"], tok));
190 }
191 let (dt, dims, bytes) = r.read_numeric_array_parts()?;
192 packed_array_from_parts(dt, dims, bytes)
193 }
194}
195
196impl<'de> FromWXF<'de> for BigInteger {
200 fn from_wxf_with_tag<R: Reader<'de>>(
201 r: &mut WxfReader<R>,
202 tok: ExpressionEnum,
203 ) -> Result<Self, Error> {
204 if tok != ExpressionEnum::BigInteger {
205 return Err(Error::unexpected_token(&["BigInteger"], tok));
206 }
207 Ok(BigInteger(r.read_symbol_name()?))
208 }
209}
210
211impl<'de> FromWXF<'de> for BigReal {
212 fn from_wxf_with_tag<R: Reader<'de>>(
213 r: &mut WxfReader<R>,
214 tok: ExpressionEnum,
215 ) -> Result<Self, Error> {
216 if tok != ExpressionEnum::BigReal {
217 return Err(Error::unexpected_token(&["BigReal"], tok));
218 }
219 Ok(BigReal(r.read_symbol_name()?))
220 }
221}
222
223fn read_association<'de, R: Reader<'de>>(
225 r: &mut WxfReader<R>,
226) -> Result<Association, Error> {
227 let n = r.read_varint()?;
228 let mut a = Association::new();
229 for _ in 0..n {
230 let delayed = r.read_rule()?;
231 let key = Expr::from_wxf(r)?;
232 let value = Expr::from_wxf(r)?;
233 a.push(RuleEntry {
234 key,
235 value,
236 delayed,
237 });
238 }
239 Ok(a)
240}
241
242impl<'de> FromWXF<'de> for Expr {
243 fn from_wxf_with_tag<R: Reader<'de>>(
244 r: &mut WxfReader<R>,
245 tok: ExpressionEnum,
246 ) -> Result<Self, Error> {
247 match tok {
248 ExpressionEnum::Integer8 => Ok(Expr::from(i64::from(r.read_i8()?))),
249 ExpressionEnum::Integer16 => Ok(Expr::from(i64::from(r.read_i16()?))),
250 ExpressionEnum::Integer32 => Ok(Expr::from(i64::from(r.read_i32()?))),
251 ExpressionEnum::Integer64 => Ok(Expr::from(r.read_i64()?)),
252 ExpressionEnum::Real64 => {
253 let f = r.read_f64()?;
254 if f.is_nan() {
255 return Err(Error::invalid("Real64 token contained NaN".into()));
256 }
257 Ok(Expr::real(f))
258 },
259 ExpressionEnum::String => Ok(Expr::string(r.read_str()?.to_owned())),
260 ExpressionEnum::Symbol => {
261 Ok(Expr::symbol(symbol_from_name(r.read_symbol_name()?)))
262 },
263 ExpressionEnum::ByteArray => Ok(Expr::from(r.read_byte_array()?.to_vec())),
264 ExpressionEnum::BigInteger => {
265 Ok(Expr::from(BigInteger(r.read_symbol_name()?)))
266 },
267 ExpressionEnum::BigReal => Ok(Expr::from(BigReal(r.read_symbol_name()?))),
268 ExpressionEnum::NumericArray => {
269 let (dt, dims, bytes) = r.read_numeric_array_parts()?;
270 Ok(Expr::from(numeric_array_from_parts(dt, dims, bytes)))
271 },
272 ExpressionEnum::PackedArray => {
273 let (dt, dims, bytes) = r.read_numeric_array_parts()?;
274 Ok(Expr::from(packed_array_from_parts(dt, dims, bytes)?))
275 },
276 ExpressionEnum::Function => {
277 let n = r.read_varint()?;
278 let head = Expr::from_wxf(r)?;
279 let mut args = Vec::with_capacity(n as usize);
280 for _ in 0..n {
281 args.push(Expr::from_wxf(r)?);
282 }
283 Ok(Expr::normal(head, args))
284 },
285 ExpressionEnum::Association => Ok(Expr::from(read_association(r)?)),
286 other @ (ExpressionEnum::Rule | ExpressionEnum::RuleDelayed) => {
287 Err(Error::unexpected_token(&[], other))
288 },
289 }
290 }
291}