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 storage::{Cow, Storage},
15 value::{Value, container::varlen::VarlenContainer, value_type::ValueType},
16};
17
18pub struct Utf8Container<S: Storage = Cow> {
19 inner: VarlenContainer<S>,
20}
21
22impl<S: Storage> Clone for Utf8Container<S> {
23 fn clone(&self) -> Self {
24 Self {
25 inner: self.inner.clone(),
26 }
27 }
28}
29
30impl<S: Storage> Debug for Utf8Container<S>
31where
32 VarlenContainer<S>: 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<S: Storage> PartialEq for Utf8Container<S>
40where
41 VarlenContainer<S>: PartialEq,
42{
43 fn eq(&self, other: &Self) -> bool {
44 self.inner == other.inner
45 }
46}
47
48impl Serialize for Utf8Container<Cow> {
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<Cow> {
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<Cow> {
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<S: Storage> Utf8Container<S> {
106 pub fn from_inner(inner: VarlenContainer<S>) -> Self {
107 Self {
108 inner,
109 }
110 }
111
112 pub fn from_storage_parts(data: S::Vec<u8>, offsets: S::Vec<u64>) -> Self {
113 Self {
114 inner: VarlenContainer::from_storage_parts(data, offsets),
115 }
116 }
117
118 pub fn data_storage(&self) -> &S::Vec<u8> {
119 self.inner.data()
120 }
121
122 pub fn offsets_storage(&self) -> &S::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 is_empty(&self) -> bool {
135 self.inner.is_empty()
136 }
137
138 pub fn clear(&mut self) {
139 self.inner.clear_generic();
140 }
141
142 pub fn get(&self, index: usize) -> Option<&str> {
143 let bytes = self.inner.get_bytes(index)?;
144 Some(unsafe { str::from_utf8_unchecked(bytes) })
147 }
148
149 pub fn is_defined(&self, idx: usize) -> bool {
150 idx < self.len()
151 }
152
153 pub fn is_fully_defined(&self) -> bool {
154 true
155 }
156
157 pub fn data_bytes(&self) -> &[u8] {
158 self.inner.data_bytes()
159 }
160
161 pub fn offsets(&self) -> &[u64] {
162 self.inner.offsets()
163 }
164
165 pub fn inner(&self) -> &VarlenContainer<S> {
166 &self.inner
167 }
168
169 pub fn as_string(&self, index: usize) -> String {
170 self.get(index).map(str::to_string).unwrap_or_else(|| "none".to_string())
171 }
172
173 pub fn get_value(&self, index: usize) -> Value {
174 match self.get(index) {
175 Some(s) => Value::Utf8(s.to_string()),
176 None => Value::none_of(ValueType::Utf8),
177 }
178 }
179
180 pub fn iter(&self) -> impl Iterator<Item = Option<&str>> + '_ {
181 (0..self.len()).map(|i| self.get(i))
182 }
183
184 pub fn iter_str(&self) -> impl Iterator<Item = &str> + '_ {
185 (0..self.len()).map(|i| self.get(i).unwrap())
186 }
187}
188
189impl Utf8Container<Cow> {
190 pub fn push(&mut self, value: String) {
191 self.inner.push_bytes(value.as_bytes());
192 }
193
194 pub fn push_str(&mut self, value: &str) {
195 self.inner.push_bytes(value.as_bytes());
196 }
197
198 pub fn push_default(&mut self) {
199 self.inner.push_bytes(&[]);
200 }
201
202 pub fn extend(&mut self, other: &Self) -> Result<()> {
203 self.inner.extend_from(&other.inner);
204 Ok(())
205 }
206
207 pub fn slice(&self, start: usize, end: usize) -> Self {
208 Self {
209 inner: self.inner.slice(start, end),
210 }
211 }
212
213 pub fn filter(&mut self, mask: &<Cow as Storage>::BitVec) {
214 let bits: Vec<bool> = mask.iter().collect();
215 self.inner.filter_in_place(|i| bits.get(i).copied().unwrap_or(false));
216 }
217
218 pub fn reorder(&mut self, indices: &[usize]) {
219 self.inner.reorder_in_place(indices);
220 }
221
222 pub fn take(&self, num: usize) -> Self {
223 Self {
224 inner: self.inner.take_n(num),
225 }
226 }
227}
228
229impl Default for Utf8Container<Cow> {
230 fn default() -> Self {
231 Self::with_capacity(0)
232 }
233}
234
235#[cfg(test)]
236pub mod tests {
237 use postcard::to_allocvec as postcard_to_allocvec;
238
239 use super::*;
240 use crate::util::bitvec::BitVec;
241
242 #[test]
243 fn test_new() {
244 let data = vec!["hello".to_string(), "world".to_string(), "test".to_string()];
245 let container = Utf8Container::new(data.clone());
246
247 assert_eq!(container.len(), 3);
248 assert_eq!(container.get(0), Some("hello"));
249 assert_eq!(container.get(1), Some("world"));
250 assert_eq!(container.get(2), Some("test"));
251 }
252
253 #[test]
254 fn test_from_vec() {
255 let data = vec!["foo".to_string(), "bar".to_string(), "baz".to_string()];
256 let container = Utf8Container::from_vec(data);
257
258 assert_eq!(container.len(), 3);
259 assert_eq!(container.get(0), Some("foo"));
260 assert_eq!(container.get(1), Some("bar"));
261 assert_eq!(container.get(2), Some("baz"));
262
263 for i in 0..3 {
264 assert!(container.is_defined(i));
265 }
266 }
267
268 #[test]
269 fn test_from_repeated_str() {
270 let container = Utf8Container::from_repeated_str("mint", 3);
271 let explicit =
272 Utf8Container::from_vec(vec!["mint".to_string(), "mint".to_string(), "mint".to_string()]);
273 assert_eq!(container, explicit);
274 assert_eq!(container.len(), 3);
275 assert_eq!(container.get(0), Some("mint"));
276 assert_eq!(container.get(2), Some("mint"));
277 for i in 0..3 {
278 assert!(container.is_defined(i));
279 }
280 }
281
282 #[test]
283 fn test_with_capacity() {
284 let container = Utf8Container::with_capacity(10);
285 assert_eq!(container.len(), 0);
286 assert!(container.is_empty());
287 assert!(container.capacity() >= 10);
288 }
289
290 #[test]
291 fn test_push() {
292 let mut container = Utf8Container::with_capacity(3);
293
294 container.push("first".to_string());
295 container.push("second".to_string());
296 container.push_default();
297
298 assert_eq!(container.len(), 3);
299 assert_eq!(container.get(0), Some("first"));
300 assert_eq!(container.get(1), Some("second"));
301 assert_eq!(container.get(2), Some(""));
302
303 assert!(container.is_defined(0));
304 assert!(container.is_defined(1));
305 assert!(container.is_defined(2));
306 }
307
308 #[test]
309 fn test_extend() {
310 let mut container1 = Utf8Container::from_vec(vec!["a".to_string(), "b".to_string()]);
311 let container2 = Utf8Container::from_vec(vec!["c".to_string(), "d".to_string()]);
312
313 container1.extend(&container2).unwrap();
314
315 assert_eq!(container1.len(), 4);
316 assert_eq!(container1.get(0), Some("a"));
317 assert_eq!(container1.get(1), Some("b"));
318 assert_eq!(container1.get(2), Some("c"));
319 assert_eq!(container1.get(3), Some("d"));
320 }
321
322 #[test]
323 fn test_iter() {
324 let data = vec!["x".to_string(), "y".to_string(), "z".to_string()];
325 let container = Utf8Container::new(data);
326
327 let collected: Vec<Option<&str>> = container.iter().collect();
328 assert_eq!(collected, vec![Some("x"), Some("y"), Some("z")]);
329 }
330
331 #[test]
332 fn test_slice() {
333 let container = Utf8Container::from_vec(vec![
334 "one".to_string(),
335 "two".to_string(),
336 "three".to_string(),
337 "four".to_string(),
338 ]);
339 let sliced = container.slice(1, 3);
340
341 assert_eq!(sliced.len(), 2);
342 assert_eq!(sliced.get(0), Some("two"));
343 assert_eq!(sliced.get(1), Some("three"));
344 }
345
346 #[test]
347 fn test_filter() {
348 let mut container = Utf8Container::from_vec(vec![
349 "keep".to_string(),
350 "drop".to_string(),
351 "keep".to_string(),
352 "drop".to_string(),
353 ]);
354 let mask = BitVec::from_slice(&[true, false, true, false]);
355
356 container.filter(&mask);
357
358 assert_eq!(container.len(), 2);
359 assert_eq!(container.get(0), Some("keep"));
360 assert_eq!(container.get(1), Some("keep"));
361 }
362
363 #[test]
364 fn test_reorder() {
365 let mut container =
366 Utf8Container::from_vec(vec!["first".to_string(), "second".to_string(), "third".to_string()]);
367 let indices = [2, 0, 1];
368
369 container.reorder(&indices);
370
371 assert_eq!(container.len(), 3);
372 assert_eq!(container.get(0), Some("third"));
373 assert_eq!(container.get(1), Some("first"));
374 assert_eq!(container.get(2), Some("second"));
375 }
376
377 #[test]
378 fn test_reorder_with_out_of_bounds() {
379 let mut container = Utf8Container::from_vec(vec!["a".to_string(), "b".to_string()]);
380 let indices = [1, 5, 0];
381
382 container.reorder(&indices);
383
384 assert_eq!(container.len(), 3);
385 assert_eq!(container.get(0), Some("b"));
386 assert_eq!(container.get(1), Some(""));
387 assert_eq!(container.get(2), Some("a"));
388 }
389
390 #[test]
391 fn test_empty_strings() {
392 let mut container = Utf8Container::with_capacity(2);
393 container.push("".to_string());
394 container.push_default();
395
396 assert_eq!(container.len(), 2);
397 assert_eq!(container.get(0), Some(""));
398 assert_eq!(container.get(1), Some(""));
399
400 assert!(container.is_defined(0));
401 assert!(container.is_defined(1));
402 }
403
404 #[test]
405 fn testault() {
406 let container = Utf8Container::default();
407 assert_eq!(container.len(), 0);
408 assert!(container.is_empty());
409 }
410
411 #[test]
412 fn test_data_bytes_and_offsets_match_zero_copy_layout() {
413 let container = Utf8Container::from_vec(vec!["aa".to_string(), "bb".to_string()]);
414 assert_eq!(container.data_bytes(), b"aabb");
415 assert_eq!(container.offsets(), &[0u64, 2, 4]);
416 }
417
418 #[test]
419 fn test_postcard_wire_compat() {
420 let strings = vec!["hello".to_string(), "world".to_string()];
423 let strings_bytes: Vec<u8> = postcard_to_allocvec(&strings).unwrap();
424
425 let container = Utf8Container::from_vec(strings.clone());
426 let container_bytes: Vec<u8> = postcard_to_allocvec(&container).unwrap();
427
428 assert_eq!(strings_bytes, container_bytes);
429 }
430}