compose_library/foundations/iterator/
string_iter.rs

1use compose_library::diag::SourceResult;
2use compose_library::vm::Vm;
3use compose_library::{IntoValue, Value, ValueIterator};
4use ecow::EcoString;
5use std::sync::{Arc, Mutex};
6
7#[derive(Debug, Clone)]
8pub struct StringIterator {
9    s: EcoString,
10    byte_pos: Arc<Mutex<usize>>,
11}
12
13impl PartialEq for StringIterator {
14    fn eq(&self, other: &Self) -> bool {
15        if self.s != other.s {
16            return false;
17        }
18
19        // Load the positions of each iterator. 
20        let pos_a = self.byte_pos.lock().expect("Poisoned");
21        let pos_b = self.byte_pos.lock().expect("Poisoned");
22
23        if *pos_a != *pos_b {
24            return false;
25        }
26
27        true
28    }
29}
30
31impl StringIterator {
32    pub fn new(s: EcoString) -> Self {
33        Self { s, byte_pos: Arc::new(Mutex::new(0)) }
34    }
35}
36
37impl ValueIterator for StringIterator {
38    fn next(&self, _: &mut dyn Vm) -> SourceResult<Option<Value>> {
39        let mut idx = self.byte_pos.lock().expect("Poisoned");
40
41        if *idx >= self.s.len() {
42            return Ok(None);
43        }
44
45        let Some(c) = self.s[*idx..].chars().next() else {
46            return Ok(None)
47        };
48
49        *idx += c.len_utf8();
50
51        Ok(Some(c.into_value()))
52    }
53}