tvm_ffi/extra/
structural_common.rs1use crate::any::{Any, AnyView};
21use crate::error::Error;
22use crate::object::{self, ObjectCore};
23use crate::tvm_ffi_sys::{TVMFFIAny, TVMFFIGetTypeInfo, TVMFFITypeIndex};
24
25pub(crate) fn with_structural_error_context(error: Error, operation: &str, frame: &str) -> Error {
27 Error::with_appended_backtrace(error, &format!("[native structural {operation}] {frame}\n"))
28}
29
30macro_rules! impl_callback_chain_tuple_arities {
32 ($impl_chain:ident) => {
33 impl_callback_chain_tuple_arities!(
34 @prefixes $impl_chain;
35 [];
36 (F0, M0, 0),
37 (F1, M1, 1),
38 (F2, M2, 2),
39 (F3, M3, 3),
40 (F4, M4, 4),
41 (F5, M5, 5),
42 (F6, M6, 6),
43 (F7, M7, 7),
44 (F8, M8, 8),
45 (F9, M9, 9),
46 (F10, M10, 10),
47 (F11, M11, 11)
48 );
49 };
50 (@prefixes $impl_chain:ident; [$($prefix:tt)*];) => {};
51 (
52 @prefixes $impl_chain:ident;
53 [$($prefix:tt)*];
54 $next:tt $(, $rest:tt)*
55 ) => {
56 $impl_chain!($($prefix)* $next);
57 impl_callback_chain_tuple_arities!(
58 @prefixes $impl_chain;
59 [$($prefix)* $next,];
60 $($rest),*
61 );
62 };
63}
64
65pub(crate) use impl_callback_chain_tuple_arities;
66
67#[repr(transparent)]
73pub struct StructuralValue(TVMFFIAny);
74
75impl StructuralValue {
76 #[inline]
77 pub(crate) fn from_raw(raw: TVMFFIAny) -> Self {
78 Self(raw)
79 }
80
81 #[inline]
82 pub(crate) fn raw(&self) -> TVMFFIAny {
83 self.0
84 }
85
86 #[inline]
88 pub fn to_owned(&self) -> Any {
89 if let Some(owned) = try_to_owned_without_normalization(self.0) {
90 return owned;
91 }
92 Any::from(unsafe { AnyView::from_raw_ffi_any(self.0) })
93 }
94
95 #[inline]
97 pub fn cast<R: crate::type_traits::AnyCompatible>(&self) -> Option<R> {
98 unsafe {
99 if R::check_any_strict(&self.0) {
100 Some(R::copy_from_any_view_after_check(&self.0))
101 } else {
102 None
103 }
104 }
105 }
106
107 #[inline]
109 pub fn type_index(&self) -> i32 {
110 self.0.type_index
111 }
112
113 #[inline]
115 pub fn as_node<N: ObjectCore>(&self) -> Option<&N> {
116 if self.0.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
117 return None;
118 }
119 let base_type_index = N::type_index();
120 if self.0.type_index != base_type_index {
121 if N::TYPE_FINAL {
125 return None;
126 }
127 if !is_instance_at_depth(self.0.type_index, base_type_index, N::TYPE_DEPTH) {
128 return None;
129 }
130 }
131 Some(unsafe { &*(self.0.data_union.v_obj as *const N) })
132 }
133}
134
135#[inline]
141pub(crate) fn try_to_owned_without_normalization(raw: TVMFFIAny) -> Option<Any> {
142 if is_plain_inline(raw.type_index) {
143 return Some(unsafe { Any::from_raw_ffi_any(raw) });
144 }
145 if raw.type_index >= TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
146 let object = unsafe { raw.data_union.v_obj };
147 if object.is_null() {
148 return None;
149 }
150 unsafe { object::unsafe_::inc_ref(object) };
151 return Some(unsafe { Any::from_raw_ffi_any(raw) });
152 }
153 None
154}
155
156pub(crate) use crate::any::is_plain_inline;
157
158#[inline]
159pub(crate) fn same_shallow(lhs: TVMFFIAny, rhs: TVMFFIAny) -> bool {
160 lhs.type_index == rhs.type_index
161 && lhs.small_str_len == rhs.small_str_len
162 && unsafe { lhs.data_union.v_uint64 == rhs.data_union.v_uint64 }
163}
164
165#[inline]
168fn is_instance_at_depth(object_type_index: i32, base_type_index: i32, base_depth: i32) -> bool {
169 if object_type_index == base_type_index {
170 return true;
171 }
172 if object_type_index < base_type_index {
175 return false;
176 }
177 unsafe {
178 let info = TVMFFIGetTypeInfo(object_type_index);
179 if info.is_null() {
180 return false;
181 }
182 if (*info).type_depth <= base_depth {
183 return false;
184 }
185 let ancestors = (*info).type_acenstors;
186 if ancestors.is_null() {
187 return false;
188 }
189 let ancestor = *ancestors.offset(base_depth as isize);
190 !ancestor.is_null() && (*ancestor).type_index == base_type_index
191 }
192}