1use std::borrow::Borrow;
2use std::collections::BTreeMap;
3use std::marker::PhantomData;
4
5use super::{
6 aug_dict_find_by_extra, aug_dict_insert, aug_dict_remove_owned,
7 build_aug_dict_from_sorted_iter, SearchByExtra, SetMode,
8};
9use crate::cell::*;
10use crate::error::*;
11use crate::util::*;
12
13use super::raw::*;
14use super::typed::*;
15use super::{read_label, DictKey};
16
17pub trait AugDictExtra: Default {
19 fn comp_add(
27 left: &mut CellSlice,
28 right: &mut CellSlice,
29 b: &mut CellBuilder,
30 cx: &mut dyn CellContext,
31 ) -> Result<(), Error>;
32}
33
34pub struct AugDict<K, A, V> {
51 dict: Dict<K, (A, V)>,
52 extra: A,
53 _key: PhantomData<K>,
54 _value: PhantomData<(A, V)>,
55}
56
57impl<K, A: ExactSize, V> ExactSize for AugDict<K, A, V> {
58 #[inline]
59 fn exact_size(&self) -> Size {
60 self.dict.exact_size() + self.extra.exact_size()
61 }
62}
63
64impl<'a, K, A: Load<'a>, V> Load<'a> for AugDict<K, A, V> {
65 #[inline]
66 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
67 Ok(Self {
68 dict: ok!(Dict::load_from(slice)),
69 extra: ok!(A::load_from(slice)),
70 _key: PhantomData,
71 _value: PhantomData,
72 })
73 }
74}
75
76impl<K, A: Store, V> Store for AugDict<K, A, V> {
77 #[inline]
78 fn store_into(
79 &self,
80 builder: &mut CellBuilder,
81 context: &mut dyn CellContext,
82 ) -> Result<(), Error> {
83 ok!(self.dict.store_into(builder, context));
84 self.extra.store_into(builder, context)
85 }
86}
87
88impl<K, A: Default, V> Default for AugDict<K, A, V> {
89 #[inline]
90 fn default() -> Self {
91 Self::new()
92 }
93}
94
95impl<K, A: Clone, V> Clone for AugDict<K, A, V> {
96 fn clone(&self) -> Self {
97 Self {
98 dict: self.dict.clone(),
99 extra: self.extra.clone(),
100 _key: PhantomData,
101 _value: PhantomData,
102 }
103 }
104}
105
106impl<K, A: Eq, V> Eq for AugDict<K, A, V> {}
107
108impl<K, A: PartialEq, V> PartialEq for AugDict<K, A, V> {
109 fn eq(&self, other: &Self) -> bool {
110 self.dict.eq(&other.dict) && self.extra.eq(&other.extra)
111 }
112}
113
114impl<K, A: std::fmt::Debug, V> std::fmt::Debug for AugDict<K, A, V> {
115 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116 debug_struct_field2_finish(f, "AugDict", "dict", &self.dict, "extra", &self.extra)
117 }
118}
119
120impl<K, A: Default, V> AugDict<K, A, V> {
121 pub fn new() -> Self {
123 Self {
124 dict: Dict::new(),
125 extra: A::default(),
126 _key: PhantomData,
127 _value: PhantomData,
128 }
129 }
130
131 pub const fn from_parts(dict: Dict<K, (A, V)>, extra: A) -> Self {
133 Self {
134 dict,
135 extra,
136 _key: PhantomData,
137 _value: PhantomData,
138 }
139 }
140
141 pub fn into_parts(self) -> (Dict<K, (A, V)>, A) {
143 (self.dict, self.extra)
144 }
145
146 #[inline]
148 pub fn cast_into<Q, T>(self) -> AugDict<Q, A, T>
149 where
150 Q: EquivalentRepr<K>,
151 (A, T): EquivalentRepr<(A, V)>,
152 {
153 AugDict {
154 dict: self.dict.cast_into(),
155 extra: self.extra,
156 _key: PhantomData,
157 _value: PhantomData,
158 }
159 }
160}
161
162impl<K: DictKey, A, V> AugDict<K, A, V> {
163 #[allow(unused)]
164 pub(crate) fn load_from_root<'a>(
165 slice: &mut CellSlice<'a>,
166 context: &mut dyn CellContext,
167 ) -> Result<Self, Error>
168 where
169 A: Load<'a>,
170 V: Load<'a>,
171 {
172 let (extra, root) = ok!(load_from_root::<A, V>(slice, K::BITS, context));
173
174 Ok(Self {
175 dict: Dict::from(Some(root)),
176 extra,
177 _key: PhantomData,
178 _value: PhantomData,
179 })
180 }
181}
182
183impl<K, A, V> AugDict<K, A, V>
184where
185 K: DictKey,
186 for<'a> A: Default + Load<'a>,
187{
188 pub fn update_root_extra(&mut self) -> Result<(), Error> {
190 self.extra = match &self.dict.root {
191 Some(root) => {
192 let slice = &mut ok!(root.as_slice());
193 let prefix = ok!(read_label(slice, K::BITS));
194 if prefix.size_bits() != K::BITS {
195 ok!(slice.skip_first(0, 2));
196 }
197 ok!(A::load_from(slice))
198 }
199 None => A::default(),
200 };
201 Ok(())
202 }
203}
204
205fn load_from_root<'a, A, V>(
206 slice: &mut CellSlice<'a>,
207 key_bit_len: u16,
208 context: &mut dyn CellContext,
209) -> Result<(A, Cell), Error>
210where
211 A: Load<'a>,
212 V: Load<'a>,
213{
214 let root = *slice;
215
216 let label = ok!(read_label(slice, key_bit_len));
217 let extra = if label.size_bits() != key_bit_len {
218 ok!(slice.skip_first(0, 2));
219 ok!(A::load_from(slice))
220 } else {
221 let extra = ok!(A::load_from(slice));
222 ok!(V::load_from(slice));
223 extra
224 };
225
226 let root_bits = root.size_bits() - slice.size_bits();
227 let root_refs = root.size_refs() - slice.size_refs();
228
229 let mut b = CellBuilder::new();
230 ok!(b.store_slice(root.get_prefix(root_bits, root_refs)));
231 match b.build_ext(context) {
232 Ok(cell) => Ok((extra, cell)),
233 Err(e) => Err(e),
234 }
235}
236
237impl<K, A, V> AugDict<K, A, V> {
238 pub const fn is_empty(&self) -> bool {
240 self.dict.is_empty()
241 }
242
243 #[inline]
245 pub const fn dict(&self) -> &Dict<K, (A, V)> {
246 &self.dict
247 }
248
249 #[inline]
251 pub const fn root_extra(&self) -> &A {
252 &self.extra
253 }
254}
255
256impl<K, A, V> AugDict<K, A, V>
257where
258 K: Store + DictKey,
259{
260 pub fn contains_key<Q>(&self, key: Q) -> Result<bool, Error>
262 where
263 Q: Borrow<K>,
264 {
265 self.dict.contains_key(key)
266 }
267}
268
269impl<K, A, V> AugDict<K, A, V>
270where
271 K: Store + DictKey,
272{
273 pub fn get<'a: 'b, 'b, Q>(&'a self, key: Q) -> Result<Option<(A, V)>, Error>
275 where
276 Q: Borrow<K> + 'b,
277 (A, V): Load<'a>,
278 {
279 self.dict.get(key)
280 }
281}
282
283impl<K, A, V> AugDict<K, A, V>
284where
285 K: DictKey,
286{
287 pub fn find_by_extra<'a, S>(&'a self, flow: S) -> Result<Option<(K, A, V)>, Error>
291 where
292 S: SearchByExtra<A>,
293 A: Load<'a>,
294 V: Load<'a>,
295 {
296 let Some((key, extra, mut value)) = ok!(aug_dict_find_by_extra::<A, S>(
297 self.dict.root.as_ref(),
298 K::BITS,
299 flow
300 )) else {
301 return Ok(None);
302 };
303
304 let Some(key) = K::from_raw_data(key.raw_data()) else {
305 return Err(Error::CellUnderflow);
306 };
307 let value = ok!(V::load_from(&mut value));
308 Ok(Some((key, extra, value)))
309 }
310}
311
312impl<K, A, V> AugDict<K, A, V>
313where
314 K: Store + DictKey,
315 for<'a> A: AugDictExtra + Store + Load<'a>,
316 V: Store,
317{
318 pub fn try_from_btree<Q, E, T>(sorted: &BTreeMap<Q, (E, T)>) -> Result<Self, Error>
320 where
321 Q: Borrow<K>,
322 E: Borrow<A>,
323 T: Borrow<V>,
324 K: Ord,
325 {
326 let root = ok!(build_aug_dict_from_sorted_iter(
327 sorted
328 .iter()
329 .map(|(k, (a, v))| (k.borrow(), a.borrow(), v.borrow())),
330 K::BITS,
331 A::comp_add,
332 &mut Cell::empty_context()
333 ));
334
335 let mut result = Self {
336 dict: Dict::from_raw(root),
337 extra: A::default(),
338 _key: PhantomData,
339 _value: PhantomData,
340 };
341 ok!(result.update_root_extra());
342 Ok(result)
343 }
344
345 pub fn try_from_sorted_slice<Q, E, T>(sorted: &[(Q, E, T)]) -> Result<Self, Error>
347 where
348 Q: Borrow<K>,
349 E: Borrow<A>,
350 T: Borrow<V>,
351 K: Ord,
352 {
353 let root = ok!(build_aug_dict_from_sorted_iter(
354 sorted
355 .iter()
356 .map(|(k, a, v)| (k.borrow(), a.borrow(), v.borrow())),
357 K::BITS,
358 A::comp_add,
359 &mut Cell::empty_context()
360 ));
361
362 let mut result = Self {
363 dict: Dict::from_raw(root),
364 extra: A::default(),
365 _key: PhantomData,
366 _value: PhantomData,
367 };
368 ok!(result.update_root_extra());
369 Ok(result)
370 }
371
372 pub fn set<Q, E, T>(&mut self, key: Q, aug: E, value: T) -> Result<bool, Error>
378 where
379 Q: Borrow<K>,
380 E: Borrow<A>,
381 T: Borrow<V>,
382 {
383 self.set_ext(key, aug, value, &mut Cell::empty_context())
384 }
385
386 pub fn set_ext<Q, E, T>(
388 &mut self,
389 key: Q,
390 aug: E,
391 value: T,
392 context: &mut dyn CellContext,
393 ) -> Result<bool, Error>
394 where
395 Q: Borrow<K>,
396 E: Borrow<A>,
397 T: Borrow<V>,
398 {
399 self.insert_impl(
400 key.borrow(),
401 aug.borrow(),
402 value.borrow(),
403 SetMode::Set,
404 context,
405 )
406 }
407
408 pub fn replace<Q, E, T>(&mut self, key: Q, aug: E, value: T) -> Result<bool, Error>
415 where
416 Q: Borrow<K>,
417 E: Borrow<A>,
418 T: Borrow<V>,
419 {
420 self.replace_ext(key, aug, value, &mut Cell::empty_context())
421 }
422
423 pub fn replace_ext<Q, E, T>(
426 &mut self,
427 key: Q,
428 aug: E,
429 value: T,
430 context: &mut dyn CellContext,
431 ) -> Result<bool, Error>
432 where
433 Q: Borrow<K>,
434 E: Borrow<A>,
435 T: Borrow<V>,
436 {
437 self.insert_impl(
438 key.borrow(),
439 aug.borrow(),
440 value.borrow(),
441 SetMode::Replace,
442 context,
443 )
444 }
445
446 pub fn add<Q, E, T>(&mut self, key: Q, aug: E, value: T) -> Result<bool, Error>
453 where
454 Q: Borrow<K>,
455 E: Borrow<A>,
456 T: Borrow<V>,
457 {
458 self.add_ext(key, aug, value, &mut Cell::empty_context())
459 }
460
461 pub fn add_ext<Q, E, T>(
464 &mut self,
465 key: Q,
466 aug: E,
467 value: T,
468 context: &mut dyn CellContext,
469 ) -> Result<bool, Error>
470 where
471 Q: Borrow<K>,
472 E: Borrow<A>,
473 T: Borrow<V>,
474 {
475 self.insert_impl(
476 key.borrow(),
477 aug.borrow(),
478 value.borrow(),
479 SetMode::Add,
480 context,
481 )
482 }
483
484 pub fn remove<Q>(&mut self, key: Q) -> Result<Option<(A, V)>, Error>
487 where
488 Q: Borrow<K>,
489 for<'a> A: Load<'a> + 'static,
490 for<'a> V: Load<'a> + 'static,
491 {
492 match ok!(self.remove_raw_ext(key, &mut Cell::empty_context())) {
493 Some((cell, range)) => {
494 let mut slice = ok!(range.apply(&cell));
495 let extra = ok!(A::load_from(&mut slice));
496 let value = ok!(V::load_from(&mut slice));
497 Ok(Some((extra, value)))
498 }
499 None => Ok(None),
500 }
501 }
502
503 pub fn remove_raw_ext<Q>(
506 &mut self,
507 key: Q,
508 context: &mut dyn CellContext,
509 ) -> Result<Option<CellSliceParts>, Error>
510 where
511 Q: Borrow<K>,
512 {
513 self.remove_impl(key.borrow(), context)
514 }
515
516 fn insert_impl(
517 &mut self,
518 key: &K,
519 extra: &A,
520 value: &V,
521 mode: SetMode,
522 context: &mut dyn CellContext,
523 ) -> Result<bool, Error> {
524 let mut key_builder = CellBuilder::new();
525 ok!(key.store_into(&mut key_builder, &mut Cell::empty_context()));
526 let inserted = ok!(aug_dict_insert(
527 &mut self.dict.root,
528 &mut key_builder.as_data_slice(),
529 K::BITS,
530 extra,
531 value,
532 mode,
533 A::comp_add,
534 context,
535 ));
536
537 if inserted {
538 ok!(self.update_root_extra());
539 }
540
541 Ok(inserted)
542 }
543
544 fn remove_impl(
545 &mut self,
546 key: &K,
547 context: &mut dyn CellContext,
548 ) -> Result<Option<(Cell, CellSliceRange)>, Error> {
549 let mut key_builder = CellBuilder::new();
550 ok!(key.store_into(&mut key_builder, &mut Cell::empty_context()));
551 let res = ok!(aug_dict_remove_owned(
552 &mut self.dict.root,
553 &mut key_builder.as_data_slice(),
554 K::BITS,
555 false,
556 A::comp_add,
557 context,
558 ));
559
560 if res.is_some() {
561 ok!(self.update_root_extra());
562 }
563
564 Ok(res)
565 }
566
567 pub fn split(&self) -> Result<(Self, Self), Error> {
569 self.split_by_prefix_ext(&Default::default(), &mut Cell::empty_context())
570 }
571
572 pub fn split_ext(&self, context: &mut dyn CellContext) -> Result<(Self, Self), Error> {
574 self.split_by_prefix_ext(&Default::default(), context)
575 }
576
577 pub fn split_by_prefix(&self, key_prefix: &CellSlice<'_>) -> Result<(Self, Self), Error> {
579 self.split_by_prefix_ext(key_prefix, &mut Cell::empty_context())
580 }
581
582 pub fn split_by_prefix_ext(
584 &self,
585 key_prefix: &CellSlice<'_>,
586 context: &mut dyn CellContext,
587 ) -> Result<(Self, Self), Error> {
588 let (left, right) = ok!(self.dict.split_by_prefix_ext(key_prefix, context));
589
590 let mut left = Self {
591 dict: left,
592 extra: A::default(),
593 _key: PhantomData,
594 _value: PhantomData,
595 };
596 ok!(left.update_root_extra());
597
598 let mut right = Self {
599 dict: right,
600 extra: A::default(),
601 _key: PhantomData,
602 _value: PhantomData,
603 };
604 ok!(right.update_root_extra());
605
606 Ok((left, right))
607 }
608}
609
610impl<K, A, V> AugDict<K, A, V>
611where
612 K: DictKey,
613{
614 pub fn iter<'a>(&'a self) -> AugIter<'a, K, A, V>
628 where
629 V: Load<'a>,
630 {
631 AugIter::new(self.dict.root())
632 }
633
634 pub fn keys(&'_ self) -> Keys<'_, K> {
647 Keys::new(self.dict.root())
648 }
649}
650
651impl<K, A, V> AugDict<K, A, V>
652where
653 K: DictKey,
654{
655 pub fn values<'a>(&'a self) -> Values<'a, (A, V)>
661 where
662 V: Load<'a>,
663 {
664 Values::new(self.dict.root(), K::BITS)
665 }
666}
667
668impl<K, A, V> AugDict<K, A, V>
669where
670 K: Store + DictKey,
671{
672 pub fn raw_iter(&'_ self) -> RawIter<'_> {
686 RawIter::new(self.dict.root(), K::BITS)
687 }
688
689 pub fn raw_keys(&'_ self) -> RawKeys<'_> {
703 RawKeys::new(self.dict.root(), K::BITS)
704 }
705}
706
707impl<K, A, V> AugDict<K, A, V>
708where
709 K: DictKey,
710{
711 pub fn raw_values(&'_ self) -> RawValues<'_> {
717 RawValues::new(self.dict.root(), K::BITS)
718 }
719}
720
721#[cfg(feature = "serde")]
722impl<K, A, V> serde::Serialize for AugDict<K, A, V>
723where
724 K: serde::Serialize + Store + DictKey,
725 for<'a> A: serde::Serialize + Store + Load<'a>,
726 for<'a> V: serde::Serialize + Load<'a>,
727{
728 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
729 where
730 S: serde::Serializer,
731 {
732 use serde::ser::{Error, SerializeMap};
733
734 #[derive(serde::Serialize)]
735 struct AugDictHelper<'a, K, A, V>
736 where
737 K: serde::Serialize + Store + DictKey,
738 A: serde::Serialize + Store + Load<'a>,
739 V: serde::Serialize + Load<'a>,
740 {
741 #[serde(serialize_with = "serialize_dict_entries")]
742 entires: &'a AugDict<K, A, V>,
743 extra: &'a A,
744 }
745
746 fn serialize_dict_entries<'a, K, A, V, S>(
747 dict: &'a AugDict<K, A, V>,
748 serializer: S,
749 ) -> Result<S::Ok, S::Error>
750 where
751 S: serde::Serializer,
752 K: serde::Serialize + Store + DictKey,
753 A: serde::Serialize + Store + Load<'a>,
754 V: serde::Serialize + Load<'a>,
755 {
756 let mut ser = serializer.serialize_map(None)?;
757 for ref entry in dict.iter() {
758 let (key, extra, value) = match entry {
759 Ok(entry) => entry,
760 Err(e) => return Err(Error::custom(e)),
761 };
762 ok!(ser.serialize_entry(key, &(extra, value)));
763 }
764 ser.end()
765 }
766
767 if serializer.is_human_readable() {
768 AugDictHelper {
769 entires: self,
770 extra: &self.extra,
771 }
772 .serialize(serializer)
773 } else {
774 crate::boc::BocRepr::serialize(self, serializer)
775 }
776 }
777}
778
779pub struct AugIter<'a, K, A, V> {
785 inner: Iter<'a, K, (A, V)>,
786}
787
788impl<K, A, V> Clone for AugIter<'_, K, A, V> {
789 fn clone(&self) -> Self {
790 Self {
791 inner: self.inner.clone(),
792 }
793 }
794}
795
796impl<'a, K, A, V> AugIter<'a, K, A, V>
797where
798 K: DictKey,
799{
800 pub fn new(root: &'a Option<Cell>) -> Self {
802 Self {
803 inner: Iter::new(root),
804 }
805 }
806
807 #[inline]
809 pub fn reversed(mut self) -> Self {
810 self.inner = self.inner.reversed();
811 self
812 }
813
814 #[inline]
816 pub fn signed(mut self) -> Self {
817 self.inner = self.inner.signed();
818 self
819 }
820}
821
822impl<'a, K, A, V> Iterator for AugIter<'a, K, A, V>
823where
824 K: DictKey,
825 (A, V): Load<'a>,
826{
827 type Item = Result<(K, A, V), Error>;
828
829 fn next(&mut self) -> Option<Self::Item> {
830 match self.inner.next()? {
831 Ok((key, (aug, value))) => Some(Ok((key, aug, value))),
832 Err(e) => Some(Err(e)),
833 }
834 }
835}
836
837#[cfg(test)]
838mod tests {
839 use anyhow::Context;
840
841 use super::*;
842
843 #[derive(Debug, Default, Load, Store, Eq, PartialEq)]
844 struct OrCmp(bool);
845
846 impl AugDictExtra for OrCmp {
847 fn comp_add(
848 left: &mut CellSlice,
849 right: &mut CellSlice,
850 b: &mut CellBuilder,
851 _: &mut dyn CellContext,
852 ) -> Result<(), Error> {
853 let left = left.load_bit()?;
854 let right = right.load_bit()?;
855 b.store_bit(left | right)
856 }
857 }
858
859 #[derive(Debug, Default, Load, Store, Eq, PartialEq)]
860 struct SomeValue(u32);
861
862 impl AugDictExtra for SomeValue {
863 fn comp_add(
864 left: &mut CellSlice,
865 right: &mut CellSlice,
866 b: &mut CellBuilder,
867 _: &mut dyn CellContext,
868 ) -> Result<(), Error> {
869 let left = left.load_u32()?;
870 let right = right.load_u32()?;
871 b.store_u32(left.saturating_add(right))
872 }
873 }
874
875 impl rand::distributions::Distribution<SomeValue> for rand::distributions::Standard {
876 #[inline]
877 fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> SomeValue {
878 SomeValue(rand::distributions::Standard.sample(rng))
879 }
880 }
881
882 #[test]
883 fn dict_set() {
884 let mut dict = AugDict::<u32, OrCmp, u16>::new();
885 assert_eq!(*dict.root_extra(), OrCmp(false));
886
887 dict.set(123, OrCmp(false), 0xffff).unwrap();
888 assert_eq!(dict.get(123).unwrap(), Some((OrCmp(false), 0xffff)));
889 assert_eq!(*dict.root_extra(), OrCmp(false));
890
891 dict.set(123, OrCmp(true), 0xcafe).unwrap();
892 assert_eq!(dict.get(123).unwrap(), Some((OrCmp(true), 0xcafe)));
893 assert_eq!(*dict.root_extra(), OrCmp(true));
894 }
895
896 #[test]
897 fn dict_set_complex() {
898 let mut dict = AugDict::<u32, OrCmp, u32>::new();
899 assert_eq!(*dict.root_extra(), OrCmp(false));
900
901 for i in 0..520 {
902 dict.set(i, OrCmp(true), 123).unwrap();
903 }
904 assert_eq!(*dict.root_extra(), OrCmp(true));
905 }
906
907 #[test]
908 fn dict_replace() {
909 let mut dict = AugDict::<u32, OrCmp, u16>::new();
910 assert_eq!(*dict.root_extra(), OrCmp(false));
911 dict.replace(123, OrCmp(false), 0xff).unwrap();
912 assert!(!dict.contains_key(123).unwrap());
913 assert_eq!(*dict.root_extra(), OrCmp(false));
914
915 dict.set(123, OrCmp(false), 0xff).unwrap();
916 assert_eq!(dict.get(123).unwrap(), Some((OrCmp(false), 0xff)));
917 assert_eq!(*dict.root_extra(), OrCmp(false));
918
919 dict.replace(123, OrCmp(true), 0xaa).unwrap();
920 assert_eq!(dict.get(123).unwrap(), Some((OrCmp(true), 0xaa)));
921 assert_eq!(*dict.root_extra(), OrCmp(true));
922 }
923
924 #[test]
925 fn dict_add() {
926 let mut dict = AugDict::<u32, OrCmp, u16>::new();
927 assert_eq!(*dict.root_extra(), OrCmp(false));
928
929 dict.add(123, OrCmp(false), 0x12).unwrap();
930 assert_eq!(dict.get(123).unwrap(), Some((OrCmp(false), 0x12)));
931 assert_eq!(*dict.root_extra(), OrCmp(false));
932
933 dict.add(123, OrCmp(true), 0x11).unwrap();
934 assert_eq!(dict.get(123).unwrap(), Some((OrCmp(false), 0x12)));
935 assert_eq!(*dict.root_extra(), OrCmp(false));
936 }
937
938 #[test]
939 fn dict_remove() {
940 let mut dict = AugDict::<u32, OrCmp, u32>::new();
941 assert_eq!(*dict.root_extra(), OrCmp(false));
942
943 for i in 0..10 {
944 assert!(dict.set(i, OrCmp(i % 2 == 0), i).unwrap());
945 }
946 assert_eq!(*dict.root_extra(), OrCmp(true));
947
948 let mut check_remove = |n: u32, expected: Option<(OrCmp, u32)>| -> anyhow::Result<()> {
949 let removed = dict.remove(n).context("Failed to remove")?;
950 anyhow::ensure!(removed == expected);
951 Ok(())
952 };
953
954 check_remove(0, Some((OrCmp(true), 0))).unwrap();
955
956 check_remove(4, Some((OrCmp(true), 4))).unwrap();
957
958 check_remove(9, Some((OrCmp(false), 9))).unwrap();
959 check_remove(9, None).unwrap();
960
961 check_remove(5, Some((OrCmp(false), 5))).unwrap();
962 check_remove(5, None).unwrap();
963
964 check_remove(100, None).unwrap();
965
966 check_remove(1, Some((OrCmp(false), 1))).unwrap();
967 check_remove(2, Some((OrCmp(true), 2))).unwrap();
968 check_remove(3, Some((OrCmp(false), 3))).unwrap();
969 check_remove(6, Some((OrCmp(true), 6))).unwrap();
970 check_remove(7, Some((OrCmp(false), 7))).unwrap();
971 check_remove(8, Some((OrCmp(true), 8))).unwrap();
972
973 assert!(dict.is_empty());
974 }
975
976 #[test]
977 fn dict_iter() {
978 let mut dict = AugDict::<u32, SomeValue, u32>::new();
979 assert_eq!(*dict.root_extra(), SomeValue(0));
980
981 let mut expected_extra = 0;
982 for i in 0..10 {
983 expected_extra += i;
984 dict.set(i, SomeValue(i), 9 - i).unwrap();
985 }
986 assert_eq!(*dict.root_extra(), SomeValue(expected_extra));
987
988 let size = dict.values().count();
989 assert_eq!(size, 10);
990
991 for (i, entry) in dict.iter().enumerate() {
992 let (key, aug, value) = entry.unwrap();
993 assert_eq!(SomeValue(key), aug);
994 assert_eq!(key, i as u32);
995 assert_eq!(value, 9 - i as u32);
996 }
997 }
998
999 #[cfg(feature = "models")]
1000 #[test]
1001 fn aug_test() {
1002 use crate::models::{AccountBlock, CurrencyCollection};
1003 use crate::prelude::Boc;
1004
1005 let boc = Boc::decode(include_bytes!("./tests/account_blocks_aug_dict.boc")).unwrap();
1006
1007 let original_dict = boc
1008 .parse::<AugDict<HashBytes, CurrencyCollection, AccountBlock>>()
1009 .unwrap();
1010
1011 let mut data = Vec::new();
1012 for entry in original_dict.iter() {
1013 data.push(entry.unwrap());
1014 }
1015 data.reverse();
1016
1017 let mut new_dict: AugDict<HashBytes, CurrencyCollection, AccountBlock> = AugDict::new();
1018 for (key, aug, value) in data.iter() {
1019 new_dict.add(key, aug, value).unwrap();
1020 }
1021 assert_eq!(new_dict.root_extra(), original_dict.root_extra());
1022
1023 let serialized = CellBuilder::build_from(&new_dict).unwrap();
1024 assert_eq!(serialized.repr_hash(), boc.repr_hash());
1025
1026 for (key, _, _) in data.iter() {
1027 new_dict.remove(key).unwrap();
1028 }
1029 assert!(new_dict.is_empty());
1030 assert_eq!(new_dict.root_extra(), &CurrencyCollection::ZERO);
1031 }
1032
1033 #[test]
1034 fn build_from_array() {
1035 for entries in [
1036 &[
1037 (0u32, SomeValue(123), 1u32),
1038 (1, SomeValue(10), 2),
1039 (2, SomeValue(20), 4),
1040 (2, SomeValue(20), 3),
1041 (3, SomeValue(40), 4),
1042 (4, SomeValue(50), 5),
1043 ][..],
1044 &[
1045 (534837844, SomeValue(331123), 3117028142),
1046 (1421713188, SomeValue(5345345), 3155891450),
1047 (1526242096, SomeValue(567567), 2789399854),
1048 (1971086295, SomeValue(5345), 1228713494),
1049 (4258889371, SomeValue(4956495), 3256452222),
1050 ],
1051 ] {
1052 let result = AugDict::<u32, SomeValue, u32>::try_from_sorted_slice(entries).unwrap();
1053
1054 let mut dict = AugDict::<u32, SomeValue, u32>::new();
1055 for (k, a, v) in entries {
1056 dict.add(k, a, v).unwrap();
1057 }
1058
1059 println!("{}", result.dict.root.as_ref().unwrap().display_tree());
1060 println!(
1061 "BOC: {}",
1062 crate::boc::BocRepr::encode_base64(&result).unwrap()
1063 );
1064
1065 assert_eq!(result, dict);
1066 }
1067 }
1068
1069 #[test]
1070 fn build_from_any_array() {
1071 for _ in 0..100 {
1072 let n = 1 + rand::random::<usize>() % 1000;
1073 let mut entries = (0..n)
1074 .map(|_| {
1075 (
1076 rand::random::<u32>(),
1077 rand::random::<SomeValue>(),
1078 rand::random::<u32>(),
1079 )
1080 })
1081 .collect::<Vec<_>>();
1082 entries.sort_by_key(|(k, _, _)| *k);
1083
1084 let built_from_dict =
1085 AugDict::<u32, SomeValue, u32>::try_from_sorted_slice(&entries).unwrap();
1086
1087 let mut dict = AugDict::<u32, SomeValue, u32>::new();
1088 for (k, a, v) in entries {
1089 dict.add(k, a, v).unwrap();
1090 }
1091
1092 assert_eq!(built_from_dict, dict);
1095 }
1096 }
1097
1098 #[test]
1099 fn search_by_lt() {
1100 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Store, Load)]
1101 struct MaxValue(u64);
1102
1103 impl AugDictExtra for MaxValue {
1104 fn comp_add(
1105 left: &mut CellSlice,
1106 right: &mut CellSlice,
1107 b: &mut CellBuilder,
1108 _: &mut dyn CellContext,
1109 ) -> Result<(), Error> {
1110 let left = left.load_u64()?;
1111 let right = right.load_u64()?;
1112 b.store_u64(left.max(right))
1113 }
1114 }
1115
1116 let mut items = AugDict::<u32, MaxValue, u32>::new();
1117 items.set(0, MaxValue(100), 123).unwrap();
1118 items.set(2, MaxValue(150), 234).unwrap();
1119 items.set(4, MaxValue(200), 345).unwrap();
1120 items.set(6, MaxValue(350), 456).unwrap();
1121 items.set(7, MaxValue(300), 567).unwrap();
1122 items.set(8, MaxValue(250), 678).unwrap();
1123
1124 let highest = items.find_by_extra(std::cmp::Ordering::Greater).unwrap();
1126 assert_eq!(highest, Some((6, MaxValue(350), 456)));
1127 }
1128}