1use reifydb_core::value::column::buffer::ColumnBuffer;
5use reifydb_type::{
6 error::{Error, TypeError},
7 fragment::{Fragment, LazyFragment},
8 value::{
9 container::number::NumberContainer,
10 decimal::{Decimal, parse::parse_decimal},
11 int::Int,
12 is::IsNumber,
13 number::{
14 parse::{parse_float, parse_primitive_int, parse_primitive_uint},
15 safe::convert::SafeConvert,
16 },
17 r#type::{Type, get::GetType},
18 uint::Uint,
19 },
20};
21
22use crate::{Result, error::CastError, expression::convert::Convert};
23
24pub fn to_number(
25 ctx: impl Convert,
26 data: &ColumnBuffer,
27 target: Type,
28 lazy_fragment: impl LazyFragment,
29) -> Result<ColumnBuffer> {
30 if !target.is_number() {
31 let from = data.get_type();
32 return Err(TypeError::UnsupportedCast {
33 from,
34 to: target,
35 fragment: lazy_fragment.fragment(),
36 }
37 .into());
38 }
39
40 if data.get_type().is_number() {
41 return number_to_number(data, target, ctx, lazy_fragment);
42 }
43
44 if data.is_bool() {
45 return boolean_to_number(data, target, lazy_fragment);
46 }
47
48 if data.is_utf8() {
49 return match &target {
50 Type::Float4 | Type::Float8 => text_to_float(data, target, lazy_fragment),
51 Type::Decimal => text_to_decimal(data, target, lazy_fragment),
52 _ => text_to_integer(data, target, lazy_fragment),
53 };
54 }
55
56 if data.is_float() {
57 return float_to_integer(data, target, lazy_fragment);
58 }
59
60 let from = data.get_type();
61 Err(TypeError::UnsupportedCast {
62 from,
63 to: target,
64 fragment: lazy_fragment.fragment(),
65 }
66 .into())
67}
68
69fn boolean_to_number(data: &ColumnBuffer, target: Type, lazy_fragment: impl LazyFragment) -> Result<ColumnBuffer> {
70 macro_rules! boolean_to_number {
71 ($target_ty:ty, $true_val:expr, $false_val:expr) => {{
72 |out: &mut ColumnBuffer, val: bool| {
73 out.push::<$target_ty>(if val {
74 $true_val
75 } else {
76 $false_val
77 })
78 }
79 }};
80 }
81
82 match data {
83 ColumnBuffer::Bool(container) => {
84 let converter = match &target {
85 Type::Int1 => boolean_to_number!(i8, 1i8, 0i8),
86 Type::Int2 => {
87 boolean_to_number!(i16, 1i16, 0i16)
88 }
89 Type::Int4 => {
90 boolean_to_number!(i32, 1i32, 0i32)
91 }
92 Type::Int8 => {
93 boolean_to_number!(i64, 1i64, 0i64)
94 }
95 Type::Int16 => {
96 boolean_to_number!(i128, 1i128, 0i128)
97 }
98 Type::Uint1 => boolean_to_number!(u8, 1u8, 0u8),
99 Type::Uint2 => {
100 boolean_to_number!(u16, 1u16, 0u16)
101 }
102 Type::Uint4 => {
103 boolean_to_number!(u32, 1u32, 0u32)
104 }
105 Type::Uint8 => {
106 boolean_to_number!(u64, 1u64, 0u64)
107 }
108 Type::Uint16 => {
109 boolean_to_number!(u128, 1u128, 0u128)
110 }
111 Type::Float4 => {
112 boolean_to_number!(f32, 1.0f32, 0.0f32)
113 }
114 Type::Float8 => {
115 boolean_to_number!(f64, 1.0f64, 0.0f64)
116 }
117 Type::Int => |out: &mut ColumnBuffer, val: bool| {
118 out.push::<Int>(if val {
119 Int::from_i64(1)
120 } else {
121 Int::from_i64(0)
122 })
123 },
124 Type::Uint => |out: &mut ColumnBuffer, val: bool| {
125 out.push::<Uint>(if val {
126 Uint::from_u64(1)
127 } else {
128 Uint::from_u64(0)
129 })
130 },
131 Type::Decimal => |out: &mut ColumnBuffer, val: bool| {
132 let decimal = if val {
133 Decimal::from_i64(1)
134 } else {
135 Decimal::from_i64(0)
136 };
137 out.push::<Decimal>(decimal)
138 },
139 _ => {
140 let from = data.get_type();
141 return Err(TypeError::UnsupportedCast {
142 from,
143 to: target,
144 fragment: lazy_fragment.fragment(),
145 }
146 .into());
147 }
148 };
149
150 let mut out = ColumnBuffer::with_capacity(target, container.len());
151 for idx in 0..container.len() {
152 if container.is_defined(idx) {
153 let val = container.data().get(idx);
154 converter(&mut out, val);
155 } else {
156 out.push_none();
157 }
158 }
159 Ok(out)
160 }
161 _ => {
162 let from = data.get_type();
163 Err(TypeError::UnsupportedCast {
164 from,
165 to: target,
166 fragment: lazy_fragment.fragment(),
167 }
168 .into())
169 }
170 }
171}
172
173fn float_to_integer(data: &ColumnBuffer, target: Type, lazy_fragment: impl LazyFragment) -> Result<ColumnBuffer> {
174 match data {
175 ColumnBuffer::Float4(container) => match &target {
176 Type::Int1 => f32_to_i8_vec(container),
177 Type::Int2 => f32_to_i16_vec(container),
178 Type::Int4 => f32_to_i32_vec(container),
179 Type::Int8 => f32_to_i64_vec(container),
180 Type::Int16 => f32_to_i128_vec(container),
181 Type::Uint1 => f32_to_u8_vec(container),
182 Type::Uint2 => f32_to_u16_vec(container),
183 Type::Uint4 => f32_to_u32_vec(container),
184 Type::Uint8 => f32_to_u64_vec(container),
185 Type::Uint16 => f32_to_u128_vec(container),
186 Type::Int => f32_to_int_vec(container),
187 Type::Uint => f32_to_uint_vec(container),
188 Type::Decimal => f32_to_decimal_vec(container, target),
189 _ => {
190 let from = data.get_type();
191 Err(TypeError::UnsupportedCast {
192 from,
193 to: target,
194 fragment: lazy_fragment.fragment(),
195 }
196 .into())
197 }
198 },
199 ColumnBuffer::Float8(container) => match &target {
200 Type::Int1 => f64_to_i8_vec(container),
201 Type::Int2 => f64_to_i16_vec(container),
202 Type::Int4 => f64_to_i32_vec(container),
203 Type::Int8 => f64_to_i64_vec(container),
204 Type::Int16 => f64_to_i128_vec(container),
205 Type::Uint1 => f64_to_u8_vec(container),
206 Type::Uint2 => f64_to_u16_vec(container),
207 Type::Uint4 => f64_to_u32_vec(container),
208 Type::Uint8 => f64_to_u64_vec(container),
209 Type::Uint16 => f64_to_u128_vec(container),
210 Type::Int => f64_to_int_vec(container),
211 Type::Uint => f64_to_uint_vec(container),
212 Type::Decimal => f64_to_decimal_vec(container, target),
213 _ => {
214 let from = data.get_type();
215 Err(TypeError::UnsupportedCast {
216 from,
217 to: target,
218 fragment: lazy_fragment.fragment(),
219 }
220 .into())
221 }
222 },
223 _ => {
224 let from = data.get_type();
225 Err(TypeError::UnsupportedCast {
226 from,
227 to: target,
228 fragment: lazy_fragment.fragment(),
229 }
230 .into())
231 }
232 }
233}
234
235macro_rules! parse_and_push {
236 (parse_int, $ty:ty, $target_type:expr, $out:expr, $temp_fragment:expr, $base_fragment:expr) => {{
237 let result = parse_primitive_int::<$ty>($temp_fragment.clone()).map_err(|mut e| {
238 e.0.with_fragment($base_fragment.clone());
239 Error::from(CastError::InvalidNumber {
240 fragment: $base_fragment.clone(),
241 target: $target_type,
242 cause: e.diagnostic(),
243 })
244 })?;
245 $out.push::<$ty>(result);
246 }};
247 (parse_uint, $ty:ty, $target_type:expr, $out:expr, $temp_fragment:expr, $base_fragment:expr) => {{
248 let result = parse_primitive_uint::<$ty>($temp_fragment.clone()).map_err(|mut e| {
249 e.0.with_fragment($base_fragment.clone());
250 Error::from(CastError::InvalidNumber {
251 fragment: $base_fragment.clone(),
252 target: $target_type,
253 cause: e.diagnostic(),
254 })
255 })?;
256 $out.push::<$ty>(result);
257 }};
258}
259
260fn text_to_integer(data: &ColumnBuffer, target: Type, lazy_fragment: impl LazyFragment) -> Result<ColumnBuffer> {
261 match data {
262 ColumnBuffer::Utf8 {
263 container,
264 ..
265 } => {
266 let base_fragment = lazy_fragment.fragment();
267 let mut out = ColumnBuffer::with_capacity(target.clone(), container.len());
268 for idx in 0..container.len() {
269 if container.is_defined(idx) {
270 let val = container.get(idx).unwrap();
271 let temp_fragment = Fragment::internal(val);
272
273 match target.clone() {
274 Type::Int1 => {
275 parse_and_push!(
276 parse_int,
277 i8,
278 Type::Int1,
279 out,
280 temp_fragment,
281 base_fragment
282 )
283 }
284 Type::Int2 => {
285 parse_and_push!(
286 parse_int,
287 i16,
288 Type::Int2,
289 out,
290 temp_fragment,
291 base_fragment
292 )
293 }
294 Type::Int4 => {
295 parse_and_push!(
296 parse_int,
297 i32,
298 Type::Int4,
299 out,
300 temp_fragment,
301 base_fragment
302 )
303 }
304 Type::Int8 => {
305 parse_and_push!(
306 parse_int,
307 i64,
308 Type::Int8,
309 out,
310 temp_fragment,
311 base_fragment
312 )
313 }
314 Type::Int16 => {
315 parse_and_push!(
316 parse_int,
317 i128,
318 Type::Int16,
319 out,
320 temp_fragment,
321 base_fragment
322 )
323 }
324 Type::Uint1 => {
325 parse_and_push!(
326 parse_uint,
327 u8,
328 Type::Uint1,
329 out,
330 temp_fragment,
331 base_fragment
332 )
333 }
334 Type::Uint2 => {
335 parse_and_push!(
336 parse_uint,
337 u16,
338 Type::Uint2,
339 out,
340 temp_fragment,
341 base_fragment
342 )
343 }
344 Type::Uint4 => {
345 parse_and_push!(
346 parse_uint,
347 u32,
348 Type::Uint4,
349 out,
350 temp_fragment,
351 base_fragment
352 )
353 }
354 Type::Uint8 => {
355 parse_and_push!(
356 parse_uint,
357 u64,
358 Type::Uint8,
359 out,
360 temp_fragment,
361 base_fragment
362 )
363 }
364 Type::Uint16 => {
365 parse_and_push!(
366 parse_uint,
367 u128,
368 Type::Uint16,
369 out,
370 temp_fragment,
371 base_fragment
372 )
373 }
374 Type::Int => {
375 let result = parse_primitive_int(temp_fragment.clone())
376 .map_err(|mut e| {
377 e.0.with_fragment(base_fragment.clone());
378 Error::from(CastError::InvalidNumber {
379 fragment: base_fragment.clone(),
380 target: Type::Int,
381 cause: e.diagnostic(),
382 })
383 })?;
384 out.push::<Int>(result);
385 }
386 Type::Uint => {
387 let result = parse_primitive_uint(temp_fragment.clone())
388 .map_err(|mut e| {
389 e.0.with_fragment(base_fragment.clone());
390 Error::from(CastError::InvalidNumber {
391 fragment: base_fragment.clone(),
392 target: Type::Uint,
393 cause: e.diagnostic(),
394 })
395 })?;
396 out.push::<Uint>(result);
397 }
398 Type::Decimal => {
399 let target_clone = target.clone();
400 let result = parse_decimal(temp_fragment.clone()).map_err(
401 |mut e| {
402 e.0.with_fragment(base_fragment.clone());
403 Error::from(CastError::InvalidNumber {
404 fragment: base_fragment.clone(),
405 target: target_clone,
406 cause: e.diagnostic(),
407 })
408 },
409 )?;
410 out.push::<Decimal>(result);
411 }
412 _ => {
413 let from = data.get_type();
414 return Err(TypeError::UnsupportedCast {
415 from,
416 to: target,
417 fragment: base_fragment.clone(),
418 }
419 .into());
420 }
421 }
422 } else {
423 out.push_none();
424 }
425 }
426 Ok(out)
427 }
428 _ => {
429 let from = data.get_type();
430 Err(TypeError::UnsupportedCast {
431 from,
432 to: target,
433 fragment: lazy_fragment.fragment(),
434 }
435 .into())
436 }
437 }
438}
439
440fn text_to_float(column_data: &ColumnBuffer, target: Type, lazy_fragment: impl LazyFragment) -> Result<ColumnBuffer> {
441 if let ColumnBuffer::Utf8 {
442 container,
443 ..
444 } = column_data
445 {
446 let base_fragment = lazy_fragment.fragment();
448 let mut out = ColumnBuffer::with_capacity(target.clone(), container.len());
449 for idx in 0..container.len() {
450 if container.is_defined(idx) {
451 let val = container.get(idx).unwrap();
452 let temp_fragment = Fragment::internal(val);
455
456 match target.clone() {
457 Type::Float4 => out.push::<f32>(
458 parse_float::<f32>(temp_fragment.clone()).map_err(|mut e| {
459 e.0.with_fragment(base_fragment.clone());
460 Error::from(CastError::InvalidNumber {
461 fragment: base_fragment.clone(),
462 target: Type::Float4,
463 cause: e.diagnostic(),
464 })
465 })?,
466 ),
467
468 Type::Float8 => out.push::<f64>(parse_float::<f64>(temp_fragment).map_err(
469 |mut e| {
470 e.0.with_fragment(base_fragment.clone());
471 Error::from(CastError::InvalidNumber {
472 fragment: base_fragment.clone(),
473 target: Type::Float8,
474 cause: e.diagnostic(),
475 })
476 },
477 )?),
478 _ => {
479 let from = column_data.get_type();
480 return Err(TypeError::UnsupportedCast {
481 from,
482 to: target,
483 fragment: base_fragment.clone(),
484 }
485 .into());
486 }
487 }
488 } else {
489 out.push_none();
490 }
491 }
492 Ok(out)
493 } else {
494 let from = column_data.get_type();
495 Err(TypeError::UnsupportedCast {
496 from,
497 to: target,
498 fragment: lazy_fragment.fragment(),
499 }
500 .into())
501 }
502}
503
504fn text_to_decimal(column_data: &ColumnBuffer, target: Type, lazy_fragment: impl LazyFragment) -> Result<ColumnBuffer> {
505 if let ColumnBuffer::Utf8 {
506 container,
507 ..
508 } = column_data
509 {
510 let base_fragment = lazy_fragment.fragment();
511 let mut out = ColumnBuffer::with_capacity(target.clone(), container.len());
512 for idx in 0..container.len() {
513 if container.is_defined(idx) {
514 let val = container.get(idx).unwrap();
515 let temp_fragment = Fragment::internal(val);
516
517 let result = parse_decimal(temp_fragment.clone()).map_err(|mut e| {
518 e.0.with_fragment(base_fragment.clone());
519 Error::from(CastError::InvalidNumber {
520 fragment: base_fragment.clone(),
521 target: target.clone(),
522 cause: e.diagnostic(),
523 })
524 })?;
525 out.push::<Decimal>(result);
526 } else {
527 out.push_none();
528 }
529 }
530 Ok(out)
531 } else {
532 let from = column_data.get_type();
533 Err(TypeError::UnsupportedCast {
534 from,
535 to: target,
536 fragment: lazy_fragment.fragment(),
537 }
538 .into())
539 }
540}
541
542macro_rules! float_to_int_vec {
543 ($fn_name:ident, $float_ty:ty, $int_ty:ty, $target_type:expr, $min_val:expr, $max_val:expr) => {
544 fn $fn_name(container: &NumberContainer<$float_ty>) -> Result<ColumnBuffer>
545 where
546 $float_ty: Copy + IsNumber,
547 {
548 let mut out = ColumnBuffer::with_capacity($target_type, container.len());
549 for idx in 0..container.len() {
550 if container.is_defined(idx) {
551 let val = container[idx];
552 let truncated = val.trunc();
553 if truncated >= $min_val && truncated <= $max_val {
554 out.push::<$int_ty>(truncated as $int_ty);
555 } else {
556 out.push_none();
557 }
558 } else {
559 out.push_none();
560 }
561 }
562 Ok(out)
563 }
564 };
565}
566
567float_to_int_vec!(f32_to_i8_vec, f32, i8, Type::Int1, i8::MIN as f32, i8::MAX as f32);
568float_to_int_vec!(f32_to_i16_vec, f32, i16, Type::Int2, i16::MIN as f32, i16::MAX as f32);
569float_to_int_vec!(f32_to_i32_vec, f32, i32, Type::Int4, i32::MIN as f32, i32::MAX as f32);
570float_to_int_vec!(f32_to_i64_vec, f32, i64, Type::Int8, i64::MIN as f32, i64::MAX as f32);
571float_to_int_vec!(f32_to_i128_vec, f32, i128, Type::Int16, i128::MIN as f32, i128::MAX as f32);
572float_to_int_vec!(f32_to_u8_vec, f32, u8, Type::Uint1, 0.0, u8::MAX as f32);
573float_to_int_vec!(f32_to_u16_vec, f32, u16, Type::Uint2, 0.0, u16::MAX as f32);
574float_to_int_vec!(f32_to_u32_vec, f32, u32, Type::Uint4, 0.0, u32::MAX as f32);
575float_to_int_vec!(f32_to_u64_vec, f32, u64, Type::Uint8, 0.0, u64::MAX as f32);
576float_to_int_vec!(f32_to_u128_vec, f32, u128, Type::Uint16, 0.0, u128::MAX as f32);
577
578float_to_int_vec!(f64_to_i8_vec, f64, i8, Type::Int1, i8::MIN as f64, i8::MAX as f64);
579float_to_int_vec!(f64_to_i16_vec, f64, i16, Type::Int2, i16::MIN as f64, i16::MAX as f64);
580float_to_int_vec!(f64_to_i32_vec, f64, i32, Type::Int4, i32::MIN as f64, i32::MAX as f64);
581float_to_int_vec!(f64_to_i64_vec, f64, i64, Type::Int8, i64::MIN as f64, i64::MAX as f64);
582float_to_int_vec!(f64_to_i128_vec, f64, i128, Type::Int16, i128::MIN as f64, i128::MAX as f64);
583float_to_int_vec!(f64_to_u8_vec, f64, u8, Type::Uint1, 0.0, u8::MAX as f64);
584float_to_int_vec!(f64_to_u16_vec, f64, u16, Type::Uint2, 0.0, u16::MAX as f64);
585float_to_int_vec!(f64_to_u32_vec, f64, u32, Type::Uint4, 0.0, u32::MAX as f64);
586float_to_int_vec!(f64_to_u64_vec, f64, u64, Type::Uint8, 0.0, u64::MAX as f64);
587float_to_int_vec!(f64_to_u128_vec, f64, u128, Type::Uint16, 0.0, u128::MAX as f64);
588
589fn f32_to_int_vec(container: &NumberContainer<f32>) -> Result<ColumnBuffer> {
591 let mut out = ColumnBuffer::with_capacity(Type::Int, container.len());
592 for idx in 0..container.len() {
593 if container.is_defined(idx) {
594 let val = container[idx];
595 let truncated = val.trunc();
596 let int = Int::from_i64(truncated as i64);
597 out.push::<Int>(int);
598 } else {
599 out.push_none();
600 }
601 }
602 Ok(out)
603}
604
605fn f64_to_int_vec(container: &NumberContainer<f64>) -> Result<ColumnBuffer> {
606 let mut out = ColumnBuffer::with_capacity(Type::Int, container.len());
607 for idx in 0..container.len() {
608 if container.is_defined(idx) {
609 let val = container[idx];
610 let truncated = val.trunc();
611 let int = Int::from_i64(truncated as i64);
612 out.push::<Int>(int);
613 } else {
614 out.push_none();
615 }
616 }
617 Ok(out)
618}
619
620fn f32_to_uint_vec(container: &NumberContainer<f32>) -> Result<ColumnBuffer> {
622 let mut out = ColumnBuffer::with_capacity(Type::Uint, container.len());
623 for idx in 0..container.len() {
624 if container.is_defined(idx) {
625 let val = container[idx];
626 let truncated = val.trunc();
627 if truncated >= 0.0 {
628 let uint = Uint::from_u64(truncated as u64);
629 out.push::<Uint>(uint);
630 } else {
631 out.push_none();
632 }
633 } else {
634 out.push_none();
635 }
636 }
637 Ok(out)
638}
639
640fn f64_to_uint_vec(container: &NumberContainer<f64>) -> Result<ColumnBuffer> {
641 let mut out = ColumnBuffer::with_capacity(Type::Uint, container.len());
642 for idx in 0..container.len() {
643 if container.is_defined(idx) {
644 let val = container[idx];
645 let truncated = val.trunc();
646 if truncated >= 0.0 {
647 let uint = Uint::from_u64(truncated as u64);
648 out.push::<Uint>(uint);
649 } else {
650 out.push_none();
651 }
652 } else {
653 out.push_none();
654 }
655 }
656 Ok(out)
657}
658
659fn f32_to_decimal_vec(container: &NumberContainer<f32>, target: Type) -> Result<ColumnBuffer> {
661 let mut out = ColumnBuffer::with_capacity(target, container.len());
662 for idx in 0..container.len() {
663 if container.is_defined(idx) {
664 let val = container[idx];
665 let decimal = Decimal::from_i64(val.trunc() as i64);
667 out.push::<Decimal>(decimal);
668 } else {
669 out.push_none();
670 }
671 }
672 Ok(out)
673}
674
675fn f64_to_decimal_vec(container: &NumberContainer<f64>, target: Type) -> Result<ColumnBuffer> {
676 let mut out = ColumnBuffer::with_capacity(target, container.len());
677 for idx in 0..container.len() {
678 if container.is_defined(idx) {
679 let val = container[idx];
680 let decimal = Decimal::from_i64(val.trunc() as i64);
682 out.push::<Decimal>(decimal);
683 } else {
684 out.push_none();
685 }
686 }
687 Ok(out)
688}
689
690fn number_to_number(
691 data: &ColumnBuffer,
692 target: Type,
693 ctx: impl Convert,
694 lazy_fragment: impl LazyFragment,
695) -> Result<ColumnBuffer> {
696 if !target.is_number() {
697 return Err(TypeError::UnsupportedCast {
698 from: data.get_type(),
699 to: target,
700 fragment: lazy_fragment.fragment(),
701 }
702 .into());
703 }
704
705 macro_rules! cast {
706 (
707 $src_variant:ident, $src_ty:ty,
708 to => [ $( ($dst_variant:ident, $dst_ty:ty) ),* ]
709 $(, to_struct => [ $( ($struct_variant:ident, $struct_ty:ty) ),* ])?
710 ) => {
711 if let ColumnBuffer::$src_variant(container) = data {
712 match target {
713 $(
714 Type::$dst_variant => return convert_vec::<$src_ty, $dst_ty>(
715 &container,
716 ctx,
717 lazy_fragment,
718 Type::$dst_variant,
719 ColumnBuffer::push::<$dst_ty>,
720 ),
721 )*
722 $($(
723 Type::$struct_variant { .. } => return convert_vec::<$src_ty, $struct_ty>(
724 &container,
725 ctx,
726 lazy_fragment,
727 target,
728 ColumnBuffer::push::<$struct_ty>,
729 ),
730 )*)?
731 _ => {}
732 }
733 }
734 }
735 }
736
737 cast!(Float4, f32,
738 to => [(Float8, f64), (Int1, i8), (Int2, i16), (Int4, i32), (Int8, i64), (Int16, i128), (Uint1, u8), (Uint2, u16), (Uint4, u32), (Uint8, u64), (Uint16, u128), (Int, Int), (Uint, Uint)],
739 to_struct => [(Decimal, Decimal)]
740 );
741
742 cast!(Float8, f64,
743 to => [(Float4, f32), (Int1, i8), (Int2, i16), (Int4, i32), (Int8, i64), (Int16, i128), (Uint1, u8), (Uint2, u16), (Uint4, u32), (Uint8, u64), (Uint16, u128), (Int, Int), (Uint, Uint)],
744 to_struct => [(Decimal, Decimal)]
745 );
746
747 cast!(Int1, i8,
748 to => [(Int2, i16), (Int4, i32), (Int8, i64), (Int16, i128), (Float4, f32), (Float8, f64), (Uint1, u8), (Uint2, u16), (Uint4, u32), (Uint8, u64), (Uint16, u128), (Int, Int), (Uint, Uint)],
749 to_struct => [(Decimal, Decimal)]
750 );
751
752 cast!(Int2, i16,
753 to => [(Int1, i8), (Int4, i32), (Int8, i64), (Int16, i128), (Float4, f32), (Float8, f64), (Uint1, u8), (Uint2, u16), (Uint4, u32), (Uint8, u64), (Uint16, u128), (Int, Int), (Uint, Uint)],
754 to_struct => [(Decimal, Decimal)]
755 );
756
757 cast!(Int4, i32,
758 to => [(Int1, i8), (Int2, i16), (Int8, i64), (Int16, i128), (Float4, f32), (Float8, f64), (Uint1, u8), (Uint2, u16), (Uint4, u32), (Uint8, u64), (Uint16, u128), (Int, Int), (Uint, Uint)],
759 to_struct => [(Decimal, Decimal)]
760 );
761
762 cast!(Int8, i64,
763 to => [(Int1, i8), (Int2, i16), (Int4, i32), (Int16, i128), (Float4, f32), (Float8, f64), (Uint1, u8), (Uint2, u16), (Uint4, u32), (Uint8, u64), (Uint16, u128), (Int, Int), (Uint, Uint)],
764 to_struct => [(Decimal, Decimal)]
765 );
766
767 cast!(Int16, i128,
768 to => [(Int1, i8), (Int2, i16), (Int4, i32), (Int8, i64), (Float4, f32), (Float8, f64), (Uint1, u8), (Uint2, u16), (Uint4, u32), (Uint8, u64), (Uint16, u128), (Int, Int), (Uint, Uint)],
769 to_struct => [(Decimal, Decimal)]
770 );
771
772 cast!(Uint1, u8,
773 to => [(Uint2, u16), (Uint4, u32), (Uint8, u64), (Uint16, u128), (Float4, f32), (Float8, f64), (Int1, i8), (Int2, i16), (Int4, i32), (Int8, i64), (Int16, i128), (Int, Int), (Uint, Uint)],
774 to_struct => [(Decimal, Decimal)]
775 );
776
777 cast!(Uint2, u16,
778 to => [(Uint1, u8), (Uint4, u32), (Uint8, u64), (Uint16, u128), (Float4, f32), (Float8, f64), (Int1, i8), (Int2, i16), (Int4, i32), (Int8, i64), (Int16, i128), (Int, Int), (Uint, Uint)],
779 to_struct => [(Decimal, Decimal)]
780 );
781
782 cast!(Uint4, u32,
783 to => [(Uint1, u8), (Uint2, u16), (Uint8, u64), (Uint16, u128), (Float4, f32), (Float8, f64), (Int1, i8), (Int2, i16), (Int4, i32), (Int8, i64), (Int16, i128), (Int, Int), (Uint, Uint)],
784 to_struct => [(Decimal, Decimal)]
785 );
786
787 cast!(Uint8, u64,
788 to => [(Uint1, u8), (Uint2, u16), (Uint4, u32), (Uint16, u128), (Float4, f32), (Float8, f64), (Int1, i8), (Int2, i16), (Int4, i32), (Int8, i64), (Int16, i128), (Int, Int), (Uint, Uint)],
789 to_struct => [(Decimal, Decimal)]
790 );
791
792 cast!(Uint16, u128,
793 to => [(Uint1, u8), (Uint2, u16), (Uint4, u32), (Uint8, u64), (Float4, f32), (Float8, f64), (Int1, i8), (Int2, i16), (Int4, i32), (Int8, i64), (Int16, i128), (Int, Int), (Uint, Uint)],
794 to_struct => [(Decimal, Decimal)]
795 );
796
797 if let ColumnBuffer::Int {
799 container,
800 ..
801 } = data
802 {
803 match target {
804 Type::Int1 => {
805 return convert_vec_clone::<Int, i8>(
806 container,
807 ctx,
808 lazy_fragment,
809 Type::Int1,
810 ColumnBuffer::push::<i8>,
811 );
812 }
813 Type::Int2 => {
814 return convert_vec_clone::<Int, i16>(
815 container,
816 ctx,
817 lazy_fragment,
818 Type::Int2,
819 ColumnBuffer::push::<i16>,
820 );
821 }
822 Type::Int4 => {
823 return convert_vec_clone::<Int, i32>(
824 container,
825 ctx,
826 lazy_fragment,
827 Type::Int4,
828 ColumnBuffer::push::<i32>,
829 );
830 }
831 Type::Int8 => {
832 return convert_vec_clone::<Int, i64>(
833 container,
834 ctx,
835 lazy_fragment,
836 Type::Int8,
837 ColumnBuffer::push::<i64>,
838 );
839 }
840 Type::Int16 => {
841 return convert_vec_clone::<Int, i128>(
842 container,
843 ctx,
844 lazy_fragment,
845 Type::Int16,
846 ColumnBuffer::push::<i128>,
847 );
848 }
849 Type::Uint1 => {
850 return convert_vec_clone::<Int, u8>(
851 container,
852 ctx,
853 lazy_fragment,
854 Type::Uint1,
855 ColumnBuffer::push::<u8>,
856 );
857 }
858 Type::Uint2 => {
859 return convert_vec_clone::<Int, u16>(
860 container,
861 ctx,
862 lazy_fragment,
863 Type::Uint2,
864 ColumnBuffer::push::<u16>,
865 );
866 }
867 Type::Uint4 => {
868 return convert_vec_clone::<Int, u32>(
869 container,
870 ctx,
871 lazy_fragment,
872 Type::Uint4,
873 ColumnBuffer::push::<u32>,
874 );
875 }
876 Type::Uint8 => {
877 return convert_vec_clone::<Int, u64>(
878 container,
879 ctx,
880 lazy_fragment,
881 Type::Uint8,
882 ColumnBuffer::push::<u64>,
883 );
884 }
885 Type::Uint16 => {
886 return convert_vec_clone::<Int, u128>(
887 container,
888 ctx,
889 lazy_fragment,
890 Type::Uint16,
891 ColumnBuffer::push::<u128>,
892 );
893 }
894 Type::Float4 => {
895 return convert_vec_clone::<Int, f32>(
896 container,
897 ctx,
898 lazy_fragment,
899 Type::Float4,
900 ColumnBuffer::push::<f32>,
901 );
902 }
903 Type::Float8 => {
904 return convert_vec_clone::<Int, f64>(
905 container,
906 ctx,
907 lazy_fragment,
908 Type::Float8,
909 ColumnBuffer::push::<f64>,
910 );
911 }
912 Type::Uint => {
913 return convert_vec_clone::<Int, Uint>(
914 container,
915 ctx,
916 lazy_fragment,
917 Type::Uint,
918 ColumnBuffer::push::<Uint>,
919 );
920 }
921 Type::Decimal => {
922 return convert_vec_clone::<Int, Decimal>(
923 container,
924 ctx,
925 lazy_fragment,
926 target,
927 ColumnBuffer::push::<Decimal>,
928 );
929 }
930 _ => {}
931 }
932 }
933
934 if let ColumnBuffer::Uint {
936 container,
937 ..
938 } = data
939 {
940 match target {
941 Type::Uint1 => {
942 return convert_vec_clone::<Uint, u8>(
943 container,
944 ctx,
945 lazy_fragment,
946 Type::Uint1,
947 ColumnBuffer::push::<u8>,
948 );
949 }
950 Type::Uint2 => {
951 return convert_vec_clone::<Uint, u16>(
952 container,
953 ctx,
954 lazy_fragment,
955 Type::Uint2,
956 ColumnBuffer::push::<u16>,
957 );
958 }
959 Type::Uint4 => {
960 return convert_vec_clone::<Uint, u32>(
961 container,
962 ctx,
963 lazy_fragment,
964 Type::Uint4,
965 ColumnBuffer::push::<u32>,
966 );
967 }
968 Type::Uint8 => {
969 return convert_vec_clone::<Uint, u64>(
970 container,
971 ctx,
972 lazy_fragment,
973 Type::Uint8,
974 ColumnBuffer::push::<u64>,
975 );
976 }
977 Type::Uint16 => {
978 return convert_vec_clone::<Uint, u128>(
979 container,
980 ctx,
981 lazy_fragment,
982 Type::Uint16,
983 ColumnBuffer::push::<u128>,
984 );
985 }
986 Type::Int1 => {
987 return convert_vec_clone::<Uint, i8>(
988 container,
989 ctx,
990 lazy_fragment,
991 Type::Int1,
992 ColumnBuffer::push::<i8>,
993 );
994 }
995 Type::Int2 => {
996 return convert_vec_clone::<Uint, i16>(
997 container,
998 ctx,
999 lazy_fragment,
1000 Type::Int2,
1001 ColumnBuffer::push::<i16>,
1002 );
1003 }
1004 Type::Int4 => {
1005 return convert_vec_clone::<Uint, i32>(
1006 container,
1007 ctx,
1008 lazy_fragment,
1009 Type::Int4,
1010 ColumnBuffer::push::<i32>,
1011 );
1012 }
1013 Type::Int8 => {
1014 return convert_vec_clone::<Uint, i64>(
1015 container,
1016 ctx,
1017 lazy_fragment,
1018 Type::Int8,
1019 ColumnBuffer::push::<i64>,
1020 );
1021 }
1022 Type::Int16 => {
1023 return convert_vec_clone::<Uint, i128>(
1024 container,
1025 ctx,
1026 lazy_fragment,
1027 Type::Int16,
1028 ColumnBuffer::push::<i128>,
1029 );
1030 }
1031 Type::Float4 => {
1032 return convert_vec_clone::<Uint, f32>(
1033 container,
1034 ctx,
1035 lazy_fragment,
1036 Type::Float4,
1037 ColumnBuffer::push::<f32>,
1038 );
1039 }
1040 Type::Float8 => {
1041 return convert_vec_clone::<Uint, f64>(
1042 container,
1043 ctx,
1044 lazy_fragment,
1045 Type::Float8,
1046 ColumnBuffer::push::<f64>,
1047 );
1048 }
1049 Type::Int => {
1050 return convert_vec_clone::<Uint, Int>(
1051 container,
1052 ctx,
1053 lazy_fragment,
1054 Type::Int,
1055 ColumnBuffer::push::<Int>,
1056 );
1057 }
1058 Type::Decimal => {
1059 return convert_vec_clone::<Uint, Decimal>(
1060 container,
1061 ctx,
1062 lazy_fragment,
1063 target,
1064 ColumnBuffer::push::<Decimal>,
1065 );
1066 }
1067 _ => {}
1068 }
1069 }
1070
1071 if let ColumnBuffer::Decimal {
1074 container,
1075 ..
1076 } = data
1077 {
1078 match target {
1079 Type::Int1 => {
1080 return convert_vec_clone::<Decimal, i8>(
1081 container,
1082 ctx,
1083 lazy_fragment,
1084 Type::Int1,
1085 ColumnBuffer::push::<i8>,
1086 );
1087 }
1088 Type::Int2 => {
1089 return convert_vec_clone::<Decimal, i16>(
1090 container,
1091 ctx,
1092 lazy_fragment,
1093 Type::Int2,
1094 ColumnBuffer::push::<i16>,
1095 );
1096 }
1097 Type::Int4 => {
1098 return convert_vec_clone::<Decimal, i32>(
1099 container,
1100 ctx,
1101 lazy_fragment,
1102 Type::Int4,
1103 ColumnBuffer::push::<i32>,
1104 );
1105 }
1106 Type::Int8 => {
1107 return convert_vec_clone::<Decimal, i64>(
1108 container,
1109 ctx,
1110 lazy_fragment,
1111 Type::Int8,
1112 ColumnBuffer::push::<i64>,
1113 );
1114 }
1115 Type::Int16 => {
1116 return convert_vec_clone::<Decimal, i128>(
1117 container,
1118 ctx,
1119 lazy_fragment,
1120 Type::Int16,
1121 ColumnBuffer::push::<i128>,
1122 );
1123 }
1124 Type::Uint1 => {
1125 return convert_vec_clone::<Decimal, u8>(
1126 container,
1127 ctx,
1128 lazy_fragment,
1129 Type::Uint1,
1130 ColumnBuffer::push::<u8>,
1131 );
1132 }
1133 Type::Uint2 => {
1134 return convert_vec_clone::<Decimal, u16>(
1135 container,
1136 ctx,
1137 lazy_fragment,
1138 Type::Uint2,
1139 ColumnBuffer::push::<u16>,
1140 );
1141 }
1142 Type::Uint4 => {
1143 return convert_vec_clone::<Decimal, u32>(
1144 container,
1145 ctx,
1146 lazy_fragment,
1147 Type::Uint4,
1148 ColumnBuffer::push::<u32>,
1149 );
1150 }
1151 Type::Uint8 => {
1152 return convert_vec_clone::<Decimal, u64>(
1153 container,
1154 ctx,
1155 lazy_fragment,
1156 Type::Uint8,
1157 ColumnBuffer::push::<u64>,
1158 );
1159 }
1160 Type::Uint16 => {
1161 return convert_vec_clone::<Decimal, u128>(
1162 container,
1163 ctx,
1164 lazy_fragment,
1165 Type::Uint16,
1166 ColumnBuffer::push::<u128>,
1167 );
1168 }
1169 Type::Float4 => {
1170 return convert_vec_clone::<Decimal, f32>(
1171 container,
1172 ctx,
1173 lazy_fragment,
1174 Type::Float4,
1175 ColumnBuffer::push::<f32>,
1176 );
1177 }
1178 Type::Float8 => {
1179 return convert_vec_clone::<Decimal, f64>(
1180 container,
1181 ctx,
1182 lazy_fragment,
1183 Type::Float8,
1184 ColumnBuffer::push::<f64>,
1185 );
1186 }
1187 Type::Int => {
1188 return convert_vec_clone::<Decimal, Int>(
1189 container,
1190 ctx,
1191 lazy_fragment,
1192 Type::Int,
1193 ColumnBuffer::push::<Int>,
1194 );
1195 }
1196 Type::Uint => {
1197 return convert_vec_clone::<Decimal, Uint>(
1198 container,
1199 ctx,
1200 lazy_fragment,
1201 Type::Uint,
1202 ColumnBuffer::push::<Uint>,
1203 );
1204 }
1205 Type::Decimal => {
1206 return convert_vec_clone::<Decimal, Decimal>(
1207 container,
1208 ctx,
1209 lazy_fragment,
1210 target,
1211 ColumnBuffer::push::<Decimal>,
1212 );
1213 }
1214 _ => {}
1215 }
1216 }
1217
1218 let from = data.get_type();
1219 Err(TypeError::UnsupportedCast {
1220 from,
1221 to: target,
1222 fragment: lazy_fragment.fragment(),
1223 }
1224 .into())
1225}
1226
1227pub(crate) fn convert_vec<From, To>(
1228 container: &NumberContainer<From>,
1229 ctx: impl Convert,
1230 lazy_fragment: impl LazyFragment,
1231 target_kind: Type,
1232 mut push: impl FnMut(&mut ColumnBuffer, To),
1233) -> Result<ColumnBuffer>
1234where
1235 From: Copy + SafeConvert<To> + GetType + IsNumber + Default,
1236 To: GetType,
1237{
1238 let mut out = ColumnBuffer::with_capacity(target_kind, container.len());
1239 for idx in 0..container.len() {
1240 if container.is_defined(idx) {
1241 let val = container[idx];
1242 let fragment = lazy_fragment.fragment();
1243 match ctx.convert::<From, To>(val, fragment)? {
1244 Some(v) => push(&mut out, v),
1245 None => out.push_none(),
1246 }
1247 } else {
1248 out.push_none();
1249 }
1250 }
1251 Ok(out)
1252}
1253
1254pub(crate) fn convert_vec_clone<From, To>(
1255 container: &NumberContainer<From>,
1256 ctx: impl Convert,
1257 lazy_fragment: impl LazyFragment,
1258 target_kind: Type,
1259 mut push: impl FnMut(&mut ColumnBuffer, To),
1260) -> Result<ColumnBuffer>
1261where
1262 From: Clone + SafeConvert<To> + GetType + IsNumber + Default,
1263 To: GetType,
1264{
1265 let mut out = ColumnBuffer::with_capacity(target_kind, container.len());
1266 for idx in 0..container.len() {
1267 if container.is_defined(idx) {
1268 let val = container[idx].clone();
1269 let fragment = lazy_fragment.fragment();
1270 match ctx.convert::<From, To>(val, fragment)? {
1271 Some(v) => push(&mut out, v),
1272 None => out.push_none(),
1273 }
1274 } else {
1275 out.push_none();
1276 }
1277 }
1278 Ok(out)
1279}
1280
1281#[cfg(test)]
1282pub mod tests {
1283 mod convert {
1284 use std::mem;
1285
1286 use reifydb_type::{
1287 Result,
1288 fragment::Fragment,
1289 value::{
1290 container::number::NumberContainer,
1291 number::safe::convert::SafeConvert,
1292 r#type::{Type, get::GetType},
1293 },
1294 };
1295
1296 use crate::expression::{cast::number::convert_vec, convert::Convert};
1297
1298 #[test]
1299 fn test_promote_ok() {
1300 let data = [1i8, 2i8];
1301 let ctx = TestCtx::new();
1302
1303 let container = NumberContainer::new(data.to_vec());
1304 let result = convert_vec::<i8, i16>(
1305 &container,
1306 &ctx,
1307 || Fragment::testing_empty(),
1308 Type::Int2,
1309 |col, v| col.push::<i16>(v),
1310 )
1311 .unwrap();
1312
1313 let slice: &[i16] = result.as_slice();
1314 assert_eq!(slice, &[1i16, 2i16]);
1315 }
1316
1317 #[test]
1318 fn test_promote_none_maps_to_undefined() {
1319 let data = [42i8];
1321 let ctx = TestCtx::new();
1322
1323 let container = NumberContainer::new(data.to_vec());
1324 let result = convert_vec::<i8, i16>(
1325 &container,
1326 &ctx,
1327 || Fragment::testing_empty(),
1328 Type::Int2,
1329 |col, v| col.push::<i16>(v),
1330 )
1331 .unwrap();
1332
1333 assert!(!result.is_defined(0));
1334 }
1335
1336 #[test]
1337 fn test_promote_valid_input_is_defined() {
1338 let data = [1i8];
1342 let ctx = TestCtx::new();
1343
1344 let container = NumberContainer::new(data.to_vec());
1345 let result = convert_vec::<i8, i16>(
1346 &container,
1347 &ctx,
1348 || Fragment::testing_empty(),
1349 Type::Int2,
1350 |col, v| col.push::<i16>(v),
1351 )
1352 .unwrap();
1353
1354 assert!(result.is_defined(0));
1355 let slice = result.as_slice::<i16>();
1356 assert_eq!(slice, &[1i16]);
1357 }
1358
1359 #[test]
1360 fn test_promote_conversion_failure_is_undefined() {
1361 let data = [1i8, 42i8, 3i8, 4i8];
1364 let ctx = TestCtx::new();
1365
1366 let container = NumberContainer::new(data.to_vec());
1367 let result = convert_vec::<i8, i16>(
1368 &container,
1369 &ctx,
1370 || Fragment::testing_empty(),
1371 Type::Int2,
1372 |col, v| col.push::<i16>(v),
1373 )
1374 .unwrap();
1375
1376 let slice = result.as_slice::<i16>();
1377 assert_eq!(slice, &[1i16, 0, 3i16, 4i16]);
1378 assert!(result.is_defined(0));
1379 assert!(!result.is_defined(1));
1380 assert!(result.is_defined(2));
1381 assert!(result.is_defined(3));
1382 }
1383
1384 struct TestCtx;
1385
1386 impl TestCtx {
1387 fn new() -> Self {
1388 Self
1389 }
1390 }
1391
1392 impl Convert for &TestCtx {
1393 fn convert<From, To>(&self, val: From, _fragment: impl Into<Fragment>) -> Result<Option<To>>
1395 where
1396 From: SafeConvert<To> + GetType,
1397 To: GetType,
1398 {
1399 if mem::size_of::<From>() == 1 {
1402 let raw: i8 = unsafe { mem::transmute_copy(&val) };
1403 if raw == 42 {
1404 return Ok(None);
1405 }
1406 } else if mem::size_of::<From>() == 2 {
1407 let raw: i16 = unsafe { mem::transmute_copy(&val) };
1408 if raw == 42 {
1409 return Ok(None);
1410 }
1411 }
1412 Ok(Some(val.checked_convert().unwrap()))
1413 }
1414 }
1415
1416 #[test]
1417 fn test_demote_ok() {
1418 let data = [1i16, 2i16];
1419 let ctx = TestCtx::new();
1420
1421 let container = NumberContainer::new(data.to_vec());
1422 let result = convert_vec::<i16, i8>(
1423 &container,
1424 &ctx,
1425 || Fragment::testing_empty(),
1426 Type::Int1,
1427 |col, v| col.push::<i8>(v),
1428 )
1429 .unwrap();
1430
1431 let slice: &[i8] = result.as_slice();
1432 assert_eq!(slice, &[1i8, 2i8]);
1433 assert!(result.is_defined(0));
1434 assert!(result.is_defined(1));
1435 }
1436
1437 #[test]
1438 fn test_demote_none_maps_to_undefined() {
1439 let data = [42i16];
1440 let ctx = TestCtx::new();
1441
1442 let container = NumberContainer::new(data.to_vec());
1443 let result = convert_vec::<i16, i8>(
1444 &container,
1445 &ctx,
1446 || Fragment::testing_empty(),
1447 Type::Int1,
1448 |col, v| col.push::<i8>(v),
1449 )
1450 .unwrap();
1451
1452 assert!(!result.is_defined(0));
1453 }
1454
1455 #[test]
1456 fn test_demote_valid_input_is_defined() {
1457 let data = [1i16];
1461 let ctx = TestCtx::new();
1462
1463 let container = NumberContainer::new(data.to_vec());
1464 let result = convert_vec::<i16, i8>(
1465 &container,
1466 &ctx,
1467 || Fragment::testing_empty(),
1468 Type::Int1,
1469 |col, v| col.push::<i8>(v),
1470 )
1471 .unwrap();
1472
1473 assert!(result.is_defined(0));
1474 let slice: &[i8] = result.as_slice();
1475 assert_eq!(slice, &[1i8]);
1476 }
1477
1478 #[test]
1479 fn test_demote_conversion_failure_is_undefined() {
1480 let data = [1i16, 42i16, 3i16, 4i16];
1483 let ctx = TestCtx::new();
1484
1485 let container = NumberContainer::new(data.to_vec());
1486 let result = convert_vec::<i16, i8>(
1487 &container,
1488 &ctx,
1489 || Fragment::testing_empty(),
1490 Type::Int1,
1491 |col, v| col.push::<i8>(v),
1492 )
1493 .unwrap();
1494
1495 let slice: &[i8] = result.as_slice();
1496 assert_eq!(slice, &[1i8, 0, 3i8, 4i8]);
1497 assert!(result.is_defined(0));
1498 assert!(!result.is_defined(1));
1499 assert!(result.is_defined(2));
1500 assert!(result.is_defined(3));
1501 }
1502 }
1503}