treap_map/
config.rs

1use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
2use primitives::Zero;
3use std::{cmp::Ordering, ops::Add};
4
5/// The weight type in a Treap. It is used to perform operations like
6/// calculating sums or maximum values of an interval in logrithmic time over
7/// treap.
8pub trait ConsoliableWeight: Clone + Eq {
9    /// Create a default or 'zero' value for the weight. Consolidating with this
10    /// value should not change the other value.
11    fn empty() -> Self;
12
13    /// Combine two weights into a single one.
14    fn consolidate(a: &Self, b: &Self) -> Self;
15
16    /// Combine another weight into `self`. It allows for implementing more
17    /// efficient in-place consolidation.
18    fn accure(&mut self, other: &Self) {
19        *self = Self::consolidate(&*self, other);
20    }
21}
22
23impl<T: Add<Output = T> + Clone + Zero + Eq> ConsoliableWeight for T {
24    fn empty() -> Self { T::zero() }
25
26    fn consolidate(a: &Self, b: &Self) -> Self { a.clone() + b.clone() }
27
28    fn accure(&mut self, other: &Self) { *self = self.clone() + other.clone() }
29}
30
31#[derive(Clone, PartialEq, Eq, Copy, Debug)]
32/// Represents a dummy version of `ConsolidatableWeight`.
33///
34/// `NoWeight` is a unit struct that doesn't store any data. It is used as a
35/// placeholder or a default implementation in scenarios where a weight
36/// component is required by the interface but not actually needed for the
37/// specific use case.
38pub struct NoWeight;
39
40impl ConsoliableWeight for NoWeight {
41    #[inline]
42    fn empty() -> Self { NoWeight }
43
44    #[inline]
45    fn consolidate(_: &Self, _: &Self) -> Self { NoWeight }
46
47    #[inline]
48    fn accure(&mut self, _other: &Self) {}
49}
50
51/// `TreapMap` is a struct which implements a treap which can be indexed by a
52/// different key (type `SearchKey`). The associate type `SortKey` and
53/// `SearchKey` defines how to order node in treap collaborately.
54///
55/// As the user only needs to provider the `SearchKey` in searching an element,
56/// but the underlying treap is ordered by both `SortKey` and `SearchKey`.
57/// `TreapMap` also maintains `KeyMng` to recover `SortKey` from `SearchKey`. It
58/// could be a `HashMap`.
59///
60/// If `TreapMap` is indexed in the same key as the inside treap. The `SortKey`
61/// can be deprecated to `()` and the `KeyMng` can be deprecated to a unit type.
62/// Since it is compiled through static dispatch, unnecessary operations will be
63/// optimized away.
64pub trait TreapMapConfig: Sized {
65    /// The search key type in the TreapMap, supporting query/remove a node by
66    /// key.
67    type SearchKey;
68    /// The sort key in the treap.
69    type SortKey;
70    /// The stored value.
71    type Value: Clone;
72    /// The external map which can computing `SortKey` from `SearchKey`. If not
73    /// needed, it could be a unit type.
74    type ExtMap: KeyMngTrait<Self>;
75    /// The consolidable weight.
76    type Weight: ConsoliableWeight;
77
78    /// Compare the key.
79    fn next_node_dir(
80        me: (&Self::SortKey, &Self::SearchKey),
81        other: (&Self::SortKey, &Self::SearchKey),
82    ) -> Option<Direction>;
83}
84
85/// Represents the possible directions in a binary tree search based on key
86/// comparisons.
87///
88/// This enum is defined as part of the [`TreapMapConfig`] trait and is used to
89/// determine the direction of traversal in a binary tree during key-based
90/// searches.
91#[derive(Clone, Copy, PartialEq, Eq, Debug)]
92
93pub enum Direction {
94    /// Indicates that the search should proceed to the left child of the
95    /// current node. This direction is typically chosen when the current
96    /// key is greater than the search key.
97    Left,
98
99    /// Indicates that the search should proceed to the right child of the
100    /// current node. This direction is usually selected when the current
101    /// key is less than the search key.
102    Right,
103}
104
105/// Searching in `Treap` requires sort key. This trait manages the relationship
106/// among sort keys, search keys and values in a Treap. This is necessary when
107/// the sort key is not directly derivable from the search key or is not a null
108/// element.
109pub trait KeyMngTrait<C: TreapMapConfig>: Default {
110    /// Invoked when a new key-value pair is changed in the Treap.
111    fn view_update(
112        &mut self, key: &C::SearchKey, value: Option<&C::Value>,
113        old_value: Option<&C::Value>,
114    );
115    /// Number of the keys
116    fn len(&self) -> usize;
117    /// Retrieve the sort key for a given search key.
118    /// Returns `None` if the search key is not in the treap.
119    fn get_sort_key(&self, key: &C::SearchKey) -> Option<C::SortKey>;
120    /// Generate the sort key from a key-value pair.
121    fn make_sort_key(&self, key: &C::SearchKey, value: &C::Value)
122        -> C::SortKey;
123}
124
125/// If `TreapMap` is indexed in the same key as the inside treap, it can be
126/// configed in a simple way.
127pub trait SharedKeyTreapMapConfig {
128    /// The search key in the TreapMap.
129    type Key: Ord;
130    /// The stored value.
131    type Value: Clone;
132    /// The consolidable weight.
133    type Weight: ConsoliableWeight;
134}
135
136impl<T: SharedKeyTreapMapConfig> TreapMapConfig for T {
137    type ExtMap = Counter;
138    type SearchKey = T::Key;
139    type SortKey = ();
140    type Value = T::Value;
141    type Weight = T::Weight;
142
143    #[inline]
144    fn next_node_dir(
145        (_, me): (&(), &Self::SearchKey), (_, other): (&(), &Self::SearchKey),
146    ) -> Option<Direction> {
147        match me.cmp(other) {
148            Ordering::Less => Some(Direction::Left),
149            Ordering::Equal => None,
150            Ordering::Greater => Some(Direction::Right),
151        }
152    }
153}
154#[derive(Default)]
155pub struct Counter(pub usize);
156
157impl<C: TreapMapConfig<SortKey = ()>> KeyMngTrait<C> for Counter {
158    #[inline]
159    fn view_update(
160        &mut self, _key: &C::SearchKey, value: Option<&C::Value>,
161        old_value: Option<&C::Value>,
162    ) {
163        if value.is_some() {
164            self.0 += 1;
165        }
166        if old_value.is_some() {
167            self.0 -= 1
168        }
169    }
170
171    fn len(&self) -> usize { self.0 }
172
173    fn get_sort_key(&self, _key: &C::SearchKey) -> Option<()> { Some(()) }
174
175    fn make_sort_key(
176        &self, _key: &C::SearchKey, _value: &C::Value,
177    ) -> C::SortKey {
178        ()
179    }
180}
181
182impl MallocSizeOf for Counter {
183    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
184        self.0.size_of(ops)
185    }
186}