scratch_test_value/
lists.rs1use itertools::Itertools;
2
3use crate::{
4 QuirkSink, SValue,
5 quirks::{NumberTooBigForIntQ, SValueToNumberQ},
6};
7
8#[derive(Debug, PartialEq, Clone)]
9#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
10#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
11pub struct SList {
12 data: Vec<SValue>,
13 max_length: i64,
14}
15
16#[allow(clippy::enum_variant_names)]
17pub enum NthItemOfListQ {
18 PositionIsNotInt(SValue),
19 PositionZero,
20 PositionNegative(i64),
21 PositionTooBig(i64),
22}
23
24#[derive(Debug, thiserror::Error)]
25#[error("List already reached maximum length, element insertion failed")]
26pub struct SListAlreadyFull(());
27
28pub enum Indexing {
29 Invalid,
31 Normal(usize),
33 OneMore,
35}
36
37impl IntoIterator for SList {
38 type Item = SValue;
39 type IntoIter = std::vec::IntoIter<SValue>;
40 fn into_iter(self) -> Self::IntoIter {
41 self.data.into_iter()
42 }
43}
44
45impl<C: Into<SValue>> FromIterator<C> for SList {
49 fn from_iter<T: IntoIterator<Item = C>>(iter: T) -> Self {
50 let v = iter.into_iter().map_into().collect_vec();
51 Self {
52 max_length: v.len() as i64,
53 data: v,
54 }
55 }
56}
57
58#[derive(Debug, thiserror::Error)]
59#[error("The maximum length can't be smaller than the number of items in the list")]
60pub struct ListLongerThanNewMaximum;
61
62impl SList {
63 pub fn new(max_length: i64) -> Self {
64 Self {
65 data: vec![],
66 max_length,
67 }
68 }
69 pub fn iter(&self) -> impl DoubleEndedIterator<Item = &SValue> {
70 self.data().iter()
71 }
72
73 pub fn delete_all(&mut self) {
74 self.data.clear();
75 }
76 pub fn length(&self) -> i64 {
77 self.data.len() as i64
78 }
79 pub fn textual_representation(&self) -> String {
80 self.data.iter().join(" ")
81 }
82 pub fn contains_item(&self, item: &SValue) -> bool {
83 self.data.iter().any(|x| x.q_eq(item, &mut ()))
84 }
85
86 fn index_for_value<Q>(&self, one_based_n: &SValue, sink: &mut Q, is_insert: bool) -> Indexing
87 where
88 Q: QuirkSink<NthItemOfListQ> + QuirkSink<SValueToNumberQ> + QuirkSink<NumberTooBigForIntQ>,
89 {
90 let index = one_based_n.floor(sink).int_or_border(sink);
91
92 if !one_based_n.is_int() {
93 sink.put(NthItemOfListQ::PositionIsNotInt(one_based_n.clone()));
94 Indexing::Invalid
95 } else if index < 0 {
96 sink.put(NthItemOfListQ::PositionNegative(index));
97 Indexing::Invalid
98 } else if index == 0 {
99 sink.put(NthItemOfListQ::PositionZero);
100 Indexing::Invalid
101 } else if index.try_into().unwrap_or(usize::MAX) <= self.data.len() {
102 let zero_based = (index - 1) as usize;
103 Indexing::Normal(zero_based)
104 } else if (index - 1).try_into().unwrap_or(usize::MAX) == self.data.len() {
105 if !is_insert {
106 sink.put(NthItemOfListQ::PositionTooBig(index));
107 }
108 Indexing::OneMore
109 } else {
110 sink.put(NthItemOfListQ::PositionTooBig(index));
111 Indexing::Invalid
112 }
113 }
114 pub fn delete_nth<Q>(&mut self, one_based_n: &SValue, sink: &mut Q) -> Option<SValue>
122 where
123 Q: QuirkSink<NthItemOfListQ> + QuirkSink<SValueToNumberQ> + QuirkSink<NumberTooBigForIntQ>,
124 {
125 match self.index_for_value(one_based_n, sink, false) {
126 Indexing::Normal(zero_based) => Some(self.data.remove(zero_based)),
127 Indexing::Invalid | Indexing::OneMore => None,
128 }
129 }
130
131 pub fn append_item(&mut self, item: SValue) -> Result<(), SListAlreadyFull> {
133 if self.length() < self.max_length {
134 self.data.push(item);
135 Ok(())
136 } else {
137 Err(SListAlreadyFull(()))
138 }
139 }
140
141 pub fn insert_item_at<Q>(
151 &mut self,
152 one_based_n: &SValue,
153 item: SValue,
154 sink: &mut Q,
155 ) -> Result<bool, SListAlreadyFull>
156 where
157 Q: QuirkSink<NthItemOfListQ> + QuirkSink<SValueToNumberQ> + QuirkSink<NumberTooBigForIntQ>,
158 {
159 if self.length() >= self.max_length {
160 return Err(SListAlreadyFull(()));
161 }
162 match self.index_for_value(one_based_n, sink, true) {
163 Indexing::Normal(i) => {
164 self.data.insert(i, item);
165 Ok(true)
166 }
167 Indexing::OneMore => {
168 self.data.push(item);
169 Ok(true)
170 }
171 Indexing::Invalid => Ok(false),
172 }
173 }
174
175 pub fn replace_nth_item<Q>(
178 &mut self,
179 one_based_n: &SValue,
180 new_val: SValue,
181 sink: &mut Q,
182 ) -> bool
183 where
184 Q: QuirkSink<NthItemOfListQ> + QuirkSink<SValueToNumberQ> + QuirkSink<NumberTooBigForIntQ>,
185 {
186 match self.index_for_value(one_based_n, sink, false) {
187 Indexing::Invalid | Indexing::OneMore => false,
188 Indexing::Normal(i) => {
189 self.data[i] = new_val;
190 true
191 }
192 }
193 }
194
195 pub fn nth_item<Q>(&self, one_based_n: &SValue, sink: &mut Q) -> SValue
196 where
197 Q: QuirkSink<NthItemOfListQ> + QuirkSink<SValueToNumberQ> + QuirkSink<NumberTooBigForIntQ>,
198 {
199 match self.index_for_value(one_based_n, sink, false) {
201 Indexing::Normal(i) => self.data[i].clone(),
202 Indexing::OneMore | Indexing::Invalid => SValue::Text("".into()),
203 }
204 }
205
206 pub fn first_index_of_item_in_list(&self, item: &SValue) -> i64 {
207 self.data
208 .iter()
209 .find_position(|x| x.q_eq(item, &mut ()))
210 .map(|(pos, _)| pos as i64)
211 .unwrap_or(0)
212 }
213
214 pub fn set_max_length(&mut self, mut max: i64) -> Result<(), ListLongerThanNewMaximum> {
215 max = max.max(0);
216 if max as usize > self.data.len() {
217 Err(ListLongerThanNewMaximum)
218 } else {
219 self.max_length = max;
220 Ok(())
221 }
222 }
223
224 pub fn max_length(&self) -> i64 {
225 self.max_length
226 }
227 pub fn data(&self) -> &[SValue] {
228 &self.data
229 }
230
231 pub fn make_readonly(self) -> ReadonlySList {
232 ReadonlySList {
233 data: self.data.into(),
234 max_length: self.max_length,
235 }
236 }
237}
238
239#[derive(Debug, PartialEq, PartialOrd)]
240pub struct ReadonlySList {
241 data: crate::ARc<[SValue]>,
242 max_length: i64,
243}
244impl ReadonlySList {
245 pub fn owned_data(&self) -> crate::ARc<[SValue]> {
246 self.data.clone()
247 }
248 pub fn data(&self) -> &crate::ARc<[SValue]> {
249 &self.data
250 }
251 pub fn max_length(&self) -> i64 {
252 self.max_length
253 }
254}