Skip to main content

pipa/value/
list.rs

1// SPDX-FileCopyrightText: Copyright 2026 olav@occy.org
2// SPDX-License-Identifier: MPL-2.0
3
4//! A list of values.
5
6use crate::value::Value;
7use crate::value::equivalent::Equivalent;
8use crate::value::meta::Meta;
9use crate::value::print::Print;
10use crate::value::tracer::Tracer;
11use ahash::HashSet;
12use ahash::HashSetExt;
13use serde::Deserialize;
14use serde::Serialize;
15
16#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
17pub struct List {
18    #[serde(default, skip_serializing_if = "Tracer::is_empty")]
19    pub(crate) tracer: Tracer,
20    #[serde(default, skip_serializing_if = "Meta::is_empty")]
21    pub(crate) meta: Meta,
22    pub(crate) data: Vec<Value>,
23}
24
25impl core::fmt::Display for List {
26    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
27        f.write_str(&String::from_utf8_lossy(&self.clone().print_syntax()))
28    }
29}
30
31impl<V: Into<Value>> FromIterator<V> for List {
32    fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
33        Self {
34            data: iter.into_iter().map(Into::into).collect(),
35            ..Default::default()
36        }
37    }
38}
39
40impl From<Vec<Value>> for List {
41    fn from(value: Vec<Value>) -> Self {
42        Self {
43            data: value,
44            ..Default::default()
45        }
46    }
47}
48
49impl From<List> for Vec<Value> {
50    fn from(value: List) -> Self {
51        value.data
52    }
53}
54
55impl IntoIterator for List {
56    type Item = Value;
57    type IntoIter = <Vec<Value> as IntoIterator>::IntoIter;
58
59    fn into_iter(self) -> Self::IntoIter {
60        self.data.into_iter()
61    }
62}
63
64impl List {
65    pub(crate) fn trace<T: Into<Tracer>>(&mut self, tracer: T) {
66        self.tracer.trace(tracer);
67    }
68
69    pub(crate) fn tracer(&self) -> &Tracer {
70        &self.tracer
71    }
72
73    pub fn with<V: Into<Value>>(mut self, value: V) -> Self {
74        self.data.push(value.into());
75        self
76    }
77
78    pub fn get(&self, index: usize) -> Option<&Value> {
79        self.data.get(index)
80    }
81
82    pub fn set(&mut self, index: usize, value: Value) {
83        self.data[index] = value;
84    }
85
86    pub fn push(&mut self, value: Value) {
87        self.data.push(value);
88    }
89
90    pub fn first(&self) -> Option<&Value> {
91        self.data.first()
92    }
93
94    pub fn last(&self) -> Option<&Value> {
95        self.data.last()
96    }
97
98    pub fn len(&self) -> usize {
99        self.data.len()
100    }
101
102    pub fn is_empty(&self) -> bool {
103        self.data.is_empty()
104    }
105
106    pub fn contains(&self, other: &Value) -> bool {
107        self.data.iter().any(|d| d.equivalent(other))
108    }
109
110    pub fn join(self) -> Vec<u8> {
111        self.data.into_iter().flat_map(Value::join).collect()
112    }
113
114    pub fn clear(mut self) -> Self {
115        self.data = Vec::default();
116        self
117    }
118
119    pub fn intersection(mut lists: Vec<List>) -> List {
120        if lists.is_empty() {
121            return List::default();
122        }
123
124        let mut data = lists.remove(0).data;
125        data.retain(|d| lists.iter().all(|v| v.contains(d)));
126        data.into_iter().collect()
127    }
128
129    pub fn union(lists: Vec<List>) -> List {
130        let len = lists.first().map(|v| v.data.len()).unwrap_or_default();
131        let mut data = Vec::with_capacity(len);
132        let mut seen = HashSet::<Vec<u8>>::with_capacity(len);
133
134        for list in lists {
135            for value in list.data {
136                if seen.insert(value.clone().join()) {
137                    data.push(value);
138                }
139            }
140        }
141
142        data.into_iter().collect()
143    }
144
145    pub(crate) fn fold(&mut self, mut value: Self) {
146        match value.meta.get(b"internal-insert") {
147            Some(b"prepend") => {
148                value.data.append(&mut self.data);
149                self.data = value.data;
150            }
151            Some(b"append") => {
152                self.data.append(&mut value.data);
153            }
154            _ => {
155                *self = value;
156            }
157        }
158    }
159}