1use std::fmt::Debug;
5
6use bumpalo::Bump as BumpAlloc;
7use reifydb_core::value::column::{Column, data::ColumnData};
8use reifydb_type::{
9 storage::{Cow, DataBitVec, DataVec, Storage},
10 util::{bitvec::BitVec, cowvec::CowVec},
11 value::{
12 Value,
13 blob::Blob,
14 container::{
15 any::AnyContainer, blob::BlobContainer, bool::BoolContainer, dictionary::DictionaryContainer,
16 identity_id::IdentityIdContainer, number::NumberContainer, temporal::TemporalContainer,
17 utf8::Utf8Container, uuid::UuidContainer,
18 },
19 dictionary::DictionaryEntryId,
20 identity::IdentityId,
21 is::{IsNumber, IsTemporal, IsUuid},
22 },
23};
24
25use super::{Bump, BumpBitVec, BumpVec};
26
27fn bitvec_to_cow<S: Storage>(src: &S::BitVec) -> BitVec {
28 let len = DataBitVec::len(src);
29 let mut dst = BitVec::with_capacity(len);
30 for i in 0..len {
31 dst.push(DataBitVec::get(src, i));
32 }
33 dst
34}
35
36fn bitvec_to_bump<'bump, S: Storage>(src: &S::BitVec, bump: &'bump BumpAlloc) -> BumpBitVec<'bump> {
37 let len = DataBitVec::len(src);
38 let mut dst = BumpBitVec::with_capacity_in(len, bump);
39 for i in 0..len {
40 DataBitVec::push(&mut dst, DataBitVec::get(src, i));
41 }
42 dst
43}
44
45fn vec_to_cow<T: Clone + PartialEq + 'static, S: Storage>(src: &S::Vec<T>) -> CowVec<T> {
46 let mut dst = CowVec::with_capacity(DataVec::len(src));
47 dst.extend_from_slice(DataVec::as_slice(src));
48 dst
49}
50
51fn vec_to_bump<'bump, T: Clone + PartialEq + 'static, S: Storage>(
52 src: &S::Vec<T>,
53 bump: &'bump BumpAlloc,
54) -> BumpVec<'bump, T> {
55 let mut dst = BumpVec::with_capacity_in(DataVec::len(src), bump);
56 DataVec::extend_from_slice(&mut dst, DataVec::as_slice(src));
57 dst
58}
59
60fn number_to_cow<T: IsNumber + Clone + Debug + Default, S: Storage>(
61 src: &NumberContainer<T, S>,
62) -> NumberContainer<T, Cow> {
63 NumberContainer::from_parts(vec_to_cow::<T, S>(src.data()))
64}
65
66fn number_to_bump<'bump, T: IsNumber + Clone + Debug + Default, S: Storage>(
67 src: &NumberContainer<T, S>,
68 bump: &'bump BumpAlloc,
69) -> NumberContainer<T, Bump<'bump>> {
70 NumberContainer::from_parts(vec_to_bump::<T, S>(src.data(), bump))
71}
72
73fn bool_to_cow<S: Storage>(src: &BoolContainer<S>) -> BoolContainer<Cow> {
74 BoolContainer::from_parts(bitvec_to_cow::<S>(src.data()))
75}
76
77fn bool_to_bump<'bump, S: Storage>(src: &BoolContainer<S>, bump: &'bump BumpAlloc) -> BoolContainer<Bump<'bump>> {
78 BoolContainer::from_parts(bitvec_to_bump::<S>(src.data(), bump))
79}
80
81fn temporal_to_cow<T: IsTemporal + Clone + Debug + Default, S: Storage>(
82 src: &TemporalContainer<T, S>,
83) -> TemporalContainer<T, Cow> {
84 TemporalContainer::from_parts(vec_to_cow::<T, S>(src.data()))
85}
86
87fn temporal_to_bump<'bump, T: IsTemporal + Clone + Debug + Default, S: Storage>(
88 src: &TemporalContainer<T, S>,
89 bump: &'bump BumpAlloc,
90) -> TemporalContainer<T, Bump<'bump>> {
91 TemporalContainer::from_parts(vec_to_bump::<T, S>(src.data(), bump))
92}
93
94fn uuid_to_cow<T: IsUuid + Clone + Debug + Default, S: Storage>(src: &UuidContainer<T, S>) -> UuidContainer<T, Cow> {
95 UuidContainer::from_parts(vec_to_cow::<T, S>(src.data()))
96}
97
98fn uuid_to_bump<'bump, T: IsUuid + Clone + Debug + Default, S: Storage>(
99 src: &UuidContainer<T, S>,
100 bump: &'bump BumpAlloc,
101) -> UuidContainer<T, Bump<'bump>> {
102 UuidContainer::from_parts(vec_to_bump::<T, S>(src.data(), bump))
103}
104
105fn utf8_to_cow<S: Storage>(src: &Utf8Container<S>) -> Utf8Container<Cow> {
106 Utf8Container::from_parts(vec_to_cow::<String, S>(src.data()))
107}
108
109fn utf8_to_bump<'bump, S: Storage>(src: &Utf8Container<S>, bump: &'bump BumpAlloc) -> Utf8Container<Bump<'bump>> {
110 Utf8Container::from_parts(vec_to_bump::<String, S>(src.data(), bump))
111}
112
113fn blob_to_cow<S: Storage>(src: &BlobContainer<S>) -> BlobContainer<Cow> {
114 BlobContainer::from_parts(vec_to_cow::<Blob, S>(src.data()))
115}
116
117fn blob_to_bump<'bump, S: Storage>(src: &BlobContainer<S>, bump: &'bump BumpAlloc) -> BlobContainer<Bump<'bump>> {
118 BlobContainer::from_parts(vec_to_bump::<Blob, S>(src.data(), bump))
119}
120
121fn identity_id_to_cow<S: Storage>(src: &IdentityIdContainer<S>) -> IdentityIdContainer<Cow> {
122 IdentityIdContainer::from_parts(vec_to_cow::<IdentityId, S>(src.data()))
123}
124
125fn identity_id_to_bump<'bump, S: Storage>(
126 src: &IdentityIdContainer<S>,
127 bump: &'bump BumpAlloc,
128) -> IdentityIdContainer<Bump<'bump>> {
129 IdentityIdContainer::from_parts(vec_to_bump::<IdentityId, S>(src.data(), bump))
130}
131
132fn any_to_cow<S: Storage>(src: &AnyContainer<S>) -> AnyContainer<Cow> {
133 AnyContainer::from_parts(vec_to_cow::<Box<Value>, S>(src.data()))
134}
135
136fn any_to_bump<'bump, S: Storage>(src: &AnyContainer<S>, bump: &'bump BumpAlloc) -> AnyContainer<Bump<'bump>> {
137 AnyContainer::from_parts(vec_to_bump::<Box<Value>, S>(src.data(), bump))
138}
139
140fn dictionary_to_cow<S: Storage>(src: &DictionaryContainer<S>) -> DictionaryContainer<Cow> {
141 DictionaryContainer::from_parts(vec_to_cow::<DictionaryEntryId, S>(src.data()), src.dictionary_id())
142}
143
144fn dictionary_to_bump<'bump, S: Storage>(
145 src: &DictionaryContainer<S>,
146 bump: &'bump BumpAlloc,
147) -> DictionaryContainer<Bump<'bump>> {
148 DictionaryContainer::from_parts(vec_to_bump::<DictionaryEntryId, S>(src.data(), bump), src.dictionary_id())
149}
150
151pub fn column_data_to_cow<S: Storage>(src: &ColumnData<S>) -> ColumnData<Cow> {
152 match src {
153 ColumnData::Bool(c) => ColumnData::Bool(bool_to_cow(c)),
154 ColumnData::Float4(c) => ColumnData::Float4(number_to_cow(c)),
155 ColumnData::Float8(c) => ColumnData::Float8(number_to_cow(c)),
156 ColumnData::Int1(c) => ColumnData::Int1(number_to_cow(c)),
157 ColumnData::Int2(c) => ColumnData::Int2(number_to_cow(c)),
158 ColumnData::Int4(c) => ColumnData::Int4(number_to_cow(c)),
159 ColumnData::Int8(c) => ColumnData::Int8(number_to_cow(c)),
160 ColumnData::Int16(c) => ColumnData::Int16(number_to_cow(c)),
161 ColumnData::Uint1(c) => ColumnData::Uint1(number_to_cow(c)),
162 ColumnData::Uint2(c) => ColumnData::Uint2(number_to_cow(c)),
163 ColumnData::Uint4(c) => ColumnData::Uint4(number_to_cow(c)),
164 ColumnData::Uint8(c) => ColumnData::Uint8(number_to_cow(c)),
165 ColumnData::Uint16(c) => ColumnData::Uint16(number_to_cow(c)),
166 ColumnData::Utf8 {
167 container,
168 max_bytes,
169 } => ColumnData::Utf8 {
170 container: utf8_to_cow(container),
171 max_bytes: *max_bytes,
172 },
173 ColumnData::Date(c) => ColumnData::Date(temporal_to_cow(c)),
174 ColumnData::DateTime(c) => ColumnData::DateTime(temporal_to_cow(c)),
175 ColumnData::Time(c) => ColumnData::Time(temporal_to_cow(c)),
176 ColumnData::Duration(c) => ColumnData::Duration(temporal_to_cow(c)),
177 ColumnData::IdentityId(c) => ColumnData::IdentityId(identity_id_to_cow(c)),
178 ColumnData::Uuid4(c) => ColumnData::Uuid4(uuid_to_cow(c)),
179 ColumnData::Uuid7(c) => ColumnData::Uuid7(uuid_to_cow(c)),
180 ColumnData::Blob {
181 container,
182 max_bytes,
183 } => ColumnData::Blob {
184 container: blob_to_cow(container),
185 max_bytes: *max_bytes,
186 },
187 ColumnData::Int {
188 container,
189 max_bytes,
190 } => ColumnData::Int {
191 container: number_to_cow(container),
192 max_bytes: *max_bytes,
193 },
194 ColumnData::Uint {
195 container,
196 max_bytes,
197 } => ColumnData::Uint {
198 container: number_to_cow(container),
199 max_bytes: *max_bytes,
200 },
201 ColumnData::Decimal {
202 container,
203 precision,
204 scale,
205 } => ColumnData::Decimal {
206 container: number_to_cow(container),
207 precision: *precision,
208 scale: *scale,
209 },
210 ColumnData::Any(c) => ColumnData::Any(any_to_cow(c)),
211 ColumnData::DictionaryId(c) => ColumnData::DictionaryId(dictionary_to_cow(c)),
212 ColumnData::Option {
213 inner,
214 bitvec,
215 } => ColumnData::Option {
216 inner: Box::new(column_data_to_cow(inner)),
217 bitvec: bitvec_to_cow::<S>(bitvec),
218 },
219 }
220}
221
222pub fn column_data_to_bump<'bump, S: Storage>(src: &ColumnData<S>, bump: &'bump BumpAlloc) -> ColumnData<Bump<'bump>> {
223 match src {
224 ColumnData::Bool(c) => ColumnData::Bool(bool_to_bump(c, bump)),
225 ColumnData::Float4(c) => ColumnData::Float4(number_to_bump(c, bump)),
226 ColumnData::Float8(c) => ColumnData::Float8(number_to_bump(c, bump)),
227 ColumnData::Int1(c) => ColumnData::Int1(number_to_bump(c, bump)),
228 ColumnData::Int2(c) => ColumnData::Int2(number_to_bump(c, bump)),
229 ColumnData::Int4(c) => ColumnData::Int4(number_to_bump(c, bump)),
230 ColumnData::Int8(c) => ColumnData::Int8(number_to_bump(c, bump)),
231 ColumnData::Int16(c) => ColumnData::Int16(number_to_bump(c, bump)),
232 ColumnData::Uint1(c) => ColumnData::Uint1(number_to_bump(c, bump)),
233 ColumnData::Uint2(c) => ColumnData::Uint2(number_to_bump(c, bump)),
234 ColumnData::Uint4(c) => ColumnData::Uint4(number_to_bump(c, bump)),
235 ColumnData::Uint8(c) => ColumnData::Uint8(number_to_bump(c, bump)),
236 ColumnData::Uint16(c) => ColumnData::Uint16(number_to_bump(c, bump)),
237 ColumnData::Utf8 {
238 container,
239 max_bytes,
240 } => ColumnData::Utf8 {
241 container: utf8_to_bump(container, bump),
242 max_bytes: *max_bytes,
243 },
244 ColumnData::Date(c) => ColumnData::Date(temporal_to_bump(c, bump)),
245 ColumnData::DateTime(c) => ColumnData::DateTime(temporal_to_bump(c, bump)),
246 ColumnData::Time(c) => ColumnData::Time(temporal_to_bump(c, bump)),
247 ColumnData::Duration(c) => ColumnData::Duration(temporal_to_bump(c, bump)),
248 ColumnData::IdentityId(c) => ColumnData::IdentityId(identity_id_to_bump(c, bump)),
249 ColumnData::Uuid4(c) => ColumnData::Uuid4(uuid_to_bump(c, bump)),
250 ColumnData::Uuid7(c) => ColumnData::Uuid7(uuid_to_bump(c, bump)),
251 ColumnData::Blob {
252 container,
253 max_bytes,
254 } => ColumnData::Blob {
255 container: blob_to_bump(container, bump),
256 max_bytes: *max_bytes,
257 },
258 ColumnData::Int {
259 container,
260 max_bytes,
261 } => ColumnData::Int {
262 container: number_to_bump(container, bump),
263 max_bytes: *max_bytes,
264 },
265 ColumnData::Uint {
266 container,
267 max_bytes,
268 } => ColumnData::Uint {
269 container: number_to_bump(container, bump),
270 max_bytes: *max_bytes,
271 },
272 ColumnData::Decimal {
273 container,
274 precision,
275 scale,
276 } => ColumnData::Decimal {
277 container: number_to_bump(container, bump),
278 precision: *precision,
279 scale: *scale,
280 },
281 ColumnData::Any(c) => ColumnData::Any(any_to_bump(c, bump)),
282 ColumnData::DictionaryId(c) => ColumnData::DictionaryId(dictionary_to_bump(c, bump)),
283 ColumnData::Option {
284 inner,
285 bitvec,
286 } => ColumnData::Option {
287 inner: Box::new(column_data_to_bump(inner, bump)),
288 bitvec: bitvec_to_bump::<S>(bitvec, bump),
289 },
290 }
291}
292
293pub fn column_to_cow<S: Storage>(src: &Column<S>) -> Column<Cow> {
294 Column::new(src.name().clone(), column_data_to_cow(src.data()))
295}
296
297pub fn column_to_bump<'bump, S: Storage>(src: &Column<S>, bump: &'bump BumpAlloc) -> Column<Bump<'bump>> {
298 Column::new(src.name().clone(), column_data_to_bump(src.data(), bump))
299}
300
301#[cfg(test)]
302mod tests {
303 use reifydb_core::value::column::Column;
304 use reifydb_type::value::r#type::Type;
305
306 use super::*;
307
308 #[test]
309 fn test_column_data_cow_roundtrip() {
310 let original = ColumnData::int4(vec![10, 20, 30]);
311 let bump_alloc = BumpAlloc::new();
312
313 let bump_data = column_data_to_bump::<Cow>(&original, &bump_alloc);
315 assert_eq!(bump_data.len(), 3);
316
317 let cow_data = column_data_to_cow::<Bump>(&bump_data);
319 assert_eq!(cow_data, original);
320 }
321
322 #[test]
323 fn test_column_data_bool_roundtrip() {
324 let original = ColumnData::bool(vec![true, false, true]);
325 let bump_alloc = BumpAlloc::new();
326
327 let bump_data = column_data_to_bump::<Cow>(&original, &bump_alloc);
328 let cow_data = column_data_to_cow::<Bump>(&bump_data);
329 assert_eq!(cow_data, original);
330 }
331
332 #[test]
333 fn test_column_data_utf8_roundtrip() {
334 let original = ColumnData::utf8(vec![String::from("hello"), String::from("world")]);
335 let bump_alloc = BumpAlloc::new();
336
337 let bump_data = column_data_to_bump::<Cow>(&original, &bump_alloc);
338 let cow_data = column_data_to_cow::<Bump>(&bump_data);
339 assert_eq!(cow_data, original);
340 }
341
342 #[test]
343 fn test_column_data_float8_roundtrip() {
344 let original = ColumnData::float8(vec![1.5, 2.7, 3.9]);
345 let bump_alloc = BumpAlloc::new();
346
347 let bump_data = column_data_to_bump::<Cow>(&original, &bump_alloc);
348 let cow_data = column_data_to_cow::<Bump>(&bump_data);
349 assert_eq!(cow_data, original);
350 }
351
352 #[test]
353 fn test_column_data_none_roundtrip() {
354 let original = ColumnData::none_typed(Type::Boolean, 5);
355 let bump_alloc = BumpAlloc::new();
356
357 let bump_data = column_data_to_bump::<Cow>(&original, &bump_alloc);
358 let cow_data = column_data_to_cow::<Bump>(&bump_data);
359 assert_eq!(cow_data, original);
360 }
361
362 #[test]
363 fn test_column_roundtrip() {
364 let original = Column::int4("age", vec![25, 30, 35]);
365 let bump_alloc = BumpAlloc::new();
366
367 let bump_col = column_to_bump::<Cow>(&original, &bump_alloc);
368 let cow_col = column_to_cow::<Bump>(&bump_col);
369 assert_eq!(cow_col, original);
370 }
371}