sphinx/runtime/types/
iterator.rs

1use crate::runtime::Variant;
2use crate::runtime::gc::{Gc, GcTrace};
3use crate::runtime::strings::StringValue;
4use crate::runtime::types::{Type, MetaObject};
5use crate::runtime::iter::IterState;
6use crate::runtime::errors::{ExecResult};
7
8
9/// Similar use case as UserData but a bit more limited in scope
10pub trait UserIterator: GcTrace {
11    fn next_state(&self, state: Option<&Variant>) -> ExecResult<Variant>;
12    fn get_item(&self, state: &Variant) -> ExecResult<Variant>;
13}
14
15// unlike UserData, the MetaObject impl for UserIterator is not customizable
16impl MetaObject for Gc<dyn UserIterator> {
17    fn type_tag(&self) -> Type { Type::Iterator }
18    
19    fn fmt_repr(&self) -> ExecResult<StringValue> {
20        let result = format!(
21            "<{} at {:#X}>", self.type_name()?, Gc::as_id(self)
22        );
23        
24        Ok(StringValue::new_uninterned(result))
25    }
26    
27    fn cmp_eq(&self, other: &Variant) -> Option<ExecResult<bool>> {
28        match other {
29            Variant::Iterator(other) => Some(Ok(Gc::ptr_eq(self, other))),
30            _ => Some(Ok(false)),
31        }
32    }
33    
34    fn iter_get(&self, state: &Variant) -> Option<ExecResult<Variant>> {
35        Some(self.get_item(state))
36    }
37    
38    fn iter_next(&self, state: &Variant) -> Option<ExecResult<Variant>> {
39        Some(self.next_state(Some(state)))
40    }
41    
42    fn iter_init(&self) -> Option<ExecResult<IterState>> {
43        let state = match self.next_state(None) {
44            Ok(state) => state,
45            Err(error) => return Some(Err(error)),
46        };
47        
48        let iter = Variant::Iterator(*self);
49        Some(Ok(IterState::new(iter, state)))
50    }
51}