1use std::{cmp::Ordering, fmt::Debug, marker::PhantomData};
2
3use light_hasher::{bigint::bigint_to_be_bytes_array, Hasher};
4use num_bigint::BigUint;
5use num_traits::{CheckedAdd, CheckedSub, ToBytes, Unsigned, Zero};
6
7use crate::{changelog::RawIndexedElement, errors::IndexedArrayError};
8
9#[derive(Clone, Debug, Default)]
10pub struct IndexedElement<I>
11where
12 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
13 I: Into<usize>,
14{
15 pub index: I,
16 pub value: BigUint,
17 pub next_index: I,
18}
19
20impl<I> From<RawIndexedElement<I>> for IndexedElement<I>
21where
22 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
23 I: Into<usize>,
24{
25 fn from(value: RawIndexedElement<I>) -> Self {
26 IndexedElement {
27 index: value.index,
28 value: BigUint::from_bytes_be(&value.value),
29 next_index: value.next_index,
30 }
31 }
32}
33
34impl<I> PartialEq for IndexedElement<I>
35where
36 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
37 I: Into<usize>,
38{
39 fn eq(&self, other: &Self) -> bool {
40 self.value == other.value
41 && self.index == other.index
42 && self.next_index == other.next_index
43 }
44}
45
46impl<I> Eq for IndexedElement<I>
47where
48 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
49 I: Into<usize>,
50{
51}
52
53impl<I> PartialOrd for IndexedElement<I>
54where
55 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
56 I: Into<usize>,
57{
58 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
59 Some(self.cmp(other))
60 }
61}
62
63impl<I> Ord for IndexedElement<I>
64where
65 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
66 I: Into<usize>,
67{
68 fn cmp(&self, other: &Self) -> Ordering {
69 self.value.cmp(&other.value)
70 }
71}
72
73impl<I> IndexedElement<I>
74where
75 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
76 I: Into<usize>,
77{
78 pub fn index(&self) -> usize {
79 self.index.into()
80 }
81
82 pub fn next_index(&self) -> usize {
83 self.next_index.into()
84 }
85
86 pub fn hash<H>(&self, next_value: &BigUint) -> Result<[u8; 32], IndexedArrayError>
87 where
88 H: Hasher,
89 {
90 let hash = H::hashv(&[
91 bigint_to_be_bytes_array::<32>(&self.value)?.as_ref(),
92 bigint_to_be_bytes_array::<32>(next_value)?.as_ref(),
93 ])?;
94
95 Ok(hash)
96 }
97
98 pub fn update_from_raw_element(&mut self, raw_element: &RawIndexedElement<I>) {
99 self.index = raw_element.index;
100 self.value = BigUint::from_bytes_be(&raw_element.value);
101 self.next_index = raw_element.next_index;
102 }
103}
104
105#[derive(Clone, Debug)]
106pub struct IndexedElementBundle<I>
107where
108 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
109 I: Into<usize>,
110{
111 pub new_low_element: IndexedElement<I>,
112 pub new_element: IndexedElement<I>,
113 pub new_element_next_value: BigUint,
114}
115
116#[derive(Clone, Debug)]
117pub struct IndexedArray<H, I>
118where
119 H: Hasher,
120 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
121 I: Into<usize>,
122{
123 pub elements: Vec<IndexedElement<I>>,
124 pub current_node_index: I,
125 pub highest_element_index: I,
126 pub highest_value: BigUint,
127
128 _hasher: PhantomData<H>,
129}
130
131impl<H, I> Default for IndexedArray<H, I>
132where
133 H: Hasher,
134 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
135 I: Into<usize>,
136{
137 fn default() -> Self {
138 Self {
139 elements: vec![IndexedElement {
140 index: I::zero(),
141 value: BigUint::zero(),
142 next_index: I::zero(),
143 }],
144 current_node_index: I::zero(),
145 highest_element_index: I::zero(),
146 highest_value: BigUint::zero(),
147 _hasher: PhantomData,
148 }
149 }
150}
151
152impl<H, I> IndexedArray<H, I>
153where
154 H: Hasher,
155 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
156 I: Into<usize>,
157{
158 pub fn new(value: BigUint, next_value: BigUint) -> Self {
159 Self {
160 current_node_index: I::zero(),
161 highest_element_index: I::zero(),
162 highest_value: next_value,
163 elements: vec![IndexedElement {
164 index: I::zero(),
165 value,
166 next_index: I::zero(),
167 }],
168 _hasher: PhantomData,
169 }
170 }
171 pub fn get(&self, index: usize) -> Option<&IndexedElement<I>> {
172 self.elements.get(index)
173 }
174
175 pub fn len(&self) -> usize {
176 self.current_node_index.into()
177 }
178
179 pub fn is_empty(&self) -> bool {
180 self.current_node_index == I::zero()
181 }
182
183 pub fn iter(&self) -> IndexingArrayIter<H, I> {
184 IndexingArrayIter {
185 indexing_array: self,
186 front: 0,
187 back: self.current_node_index.into(),
188 }
189 }
190
191 pub fn find_element(&self, value: &BigUint) -> Option<&IndexedElement<I>> {
192 self.elements[..self.len() + 1]
193 .iter()
194 .find(|&node| node.value == *value)
195 }
196
197 pub fn find_low_element_index_for_nonexistent(
205 &self,
206 value: &BigUint,
207 ) -> Result<I, IndexedArrayError> {
208 for (i, node) in self.elements.iter().enumerate() {
211 if node.value == *value {
212 return Err(IndexedArrayError::ElementAlreadyExists);
213 }
214 if self.elements[node.next_index()].value > *value && node.value < *value {
215 return i.try_into().map_err(|_| IndexedArrayError::IntegerOverflow);
216 }
217 }
218 Ok(self.highest_element_index)
222 }
223
224 pub fn find_low_element_for_nonexistent(
236 &self,
237 value: &BigUint,
238 ) -> Result<(IndexedElement<I>, BigUint), IndexedArrayError> {
239 let low_element_index = self.find_low_element_index_for_nonexistent(value)?;
240 let low_element = self.elements[low_element_index.into()].clone();
241 let next_value = if low_element.next_index == I::zero() {
242 self.highest_value.clone()
243 } else {
244 self.elements[low_element.next_index.into()].value.clone()
245 };
246 Ok((low_element.clone(), next_value))
247 }
248
249 pub fn find_low_element_index_for_existent(
257 &self,
258 value: &BigUint,
259 ) -> Result<I, IndexedArrayError> {
260 for (i, node) in self.elements[..self.len() + 1].iter().enumerate() {
261 if self.elements[node.next_index.into()].value == *value {
262 let i = i
263 .try_into()
264 .map_err(|_| IndexedArrayError::IntegerOverflow)?;
265 return Ok(i);
266 }
267 }
268 Err(IndexedArrayError::ElementDoesNotExist)
269 }
270
271 pub fn find_low_element_for_existent(
279 &self,
280 value: &BigUint,
281 ) -> Result<IndexedElement<I>, IndexedArrayError> {
282 let low_element_index = self.find_low_element_index_for_existent(value)?;
283 let low_element = self.elements[low_element_index.into()].clone();
284 Ok(low_element)
285 }
286
287 pub fn hash_element(&self, index: I) -> Result<[u8; 32], IndexedArrayError> {
293 let element = self
294 .elements
295 .get(index.into())
296 .ok_or(IndexedArrayError::IndexHigherThanMax)?;
297 let next_element = self
298 .elements
299 .get(element.next_index.into())
300 .ok_or(IndexedArrayError::IndexHigherThanMax)?;
301 element.hash::<H>(&next_element.value)
302 }
303
304 pub fn new_element_with_low_element_index(
307 &self,
308 low_element_index: I,
309 value: &BigUint,
310 ) -> Result<IndexedElementBundle<I>, IndexedArrayError> {
311 let mut new_low_element = self.elements[low_element_index.into()].clone();
312
313 let new_element_index = self
314 .current_node_index
315 .checked_add(&I::one())
316 .ok_or(IndexedArrayError::IntegerOverflow)?;
317 let new_element = IndexedElement {
318 index: new_element_index,
319 value: value.clone(),
320 next_index: new_low_element.next_index,
321 };
322
323 new_low_element.next_index = new_element_index;
324
325 let new_element_next_value = if new_element.next_index == I::zero() {
326 self.highest_value.clone()
327 } else {
328 self.elements[new_element.next_index.into()].value.clone()
329 };
330
331 Ok(IndexedElementBundle {
332 new_low_element,
333 new_element,
334 new_element_next_value,
335 })
336 }
337
338 pub fn new_element(
339 &self,
340 value: &BigUint,
341 ) -> Result<IndexedElementBundle<I>, IndexedArrayError> {
342 let low_element_index = self.find_low_element_index_for_nonexistent(value)?;
343 let element = self.new_element_with_low_element_index(low_element_index, value)?;
344
345 Ok(element)
346 }
347
348 pub fn append_with_low_element_index(
350 &mut self,
351 low_element_index: I,
352 value: &BigUint,
353 ) -> Result<IndexedElementBundle<I>, IndexedArrayError> {
354 let old_low_element = &self.elements[low_element_index.into()];
357
358 if old_low_element.next_index == I::zero() {
360 if value <= &old_low_element.value {
364 return Err(IndexedArrayError::LowElementGreaterOrEqualToNewElement);
365 }
366 } else {
367 if value <= &old_low_element.value {
370 return Err(IndexedArrayError::LowElementGreaterOrEqualToNewElement);
371 }
372 if value >= &self.elements[old_low_element.next_index.into()].value {
375 return Err(IndexedArrayError::NewElementGreaterOrEqualToNextElement);
376 }
377 }
378
379 let new_element_bundle =
381 self.new_element_with_low_element_index(low_element_index, value)?;
382
383 if old_low_element.next_index == I::zero() {
392 self.highest_element_index = new_element_bundle.new_element.index;
393 }
394
395 self.current_node_index = new_element_bundle.new_element.index;
397 self.elements.push(new_element_bundle.new_element.clone());
398
399 self.elements[low_element_index.into()] = new_element_bundle.new_low_element.clone();
401
402 Ok(new_element_bundle)
403 }
404
405 pub fn append(
406 &mut self,
407 value: &BigUint,
408 ) -> Result<IndexedElementBundle<I>, IndexedArrayError> {
409 let low_element_index = self.find_low_element_index_for_nonexistent(value)?;
410 self.append_with_low_element_index(low_element_index, value)
411 }
412
413 pub fn lowest(&self) -> Option<IndexedElement<I>> {
414 if self.current_node_index < I::one() {
415 None
416 } else {
417 self.elements.get(1).cloned()
418 }
419 }
420}
421
422pub struct IndexingArrayIter<'a, H, I>
423where
424 H: Hasher,
425 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
426 I: Into<usize>,
427{
428 indexing_array: &'a IndexedArray<H, I>,
429 front: usize,
430 back: usize,
431}
432
433impl<'a, H, I> Iterator for IndexingArrayIter<'a, H, I>
434where
435 H: Hasher,
436 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
437 I: Into<usize>,
438{
439 type Item = &'a IndexedElement<I>;
440
441 fn next(&mut self) -> Option<Self::Item> {
442 if self.front <= self.back {
443 let result = self.indexing_array.elements.get(self.front);
444 self.front += 1;
445 result
446 } else {
447 None
448 }
449 }
450}
451
452impl<H, I> DoubleEndedIterator for IndexingArrayIter<'_, H, I>
453where
454 H: Hasher,
455 I: CheckedAdd + CheckedSub + Copy + Clone + PartialOrd + ToBytes + TryFrom<usize> + Unsigned,
456 I: Into<usize>,
457{
458 fn next_back(&mut self) -> Option<Self::Item> {
459 if self.back >= self.front {
460 let result = self.indexing_array.elements.get(self.back);
461 self.back -= 1;
462 result
463 } else {
464 None
465 }
466 }
467}