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]
57 pub(crate) fn as_raw_ffi_any(&self) -> &TVMFFIAny {
58 &self.data
59 }
60
61 #[inline]
74 pub(crate) unsafe fn from_raw_ffi_any(data: TVMFFIAny) -> Self {
75 Self {
76 data,
77 _phantom: std::marker::PhantomData,
78 }
79 }
80
81 #[inline]
90 pub fn try_as<T>(&self) -> Option<T>
91 where
92 T: AnyCompatible,
93 {
94 unsafe {
95 if T::check_any_strict(&self.data) {
96 Some(T::copy_from_any_view_after_check(&self.data))
97 } else {
98 None
99 }
100 }
101 }
102
103 pub fn debug_strong_count(&self) -> Option<usize> {
107 unsafe {
108 if self.data.type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32 {
109 Some(object::unsafe_::strong_count(self.data.data_union.v_obj))
110 } else {
111 None
112 }
113 }
114 }
115}
116
117impl<'a, T: AnyCompatible> From<&'a T> for AnyView<'a> {
118 #[inline]
119 fn from(value: &'a T) -> Self {
120 unsafe {
121 let mut data = TVMFFIAny::new();
122 T::copy_to_any_view(&value, &mut data);
123 Self {
124 data: data,
125 _phantom: std::marker::PhantomData,
126 }
127 }
128 }
129}
130
131impl<'a> From<&AnyView<'a>> for AnyView<'a> {
132 #[inline]
133 fn from(value: &AnyView<'a>) -> Self {
134 *value
135 }
136}
137
138impl Default for AnyView<'_> {
139 fn default() -> Self {
140 Self::new()
141 }
142}
143
144pub struct TryFromTemp<T> {
149 value: T,
150}
151
152impl<T> TryFromTemp<T> {
153 #[inline(always)]
155 pub fn new(value: T) -> Self {
156 Self { value }
157 }
158
159 #[inline(always)]
161 pub fn into_value(this: Self) -> T {
162 this.value
163 }
164}
165
166impl Any {
170 pub fn new() -> Self {
171 Self {
172 data: TVMFFIAny::new(),
173 }
174 }
175 #[inline]
176 pub fn type_index(&self) -> i32 {
177 self.data.type_index
178 }
179 #[inline]
180 pub(crate) fn as_raw_ffi_any(&self) -> &TVMFFIAny {
181 &self.data
182 }
183 #[inline]
196 pub fn try_as<T>(&self) -> Option<T>
197 where
198 T: AnyCompatible,
199 {
200 unsafe {
201 if T::check_any_strict(&self.data) {
202 Some(T::copy_from_any_view_after_check(&self.data))
203 } else {
204 None
205 }
206 }
207 }
208
209 #[inline]
210 pub unsafe fn as_data_ptr(&mut self) -> *mut TVMFFIAny {
211 &mut self.data
212 }
213
214 #[inline]
215 pub unsafe fn into_raw_ffi_any(this: Self) -> TVMFFIAny {
216 let this = std::mem::ManuallyDrop::new(this);
217 this.data
218 }
219
220 #[inline]
221 pub unsafe fn from_raw_ffi_any(data: TVMFFIAny) -> Self {
222 Self { data }
223 }
224
225 pub fn debug_strong_count(&self) -> Option<usize> {
229 unsafe {
230 if self.data.type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32 {
231 Some(object::unsafe_::strong_count(self.data.data_union.v_obj))
232 } else {
233 None
234 }
235 }
236 }
237}
238
239impl Default for Any {
240 fn default() -> Self {
241 Self::new()
242 }
243}
244
245impl Clone for Any {
246 #[inline]
247 fn clone(&self) -> Self {
248 if self.data.type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32 {
249 unsafe { object::unsafe_::inc_ref(self.data.data_union.v_obj) }
250 }
251 Self { data: self.data }
252 }
253}
254
255impl Drop for Any {
256 #[inline]
257 fn drop(&mut self) {
258 if self.data.type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32 {
259 unsafe { object::unsafe_::dec_ref(self.data.data_union.v_obj) }
260 }
261 }
262}
263
264#[inline]
266pub(crate) fn try_cast_from_any_view<T>(value: &AnyView<'_>) -> Result<T, ()>
267where
268 T: AnyCompatible,
269{
270 unsafe { T::try_cast_from_any_view(&value.data) }
271}
272
273#[inline(always)]
280pub(crate) unsafe fn copy_from_any_view_after_check<T>(value: &AnyView<'_>) -> T
281where
282 T: AnyCompatible,
283{
284 debug_assert!(T::MATCH_ANY_EXACT);
285 debug_assert!(T::check_any_strict(&value.data));
286 T::copy_from_any_view_after_check(&value.data)
287}
288
289impl<'a> From<&'a Any> for AnyView<'a> {
291 #[inline]
292 fn from(value: &'a Any) -> Self {
293 Self {
294 data: value.data,
295 _phantom: std::marker::PhantomData,
296 }
297 }
298}
299
300#[inline]
303pub(crate) fn is_plain_inline(type_index: i32) -> bool {
304 type_index < TypeIndex::kTVMFFIRawStr as i32
305 || type_index == TypeIndex::kTVMFFISmallStr as i32
306 || type_index == TypeIndex::kTVMFFISmallBytes as i32
307 || type_index == TypeIndex::kTVMFFIUnchanged as i32
308}
309
310impl From<AnyView<'_>> for Any {
312 #[inline]
313 fn from(value: AnyView<'_>) -> Self {
314 let data = value.data;
315 if data.type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32 {
317 unsafe { object::unsafe_::inc_ref(data.data_union.v_obj) };
318 return Self { data };
319 }
320 if is_plain_inline(data.type_index) {
321 return Self { data };
322 }
323 any_view_to_owned_via_runtime(data)
325 }
326}
327
328#[cold]
331#[inline(never)]
332fn any_view_to_owned_via_runtime(view: TVMFFIAny) -> Any {
333 unsafe {
334 let mut data = TVMFFIAny::new();
335 crate::check_safe_call!(TVMFFIAnyViewToOwnedAny(&view, &mut data)).unwrap();
336 Any { data }
337 }
338}
339
340impl<T: AnyCompatible> From<T> for Any {
341 #[inline]
342 fn from(value: T) -> Self {
343 unsafe {
344 let mut data = TVMFFIAny::new();
345 T::move_to_any(value, &mut data);
346 Self { data }
347 }
348 }
349}
350
351impl<'a, T: AnyCompatible> TryFrom<AnyView<'a>> for TryFromTemp<T> {
352 type Error = crate::error::Error;
353 #[inline]
354 fn try_from(value: AnyView<'a>) -> Result<Self, Self::Error> {
355 unsafe {
356 if T::check_any_strict(&value.data) {
357 Ok(TryFromTemp::new(T::copy_from_any_view_after_check(
358 &value.data,
359 )))
360 } else {
361 T::try_cast_from_any_view(&value.data)
362 .map_err(|_| {
363 let msg = format!(
364 "Cannot convert from type `{}` to `{}`",
365 T::get_mismatch_type_info(&value.data),
366 T::type_str()
367 );
368 crate::error::Error::new(crate::error::TYPE_ERROR, &msg, "")
369 })
370 .map(TryFromTemp::new)
371 }
372 }
373 }
374}
375
376impl<T: AnyCompatible> TryFrom<Any> for TryFromTemp<T> {
377 type Error = crate::error::Error;
378 #[inline]
379 fn try_from(value: Any) -> Result<Self, Self::Error> {
380 unsafe {
381 if T::check_any_strict(&value.data) {
382 let mut value = std::mem::ManuallyDrop::new(value);
383 Ok(TryFromTemp::new(T::move_from_any_after_check(
384 &mut value.data,
385 )))
386 } else {
387 T::try_cast_from_any_view(&value.data)
388 .map_err(|_| {
389 let msg = format!(
390 "Cannot convert from type `{}` to `{}`",
391 T::get_mismatch_type_info(&value.data),
392 T::type_str()
393 );
394 crate::error::Error::new(crate::error::TYPE_ERROR, &msg, "")
395 })
396 .map(TryFromTemp::new)
397 }
398 }
399 }
400}
401
402crate::impl_try_from_any!(
403 bool,
404 i8,
405 i16,
406 i32,
407 i64,
408 isize,
409 u8,
410 u16,
411 u32,
412 u64,
413 usize,
414 f32,
415 f64,
416 (),
417 *mut core::ffi::c_void,
418 crate::string::String,
419 crate::string::Bytes,
420 crate::object::ObjectRef,
421 tvm_ffi_sys::dlpack::DLDataType,
422 tvm_ffi_sys::dlpack::DLDevice,
423);
424
425crate::impl_try_from_any_for_parametric!(Option<T>);
426
427pub(crate) trait ArgTryFromAnyView: Sized {
431 fn try_from_any_view(value: &AnyView, arg_index: usize) -> Result<Self, Error>;
432}
433
434impl<T: AnyCompatible> ArgTryFromAnyView for T {
435 fn try_from_any_view(value: &AnyView, arg_index: usize) -> Result<Self, Error> {
436 unsafe {
437 if T::check_any_strict(&value.data) {
438 Ok(T::copy_from_any_view_after_check(&value.data))
439 } else {
440 T::try_cast_from_any_view(&value.data).map_err(|_| {
441 let msg = format!(
442 "Argument #{}: Cannot convert from type `{}` to `{}`",
443 arg_index,
444 T::get_mismatch_type_info(&value.data),
445 T::type_str()
446 );
447 crate::error::Error::new(crate::error::TYPE_ERROR, &msg, "")
448 })
449 }
450 }
451 }
452}