1mod from_value;
2
3pub use self::from_value::BTreeMapFromValueError;
4pub use self::from_value::FromValue;
5pub use self::from_value::FromValueContext;
6pub use self::from_value::FromValueError;
7pub use self::from_value::HashMapFromValueError;
8use crate::ValueArena;
9use crate::ValueHandle;
10use std::collections::BTreeMap;
11use std::collections::HashMap;
12
13#[derive(Debug)]
15pub struct DisplayByteString<'a>(pub &'a [u8]);
16
17impl std::fmt::Display for DisplayByteString<'_> {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 let string = self.0;
20 match std::str::from_utf8(string) {
21 Ok(string) => write!(f, "{string}"),
22 Err(_error) => write!(f, "{string:?}"),
23 }
24 }
25}
26
27#[derive(Debug)]
29pub enum IntoValueError {
30 Other {
32 error: Box<dyn std::error::Error + Send + Sync + 'static>,
33 },
34}
35
36impl IntoValueError {
37 pub fn new_other<E>(error: E) -> Self
39 where
40 E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
41 {
42 Self::Other {
43 error: error.into(),
44 }
45 }
46}
47
48impl std::fmt::Display for IntoValueError {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 match self {
51 Self::Other { .. } => write!(f, "a user-provided error was encountered"),
52 }
53 }
54}
55
56impl std::error::Error for IntoValueError {
57 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
58 match self {
59 Self::Other { error } => Some(&**error),
60 }
62 }
63}
64
65pub trait IntoValue: Sized {
67 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError>;
69}
70
71impl IntoValue for bool {
72 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
73 Ok(arena.create_bool(self).into())
74 }
75}
76
77impl IntoValue for i32 {
78 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
79 Ok(arena.create_fixnum(self).into())
80 }
81}
82
83impl<T> IntoValue for Vec<T>
84where
85 T: IntoValue,
86{
87 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
88 let mut array = Vec::with_capacity(self.len());
89 for item in self.into_iter() {
90 array.push(item.into_value(arena)?);
91 }
92 Ok(arena.create_array(array).into())
93 }
94}
95
96impl<K, V> IntoValue for HashMap<K, V>
97where
98 K: IntoValue,
99 V: IntoValue,
100{
101 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
102 let mut items = Vec::new();
103
104 for (key, value) in self.into_iter() {
105 let key_handle = key.into_value(arena)?;
106 let value_handle = value.into_value(arena)?;
107
108 items.push((key_handle, value_handle));
109 }
110
111 Ok(arena.create_hash(items, None).into())
112 }
113}
114
115impl<K, V> IntoValue for BTreeMap<K, V>
116where
117 K: IntoValue,
118 V: IntoValue,
119{
120 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
121 let mut items = Vec::new();
122
123 for (key, value) in self.into_iter() {
124 let key_handle = key.into_value(arena)?;
125 let value_handle = value.into_value(arena)?;
126
127 items.push((key_handle, value_handle));
128 }
129
130 Ok(arena.create_hash(items, None).into())
131 }
132}
133
134impl<T> IntoValue for Option<T>
135where
136 T: IntoValue,
137{
138 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
139 match self {
140 Some(value) => value.into_value(arena),
141 None => Ok(arena.create_nil().into()),
142 }
143 }
144}
145
146#[cfg(test)]
147mod test {
148 use super::*;
149 use crate::ArrayValue;
150 use crate::BoolValue;
151 use crate::FixnumValue;
152 use crate::HashValue;
153 use crate::NilValue;
154 use crate::ObjectValue;
155 use crate::StringValue;
156 use crate::SymbolValue;
157 use crate::UserDefinedValue;
158 use crate::Value;
159
160 #[test]
161 fn sanity() {
162 let mut arena = ValueArena::new();
163
164 let nil_handle = arena.create_nil().into_raw();
165 let bool_handle = arena.create_bool(true).into_raw();
166 let fixnum_handle = arena.create_fixnum(23).into_raw();
167 let symbol_handle = arena.create_symbol("symbol".into());
168 let array_handle = arena.create_array(vec![fixnum_handle]).into_raw();
169 let hash_handle = arena.create_hash(Vec::new(), None).into_raw();
170 let object_handle = arena.create_object(symbol_handle, Vec::new()).into_raw();
171 let string_handle = arena.create_string("string".into()).into_raw();
172 let user_defined_handle = arena
173 .create_user_defined(symbol_handle, Vec::new())
174 .into_raw();
175
176 let symbol_handle = symbol_handle.into_raw();
177
178 let ctx = FromValueContext::new(&arena);
179
180 let _value: &Value = ctx
181 .from_value(nil_handle)
182 .expect("failed to exec &Value::from_value");
183
184 let _nil_value: &NilValue = ctx
185 .from_value(nil_handle)
186 .expect("failed exec &NilValue::from_value");
187
188 let _bool_value: &BoolValue = ctx
189 .from_value(bool_handle)
190 .expect("failed exec &BoolValue::from_value");
191
192 let _fixnum_value: &FixnumValue = ctx
193 .from_value(fixnum_handle)
194 .expect("failed exec &FixnumValue::from_value");
195
196 let _symbol_value: &SymbolValue = ctx
197 .from_value(symbol_handle)
198 .expect("failed exec &SymbolValue::from_value");
199
200 let _array_value: &ArrayValue = ctx
201 .from_value(array_handle)
202 .expect("failed exec &ArrayValue::from_value");
203
204 let _hash_value: &HashValue = ctx
205 .from_value(hash_handle)
206 .expect("failed exec &HashValue::from_value");
207
208 let _string_value: &ObjectValue = ctx
209 .from_value(object_handle)
210 .expect("failed exec &ObjectValue::from_value");
211
212 let _string_value: &StringValue = ctx
213 .from_value(string_handle)
214 .expect("failed exec &StringValue::from_value");
215
216 let _user_defined_value: &UserDefinedValue = ctx
217 .from_value(user_defined_handle)
218 .expect("failed exec &UserDefinedValue::from_value");
219
220 let _bool_value: bool = ctx
221 .from_value(bool_handle)
222 .expect("failed exec bool::from_value");
223
224 let _i32_value: i32 = ctx
225 .from_value(fixnum_handle)
226 .expect("failed exec i32::from_value");
227
228 let _some_symbol_value: Option<&SymbolValue> = ctx
229 .from_value(symbol_handle)
230 .expect("failed exec Option<&SymbolValue>::from_value");
231
232 let _none_symbol_value: Option<&SymbolValue> = ctx
233 .from_value(nil_handle)
234 .expect("failed exec Option<&SymbolValue>::from_value");
235
236 let _vec_value: Vec<i32> = ctx
237 .from_value(array_handle)
238 .expect("failed exec <Vec<i32>>::from_value");
239
240 let _hash_map_value: HashMap<i32, i32> = ctx
241 .from_value(hash_handle)
242 .expect("failed exec <HashMap<i32, i32>>::from_value");
243
244 let _btree_map_value: BTreeMap<i32, i32> = ctx
245 .from_value(hash_handle)
246 .expect("failed exec <BTreeMap<i32, i32>>::from_value");
247
248 true.into_value(&mut arena)
249 .expect("failed to exec bool::into_value");
250
251 0_i32
252 .into_value(&mut arena)
253 .expect("failed to exec i32::into_value");
254
255 vec![0, 1, 2]
256 .into_value(&mut arena)
257 .expect("failed to exec Vec::<i32>::into_value");
258
259 HashMap::<i32, i32>::new()
260 .into_value(&mut arena)
261 .expect("failed to exec HashMap::<i32, i32>::into_value");
262
263 BTreeMap::<i32, i32>::new()
264 .into_value(&mut arena)
265 .expect("failed to exec BTreeMap::<i32, i32>::into_value");
266
267 Some(2_i32)
268 .into_value(&mut arena)
269 .expect("failed to exec Option::<i32>::Some::into_value");
270
271 None::<i32>
272 .into_value(&mut arena)
273 .expect("failed to exec Option::<i32>::None::into_value");
274 }
275}