1use std::convert::TryFrom;
9
10use wolfram_serialize::Error;
11use wolfram_serialize::{
12 ExpressionEnum, FromWXF, NumericArrayEnum, PackedArrayEnum, Reader, ToWXF, Writer,
13 WxfReader, 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
111fn symbol_from_name(name: String) -> Symbol {
119 unsafe { Symbol::unchecked_new(name) }
122}
123
124fn numeric_array_from_parts(
125 dt: NumericArrayEnum,
126 dims: Vec<usize>,
127 bytes: Vec<u8>,
128) -> NumericArray {
129 NumericArray::new(dt, dims, bytes)
130}
131
132fn packed_array_from_parts(
133 dt: NumericArrayEnum,
134 dims: Vec<usize>,
135 bytes: Vec<u8>,
136) -> Result<PackedArray, Error> {
137 let pdt = PackedArrayEnum::try_from(dt).map_err(|_| {
138 Error::invalid(format!(
139 "PackedArray does not support element type {}",
140 dt.name()
141 ))
142 })?;
143 Ok(PackedArray::new(pdt, dims, bytes))
144}
145
146impl<'de> FromWXF<'de> for Symbol {
147 fn from_wxf_with_tag<R: Reader<'de>>(
148 r: &mut WxfReader<R>,
149 tok: ExpressionEnum,
150 ) -> Result<Self, Error> {
151 if tok != ExpressionEnum::Symbol {
152 return Err(Error::unexpected_token(&["Symbol"], tok));
153 }
154 Ok(symbol_from_name(r.read_symbol_name()?))
155 }
156}
157
158impl<'de> FromWXF<'de> for NumericArray {
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::NumericArray {
164 return Err(Error::unexpected_token(&["NumericArray"], tok));
165 }
166 let (dt, dims, bytes) = r.read_numeric_array_parts()?;
167 Ok(numeric_array_from_parts(dt, dims, bytes))
168 }
169}
170
171impl<'de> FromWXF<'de> for PackedArray {
172 fn from_wxf_with_tag<R: Reader<'de>>(
173 r: &mut WxfReader<R>,
174 tok: ExpressionEnum,
175 ) -> Result<Self, Error> {
176 if tok != ExpressionEnum::PackedArray {
177 return Err(Error::unexpected_token(&["PackedArray"], tok));
178 }
179 let (dt, dims, bytes) = r.read_numeric_array_parts()?;
180 packed_array_from_parts(dt, dims, bytes)
181 }
182}
183
184impl<'de> FromWXF<'de> for BigInteger {
188 fn from_wxf_with_tag<R: Reader<'de>>(
189 r: &mut WxfReader<R>,
190 tok: ExpressionEnum,
191 ) -> Result<Self, Error> {
192 if tok != ExpressionEnum::BigInteger {
193 return Err(Error::unexpected_token(&["BigInteger"], tok));
194 }
195 Ok(BigInteger(r.read_symbol_name()?))
196 }
197}
198
199impl<'de> FromWXF<'de> for BigReal {
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::BigReal {
205 return Err(Error::unexpected_token(&["BigReal"], tok));
206 }
207 Ok(BigReal(r.read_symbol_name()?))
208 }
209}
210
211fn read_association<'de, R: Reader<'de>>(
213 r: &mut WxfReader<R>,
214) -> Result<Association, Error> {
215 let n = r.read_varint()?;
216 let mut a = Association::new();
217 for _ in 0..n {
218 let delayed = r.read_rule()?;
219 let key = Expr::from_wxf(r)?;
220 let value = Expr::from_wxf(r)?;
221 a.push(RuleEntry {
222 key,
223 value,
224 delayed,
225 });
226 }
227 Ok(a)
228}
229
230impl<'de> FromWXF<'de> for Expr {
231 fn from_wxf_with_tag<R: Reader<'de>>(
232 r: &mut WxfReader<R>,
233 tok: ExpressionEnum,
234 ) -> Result<Self, Error> {
235 match tok {
236 ExpressionEnum::Integer8 => Ok(Expr::from(i64::from(r.read_i8()?))),
237 ExpressionEnum::Integer16 => Ok(Expr::from(i64::from(r.read_i16()?))),
238 ExpressionEnum::Integer32 => Ok(Expr::from(i64::from(r.read_i32()?))),
239 ExpressionEnum::Integer64 => Ok(Expr::from(r.read_i64()?)),
240 ExpressionEnum::Real64 => {
241 let f = r.read_f64()?;
242 if f.is_nan() {
243 return Err(Error::invalid("Real64 token contained NaN".into()));
244 }
245 Ok(Expr::real(f))
246 },
247 ExpressionEnum::String => Ok(Expr::string(r.read_str()?.to_owned())),
248 ExpressionEnum::Symbol => {
249 Ok(Expr::symbol(symbol_from_name(r.read_symbol_name()?)))
250 },
251 ExpressionEnum::ByteArray => Ok(Expr::from(r.read_byte_array()?.to_vec())),
252 ExpressionEnum::BigInteger => {
253 Ok(Expr::from(BigInteger(r.read_symbol_name()?)))
254 },
255 ExpressionEnum::BigReal => {
256 Ok(Expr::from(BigReal(r.read_symbol_name()?)))
257 },
258 ExpressionEnum::NumericArray => {
259 let (dt, dims, bytes) = r.read_numeric_array_parts()?;
260 Ok(Expr::from(numeric_array_from_parts(dt, dims, bytes)))
261 },
262 ExpressionEnum::PackedArray => {
263 let (dt, dims, bytes) = r.read_numeric_array_parts()?;
264 Ok(Expr::from(packed_array_from_parts(dt, dims, bytes)?))
265 },
266 ExpressionEnum::Function => {
267 let n = r.read_varint()?;
268 let head = Expr::from_wxf(r)?;
269 let mut args = Vec::with_capacity(n as usize);
270 for _ in 0..n {
271 args.push(Expr::from_wxf(r)?);
272 }
273 Ok(Expr::normal(head, args))
274 },
275 ExpressionEnum::Association => Ok(Expr::from(read_association(r)?)),
276 other @ (ExpressionEnum::Rule | ExpressionEnum::RuleDelayed) => {
277 Err(Error::unexpected_token(&[], other))
278 },
279 }
280 }
281}