1use crate::error::Error;
20use crate::object;
21use crate::type_traits::AnyCompatible;
22use tvm_ffi_sys::TVMFFITypeIndex as TypeIndex;
23use tvm_ffi_sys::{TVMFFIAny, TVMFFIAnyViewToOwnedAny};
24
25#[derive(Copy, Clone)]
27#[repr(C)]
28pub struct AnyView<'a> {
29 data: TVMFFIAny,
30 _phantom: std::marker::PhantomData<&'a ()>,
32}
33
34#[repr(C)]
36pub struct Any {
37 data: TVMFFIAny,
38}
39
40impl<'a> AnyView<'a> {
44 pub fn new() -> Self {
45 Self {
46 data: TVMFFIAny::new(),
47 _phantom: std::marker::PhantomData,
48 }
49 }
50
51 #[inline]
52 pub fn type_index(&self) -> i32 {
53 self.data.type_index
54 }
55
56 #[inline]
65 pub fn try_as<T>(&self) -> Option<T>
66 where
67 T: AnyCompatible,
68 {
69 unsafe {
70 if T::check_any_strict(&self.data) {
71 Some(T::copy_from_any_view_after_check(&self.data))
72 } else {
73 None
74 }
75 }
76 }
77
78 pub fn debug_strong_count(&self) -> Option<usize> {
82 unsafe {
83 if self.data.type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32 {
84 Some(object::unsafe_::strong_count(self.data.data_union.v_obj))
85 } else {
86 None
87 }
88 }
89 }
90}
91
92impl<'a, T: AnyCompatible> From<&'a T> for AnyView<'a> {
93 #[inline]
94 fn from(value: &'a T) -> Self {
95 unsafe {
96 let mut data = TVMFFIAny::new();
97 T::copy_to_any_view(&value, &mut data);
98 Self {
99 data: data,
100 _phantom: std::marker::PhantomData,
101 }
102 }
103 }
104}
105
106impl Default for AnyView<'_> {
107 fn default() -> Self {
108 Self::new()
109 }
110}
111
112pub struct TryFromTemp<T> {
117 value: T,
118}
119
120impl<T> TryFromTemp<T> {
121 #[inline(always)]
123 pub fn new(value: T) -> Self {
124 Self { value }
125 }
126
127 #[inline(always)]
129 pub fn into_value(this: Self) -> T {
130 this.value
131 }
132}
133
134impl Any {
138 pub fn new() -> Self {
139 Self {
140 data: TVMFFIAny::new(),
141 }
142 }
143 #[inline]
144 pub fn type_index(&self) -> i32 {
145 self.data.type_index
146 }
147 #[inline]
160 pub fn try_as<T>(&self) -> Option<T>
161 where
162 T: AnyCompatible,
163 {
164 unsafe {
165 if T::check_any_strict(&self.data) {
166 Some(T::copy_from_any_view_after_check(&self.data))
167 } else {
168 None
169 }
170 }
171 }
172
173 #[inline]
174 pub unsafe fn as_data_ptr(&mut self) -> *mut TVMFFIAny {
175 &mut self.data
176 }
177
178 #[inline]
179 pub unsafe fn into_raw_ffi_any(this: Self) -> TVMFFIAny {
180 let this = std::mem::ManuallyDrop::new(this);
181 this.data
182 }
183
184 #[inline]
185 pub unsafe fn from_raw_ffi_any(data: TVMFFIAny) -> Self {
186 Self { data }
187 }
188
189 pub fn debug_strong_count(&self) -> Option<usize> {
193 unsafe {
194 if self.data.type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32 {
195 Some(object::unsafe_::strong_count(self.data.data_union.v_obj))
196 } else {
197 None
198 }
199 }
200 }
201}
202
203impl Default for Any {
204 fn default() -> Self {
205 Self::new()
206 }
207}
208
209impl Clone for Any {
210 #[inline]
211 fn clone(&self) -> Self {
212 if self.data.type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32 {
213 unsafe { object::unsafe_::inc_ref(self.data.data_union.v_obj) }
214 }
215 Self { data: self.data }
216 }
217}
218
219impl Drop for Any {
220 #[inline]
221 fn drop(&mut self) {
222 if self.data.type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32 {
223 unsafe { object::unsafe_::dec_ref(self.data.data_union.v_obj) }
224 }
225 }
226}
227
228impl<'a> From<&'a Any> for AnyView<'a> {
230 #[inline]
231 fn from(value: &'a Any) -> Self {
232 Self {
233 data: value.data,
234 _phantom: std::marker::PhantomData,
235 }
236 }
237}
238
239impl From<AnyView<'_>> for Any {
241 #[inline]
242 fn from(value: AnyView<'_>) -> Self {
243 unsafe {
244 let mut data = TVMFFIAny::new();
245 crate::check_safe_call!(TVMFFIAnyViewToOwnedAny(&value.data, &mut data)).unwrap();
246 Self { data }
247 }
248 }
249}
250
251impl<T: AnyCompatible> From<T> for Any {
252 #[inline]
253 fn from(value: T) -> Self {
254 unsafe {
255 let mut data = TVMFFIAny::new();
256 T::move_to_any(value, &mut data);
257 Self { data }
258 }
259 }
260}
261
262impl<'a, T: AnyCompatible> TryFrom<AnyView<'a>> for TryFromTemp<T> {
263 type Error = crate::error::Error;
264 #[inline]
265 fn try_from(value: AnyView<'a>) -> Result<Self, Self::Error> {
266 unsafe {
267 if T::check_any_strict(&value.data) {
268 Ok(TryFromTemp::new(T::copy_from_any_view_after_check(
269 &value.data,
270 )))
271 } else {
272 T::try_cast_from_any_view(&value.data)
273 .map_err(|_| {
274 let msg = format!(
275 "Cannot convert from type `{}` to `{}`",
276 T::get_mismatch_type_info(&value.data),
277 T::type_str()
278 );
279 crate::error::Error::new(crate::error::TYPE_ERROR, &msg, "")
280 })
281 .map(TryFromTemp::new)
282 }
283 }
284 }
285}
286
287impl<T: AnyCompatible> TryFrom<Any> for TryFromTemp<T> {
288 type Error = crate::error::Error;
289 #[inline]
290 fn try_from(value: Any) -> Result<Self, Self::Error> {
291 unsafe {
292 if T::check_any_strict(&value.data) {
293 let mut value = std::mem::ManuallyDrop::new(value);
294 Ok(TryFromTemp::new(T::move_from_any_after_check(
295 &mut value.data,
296 )))
297 } else {
298 T::try_cast_from_any_view(&value.data)
299 .map_err(|_| {
300 let msg = format!(
301 "Cannot convert from type `{}` to `{}`",
302 T::get_mismatch_type_info(&value.data),
303 T::type_str()
304 );
305 crate::error::Error::new(crate::error::TYPE_ERROR, &msg, "")
306 })
307 .map(TryFromTemp::new)
308 }
309 }
310 }
311}
312
313crate::impl_try_from_any!(
314 bool,
315 i8,
316 i16,
317 i32,
318 i64,
319 isize,
320 u8,
321 u16,
322 u32,
323 u64,
324 usize,
325 f32,
326 f64,
327 (),
328 *mut core::ffi::c_void,
329 crate::string::String,
330 crate::string::Bytes,
331 crate::object::ObjectRef,
332 tvm_ffi_sys::dlpack::DLDataType,
333 tvm_ffi_sys::dlpack::DLDevice,
334);
335
336crate::impl_try_from_any_for_parametric!(Option<T>);
337
338pub(crate) trait ArgTryFromAnyView: Sized {
342 fn try_from_any_view(value: &AnyView, arg_index: usize) -> Result<Self, Error>;
343}
344
345impl<T: AnyCompatible> ArgTryFromAnyView for T {
346 fn try_from_any_view(value: &AnyView, arg_index: usize) -> Result<Self, Error> {
347 unsafe {
348 if T::check_any_strict(&value.data) {
349 Ok(T::copy_from_any_view_after_check(&value.data))
350 } else {
351 T::try_cast_from_any_view(&value.data).map_err(|_| {
352 let msg = format!(
353 "Argument #{}: Cannot convert from type `{}` to `{}`",
354 arg_index,
355 T::get_mismatch_type_info(&value.data),
356 T::type_str()
357 );
358 crate::error::Error::new(crate::error::TYPE_ERROR, &msg, "")
359 })
360 }
361 }
362 }
363}