compose_library/foundations/iterator/
array_iter.rs

1use crate::{Array, Trace};
2use compose_library::{UntypedRef, Value, ValueIterator, Vm};
3use ecow::EcoVec;
4use std::sync::{Arc, Mutex};
5use compose_library::diag::SourceResult;
6
7#[derive(Debug, Clone)]
8pub struct ArrayIter {
9    arr: EcoVec<Value>,
10    index: Arc<Mutex<usize>>,
11}
12
13impl PartialEq for ArrayIter {
14    fn eq(&self, other: &Self) -> bool {
15        if self.arr != other.arr {
16            return false;
17        }
18
19        // Load the positions of each iterator.
20        let pos_a = self.index.lock().expect("Poisoned");
21        let pos_b = self.index.lock().expect("Poisoned");
22
23        if *pos_a != *pos_b {
24            return false;
25        }
26
27        true
28    }
29}
30
31impl ArrayIter {
32    pub fn new(arr: &Array) -> Self {
33        Self {
34            arr: EcoVec::from(arr.values.as_slice()),
35            index: Arc::new(Mutex::new(0)),
36        }
37    }
38    
39}
40
41impl From<EcoVec<Value>> for ArrayIter {
42    fn from(arr: EcoVec<Value>) -> Self {
43        Self {
44            arr,
45            index: Arc::new(Mutex::new(0)),
46        }
47    }
48}
49
50impl ValueIterator for ArrayIter {
51    fn next(&self, vm: &mut dyn Vm) -> SourceResult<Option<Value>> {
52        self.nth(vm, 0)
53    }
54
55    fn nth(&self, _: &mut dyn Vm, n: usize) -> SourceResult<Option<Value>> {
56        let mut idx = self.index.lock().expect("Poisoned");
57
58        let new_idx = *idx + n;
59
60        if new_idx >= self.arr.len() {
61            return Ok(None);
62        }
63
64        let item = &self.arr[new_idx];
65
66        *idx = new_idx + 1; // +1 to set index at next item
67
68        Ok(Some(item.clone()))
69    }
70}
71
72impl Trace for ArrayIter {
73    fn visit_refs(&self, f: &mut dyn FnMut(UntypedRef)) {
74        for item in &self.arr {
75            item.visit_refs(f);
76        }
77    }
78}