Skip to main content

rart/keys/
vector_key.rs

1use crate::keys::KeyTrait;
2use crate::partials::vector_partial::VectorPartial;
3
4/// A variable-size key type that stores data on the heap.
5///
6/// `VectorKey` is a heap-allocated key type that can store keys of any size.
7/// It's ideal for scenarios where key sizes are not known at compile time
8/// or when keys can be very large.
9///
10/// ## Features
11///
12/// - **Variable size**: Can store keys of any length
13/// - **Heap allocated**: Uses heap memory for storage
14/// - **Null termination**: Automatically adds null termination for string keys
15/// - **Efficient**: Uses `Box<[u8]>` for minimal memory overhead
16///
17/// ## Examples
18///
19/// ```rust
20/// use rart::keys::vector_key::VectorKey;
21///
22/// // Create from string (adds null terminator)
23/// let key1: VectorKey = "hello world".into();
24///
25/// // Create from numeric types
26/// let key2: VectorKey = 42u64.into();
27///
28/// // Create from long strings
29/// let long_string = "a".repeat(1000);
30/// let key3: VectorKey = long_string.into();
31/// ```
32///
33/// ## When to Use
34///
35/// Use `VectorKey` when:
36/// - Key sizes are unknown at compile time
37/// - Keys can be very large (> 32 bytes)
38/// - You need maximum flexibility
39///
40/// Use [`ArrayKey`](super::array_key::ArrayKey) when:
41/// - Key sizes are bounded and known
42/// - You want optimal performance
43/// - Keys are relatively small (< 32 bytes)
44#[derive(Clone, Eq, PartialEq, PartialOrd, Ord)]
45pub struct VectorKey {
46    data: Box<[u8]>,
47}
48
49impl AsRef<[u8]> for VectorKey {
50    fn as_ref(&self) -> &[u8] {
51        &self.data
52    }
53}
54
55impl VectorKey {
56    pub fn new_from_string(s: &String) -> Self {
57        let mut data = Vec::with_capacity(s.len() + 1);
58        data.extend_from_slice(s.as_bytes());
59        data.push(0);
60        Self {
61            data: data.into_boxed_slice(),
62        }
63    }
64
65    pub fn new_from_str(s: &str) -> Self {
66        let mut data = Vec::with_capacity(s.len() + 1);
67        data.extend_from_slice(s.as_bytes());
68        data.push(0);
69        Self {
70            data: data.into_boxed_slice(),
71        }
72    }
73
74    pub fn new_from_vec(data: Vec<u8>) -> Self {
75        Self {
76            data: data.into_boxed_slice(),
77        }
78    }
79
80    pub fn to_be_u64(&self) -> u64 {
81        // Value must be at least 8 bytes long.
82        debug_assert!(self.data.len() >= 8, "data length is less than 8 bytes");
83        // Copy from 0..min(len, 8) to a new array left-padding it, then convert to u64.
84        let mut arr = [0; 8];
85        arr[8 - self.data.len()..].copy_from_slice(&self.data[..self.data.len()]);
86        u64::from_be_bytes(arr)
87    }
88}
89
90impl KeyTrait for VectorKey {
91    type PartialType = VectorPartial;
92    const MAXIMUM_SIZE: Option<usize> = None;
93
94    fn extend_from_partial(&self, partial: &Self::PartialType) -> Self {
95        let mut v = self.data.to_vec();
96        v.extend_from_slice(partial.to_slice());
97        Self {
98            data: v.into_boxed_slice(),
99        }
100    }
101
102    fn truncate(&self, at_depth: usize) -> Self {
103        let mut v = self.data.to_vec();
104        v.truncate(at_depth);
105        Self {
106            data: v.into_boxed_slice(),
107        }
108    }
109
110    fn new_from_slice(data: &[u8]) -> Self {
111        let data = Vec::from(data);
112        Self {
113            data: data.into_boxed_slice(),
114        }
115    }
116    fn at(&self, pos: usize) -> u8 {
117        self.data[pos]
118    }
119
120    fn length_at(&self, at_depth: usize) -> usize {
121        self.data.len() - at_depth
122    }
123
124    fn to_partial(&self, at_depth: usize) -> VectorPartial {
125        VectorPartial::from_slice(&self.data[at_depth..])
126    }
127
128    fn matches_slice(&self, slice: &[u8]) -> bool {
129        self.data.len() == slice.len() && &self.data[..] == slice
130    }
131
132    fn new_from_partial(partial: &Self::PartialType) -> Self {
133        let data = Vec::from(partial.to_slice());
134        Self {
135            data: data.into_boxed_slice(),
136        }
137    }
138}
139
140impl From<String> for VectorKey {
141    fn from(data: String) -> Self {
142        Self::new_from_string(&data)
143    }
144}
145impl From<&String> for VectorKey {
146    fn from(data: &String) -> Self {
147        Self::new_from_string(data)
148    }
149}
150impl From<&str> for VectorKey {
151    fn from(data: &str) -> Self {
152        Self::new_from_str(data)
153    }
154}
155macro_rules! impl_from_unsigned {
156    ( $($t:ty),* ) => {
157    $(
158    impl From< $t > for VectorKey
159    {
160        fn from(data: $t) -> Self {
161            VectorKey::new_from_slice(&data.to_be_bytes())
162        }
163    }
164    impl From< &$t > for VectorKey
165    {
166        fn from(data: &$t) -> Self {
167            (*data).into()
168        }
169    }
170    ) *
171    }
172}
173impl_from_unsigned!(u8, u16, u32, u64, usize, u128);
174
175impl From<i8> for VectorKey {
176    fn from(val: i8) -> Self {
177        // Convert signed to unsigned preserving sort order
178        let v: u8 = val as u8;
179        let j = v ^ 0x80; // Flip sign bit
180        let v = vec![j];
181        VectorKey::new_from_vec(v)
182    }
183}
184
185macro_rules! impl_from_signed {
186    ( $t:ty, $tu:ty ) => {
187        impl From<$t> for VectorKey {
188            fn from(val: $t) -> Self {
189                // Convert signed to unsigned preserving sort order
190                let v: $tu = val as $tu;
191                let sign_bit = 1 << (std::mem::size_of::<$tu>() * 8 - 1);
192                let j = v ^ sign_bit;
193                VectorKey::new_from_slice(&j.to_be_bytes())
194            }
195        }
196
197        impl From<&$t> for VectorKey {
198            fn from(val: &$t) -> Self {
199                (*val).into()
200            }
201        }
202    };
203}
204
205impl_from_signed!(i16, u16);
206impl_from_signed!(i32, u32);
207impl_from_signed!(i64, u64);
208impl_from_signed!(i128, u128);
209impl_from_signed!(isize, usize);
210
211#[cfg(test)]
212mod test {
213    use crate::keys::KeyTrait;
214    use crate::keys::vector_key::VectorKey;
215    use crate::partials::vector_partial::VectorPartial;
216
217    #[test]
218    fn make_extend_truncate() {
219        let k = VectorKey::new_from_slice(b"hel");
220        let p = VectorPartial::from_slice(b"lo");
221        let k2 = k.extend_from_partial(&p);
222        assert!(k2.matches_slice(b"hello"));
223        let k3 = k2.truncate(3);
224        assert!(k3.matches_slice(b"hel"));
225    }
226
227    #[test]
228    fn from_to_u64() {
229        let k: VectorKey = 123u64.into();
230        assert_eq!(k.to_be_u64(), 123u64);
231
232        let k: VectorKey = 1u64.into();
233        assert_eq!(k.to_be_u64(), 1u64);
234
235        let k: VectorKey = 123213123123123u64.into();
236        assert_eq!(k.to_be_u64(), 123213123123123u64);
237    }
238}