1use core::{
2 primitive::{
3 usize,
4 bool
5 },
6 result::Result
7};
8use alloc::vec::Vec;
9use alloc::vec;
10use crate::required::SetOutcome;
11
12#[derive(Debug)]
13pub enum ListError {
14 OutOfBounds,
15 NotExist,
16}
17#[derive(Debug)]
18pub enum VariableListError {
19 List(ListError),
20 Compact,
21}
22
23fn is_null<T: Default + PartialEq>(unit: &[T]) -> bool {
24 unit.iter().all(|x| *x == T::default())
25}
26
27pub struct List<T> {
57 pub data: Vec<T>,
58}
59
60impl<T: Copy + Default + PartialEq> List<T> {
61 pub fn new(width: usize) -> Self {
62 Self {
63 data: vec![T::default(); width],
64 }
65 }
66}
67
68impl<T: Copy + Default + PartialEq> List<T> {
69
70 pub fn get<'a>(
71 &'a self,
72 identity: &usize,
73 schema: &usize,
74 ) -> Result<&'a [T], ListError> {
75 let start = identity * schema;
76 let end = start + schema;
77 let unit = self.data.get(start..end).ok_or(ListError::OutOfBounds)?;
78 if is_null(unit) {
79 return Err(ListError::NotExist);
80 }
81 Ok(unit)
82 }
83
84 pub fn set(
86 &mut self,
87 identity: &usize,
88 schema: &mut usize,
89 value: &[T],
90 reuse_vacant: bool,
91 ) -> Result<SetOutcome, ListError> {
92 if value.len() != *schema {
93 return Err(ListError::OutOfBounds);
94 }
95 let unit = *schema;
96 if *identity != 0 {
97 let start = identity * unit;
98 let end = start + unit;
99 if end > self.data.len() {
100 return Err(ListError::OutOfBounds);
101 }
102 if is_null(&self.data[start..end]) {
103 return Err(ListError::NotExist);
104 }
105 self.data[start..end].copy_from_slice(value);
106 Ok(SetOutcome::Updated)
107 } else {
108 if self.data.is_empty() {
110 self.data.extend(core::iter::repeat(T::default()).take(unit));
111 }
112 let vacant = if reuse_vacant {
113 (1..self.data.len() / unit)
114 .find(|&i| is_null(&self.data[i * unit..(i + 1) * unit]))
115 } else {
116 None
117 };
118 match vacant {
119 Some(i) => {
120 self.data[i * unit..(i + 1) * unit].copy_from_slice(value);
121 Ok(SetOutcome::Created(i))
122 }
123 None => {
124 let i = self.data.len() / unit;
125 self.data.extend_from_slice(value);
126 Ok(SetOutcome::Created(i))
127 }
128 }
129 }
130 }
131
132 pub fn delete(
133 &mut self,
134 identity: &usize,
135 schema: &mut usize,
136 ) -> Result<(), ListError> {
137 let unit = *schema;
138 let start = identity * unit;
139 let end = start + unit;
140 if end > self.data.len() {
141 return Err(ListError::OutOfBounds);
142 }
143 self.data[start..end].fill(T::default());
144 Ok(())
145 }
146}
147
148pub struct VariableList<T> {
179 pub identity: Vec<usize>,
180 pub data: Vec<T>,
181}
182
183impl<T: Copy + Default + PartialEq> VariableList<T> {
184 pub fn new() -> Self {
185 Self {
186 identity: vec![0, 0], data: Vec::new(),
188 }
189 }
190}
191
192impl<T: Copy + Default + PartialEq> VariableList<T> {
193
194 pub fn get<'a>(
195 &'a self,
196 identity: &usize,
197 ) -> Result<&'a [T], ListError> {
198 let identity_start = identity * 2;
199 let identity_end = identity_start + 2;
200 let identity_range = self.identity.get(identity_start..identity_end).ok_or(ListError::OutOfBounds)?;
201 if is_null(identity_range) {
202 return Err(ListError::NotExist);
203 }
204 let start = identity_range[0];
205 let end = identity_range[1];
206 self.data.get(start..end).ok_or(ListError::OutOfBounds)
207 }
208
209 pub fn set(
215 &mut self,
216 identity: &usize,
217 value: &[T],
218 intern: bool,
219 ) -> Result<SetOutcome, ListError> {
220 if *identity != 0 {
221 let identity_start = identity * 2;
222 let identity_end = identity_start + 2;
223 if identity_end > self.identity.len() {
224 return Err(ListError::OutOfBounds);
225 }
226 if is_null(&self.identity[identity_start..identity_end]) {
227 return Err(ListError::NotExist);
228 }
229 let old_start = self.identity[identity_start];
230 let old_end = self.identity[identity_start + 1];
231 let old_len = old_end - old_start;
232 if value.len() <= old_len {
233 self.data[old_start..old_start + value.len()].copy_from_slice(value);
235 self.identity[identity_start + 1] = old_start + value.len();
236 } else {
237 let start = self.data.len();
239 let end = start + value.len();
240 self.data.extend_from_slice(value);
241 self.identity[identity_start..identity_end].copy_from_slice(&[start, end]);
242 }
243 Ok(SetOutcome::Updated)
244 } else {
245 if intern {
246 let count = self.identity.len() / 2;
247 for i in 1..count {
248 let identity_start = i * 2;
249 let start = self.identity[identity_start];
250 let end = self.identity[identity_start + 1];
251 if !is_null(&self.identity[identity_start..identity_start + 2]) && &self.data[start..end] == value {
252 return Ok(SetOutcome::Created(i));
253 }
254 }
255 }
256 let start = self.data.len();
257 let end = start + value.len();
258 self.data.extend_from_slice(value);
259 let entry = [start, end];
261 let mut ls: List<usize> = List {
262 data: core::mem::take(&mut self.identity),
263 };
264 let outcome = ls.set(&0, &mut 2usize, &entry, false)
265 .map_err(|_| ListError::OutOfBounds)?;
266 self.identity = ls.data;
267 Ok(outcome)
268 }
269 }
270
271 pub fn delete(
272 &mut self,
273 identity: &usize,
274 ) -> Result<(), ListError> {
275 if *identity == 0 {
276 return Err(ListError::NotExist);
277 }
278 let identity_start = identity * 2;
279 let identity_end = identity_start + 2;
280 if identity_end > self.identity.len() {
281 return Err(ListError::OutOfBounds);
282 }
283 self.identity[identity_start..identity_end].fill(0);
284 Ok(())
285 }
286
287
288 pub fn compact(&mut self) -> Result<alloc::collections::BTreeMap<usize, usize>, VariableListError> {
308 let mut new_identity = vec![0, 0]; let mut new_data: Vec<T> = Vec::new();
310 let mut remap = alloc::collections::BTreeMap::new();
311 let count = self.identity.len() / 2;
312 for i in 1..count {
314 let identity_start = i * 2;
315 if is_null(&self.identity[identity_start..identity_start + 2]) {
316 continue;
317 }
318 let start = self.identity[identity_start];
319 let end = self.identity[identity_start + 1];
320 let slice = self.data.get(start..end).ok_or(VariableListError::Compact)?;
321 let new_start = new_data.len();
322 new_data.extend_from_slice(slice);
323 let new_end = new_data.len();
324 let new_id = new_identity.len() / 2;
325 new_identity.push(new_start);
326 new_identity.push(new_end);
327 remap.insert(i, new_id);
328 }
329 self.identity = new_identity;
330 self.data = new_data;
331 Ok(remap)
332 }
333}
334
335#[cfg(test)]
336mod tests {
337 use super::*;
338 use crate::required::SetOutcome;
339
340 #[test]
343 fn list_set_update_append_when_value_too_large() {
344 let mut vl: VariableList<u32> = VariableList::new();
346 vl.set(&0, &[1u32, 2], false).unwrap(); let r = vl.set(&1, &[10u32, 20, 30], false).unwrap();
349 assert!(matches!(r, SetOutcome::Updated));
350 assert_eq!(vl.get(&1).unwrap(), &[10u32, 20, 30]);
351 }
352
353 #[test]
354 fn list_set_wrong_width_returns_out_of_bounds() {
355 let mut list: List<u32> = List::new(2);
356 let err = list.set(&0, &mut 2, &[1u32], false).unwrap_err();
357 assert!(matches!(err, ListError::OutOfBounds));
358 }
359
360 #[test]
361 fn list_set_update_not_exist() {
362 let mut list: List<u32> = List::new(2);
363 list.set(&0, &mut 2, &[1u32, 2], false).unwrap();
365 list.delete(&1, &mut 2).unwrap();
366 let err = list.set(&1, &mut 2, &[3u32, 4], false).unwrap_err();
367 assert!(matches!(err, ListError::NotExist));
368 }
369
370 #[test]
371 fn list_set_update_out_of_bounds() {
372 let mut list: List<u32> = List::new(2);
373 let err = list.set(&99, &mut 2, &[1u32, 2], false).unwrap_err();
374 assert!(matches!(err, ListError::OutOfBounds));
375 }
376
377 #[test]
378 fn list_get_sentinel_returns_not_exist() {
379 let list: List<u32> = List::new(2);
380 let err = list.get(&0, &2).unwrap_err();
381 assert!(matches!(err, ListError::NotExist));
382 }
383
384 #[test]
387 fn variable_list_delete_sentinel_returns_not_exist() {
388 let mut vl: VariableList<u32> = VariableList::new();
389 let err = vl.delete(&0).unwrap_err();
390 assert!(matches!(err, ListError::NotExist));
391 }
392
393 #[test]
394 fn variable_list_compact_invalidates_old_identity() {
395 let mut vl: VariableList<u32> = VariableList::new();
396 vl.set(&0, &[1u32, 2, 3], false).unwrap(); vl.set(&0, &[4u32, 5, 6], false).unwrap(); vl.delete(&1).unwrap();
399 vl.compact().unwrap();
400 assert!(vl.get(&2).is_err());
402 assert_eq!(vl.get(&1).unwrap(), &[4u32, 5, 6]);
403 }
404}