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