1use crate::atom::Atom;
2use crate::kapi;
3use crate::kbox::KBox;
4use crate::type_traits::*;
5use crate::{error::ConversionError, Dictionary};
6use crate::{k::K, Table};
7use crate::{k_type::KTypeCode, k_type::MIXED_LIST};
8use crate::{list::List, KError};
9use std::fmt;
10use std::mem;
11
12#[repr(transparent)]
17#[derive(PartialEq)]
18pub struct Any {
19 k: K,
20}
21
22impl fmt::Debug for Any {
23 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24 write!(f, "Any(Type={})", self.k.t)
25 }
26}
27
28impl<T: KValue> AsRef<Any> for Atom<T> {
29 fn as_ref(&self) -> &Any {
30 unsafe { &*(self as *const _ as *const _) }
31 }
32}
33
34impl<T: KListable> AsRef<Any> for List<T> {
35 fn as_ref(&self) -> &Any {
36 unsafe { &*(self as *const _ as *const _) }
37 }
38}
39
40impl AsRef<Any> for Dictionary {
41 fn as_ref(&self) -> &Any {
42 unsafe { &*(self as *const _ as *const _) }
43 }
44}
45
46impl AsRef<Any> for Table {
47 fn as_ref(&self) -> &Any {
48 unsafe { &*(self as *const _ as *const _) }
49 }
50}
51
52impl AsRef<Any> for KError {
53 fn as_ref(&self) -> &Any {
54 unsafe { &*(self as *const _ as *const _) }
55 }
56}
57
58impl From<KBox<Dictionary>> for KBox<Any> {
59 fn from(value: KBox<Dictionary>) -> Self {
60 unsafe { mem::transmute(value) }
61 }
62}
63
64impl From<KBox<Table>> for KBox<Any> {
65 fn from(value: KBox<Table>) -> Self {
66 unsafe { mem::transmute(value) }
67 }
68}
69
70impl From<KBox<KError>> for KBox<Any> {
71 fn from(value: KBox<KError>) -> Self {
72 unsafe { mem::transmute(value) }
73 }
74}
75
76impl<T: KListable> From<KBox<List<T>>> for KBox<Any> {
77 fn from(value: KBox<List<T>>) -> Self {
78 unsafe { mem::transmute(value) }
79 }
80}
81
82impl<T: KValue> From<KBox<Atom<T>>> for KBox<Any> {
83 fn from(value: KBox<Atom<T>>) -> Self {
84 unsafe { mem::transmute(value) }
85 }
86}
87
88impl<T: KValue> From<T> for KBox<Any> {
89 fn from(value: T) -> Self {
90 unsafe { mem::transmute(KBox::new_atom(value)) }
91 }
92}
93
94impl KObject for Any {
95 #[inline]
96 fn k_ptr(&self) -> *const K {
97 &self.k
98 }
99
100 #[inline]
101 fn k_ptr_mut(&mut self) -> *mut K {
102 &mut self.k
103 }
104}
105
106impl<T: KListable> AsRef<Any> for KBox<List<T>> {
107 fn as_ref(&self) -> &Any {
108 unsafe { &*(self as *const _ as *const _) }
109 }
110}
111
112impl<T: KValue> AsRef<Any> for KBox<Atom<T>> {
113 fn as_ref(&self) -> &Any {
114 unsafe { &*(self as *const _ as *const _) }
115 }
116}
117
118impl AsRef<Any> for KBox<Dictionary> {
119 fn as_ref(&self) -> &Any {
120 unsafe { &*(self as *const _ as *const _) }
121 }
122}
123
124impl AsRef<Any> for KBox<Table> {
125 fn as_ref(&self) -> &Any {
126 unsafe { &*(self as *const _ as *const _) }
127 }
128}
129
130impl KListable for Any {
131 const LIST_TYPE_CODE: KTypeCode = MIXED_LIST;
132 type ListItem = KBox<Any>;
133
134 unsafe fn join_to(item: Self::ListItem, mut k: *mut K) -> *mut K {
135 kapi::jk(&mut k, mem::ManuallyDrop::new(item).k_ptr())
137 }
138}
139
140#[doc(hidden)]
141pub trait KdbCast<T: Sized> {
142 type Output;
143 fn try_cast(self) -> Result<Self::Output, ConversionError>;
144}
145
146impl<T: KObject + KTyped> KdbCast<T> for KBox<Any> {
147 type Output = KBox<T>;
148 fn try_cast(self) -> Result<Self::Output, ConversionError> {
149 unsafe {
150 if (*self.k_ptr()).t != T::K_TYPE {
151 Err(ConversionError::InvalidKCast {
152 from: (*self.k_ptr()).t,
153 to: T::K_TYPE,
154 })
155 } else {
156 #[allow(clippy::clippy::transmute_ptr_to_ptr)]
157 Ok(mem::transmute(self))
158 }
159 }
160 }
161}
162
163impl<'a, T: 'a + KObject + KTyped> KdbCast<T> for &'a KBox<Any> {
164 type Output = &'a KBox<T>;
165 fn try_cast(self) -> Result<Self::Output, ConversionError> {
166 unsafe {
167 if (*self.k_ptr()).t != T::K_TYPE {
168 Err(ConversionError::InvalidKCast {
169 from: (*self.k_ptr()).t,
170 to: T::K_TYPE,
171 })
172 } else {
173 #[allow(clippy::clippy::transmute_ptr_to_ptr)]
174 Ok(mem::transmute(self))
175 }
176 }
177 }
178}
179
180impl<'a, T: 'a + KObject + KTyped> KdbCast<T> for &'a Any {
181 type Output = &'a T;
182 fn try_cast(self) -> Result<Self::Output, ConversionError> {
183 unsafe {
184 if (*self.k_ptr()).t != T::K_TYPE {
185 Err(ConversionError::InvalidKCast {
186 from: (*self.k_ptr()).t,
187 to: T::K_TYPE,
188 })
189 } else {
190 #[allow(clippy::clippy::transmute_ptr_to_ptr)]
191 Ok(mem::transmute(self))
192 }
193 }
194 }
195}
196
197#[macro_export]
209macro_rules! try_cast {
210 ($ex:expr; $t:ty) => {
211 $crate::KdbCast::<$t>::try_cast($ex)
212 };
213}
214
215#[macro_export]
227macro_rules! cast {
228 ($ex:expr; $t:ty) => {
229 $crate::KdbCast::<$t>::try_cast($ex).unwrap()
230 };
231}