reifydb_value/value/container/
utf8.rs1use std::{
5 fmt::{self, Debug},
6 result::Result as StdResult,
7 str,
8};
9
10use serde::{Deserialize, Deserializer, Serialize, Serializer};
11
12use crate::{
13 Result, reifydb_assertions,
14 util::bitvec::BitVec,
15 value::{Value, container::varlen::VarlenContainer, value_type::ValueType},
16};
17
18pub struct Utf8Container {
19 inner: VarlenContainer,
20}
21
22impl Clone for Utf8Container {
23 fn clone(&self) -> Self {
24 Self {
25 inner: self.inner.clone(),
26 }
27 }
28}
29
30impl Debug for Utf8Container
31where
32 VarlenContainer: Debug,
33{
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 f.debug_struct("Utf8Container").field("inner", &self.inner).finish()
36 }
37}
38
39impl PartialEq for Utf8Container
40where
41 VarlenContainer: PartialEq,
42{
43 fn eq(&self, other: &Self) -> bool {
44 self.inner == other.inner
45 }
46}
47
48impl Serialize for Utf8Container {
49 fn serialize<Ser: Serializer>(&self, serializer: Ser) -> StdResult<Ser::Ok, Ser::Error> {
50 self.inner.serialize(serializer)
51 }
52}
53
54impl<'de> Deserialize<'de> for Utf8Container {
55 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
56 let inner = VarlenContainer::deserialize(deserializer)?;
57 Ok(Self {
58 inner,
59 })
60 }
61}
62
63impl Utf8Container {
64 pub fn new(data: Vec<String>) -> Self {
65 Self::from_vec(data)
66 }
67
68 pub fn from_vec(data: Vec<String>) -> Self {
69 let inner = VarlenContainer::from_byte_slices(data.iter().map(|s| s.as_bytes()));
70 Self {
71 inner,
72 }
73 }
74
75 pub fn from_repeated_str(value: &str, count: usize) -> Self {
76 Self {
77 inner: VarlenContainer::from_repeated_bytes(value.as_bytes(), count),
78 }
79 }
80
81 pub fn with_capacity(capacity: usize) -> Self {
82 Self {
83 inner: VarlenContainer::with_capacity(capacity, capacity * 16),
84 }
85 }
86
87 pub fn from_raw_parts(data: Vec<String>) -> Self {
88 Self::from_vec(data)
89 }
90
91 pub fn from_bytes_offsets(data: Vec<u8>, offsets: Vec<u64>) -> Self {
92 reifydb_assertions! {
93 assert!(str::from_utf8(&data).is_ok(), "Utf8Container data must be valid UTF-8");
94 }
95 Self {
96 inner: VarlenContainer::from_raw_parts(data, offsets),
97 }
98 }
99
100 pub fn try_into_raw_parts(self) -> Option<Vec<String>> {
101 Some(self.iter().map(|s| s.unwrap().to_string()).collect())
102 }
103}
104
105impl Utf8Container {
106 pub fn from_inner(inner: VarlenContainer) -> Self {
107 Self {
108 inner,
109 }
110 }
111
112 pub fn from_storage_parts(data: Vec<u8>, offsets: Vec<u64>) -> Self {
113 Self {
114 inner: VarlenContainer::from_storage_parts(data, offsets),
115 }
116 }
117
118 pub fn data_storage(&self) -> &Vec<u8> {
119 self.inner.data()
120 }
121
122 pub fn offsets_storage(&self) -> &Vec<u64> {
123 self.inner.offsets_data()
124 }
125
126 pub fn len(&self) -> usize {
127 self.inner.len()
128 }
129
130 pub fn capacity(&self) -> usize {
131 self.inner.capacity()
132 }
133
134 pub fn heap_size(&self) -> usize {
135 self.inner.heap_size()
136 }
137
138 pub fn is_empty(&self) -> bool {
139 self.inner.is_empty()
140 }
141
142 pub fn clear(&mut self) {
143 self.inner.clear_generic();
144 }
145
146 pub fn get(&self, index: usize) -> Option<&str> {
147 let bytes = self.inner.get_bytes(index)?;
148 Some(unsafe { str::from_utf8_unchecked(bytes) })
151 }
152
153 pub fn is_defined(&self, idx: usize) -> bool {
154 idx < self.len()
155 }
156
157 pub fn is_fully_defined(&self) -> bool {
158 true
159 }
160
161 pub fn data_bytes(&self) -> &[u8] {
162 self.inner.data_bytes()
163 }
164
165 pub fn offsets(&self) -> &[u64] {
166 self.inner.offsets()
167 }
168
169 pub fn inner(&self) -> &VarlenContainer {
170 &self.inner
171 }
172
173 pub fn as_string(&self, index: usize) -> String {
174 self.get(index).map(str::to_string).unwrap_or_else(|| "none".to_string())
175 }
176
177 pub fn get_value(&self, index: usize) -> Value {
178 match self.get(index) {
179 Some(s) => Value::Utf8(s.to_string()),
180 None => Value::none_of(ValueType::Utf8),
181 }
182 }
183
184 pub fn iter(&self) -> impl Iterator<Item = Option<&str>> + '_ {
185 (0..self.len()).map(|i| self.get(i))
186 }
187
188 pub fn iter_str(&self) -> impl Iterator<Item = &str> + '_ {
189 (0..self.len()).map(|i| self.get(i).unwrap())
190 }
191}
192
193impl Utf8Container {
194 pub fn push(&mut self, value: String) {
195 self.inner.push_bytes(value.as_bytes());
196 }
197
198 pub fn push_str(&mut self, value: &str) {
199 self.inner.push_bytes(value.as_bytes());
200 }
201
202 pub fn push_default(&mut self) {
203 self.inner.push_bytes(&[]);
204 }
205
206 pub fn extend(&mut self, other: &Self) -> Result<()> {
207 self.inner.extend_from(&other.inner);
208 Ok(())
209 }
210
211 pub fn slice(&self, start: usize, end: usize) -> Self {
212 Self {
213 inner: self.inner.slice(start, end),
214 }
215 }
216
217 pub fn filter(&mut self, mask: &BitVec) {
218 let bits: Vec<bool> = mask.iter().collect();
219 self.inner.filter_in_place(|i| bits.get(i).copied().unwrap_or(false));
220 }
221
222 pub fn reorder(&mut self, indices: &[usize]) {
223 self.inner.reorder_in_place(indices);
224 }
225
226 pub fn take(&self, num: usize) -> Self {
227 Self {
228 inner: self.inner.take_n(num),
229 }
230 }
231}
232
233impl Default for Utf8Container {
234 fn default() -> Self {
235 Self::with_capacity(0)
236 }
237}
238
239#[cfg(test)]
240pub mod tests {
241 use postcard::to_allocvec as postcard_to_allocvec;
242
243 use super::*;
244 use crate::util::bitvec::BitVec;
245
246 #[test]
247 fn test_new() {
248 let data = vec!["hello".to_string(), "world".to_string(), "test".to_string()];
249 let container = Utf8Container::new(data.clone());
250
251 assert_eq!(container.len(), 3);
252 assert_eq!(container.get(0), Some("hello"));
253 assert_eq!(container.get(1), Some("world"));
254 assert_eq!(container.get(2), Some("test"));
255 }
256
257 #[test]
258 fn test_from_vec() {
259 let data = vec!["foo".to_string(), "bar".to_string(), "baz".to_string()];
260 let container = Utf8Container::from_vec(data);
261
262 assert_eq!(container.len(), 3);
263 assert_eq!(container.get(0), Some("foo"));
264 assert_eq!(container.get(1), Some("bar"));
265 assert_eq!(container.get(2), Some("baz"));
266
267 for i in 0..3 {
268 assert!(container.is_defined(i));
269 }
270 }
271
272 #[test]
273 fn test_from_repeated_str() {
274 let container = Utf8Container::from_repeated_str("mint", 3);
275 let explicit =
276 Utf8Container::from_vec(vec!["mint".to_string(), "mint".to_string(), "mint".to_string()]);
277 assert_eq!(container, explicit);
278 assert_eq!(container.len(), 3);
279 assert_eq!(container.get(0), Some("mint"));
280 assert_eq!(container.get(2), Some("mint"));
281 for i in 0..3 {
282 assert!(container.is_defined(i));
283 }
284 }
285
286 #[test]
287 fn test_with_capacity() {
288 let container = Utf8Container::with_capacity(10);
289 assert_eq!(container.len(), 0);
290 assert!(container.is_empty());
291 assert!(container.capacity() >= 10);
292 }
293
294 #[test]
295 fn test_push() {
296 let mut container = Utf8Container::with_capacity(3);
297
298 container.push("first".to_string());
299 container.push("second".to_string());
300 container.push_default();
301
302 assert_eq!(container.len(), 3);
303 assert_eq!(container.get(0), Some("first"));
304 assert_eq!(container.get(1), Some("second"));
305 assert_eq!(container.get(2), Some(""));
306
307 assert!(container.is_defined(0));
308 assert!(container.is_defined(1));
309 assert!(container.is_defined(2));
310 }
311
312 #[test]
313 fn test_extend() {
314 let mut container1 = Utf8Container::from_vec(vec!["a".to_string(), "b".to_string()]);
315 let container2 = Utf8Container::from_vec(vec!["c".to_string(), "d".to_string()]);
316
317 container1.extend(&container2).unwrap();
318
319 assert_eq!(container1.len(), 4);
320 assert_eq!(container1.get(0), Some("a"));
321 assert_eq!(container1.get(1), Some("b"));
322 assert_eq!(container1.get(2), Some("c"));
323 assert_eq!(container1.get(3), Some("d"));
324 }
325
326 #[test]
327 fn test_iter() {
328 let data = vec!["x".to_string(), "y".to_string(), "z".to_string()];
329 let container = Utf8Container::new(data);
330
331 let collected: Vec<Option<&str>> = container.iter().collect();
332 assert_eq!(collected, vec![Some("x"), Some("y"), Some("z")]);
333 }
334
335 #[test]
336 fn test_slice() {
337 let container = Utf8Container::from_vec(vec![
338 "one".to_string(),
339 "two".to_string(),
340 "three".to_string(),
341 "four".to_string(),
342 ]);
343 let sliced = container.slice(1, 3);
344
345 assert_eq!(sliced.len(), 2);
346 assert_eq!(sliced.get(0), Some("two"));
347 assert_eq!(sliced.get(1), Some("three"));
348 }
349
350 #[test]
351 fn test_filter() {
352 let mut container = Utf8Container::from_vec(vec![
353 "keep".to_string(),
354 "drop".to_string(),
355 "keep".to_string(),
356 "drop".to_string(),
357 ]);
358 let mask = BitVec::from_slice(&[true, false, true, false]);
359
360 container.filter(&mask);
361
362 assert_eq!(container.len(), 2);
363 assert_eq!(container.get(0), Some("keep"));
364 assert_eq!(container.get(1), Some("keep"));
365 }
366
367 #[test]
368 fn test_reorder() {
369 let mut container =
370 Utf8Container::from_vec(vec!["first".to_string(), "second".to_string(), "third".to_string()]);
371 let indices = [2, 0, 1];
372
373 container.reorder(&indices);
374
375 assert_eq!(container.len(), 3);
376 assert_eq!(container.get(0), Some("third"));
377 assert_eq!(container.get(1), Some("first"));
378 assert_eq!(container.get(2), Some("second"));
379 }
380
381 #[test]
382 fn test_reorder_with_out_of_bounds() {
383 let mut container = Utf8Container::from_vec(vec!["a".to_string(), "b".to_string()]);
384 let indices = [1, 5, 0];
385
386 container.reorder(&indices);
387
388 assert_eq!(container.len(), 3);
389 assert_eq!(container.get(0), Some("b"));
390 assert_eq!(container.get(1), Some(""));
391 assert_eq!(container.get(2), Some("a"));
392 }
393
394 #[test]
395 fn test_empty_strings() {
396 let mut container = Utf8Container::with_capacity(2);
397 container.push("".to_string());
398 container.push_default();
399
400 assert_eq!(container.len(), 2);
401 assert_eq!(container.get(0), Some(""));
402 assert_eq!(container.get(1), Some(""));
403
404 assert!(container.is_defined(0));
405 assert!(container.is_defined(1));
406 }
407
408 #[test]
409 fn testault() {
410 let container = Utf8Container::default();
411 assert_eq!(container.len(), 0);
412 assert!(container.is_empty());
413 }
414
415 #[test]
416 fn test_data_bytes_and_offsets_match_zero_copy_layout() {
417 let container = Utf8Container::from_vec(vec!["aa".to_string(), "bb".to_string()]);
418 assert_eq!(container.data_bytes(), b"aabb");
419 assert_eq!(container.offsets(), &[0u64, 2, 4]);
420 }
421
422 #[test]
423 fn test_postcard_wire_compat() {
424 let strings = vec!["hello".to_string(), "world".to_string()];
427 let strings_bytes: Vec<u8> = postcard_to_allocvec(&strings).unwrap();
428
429 let container = Utf8Container::from_vec(strings.clone());
430 let container_bytes: Vec<u8> = postcard_to_allocvec(&container).unwrap();
431
432 assert_eq!(strings_bytes, container_bytes);
433 }
434}