nanvm_lib/vm/impls/
try_from.rs1use crate::{
6 common::sized_index::SizedIndex,
7 vm::{
8 Any, Array, BigInt, Function, IVm, Number, Object, String, Unpacked, error,
9 nullish::Nullish,
10 },
11};
12
13impl<A: IVm> TryFrom<Any<A>> for Nullish {
14 type Error = Any<A>;
15 fn try_from(value: Any<A>) -> Result<Self, Self::Error> {
16 let Unpacked::Nullish(result) = value.into() else {
17 return Err(error::unexpected_type());
18 };
19 Ok(result)
20 }
21}
22
23impl<A: IVm> TryFrom<Any<A>> for bool {
24 type Error = Any<A>;
25 fn try_from(value: Any<A>) -> Result<Self, Self::Error> {
26 let Unpacked::Boolean(result) = value.into() else {
27 return Err(error::unexpected_type());
28 };
29 Ok(result)
30 }
31}
32
33impl<A: IVm> TryFrom<Any<A>> for Number {
34 type Error = Any<A>;
35 fn try_from(value: Any<A>) -> Result<Self, Self::Error> {
36 let Unpacked::Number(result) = value.into() else {
37 return Err(error::unexpected_type());
38 };
39 Ok(result)
40 }
41}
42
43impl<A: IVm> TryFrom<Any<A>> for Array<A> {
44 type Error = Any<A>;
45 fn try_from(value: Any<A>) -> Result<Self, Self::Error> {
46 let Unpacked::Array(result) = value.into() else {
47 return Err(error::unexpected_type());
48 };
49 Ok(result)
50 }
51}
52
53impl<A: IVm, const N: usize> TryFrom<Array<A>> for [Any<A>; N] {
57 type Error = Array<A>;
58 fn try_from(value: Array<A>) -> Result<Self, Self::Error> {
59 if value.length() as usize != N {
60 return Err(value);
61 }
62 Ok(core::array::from_fn(|i| value[i as u32].clone()))
63 }
64}
65
66impl<A: IVm> TryFrom<Any<A>> for BigInt<A> {
67 type Error = Any<A>;
68 fn try_from(value: Any<A>) -> Result<Self, Self::Error> {
69 let Unpacked::BigInt(result) = value.into() else {
70 return Err(error::unexpected_type());
71 };
72 Ok(result)
73 }
74}
75
76impl<A: IVm> TryFrom<Any<A>> for Function<A> {
77 type Error = Any<A>;
78 fn try_from(value: Any<A>) -> Result<Self, Self::Error> {
79 let Unpacked::Function(result) = value.into() else {
80 return Err(error::unexpected_type());
81 };
82 Ok(result)
83 }
84}
85
86impl<A: IVm> TryFrom<Any<A>> for Object<A> {
87 type Error = Any<A>;
88 fn try_from(value: Any<A>) -> Result<Self, Self::Error> {
89 let Unpacked::Object(result) = value.into() else {
90 return Err(error::unexpected_type());
91 };
92 Ok(result)
93 }
94}
95
96impl<A: IVm> TryFrom<Any<A>> for String<A> {
97 type Error = Any<A>;
98 fn try_from(value: Any<A>) -> Result<Self, Self::Error> {
99 let Unpacked::String(result) = value.into() else {
100 return Err(error::unexpected_type());
101 };
102 Ok(result)
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use crate::{
109 naive::Naive,
110 vm::{Any, Array, ToAny, ToArray},
111 };
112
113 type A = Naive;
114
115 fn array<const N: usize>(items: [f64; N]) -> Array<A> {
116 items.map(|n| n.to_any::<A>()).to_array()
117 }
118
119 #[test]
120 fn an_array_of_exactly_n_items_is_unpacked() {
121 let [a, b]: [Any<A>; 2] = array([1.0, 2.0]).try_into().unwrap();
122 assert_eq!((a, b), (1.0.to_any(), 2.0.to_any()));
123 let []: [Any<A>; 0] = array([]).try_into().unwrap();
124 }
125
126 #[test]
127 fn any_other_length_is_handed_back() {
128 for items in [array([1.0]), array([1.0, 2.0, 3.0])] {
129 let refused: Result<[Any<A>; 2], _> = items.clone().try_into();
130 assert_eq!(refused, Err(items));
131 }
132 }
133}