reifydb_engine/expression/cast/
boolean.rs1use std::{fmt::Display, sync::Arc};
5
6use reifydb_core::value::column::data::ColumnData;
7use reifydb_type::{
8 error::diagnostic::{boolean::invalid_number_boolean, cast},
9 fragment::{Fragment, LazyFragment},
10 return_error,
11 value::{
12 boolean::parse::parse_bool,
13 container::{number::NumberContainer, utf8::Utf8Container},
14 is::IsNumber,
15 r#type::Type,
16 },
17};
18
19pub fn to_boolean(data: &ColumnData, lazy_fragment: impl LazyFragment) -> crate::Result<ColumnData> {
20 match data {
21 ColumnData::Int1(container) => from_int1(container, lazy_fragment),
22 ColumnData::Int2(container) => from_int2(container, lazy_fragment),
23 ColumnData::Int4(container) => from_int4(container, lazy_fragment),
24 ColumnData::Int8(container) => from_int8(container, lazy_fragment),
25 ColumnData::Int16(container) => from_int16(container, lazy_fragment),
26 ColumnData::Uint1(container) => from_uint1(container, lazy_fragment),
27 ColumnData::Uint2(container) => from_uint2(container, lazy_fragment),
28 ColumnData::Uint4(container) => from_uint4(container, lazy_fragment),
29 ColumnData::Uint8(container) => from_uint8(container, lazy_fragment),
30 ColumnData::Uint16(container) => from_uint16(container, lazy_fragment),
31 ColumnData::Float4(container) => from_float4(container, lazy_fragment),
32 ColumnData::Float8(container) => from_float8(container, lazy_fragment),
33 ColumnData::Utf8 {
34 container,
35 ..
36 } => from_utf8(container, lazy_fragment),
37 _ => {
38 let source_type = data.get_type();
39 return_error!(cast::unsupported_cast(lazy_fragment.fragment(), source_type, Type::Boolean))
40 }
41 }
42}
43
44fn to_bool<T>(
45 container: &NumberContainer<T>,
46 lazy_fragment: impl LazyFragment,
47 validate: impl Fn(T) -> Option<bool>,
48) -> crate::Result<ColumnData>
49where
50 T: Copy + Display + IsNumber + Default,
51{
52 let mut out = ColumnData::with_capacity(Type::Boolean, container.len());
53 for idx in 0..container.len() {
54 if container.is_defined(idx) {
55 match validate(container[idx]) {
56 Some(b) => out.push::<bool>(b),
57 None => {
58 let base_fragment = lazy_fragment.fragment();
59 let error_fragment = Fragment::Statement {
60 text: Arc::from(container[idx].to_string()),
61 line: base_fragment.line(),
62 column: base_fragment.column(),
63 };
64 return_error!(invalid_number_boolean(error_fragment));
65 }
66 }
67 } else {
68 out.push_none();
69 }
70 }
71 Ok(out)
72}
73
74macro_rules! impl_integer_to_bool {
75 ($fn_name:ident, $type:ty) => {
76 #[inline]
77 fn $fn_name(
78 container: &NumberContainer<$type>,
79 lazy_fragment: impl LazyFragment,
80 ) -> crate::Result<ColumnData> {
81 to_bool(container, lazy_fragment, |val| match val {
82 0 => Some(false),
83 1 => Some(true),
84 _ => None,
85 })
86 }
87 };
88}
89
90macro_rules! impl_float_to_bool {
91 ($fn_name:ident, $type:ty) => {
92 #[inline]
93 fn $fn_name(
94 container: &NumberContainer<$type>,
95 lazy_fragment: impl LazyFragment,
96 ) -> crate::Result<ColumnData> {
97 to_bool(container, lazy_fragment, |val| {
98 if val == 0.0 {
99 Some(false)
100 } else if val == 1.0 {
101 Some(true)
102 } else {
103 None
104 }
105 })
106 }
107 };
108}
109
110impl_integer_to_bool!(from_int1, i8);
111impl_integer_to_bool!(from_int2, i16);
112impl_integer_to_bool!(from_int4, i32);
113impl_integer_to_bool!(from_int8, i64);
114impl_integer_to_bool!(from_int16, i128);
115impl_integer_to_bool!(from_uint1, u8);
116impl_integer_to_bool!(from_uint2, u16);
117impl_integer_to_bool!(from_uint4, u32);
118impl_integer_to_bool!(from_uint8, u64);
119impl_integer_to_bool!(from_uint16, u128);
120impl_float_to_bool!(from_float4, f32);
121impl_float_to_bool!(from_float8, f64);
122
123fn from_utf8(container: &Utf8Container, lazy_fragment: impl LazyFragment) -> crate::Result<ColumnData> {
124 use reifydb_type::fragment::Fragment;
125 let mut out = ColumnData::with_capacity(Type::Boolean, container.len());
126 for idx in 0..container.len() {
127 if container.is_defined(idx) {
128 let temp_fragment = Fragment::internal(&container[idx]);
131 match parse_bool(temp_fragment) {
132 Ok(b) => out.push(b),
133 Err(mut e) => {
134 e.0.with_fragment(lazy_fragment.fragment());
137 return Err(e);
138 }
139 }
140 } else {
141 out.push_none();
142 }
143 }
144 Ok(out)
145}