use reifydb_core::value::column::data::ColumnData;
use reifydb_type::{
error::{Error, TypeError},
fragment::{Fragment, LazyFragment},
value::{
container::{identity_id::IdentityIdContainer, utf8::Utf8Container, uuid::UuidContainer},
identity::IdentityId,
r#type::Type,
uuid::{
Uuid4, Uuid7,
parse::{parse_identity_id, parse_uuid4, parse_uuid7},
},
},
};
use crate::{Result, error::CastError};
pub fn to_uuid(data: &ColumnData, target: Type, lazy_fragment: impl LazyFragment) -> Result<ColumnData> {
match data {
ColumnData::Utf8 {
container,
..
} => from_text(container, target, lazy_fragment),
ColumnData::Uuid4(container) => from_uuid4(container, target, lazy_fragment),
ColumnData::Uuid7(container) => from_uuid7(container, target, lazy_fragment),
ColumnData::IdentityId(container) => from_identity_id(container, target, lazy_fragment),
_ => {
let shape_type = data.get_type();
Err(TypeError::UnsupportedCast {
from: shape_type,
to: target,
fragment: lazy_fragment.fragment(),
}
.into())
}
}
}
#[inline]
fn from_text(container: &Utf8Container, target: Type, lazy_fragment: impl LazyFragment) -> Result<ColumnData> {
match target {
Type::Uuid4 => to_uuid4(container, lazy_fragment),
Type::Uuid7 => to_uuid7(container, lazy_fragment),
Type::IdentityId => to_identity_id(container, lazy_fragment),
_ => {
let shape_type = Type::Utf8;
Err(TypeError::UnsupportedCast {
from: shape_type,
to: target,
fragment: lazy_fragment.fragment(),
}
.into())
}
}
}
macro_rules! impl_to_uuid {
($fn_name:ident, $type:ty, $target_type:expr, $parse_fn:expr) => {
#[inline]
fn $fn_name(container: &Utf8Container, lazy_fragment: impl LazyFragment) -> Result<ColumnData> {
let mut out = ColumnData::with_capacity($target_type, container.len());
for idx in 0..container.len() {
if container.is_defined(idx) {
let val = &container[idx];
let temp_fragment = Fragment::internal(val.as_str());
let parsed = $parse_fn(temp_fragment).map_err(|mut e| {
let proper_fragment = lazy_fragment.fragment();
e.0.with_fragment(proper_fragment.clone());
Error::from(CastError::InvalidUuid {
fragment: proper_fragment,
target: $target_type,
cause: *e.0,
})
})?;
out.push::<$type>(parsed);
} else {
out.push_none();
}
}
Ok(out)
}
};
}
impl_to_uuid!(to_uuid4, Uuid4, Type::Uuid4, parse_uuid4);
impl_to_uuid!(to_uuid7, Uuid7, Type::Uuid7, parse_uuid7);
impl_to_uuid!(to_identity_id, IdentityId, Type::IdentityId, parse_identity_id);
#[inline]
fn from_uuid4(container: &UuidContainer<Uuid4>, target: Type, lazy_fragment: impl LazyFragment) -> Result<ColumnData> {
match target {
Type::Uuid4 => Ok(ColumnData::Uuid4(UuidContainer::new(container.data().to_vec()))),
_ => {
let shape_type = Type::Uuid4;
Err(TypeError::UnsupportedCast {
from: shape_type,
to: target,
fragment: lazy_fragment.fragment(),
}
.into())
}
}
}
#[inline]
fn from_uuid7(container: &UuidContainer<Uuid7>, target: Type, lazy_fragment: impl LazyFragment) -> Result<ColumnData> {
match target {
Type::Uuid7 => Ok(ColumnData::Uuid7(UuidContainer::new(container.data().to_vec()))),
_ => {
let shape_type = Type::Uuid7;
Err(TypeError::UnsupportedCast {
from: shape_type,
to: target,
fragment: lazy_fragment.fragment(),
}
.into())
}
}
}
#[inline]
fn from_identity_id(
container: &IdentityIdContainer,
target: Type,
lazy_fragment: impl LazyFragment,
) -> Result<ColumnData> {
match target {
Type::IdentityId => {
Ok(ColumnData::IdentityId(IdentityIdContainer::from_vec(container.data().to_vec())))
}
_ => Err(TypeError::UnsupportedCast {
from: Type::IdentityId,
to: target,
fragment: lazy_fragment.fragment(),
}
.into()),
}
}