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