pub mod behavior;
pub mod builtin;
pub mod format;
pub mod parse;
use std::any::Any;
use std::fmt::Debug;
use std::hash::Hash;
use std::sync::Arc;
use behavior::{CastErrorState, CastFailBehavior};
use glaredb_error::Result;
use crate::arrays::array::Array;
use crate::arrays::array::selection::Selection;
use crate::arrays::datatype::{DataType, DataTypeId};
use crate::util::iter::IntoExactSizeIterator;
#[derive(Debug)]
pub struct ImplicitCastScores {
pub i8: u32,
pub i16: u32,
pub i32: u32,
pub i64: u32,
pub u8: u32,
pub u16: u32,
pub u32: u32,
pub u64: u32,
pub f16: u32,
pub f32: u32,
pub f64: u32,
pub utf8: u32,
pub bool: u32,
pub interval: u32,
pub date32: u32,
pub decimal64: u32,
pub decimal128: u32,
}
pub const DEFAULT_IMPLICIT_CAST_SCORES: ImplicitCastScores = ImplicitCastScores {
i32: 191,
i64: 190,
f64: 181,
f32: 180,
f16: 179,
bool: 162,
i16: 161,
i8: 160,
u32: 154,
u64: 153,
u16: 152,
u8: 151,
decimal64: 141,
decimal128: 140,
interval: 132,
date32: 131,
utf8: 80,
};
pub const TO_INT32_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.i32);
pub const TO_UINT32_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.u32);
pub const TO_INT64_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.i64);
pub const TO_UINT64_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.u64);
pub const TO_F64_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.f64);
pub const TO_F32_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.f32);
pub const TO_F16_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.f16);
pub const TO_DECIMAL64_CAST_RULE: CastRule =
CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.decimal64);
pub const TO_DECIMAL128_CAST_RULE: CastRule =
CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.decimal128);
pub const TO_BOOL_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.bool);
pub const TO_DATE32_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.date32);
pub const TO_INTERVAL_CAST_RULE: CastRule =
CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.interval);
pub const TO_INT16_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.i16);
pub const TO_UINT16_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.u16);
pub const TO_INT8_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.i8);
pub const TO_UINT8_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.u8);
pub const TO_STRING_CAST_RULE: CastRule = CastRule::Implicit(DEFAULT_IMPLICIT_CAST_SCORES.utf8);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CastRule {
Explicit,
Implicit(u32),
}
impl CastRule {
pub const fn is_implicit(&self) -> bool {
matches!(self, Self::Implicit(_))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CastFlatten {
Safe,
Unsafe,
}
#[derive(Debug)]
pub struct CastFunctionSet {
pub name: &'static str,
pub target: DataTypeId,
pub functions: &'static [RawCastFunction],
}
#[derive(Debug, Clone)]
pub struct PlannedCastFunction {
pub(crate) name: &'static str,
pub(crate) raw: &'static RawCastFunction,
pub(crate) state: RawCastBindState,
}
impl PlannedCastFunction {
pub fn call_cast(&self, src: &Array, sel: Selection, target: &mut Array) -> Result<()> {
let error_state = CastFailBehavior::Error.new_state();
unsafe {
(self.raw.vtable.cast_fn)(self.state.state.as_ref(), error_state, src, sel, target)
}
}
pub fn call_try_cast(&self, src: &Array, sel: Selection, target: &mut Array) -> Result<()> {
let error_state = CastFailBehavior::Null.new_state();
unsafe {
(self.raw.vtable.cast_fn)(self.state.state.as_ref(), error_state, src, sel, target)
}
}
}
impl PartialEq for PlannedCastFunction {
fn eq(&self, other: &Self) -> bool {
self.name == other.name && self.raw.src == other.raw.src
}
}
impl Eq for PlannedCastFunction {}
impl Hash for PlannedCastFunction {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.raw.src.hash(state);
}
}
#[derive(Debug, Clone)]
pub struct RawCastBindState {
state: Arc<dyn Any + Sync + Send>,
}
#[derive(Debug, Clone, Copy)]
pub struct RawCastFunctionVTable {
bind_fn: unsafe fn(
function: *const (),
src: &DataType,
target: &DataType,
) -> Result<RawCastBindState>,
cast_fn: unsafe fn(
state: &dyn Any,
error_state: CastErrorState,
src: &Array,
sel: Selection,
out: &mut Array,
) -> Result<()>,
}
#[derive(Debug, Clone, Copy)]
pub struct RawCastFunction {
pub(crate) src: DataTypeId,
pub(crate) rule: CastRule,
pub(crate) flatten: CastFlatten,
function: *const (),
vtable: &'static RawCastFunctionVTable,
}
unsafe impl Send for RawCastFunction {}
unsafe impl Sync for RawCastFunction {}
impl RawCastFunction {
pub const fn new<F>(
src: DataTypeId,
function: &'static F,
rule: CastRule,
flatten: CastFlatten,
) -> Self
where
F: CastFunction,
{
let function = (function as *const F).cast();
RawCastFunction {
function,
src,
rule,
flatten,
vtable: F::VTABLE,
}
}
pub fn call_bind(&self, src: &DataType, target: &DataType) -> Result<RawCastBindState> {
unsafe { (self.vtable.bind_fn)(self.function, src, target) }
}
}
pub trait CastFunction: Copy + Debug + Sync + Send + Sized + 'static {
type State: Sync + Send;
fn bind(&self, src: &DataType, target: &DataType) -> Result<Self::State>;
fn cast(
state: &Self::State,
error_state: CastErrorState,
src: &Array,
sel: impl IntoExactSizeIterator<Item = usize>,
out: &mut Array,
) -> Result<()>;
}
trait CastFunctionVTable: CastFunction {
const VTABLE: &'static RawCastFunctionVTable = &RawCastFunctionVTable {
bind_fn: |function, src, target| -> Result<RawCastBindState> {
let function = unsafe { function.cast::<Self>().as_ref().unwrap() };
let state = function.bind(src, target)?;
Ok(RawCastBindState {
state: Arc::new(state),
})
},
cast_fn: |state, error_state, src, sel, out| -> Result<()> {
let state = state.downcast_ref::<Self::State>().unwrap();
Self::cast(state, error_state, src, sel, out)
},
};
}
impl<F> CastFunctionVTable for F where F: CastFunction {}