1use super::DisplayByteString;
2use crate::ArrayValue;
3use crate::BoolValue;
4use crate::FixnumValue;
5use crate::HashValue;
6use crate::NilValue;
7use crate::ObjectValue;
8use crate::StringValue;
9use crate::SymbolValue;
10use crate::UserDefinedValue;
11use crate::Value;
12use crate::ValueArena;
13use crate::ValueHandle;
14use crate::ValueKind;
15use std::cell::RefCell;
16use std::collections::BTreeMap;
17use std::collections::HashMap;
18use std::hash::Hash;
19
20#[derive(Debug)]
22pub enum FromValueError {
23 Cycle {
25 handle: ValueHandle,
27 },
28
29 InvalidValueHandle {
31 handle: ValueHandle,
33 },
34
35 UnexpectedValueKind {
37 kind: ValueKind,
39
40 trace: Vec<ValueHandle>,
42 },
43
44 UnexpectedObjectName {
46 name: Vec<u8>,
50 },
51
52 UnexpectedUserDefinedName {
54 name: Vec<u8>,
58 },
59
60 DuplicateInstanceVariable {
62 name: Vec<u8>,
66 },
67
68 UnknownInstanceVariable {
70 name: Vec<u8>,
74 },
75
76 MissingInstanceVariable {
78 name: Vec<u8>,
82 },
83
84 DuplicateHashKey {
86 key: ValueHandle,
90 },
91
92 Other {
94 error: Box<dyn std::error::Error + Send + Sync + 'static>,
95 },
96}
97
98impl FromValueError {
99 pub fn new_other<E>(error: E) -> Self
101 where
102 E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
103 {
104 Self::Other {
105 error: error.into(),
106 }
107 }
108}
109
110impl std::fmt::Display for FromValueError {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 match self {
113 Self::Cycle { .. } => write!(f, "attempted to extract recursively"),
114 Self::InvalidValueHandle { .. } => write!(f, "a handle was invalid"),
115 Self::UnexpectedValueKind { kind, .. } => write!(f, "unexpected value kind {kind:?}"),
116 Self::UnexpectedObjectName { name } => {
117 write!(f, "unexpected object name \"{}\"", DisplayByteString(name))
118 }
119 Self::UnexpectedUserDefinedName { name } => {
120 write!(
121 f,
122 "unexpected user defined name \"{}\"",
123 DisplayByteString(name)
124 )
125 }
126 Self::DuplicateInstanceVariable { name } => {
127 write!(
128 f,
129 "instance variable \"{}\" was encountered twice",
130 DisplayByteString(name)
131 )
132 }
133 Self::UnknownInstanceVariable { name } => {
134 write!(
135 f,
136 "instance variable \"{}\" is not known",
137 DisplayByteString(name)
138 )
139 }
140 Self::MissingInstanceVariable { name } => {
141 write!(
142 f,
143 "instance variable \"{}\" is missing",
144 DisplayByteString(name)
145 )
146 }
147 Self::DuplicateHashKey { .. } => {
148 write!(f, "duplicate hash key")
149 }
150 Self::Other { .. } => write!(f, "a user-provided error was encountered"),
151 }
152 }
153}
154
155impl std::error::Error for FromValueError {
156 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
157 match self {
158 Self::Other { error } => Some(&**error),
159 _ => None,
160 }
161 }
162}
163
164pub struct FromValueContext<'a> {
166 arena: &'a ValueArena,
167 stack: RefCell<Vec<ValueHandle>>,
168}
169
170impl<'a> FromValueContext<'a> {
171 pub fn new(arena: &'a ValueArena) -> Self {
173 Self {
174 arena,
175 stack: RefCell::new(Vec::new()),
176 }
177 }
178
179 fn begin_handle(&self, handle: ValueHandle) -> Result<(), FromValueError> {
180 let mut stack = self.stack.borrow_mut();
181
182 if stack.contains(&handle) {
183 return Err(FromValueError::Cycle { handle });
184 }
185
186 stack.push(handle);
187
188 Ok(())
189 }
190
191 fn end_handle(&self, handle: ValueHandle) {
192 let stack_handle = self.stack.borrow_mut().pop();
193
194 let stack_handle = stack_handle.unwrap();
196
197 assert!(handle == stack_handle);
198 }
199
200 #[allow(clippy::wrong_self_convention)]
202 pub fn from_value<T>(&self, handle: ValueHandle) -> Result<T, FromValueError>
204 where
205 T: FromValue<'a>,
206 {
207 let guard = FromValueGuard::new(self, handle)?;
208 let value = self
209 .arena
210 .get(handle)
211 .ok_or(FromValueError::InvalidValueHandle { handle })?;
212 let value = T::from_value(self, value)?;
213 drop(guard);
214
215 Ok(value)
216 }
217
218 pub fn new_unexpected_value_kind_error(&self, kind: ValueKind) -> FromValueError {
220 FromValueError::UnexpectedValueKind {
221 kind,
222 trace: self.stack.borrow().clone(),
223 }
224 }
225}
226
227pub struct FromValueGuard<'a, 'b> {
231 ctx: &'a FromValueContext<'b>,
232 handle: ValueHandle,
233}
234
235impl<'a, 'b> FromValueGuard<'a, 'b> {
236 fn new(ctx: &'a FromValueContext<'b>, handle: ValueHandle) -> Result<Self, FromValueError> {
237 ctx.begin_handle(handle)?;
238
239 Ok(Self { ctx, handle })
240 }
241}
242
243impl Drop for FromValueGuard<'_, '_> {
244 fn drop(&mut self) {
245 self.ctx.end_handle(self.handle);
246 }
247}
248
249pub trait FromValue<'a>: Sized {
251 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError>;
257}
258
259impl<'a> FromValue<'a> for &'a Value {
260 fn from_value(_ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
261 Ok(value)
262 }
263}
264
265impl<'a> FromValue<'a> for &'a NilValue {
266 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
267 match value {
268 Value::Nil(value) => Ok(value),
269 value => Err(ctx.new_unexpected_value_kind_error(value.kind())),
270 }
271 }
272}
273
274impl<'a> FromValue<'a> for &'a BoolValue {
275 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
276 match value {
277 Value::Bool(value) => Ok(value),
278 value => Err(ctx.new_unexpected_value_kind_error(value.kind())),
279 }
280 }
281}
282
283impl<'a> FromValue<'a> for &'a FixnumValue {
284 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
285 match value {
286 Value::Fixnum(value) => Ok(value),
287 value => Err(ctx.new_unexpected_value_kind_error(value.kind())),
288 }
289 }
290}
291
292impl<'a> FromValue<'a> for &'a SymbolValue {
293 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
294 match value {
295 Value::Symbol(value) => Ok(value),
296 value => Err(ctx.new_unexpected_value_kind_error(value.kind())),
297 }
298 }
299}
300
301impl<'a> FromValue<'a> for &'a ArrayValue {
302 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
303 match value {
304 Value::Array(value) => Ok(value),
305 value => Err(ctx.new_unexpected_value_kind_error(value.kind())),
306 }
307 }
308}
309
310impl<'a> FromValue<'a> for &'a HashValue {
311 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
312 match value {
313 Value::Hash(value) => Ok(value),
314 value => Err(ctx.new_unexpected_value_kind_error(value.kind())),
315 }
316 }
317}
318
319impl<'a> FromValue<'a> for &'a ObjectValue {
320 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
321 match value {
322 Value::Object(value) => Ok(value),
323 value => Err(ctx.new_unexpected_value_kind_error(value.kind())),
324 }
325 }
326}
327
328impl<'a> FromValue<'a> for &'a StringValue {
329 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
330 match value {
331 Value::String(value) => Ok(value),
332 value => Err(ctx.new_unexpected_value_kind_error(value.kind())),
333 }
334 }
335}
336
337impl<'a> FromValue<'a> for &'a UserDefinedValue {
338 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
339 match value {
340 Value::UserDefined(value) => Ok(value),
341 value => Err(ctx.new_unexpected_value_kind_error(value.kind())),
342 }
343 }
344}
345
346impl<'a> FromValue<'a> for bool {
347 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
348 let value: &BoolValue = FromValue::from_value(ctx, value)?;
349 Ok(value.value())
350 }
351}
352
353impl<'a> FromValue<'a> for i32 {
354 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
355 let value: &FixnumValue = FromValue::from_value(ctx, value)?;
356 Ok(value.value())
357 }
358}
359
360impl<'a, T> FromValue<'a> for Option<T>
361where
362 T: FromValue<'a>,
363{
364 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
365 match value {
366 Value::Nil(_) => Ok(None),
367 _ => T::from_value(ctx, value).map(Some),
368 }
369 }
370}
371
372impl<'a, T> FromValue<'a> for Vec<T>
373where
374 T: FromValue<'a>,
375{
376 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
377 let array: &ArrayValue = FromValue::from_value(ctx, value)?;
378 let array = array.value();
379
380 let mut vec = Vec::with_capacity(array.len());
381 for handle in array.iter().copied() {
382 let value = ctx.from_value(handle)?;
383 vec.push(value);
384 }
385
386 Ok(vec)
387 }
388}
389
390#[derive(Debug)]
392pub enum HashMapFromValueError {
393 HasDefaultValue {
395 value: ValueHandle,
397 },
398}
399
400impl std::fmt::Display for HashMapFromValueError {
401 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
402 match self {
403 Self::HasDefaultValue { .. } => {
404 write!(f, "HashValue has a default value")
405 }
406 }
407 }
408}
409
410impl std::error::Error for HashMapFromValueError {}
411
412impl<'a, K, V> FromValue<'a> for HashMap<K, V>
413where
414 K: FromValue<'a> + Hash + Eq,
415 V: FromValue<'a>,
416{
417 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
418 let value: &HashValue = FromValue::from_value(ctx, value)?;
419
420 if let Some(default_value) = value.default_value() {
421 return Err(FromValueError::new_other(
422 HashMapFromValueError::HasDefaultValue {
423 value: default_value,
424 },
425 ));
426 }
427
428 let value = value.value();
429
430 let mut map = HashMap::with_capacity(value.len());
431 for (key_handle, value_handle) in value.iter().copied() {
432 let key = ctx.from_value(key_handle)?;
433 let value = ctx.from_value(value_handle)?;
434
435 let old_value = map.insert(key, value);
436
437 if old_value.is_some() {
438 return Err(FromValueError::DuplicateHashKey { key: key_handle });
439 }
440 }
441
442 Ok(map)
443 }
444}
445
446#[derive(Debug)]
448pub enum BTreeMapFromValueError {
449 HasDefaultValue {
451 value: ValueHandle,
453 },
454}
455
456impl std::fmt::Display for BTreeMapFromValueError {
457 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
458 match self {
459 Self::HasDefaultValue { .. } => {
460 write!(f, "HashValue has a default value")
461 }
462 }
463 }
464}
465
466impl std::error::Error for BTreeMapFromValueError {}
467
468impl<'a, K, V> FromValue<'a> for BTreeMap<K, V>
469where
470 K: FromValue<'a> + Eq + Ord,
471 V: FromValue<'a>,
472{
473 fn from_value(ctx: &FromValueContext<'a>, value: &'a Value) -> Result<Self, FromValueError> {
474 let value: &HashValue = FromValue::from_value(ctx, value)?;
475
476 if let Some(default_value) = value.default_value() {
477 return Err(FromValueError::new_other(
478 BTreeMapFromValueError::HasDefaultValue {
479 value: default_value,
480 },
481 ));
482 }
483
484 let value = value.value();
485
486 let mut map = BTreeMap::new();
487 for (key_handle, value_handle) in value.iter().copied() {
488 let key = ctx.from_value(key_handle)?;
489 let value = ctx.from_value(value_handle)?;
490
491 let old_value = map.insert(key, value);
492
493 if old_value.is_some() {
494 return Err(FromValueError::DuplicateHashKey { key: key_handle });
495 }
496 }
497
498 Ok(map)
499 }
500}