1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use super::Value;
use crate::Node;

#[derive(Clone, Copy)]
/// Wrapper around the tape that allows interacting with it via a `Array`-like API.
pub struct Array<'tape, 'input>(pub(super) &'tape [Node<'input>]);

pub struct ArrayIter<'tape, 'input>(&'tape [Node<'input>]);

impl<'tape, 'input> Iterator for ArrayIter<'tape, 'input> {
    type Item = Value<'tape, 'input>;

    fn next(&mut self) -> Option<Self::Item> {
        let (head, tail) = self.0.split_at(self.0.first()?.count());
        self.0 = tail;
        Some(Value(head))
    }
}

// value_trait::Array for
impl<'tape, 'input> Array<'tape, 'input>
where
    'input: 'tape,
{
    /// FIXME: docs

    #[must_use]
    pub fn get(&self, mut idx: usize) -> Option<Value<'tape, 'input>> {
        let mut offset = 1;
        while idx > 0 {
            offset += self.0.get(offset)?.count();
            idx -= 1;
        }
        let count = self.0.get(offset)?.count();
        Some(Value(&self.0[offset..offset + count]))
    }
    /// FIXME: docs
    #[must_use]
    pub fn iter<'i>(&'i self) -> ArrayIter<'tape, 'input> {
        ArrayIter(&self.0[1..])
    }

    /// FIXME: docs
    /// # Panics
    /// if the tape is not an array
    #[must_use]
    pub fn len(&self) -> usize {
        if let Some(Node::Array { len, .. }) = self.0.first() {
            *len
        } else {
            panic!("invalid tape array")
        }
    }
    /// FIXME: docs
    #[must_use]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

impl<'tape, 'input> IntoIterator for &Array<'tape, 'input> {
    type IntoIter = ArrayIter<'tape, 'input>;
    type Item = Value<'tape, 'input>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

#[cfg(test)]
mod test {
    use crate::to_tape;
    use value_trait::base::ValueAsScalar;

    #[test]
    fn get_ints() -> crate::Result<()> {
        let mut input = b"[1,2,3,4]".to_vec();
        let t = to_tape(input.as_mut_slice())?;
        let v = t.as_value();
        let a = v.as_array().expect("is an array");
        assert_eq!(a.get(0).and_then(|v| v.as_u64()), Some(1));
        assert_eq!(a.get(1).and_then(|v| v.as_u64()), Some(2));
        assert_eq!(a.get(2).and_then(|v| v.as_u64()), Some(3));
        assert_eq!(a.get(3).and_then(|v| v.as_u64()), Some(4));
        assert_eq!(a.get(4), None);
        Ok(())
    }

    #[test]
    fn get_nested() -> crate::Result<()> {
        let mut input = b"[1,[2,3],4]".to_vec();
        let t = to_tape(input.as_mut_slice())?;
        let v = t.as_value();
        let a = v.as_array().expect("is an array");
        assert_eq!(a.get(0).and_then(|v| v.as_u64()), Some(1));
        let a1 = a.get(1).expect("has first element");
        let a2 = a1.as_array().expect("is an array");
        assert_eq!(a2.get(0).and_then(|v| v.as_u64()), Some(2));
        assert_eq!(a2.get(1).and_then(|v| v.as_u64()), Some(3));
        assert_eq!(a.get(2).and_then(|v| v.as_u64()), Some(4));
        assert_eq!(a.get(3), None);
        Ok(())
    }

    #[test]
    fn iter() -> crate::Result<()> {
        let mut input = b"[1,2,3,4]".to_vec();
        let t = to_tape(input.as_mut_slice())?;
        let v = t.as_value();
        let a = v.as_array().expect("is an array");
        let v = a
            .iter()
            .map(|v| v.as_u8().expect("integer"))
            .collect::<Vec<_>>();

        assert_eq!(v, vec![1, 2, 3, 4]);

        Ok(())
    }
    #[test]
    fn iter_container() -> crate::Result<()> {
        let mut input = b"[1,[2,3],4]".to_vec();
        let t = to_tape(input.as_mut_slice())?;
        let v = t.as_value();
        let a = v.as_array().expect("is an array");
        let v = a.iter().map(|v| v.as_u8()).collect::<Vec<_>>();

        assert_eq!(v, vec![Some(1), None, Some(4)]);

        Ok(())
    }
}