sphinx/runtime/
iter.rs

1use crate::runtime::Variant;
2use crate::runtime::gc::GcTrace;
3use crate::runtime::errors::{ExecResult};
4
5/*
6    The iterator protocol in a nutshell:
7    
8    Certain values are "iterables" and can be iterated. For example: containers, strings, streams, etc.
9    These values support the `iter_init()` method which produces an "iterator state".
10    
11    An iterator state is just a pair: an "iterator" and a state. The state can be any value, 
12    however false values are interpeted as indicating that the iterator is exhausted.
13    The iterator is a value that supports the `iter_get()` and `iter_next()` methods. 
14    
15    Both of these methods take the state value as their argument.
16    
17    `iter_next()` takes a state value and produces the next state value.
18    
19    `iter_get()` gets the item for a given state.
20    This method is expected to succeed when called for the first time with the current state (assuming
21    that the state is true), but is not required to succeed when called with the same state subsequent 
22    times or when called with a past state.
23    
24    Note: it is not required for an iterator to actually use the state argument.
25    The alternative is interior mutability: the iterator can just mutate itself when `iter_next()` is called.
26    Such iterators are called "stateful" and the state is only needed to signal the end of iteration.
27    
28*/
29
30pub struct IterState {
31    iter: Variant,
32    state: Variant,
33}
34
35unsafe impl GcTrace for IterState {
36    fn trace(&self) {
37        self.iter.trace();
38        self.state.trace();
39    }
40}
41
42impl IterState {
43    pub fn new(iter: Variant, state: Variant) -> Self {
44        Self { iter, state }
45    }
46    
47    #[inline]
48    pub fn get_iter(&self) -> &Variant { &self.iter }
49    
50    #[inline]
51    pub fn get_state(&self) -> &Variant { &self.state }
52    
53    // Helpers
54    #[inline]
55    pub fn has_value(&self) -> ExecResult<bool> {
56        self.state.as_bool()
57    }
58    
59    #[inline]
60    pub fn get_value(&self) -> ExecResult<Variant> {
61        self.iter.iter_get(&self.state)
62    }
63    
64    #[inline]
65    pub fn next_state(&self) -> ExecResult<Variant> {
66        self.iter.iter_next(&self.state)
67    }
68    
69    #[inline]
70    pub fn next(&self) -> ExecResult<IterState> {
71        Ok(Self {
72            iter: self.iter,
73            state: self.next_state()?,
74        })
75    }
76    
77    // go to the next state *in place*
78    #[inline]
79    pub fn advance(&mut self) -> ExecResult<()> {
80        self.state = self.iter.iter_next(&self.state)?;
81        Ok(())
82    }
83}
84
85impl IntoIterator for IterState {
86    type Item = ExecResult<Variant>;
87    type IntoIter = Iter;
88    fn into_iter(self) -> Self::IntoIter {
89        Iter(self)
90    }
91}
92
93
94/// wrapper for IterState that allows it to be used as a Rust Iterator
95pub struct Iter(IterState);
96
97impl Iter {
98    fn next_value(&mut self) -> ExecResult<Option<Variant>> {
99        if !self.0.has_value()? {
100            return Ok(None)
101        }
102        
103        let next = self.0.get_value()?;
104        self.0.advance()?;
105        Ok(Some(next))
106    }
107}
108
109impl Iterator for Iter {
110    type Item = ExecResult<Variant>;
111    
112    fn next(&mut self) -> Option<Self::Item> {
113        match self.next_value() {
114            Ok(None) => None,
115            Ok(Some(value)) => Some(Ok(value)),
116            Err(error) => Some(Err(error)),
117        }
118    }
119}
120