use crate::atom::Atom;
use crate::kapi;
use crate::kbox::KBox;
use crate::type_traits::*;
use crate::{error::ConversionError, Dictionary};
use crate::{k::K, Table};
use crate::{k_type::KTypeCode, k_type::MIXED_LIST};
use crate::{list::List, KError};
use std::fmt;
use std::mem;
#[repr(transparent)]
#[derive(PartialEq)]
pub struct Any {
k: K,
}
impl fmt::Debug for Any {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Any(Type={})", self.k.t)
}
}
impl<T: KValue> AsRef<Any> for Atom<T> {
fn as_ref(&self) -> &Any {
unsafe { &*(self as *const _ as *const _) }
}
}
impl<T: KListable> AsRef<Any> for List<T> {
fn as_ref(&self) -> &Any {
unsafe { &*(self as *const _ as *const _) }
}
}
impl AsRef<Any> for Dictionary {
fn as_ref(&self) -> &Any {
unsafe { &*(self as *const _ as *const _) }
}
}
impl AsRef<Any> for Table {
fn as_ref(&self) -> &Any {
unsafe { &*(self as *const _ as *const _) }
}
}
impl AsRef<Any> for KError {
fn as_ref(&self) -> &Any {
unsafe { &*(self as *const _ as *const _) }
}
}
impl From<KBox<Dictionary>> for KBox<Any> {
fn from(value: KBox<Dictionary>) -> Self {
unsafe { mem::transmute(value) }
}
}
impl From<KBox<Table>> for KBox<Any> {
fn from(value: KBox<Table>) -> Self {
unsafe { mem::transmute(value) }
}
}
impl From<KBox<KError>> for KBox<Any> {
fn from(value: KBox<KError>) -> Self {
unsafe { mem::transmute(value) }
}
}
impl<T: KListable> From<KBox<List<T>>> for KBox<Any> {
fn from(value: KBox<List<T>>) -> Self {
unsafe { mem::transmute(value) }
}
}
impl<T: KValue> From<KBox<Atom<T>>> for KBox<Any> {
fn from(value: KBox<Atom<T>>) -> Self {
unsafe { mem::transmute(value) }
}
}
impl<T: KValue> From<T> for KBox<Any> {
fn from(value: T) -> Self {
unsafe { mem::transmute(KBox::new_atom(value)) }
}
}
impl KObject for Any {
#[inline]
fn k_ptr(&self) -> *const K {
&self.k
}
#[inline]
fn k_ptr_mut(&mut self) -> *mut K {
&mut self.k
}
}
impl<T: KListable> AsRef<Any> for KBox<List<T>> {
fn as_ref(&self) -> &Any {
unsafe { &*(self as *const _ as *const _) }
}
}
impl<T: KValue> AsRef<Any> for KBox<Atom<T>> {
fn as_ref(&self) -> &Any {
unsafe { &*(self as *const _ as *const _) }
}
}
impl AsRef<Any> for KBox<Dictionary> {
fn as_ref(&self) -> &Any {
unsafe { &*(self as *const _ as *const _) }
}
}
impl AsRef<Any> for KBox<Table> {
fn as_ref(&self) -> &Any {
unsafe { &*(self as *const _ as *const _) }
}
}
impl KListable for Any {
const LIST_TYPE_CODE: KTypeCode = MIXED_LIST;
type ListItem = KBox<Any>;
unsafe fn join_to(item: Self::ListItem, mut k: *mut K) -> *mut K {
kapi::jk(&mut k, mem::ManuallyDrop::new(item).k_ptr())
}
}
#[doc(hidden)]
pub trait KdbCast<T: Sized> {
type Output;
fn try_cast(self) -> Result<Self::Output, ConversionError>;
}
impl<T: KObject + KTyped> KdbCast<T> for KBox<Any> {
type Output = KBox<T>;
fn try_cast(self) -> Result<Self::Output, ConversionError> {
unsafe {
if (*self.k_ptr()).t != T::K_TYPE {
Err(ConversionError::InvalidKCast {
from: (*self.k_ptr()).t,
to: T::K_TYPE,
})
} else {
#[allow(clippy::clippy::transmute_ptr_to_ptr)]
Ok(mem::transmute(self))
}
}
}
}
impl<'a, T: 'a + KObject + KTyped> KdbCast<T> for &'a KBox<Any> {
type Output = &'a KBox<T>;
fn try_cast(self) -> Result<Self::Output, ConversionError> {
unsafe {
if (*self.k_ptr()).t != T::K_TYPE {
Err(ConversionError::InvalidKCast {
from: (*self.k_ptr()).t,
to: T::K_TYPE,
})
} else {
#[allow(clippy::clippy::transmute_ptr_to_ptr)]
Ok(mem::transmute(self))
}
}
}
}
impl<'a, T: 'a + KObject + KTyped> KdbCast<T> for &'a Any {
type Output = &'a T;
fn try_cast(self) -> Result<Self::Output, ConversionError> {
unsafe {
if (*self.k_ptr()).t != T::K_TYPE {
Err(ConversionError::InvalidKCast {
from: (*self.k_ptr()).t,
to: T::K_TYPE,
})
} else {
#[allow(clippy::clippy::transmute_ptr_to_ptr)]
Ok(mem::transmute(self))
}
}
}
}
#[macro_export]
macro_rules! try_cast {
($ex:expr; $t:ty) => {
$crate::KdbCast::<$t>::try_cast($ex)
};
}
#[macro_export]
macro_rules! cast {
($ex:expr; $t:ty) => {
$crate::KdbCast::<$t>::try_cast($ex).unwrap()
};
}