wolfram_expr/conversion.rs
1use std::convert::TryFrom;
2
3use super::*;
4
5// Each `TryFrom<&'e Expr>` impl below fails with the original `&'e Expr`
6// back (mirroring `TryFrom<Vec<T>> for [T; N]` in std) so callers can
7// report or inspect what they actually got, without a bespoke error type.
8
9impl<'e> TryFrom<&'e Expr> for bool {
10 type Error = &'e Expr;
11
12 /// If this is the `True` or `False` symbol, return that.
13 ///
14 /// ```
15 /// # use wolfram_expr::{Expr, expr};
16 /// # use std::convert::TryFrom;
17 /// let is_true = bool::try_from(&expr!(System::True)).unwrap();
18 /// assert_eq!(is_true, true);
19 /// ```
20 fn try_from(expr: &'e Expr) -> Result<bool, &'e Expr> {
21 match expr.kind() {
22 ExprKind::Symbol(symbol) => match symbol.as_str() {
23 "System`True" => Ok(true),
24 "System`False" => Ok(false),
25 _ => Err(expr),
26 },
27 _ => Err(expr),
28 }
29 }
30}
31
32impl<'e> TryFrom<&'e Expr> for &'e str {
33 type Error = &'e Expr;
34
35 /// If this is an [`ExprKind::String`] expression, return that.
36 ///
37 /// ```
38 /// # use wolfram_expr::{Expr, expr};
39 /// # use std::convert::TryFrom;
40 /// let expr = expr!("hello");
41 /// let s = <&str>::try_from(&expr).unwrap();
42 /// assert_eq!(s, "hello");
43 /// ```
44 fn try_from(expr: &'e Expr) -> Result<&'e str, &'e Expr> {
45 match expr.kind() {
46 ExprKind::String(string) => Ok(string.as_str()),
47 _ => Err(expr),
48 }
49 }
50}
51
52impl<'e> TryFrom<&'e Expr> for &'e Symbol {
53 type Error = &'e Expr;
54
55 /// If this is a [`Symbol`] expression, return that.
56 ///
57 /// ```
58 /// # use wolfram_expr::{Expr, Symbol, expr};
59 /// # use std::convert::TryFrom;
60 /// let expr = expr!(System::Pi);
61 /// let sym = <&Symbol>::try_from(&expr).unwrap();
62 /// assert_eq!(sym.as_str(), "System`Pi");
63 /// ```
64 fn try_from(expr: &'e Expr) -> Result<&'e Symbol, &'e Expr> {
65 match expr.kind() {
66 ExprKind::Symbol(symbol) => Ok(symbol),
67 _ => Err(expr),
68 }
69 }
70}
71
72impl<'e> TryFrom<&'e Expr> for &'e Normal {
73 type Error = &'e Expr;
74
75 /// If this is a [`Normal`] expression, return that.
76 ///
77 /// ```
78 /// # use wolfram_expr::{Expr, Normal, expr};
79 /// # use std::convert::TryFrom;
80 /// let expr = expr!(System::List[1, 2, 3]);
81 /// let normal = <&Normal>::try_from(&expr).unwrap();
82 /// assert_eq!(normal.elements().len(), 3);
83 /// ```
84 fn try_from(expr: &'e Expr) -> Result<&'e Normal, &'e Expr> {
85 match expr.kind() {
86 ExprKind::Normal(normal) => Ok(normal),
87 _ => Err(expr),
88 }
89 }
90}
91
92impl<'e> TryFrom<&'e Expr> for i64 {
93 type Error = &'e Expr;
94
95 /// If this is an [`ExprKind::Integer`] expression, return that.
96 ///
97 /// ```
98 /// # use wolfram_expr::{Expr, expr};
99 /// # use std::convert::TryFrom;
100 /// let i = i64::try_from(&expr!(42)).unwrap();
101 /// assert_eq!(i, 42);
102 /// ```
103 fn try_from(expr: &'e Expr) -> Result<i64, &'e Expr> {
104 match expr.kind() {
105 ExprKind::Integer(int) => Ok(*int),
106 _ => Err(expr),
107 }
108 }
109}
110
111impl<'e> TryFrom<&'e Expr> for f64 {
112 type Error = &'e Expr;
113
114 /// If this is an [`ExprKind::Real`] expression, return that.
115 ///
116 /// ```
117 /// # use wolfram_expr::{Expr, expr};
118 /// # use std::convert::TryFrom;
119 /// let r = f64::try_from(&expr!(4.2)).unwrap();
120 /// assert_eq!(r, 4.2);
121 /// ```
122 fn try_from(expr: &'e Expr) -> Result<f64, &'e Expr> {
123 match expr.kind() {
124 ExprKind::Real(real) => Ok(real.into_inner()),
125 _ => Err(expr),
126 }
127 }
128}
129
130impl Expr {
131 // These accessors are deprecated: use the `TryFrom<&Expr>` impls above
132 // instead — same behavior, drop-in replacement. None of them are used
133 // inside this crate.
134
135 /// If this is a [`Normal`] expression, return that. Otherwise return None.
136 ///
137 /// # Migration
138 ///
139 /// ```
140 /// # use wolfram_expr::{Expr, Normal, expr};
141 /// # use std::convert::TryFrom;
142 /// # let expr = expr!(System::List[1, 2, 3]);
143 /// let normal: Option<&Normal> = <&Normal>::try_from(&expr).ok();
144 /// ```
145 #[deprecated(note = "use `<&Normal>::try_from(expr)` instead")]
146 pub fn try_as_normal(&self) -> Option<&Normal> {
147 <&Normal>::try_from(self).ok()
148 }
149
150 /// If this is the `True` or `False` symbol, return that. Otherwise None.
151 ///
152 /// # Migration
153 ///
154 /// ```
155 /// # use wolfram_expr::{Expr, expr};
156 /// # use std::convert::TryFrom;
157 /// # let expr = expr!(System::True);
158 /// let is_true_or_false: Option<bool> = bool::try_from(&expr).ok();
159 /// ```
160 #[deprecated(note = "use `bool::try_from(expr)` instead")]
161 pub fn try_as_bool(&self) -> Option<bool> {
162 bool::try_from(self).ok()
163 }
164
165 /// If this is an [`ExprKind::String`] expression, return that. Otherwise return None.
166 ///
167 /// # Migration
168 ///
169 /// ```
170 /// # use wolfram_expr::{Expr, expr};
171 /// # use std::convert::TryFrom;
172 /// # let expr = expr!("hello");
173 /// let s: Option<&str> = <&str>::try_from(&expr).ok();
174 /// ```
175 #[deprecated(note = "use `<&str>::try_from(expr)` instead")]
176 pub fn try_as_str(&self) -> Option<&str> {
177 <&str>::try_from(self).ok()
178 }
179
180 /// If this is a [`Symbol`] expression, return that. Otherwise return None.
181 ///
182 /// # Migration
183 ///
184 /// ```
185 /// # use wolfram_expr::{Expr, Symbol, expr};
186 /// # use std::convert::TryFrom;
187 /// # let expr = expr!(System::Pi);
188 /// let sym: Option<&Symbol> = <&Symbol>::try_from(&expr).ok();
189 /// ```
190 #[deprecated(note = "use `<&Symbol>::try_from(expr)` instead")]
191 pub fn try_as_symbol(&self) -> Option<&Symbol> {
192 <&Symbol>::try_from(self).ok()
193 }
194
195 /// If this is a [`Number`] expression, return that. Otherwise return None.
196 ///
197 /// # Migration
198 ///
199 /// ```
200 /// # use wolfram_expr::{Expr, expr};
201 /// # use std::convert::TryFrom;
202 /// # let expr = expr!(42);
203 /// let int: Option<i64> = i64::try_from(&expr).ok();
204 /// let real: Option<f64> = f64::try_from(&expr).ok();
205 /// ```
206 #[deprecated(note = "use `i64::try_from(expr)` / `f64::try_from(expr)` instead")]
207 #[allow(deprecated)]
208 pub fn try_as_number(&self) -> Option<Number> {
209 match self.kind() {
210 ExprKind::Integer(int) => Some(Number::Integer(*int)),
211 ExprKind::Real(real) => Some(Number::Real(*real)),
212 _ => None,
213 }
214 }
215
216 //---------------------------------------------------------------------------
217 // SEMVER: These methods have been replaced; remove them in a future version.
218 //---------------------------------------------------------------------------
219
220 #[deprecated(note = "use `<&Normal>::try_from(expr)` instead")]
221 #[allow(missing_docs, deprecated)]
222 pub fn try_normal(&self) -> Option<&Normal> {
223 self.try_as_normal()
224 }
225
226 #[deprecated(note = "use `<&Symbol>::try_from(expr)` instead")]
227 #[allow(missing_docs, deprecated)]
228 pub fn try_symbol(&self) -> Option<&Symbol> {
229 self.try_as_symbol()
230 }
231
232 #[deprecated(note = "use `i64::try_from(expr)` / `f64::try_from(expr)` instead")]
233 #[allow(missing_docs, deprecated)]
234 pub fn try_number(&self) -> Option<Number> {
235 self.try_as_number()
236 }
237}
238
239//=======================================
240// Conversion trait impl's
241//=======================================
242
243impl From<Symbol> for Expr {
244 fn from(sym: Symbol) -> Expr {
245 Expr::symbol(sym)
246 }
247}
248
249impl From<&Symbol> for Expr {
250 fn from(sym: &Symbol) -> Expr {
251 Expr::symbol(sym)
252 }
253}
254
255impl From<Normal> for Expr {
256 fn from(normal: Normal) -> Expr {
257 Expr {
258 inner: Arc::new(ExprKind::Normal(normal)),
259 }
260 }
261}
262
263impl From<bool> for Expr {
264 fn from(value: bool) -> Expr {
265 match value {
266 true => crate::expr!(System::True),
267 false => crate::expr!(System::False),
268 }
269 }
270}
271
272macro_rules! string_like {
273 ($($t:ty),*) => {
274 $(
275 impl From<$t> for Expr {
276 fn from(s: $t) -> Expr {
277 Expr::string(s)
278 }
279 }
280 )*
281 }
282}
283
284string_like!(&str, &String, String);
285
286//--------------------
287// Integer conversions
288//--------------------
289
290impl From<u8> for Expr {
291 fn from(int: u8) -> Expr {
292 Expr::from(i64::from(int))
293 }
294}
295
296impl From<i8> for Expr {
297 fn from(int: i8) -> Expr {
298 Expr::from(i64::from(int))
299 }
300}
301
302impl From<u16> for Expr {
303 fn from(int: u16) -> Expr {
304 Expr::from(i64::from(int))
305 }
306}
307
308impl From<i16> for Expr {
309 fn from(int: i16) -> Expr {
310 Expr::from(i64::from(int))
311 }
312}
313
314impl From<u32> for Expr {
315 fn from(int: u32) -> Expr {
316 Expr::from(i64::from(int))
317 }
318}
319
320impl From<i32> for Expr {
321 fn from(int: i32) -> Expr {
322 Expr::from(i64::from(int))
323 }
324}
325
326impl From<i64> for Expr {
327 fn from(int: i64) -> Expr {
328 Expr::new(ExprKind::Integer(int))
329 }
330}
331
332impl From<f64> for Expr {
333 fn from(f: f64) -> Expr {
334 Expr::real(f)
335 }
336}
337
338// impl From<Normal> for ExprKind {
339// fn from(normal: Normal) -> ExprKind {
340// ExprKind::Normal(Box::new(normal))
341// }
342// }
343
344// impl From<Symbol> for ExprKind {
345// fn from(symbol: Symbol) -> ExprKind {
346// ExprKind::Symbol(symbol)
347// }
348// }
349
350#[allow(deprecated)]
351impl From<Number> for ExprKind {
352 fn from(number: Number) -> ExprKind {
353 match number {
354 Number::Integer(int) => ExprKind::Integer(int),
355 Number::Real(real) => ExprKind::Real(real),
356 }
357 }
358}
359
360//==============================
361// New WXF-derived From<T> impls
362//==============================
363
364impl From<ByteArray> for Expr {
365 fn from(b: ByteArray) -> Expr {
366 Expr {
367 inner: Arc::new(ExprKind::ByteArray(b)),
368 }
369 }
370}
371
372impl From<Association> for Expr {
373 fn from(a: Association) -> Expr {
374 Expr {
375 inner: Arc::new(ExprKind::Association(a)),
376 }
377 }
378}
379
380impl From<Vec<Expr>> for Expr {
381 fn from(v: Vec<Expr>) -> Expr {
382 Expr::list(v)
383 }
384}
385
386impl From<NumericArray> for Expr {
387 fn from(a: NumericArray) -> Expr {
388 Expr {
389 inner: Arc::new(ExprKind::NumericArray(a)),
390 }
391 }
392}
393
394impl From<PackedArray> for Expr {
395 fn from(a: PackedArray) -> Expr {
396 Expr {
397 inner: Arc::new(ExprKind::PackedArray(a)),
398 }
399 }
400}
401impl From<BigInteger> for Expr {
402 fn from(n: BigInteger) -> Expr {
403 Expr {
404 inner: Arc::new(ExprKind::BigInteger(n)),
405 }
406 }
407}
408impl From<BigReal> for Expr {
409 fn from(r: BigReal) -> Expr {
410 Expr {
411 inner: Arc::new(ExprKind::BigReal(r)),
412 }
413 }
414}