1use std::ops::{Deref, DerefMut};
20use std::sync::atomic::AtomicU64;
21
22use crate::derive::ObjectRef;
23use crate::type_traits::AnyCompatible;
24pub use tvm_ffi_sys::TVMFFITypeIndex as TypeIndex;
25use tvm_ffi_sys::{TVMFFIAny, TVMFFIGetTypeInfo, TVMFFIObject, COMBINED_REF_COUNT_BOTH_ONE};
27
28#[repr(C)]
30pub struct Object {
31 header: TVMFFIObject,
33}
34
35#[repr(C)]
39pub struct ObjectArc<T: ObjectCore> {
40 ptr: std::ptr::NonNull<T>,
41 _phantom: std::marker::PhantomData<T>,
42}
43
44unsafe impl<T: Send + Sync + ObjectCore> Send for ObjectArc<T> {}
45unsafe impl<T: Send + Sync + ObjectCore> Sync for ObjectArc<T> {}
46
47pub unsafe trait ObjectCore: Sized + 'static {
52 const TYPE_KEY: &'static str;
54 const TYPE_DEPTH: i32;
60 #[doc(hidden)]
64 const TYPE_FINAL: bool = false;
65 fn type_index() -> i32;
67 unsafe fn object_header_mut(this: &mut Self) -> &mut TVMFFIObject;
77}
78
79pub unsafe trait ObjectCoreWithExtraItems: ObjectCore {
83 type ExtraItem;
85 fn extra_items_count(this: &Self) -> usize;
87 unsafe fn extra_items(this: &Self) -> &[Self::ExtraItem] {
89 let extra_items_ptr = (this as *const Self as *const u8).add(std::mem::size_of::<Self>());
90 std::slice::from_raw_parts(
91 extra_items_ptr as *const Self::ExtraItem,
92 Self::extra_items_count(this),
93 )
94 }
95 unsafe fn extra_items_mut(this: &mut Self) -> &mut [Self::ExtraItem] {
97 let extra_items_ptr = (this as *mut Self as *mut u8).add(std::mem::size_of::<Self>());
98 std::slice::from_raw_parts_mut(
99 extra_items_ptr as *mut Self::ExtraItem,
100 Self::extra_items_count(this),
101 )
102 }
103}
104
105pub unsafe trait ObjectRefCore: Sized + Clone {
125 type ContainerType: ObjectCore;
126 fn data(this: &Self) -> &ObjectArc<Self::ContainerType>;
127 fn into_data(this: Self) -> ObjectArc<Self::ContainerType>;
128
129 unsafe fn from_data(data: ObjectArc<Self::ContainerType>) -> Self;
138
139 #[inline]
141 fn same_as<Other: ObjectRefCore>(&self, other: &Other) -> bool {
142 unsafe {
143 ObjectArc::as_raw(Self::data(self)).cast::<()>()
144 == ObjectArc::as_raw(Other::data(other)).cast::<()>()
145 }
146 }
147
148 #[inline(always)]
154 fn as_node<N: ObjectCore>(&self) -> Option<&N> {
155 let object = unsafe { ObjectArc::as_raw(Self::data(self)) };
156 let type_index = unsafe { (*object.cast::<TVMFFIObject>()).type_index };
157 if !is_instance_of::<N>(type_index) {
158 return None;
159 }
160 Some(unsafe { &*object.cast::<N>() })
161 }
162}
163
164#[derive(Clone)]
170pub struct ObjectIdentity {
171 data: ObjectArc<Object>,
172}
173
174impl ObjectIdentity {
175 pub fn of<T: ObjectRefCore>(value: &T) -> Self {
177 unsafe {
178 let ptr = ObjectArc::as_raw(T::data(value)) as *mut TVMFFIObject;
179 unsafe_::inc_ref(ptr);
180 Self {
181 data: ObjectArc::from_raw(ptr.cast::<Object>()),
182 }
183 }
184 }
185
186 #[inline]
187 fn as_ptr(&self) -> *const TVMFFIObject {
188 unsafe { ObjectArc::as_raw(&self.data).cast::<TVMFFIObject>() }
189 }
190}
191
192impl PartialEq for ObjectIdentity {
193 #[inline]
194 fn eq(&self, other: &Self) -> bool {
195 self.as_ptr() == other.as_ptr()
196 }
197}
198
199impl Eq for ObjectIdentity {}
200
201impl std::hash::Hash for ObjectIdentity {
202 #[inline]
203 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
204 self.as_ptr().hash(state);
205 }
206}
207
208impl std::fmt::Debug for ObjectIdentity {
209 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
210 f.debug_tuple("ObjectIdentity")
211 .field(&self.as_ptr())
212 .finish()
213 }
214}
215
216#[doc(hidden)]
229#[inline(always)]
230pub fn is_instance_of<Target: ObjectCore>(object_type_index: i32) -> bool {
231 let target_type_index = Target::type_index();
232 if object_type_index == target_type_index {
233 return true;
234 }
235 if Target::TYPE_FINAL {
238 return false;
239 }
240 let object_begin = TypeIndex::kTVMFFIStaticObjectBegin as i32;
241 if object_type_index < object_begin || target_type_index < object_begin {
243 return false;
244 }
245 if object_type_index < target_type_index {
247 return false;
248 }
249 unsafe {
250 let object_info = TVMFFIGetTypeInfo(object_type_index);
251 if object_info.is_null() {
252 return false;
253 }
254 let target_depth = Target::TYPE_DEPTH;
255 if (*object_info).type_depth <= target_depth {
256 return false;
257 }
258 let ancestor = *(*object_info).type_acenstors.add(target_depth as usize);
259 !ancestor.is_null() && (*ancestor).type_index == target_type_index
260 }
261}
262
263pub trait ObjectRefCast: ObjectRefCore + AnyCompatible {
272 #[inline(always)]
274 fn try_cast<B>(self) -> crate::error::Result<B>
275 where
276 B: ObjectRefCore + AnyCompatible,
277 {
278 let mut any_data = TVMFFIAny::new();
279 unsafe {
280 Self::copy_to_any_view(&self, &mut any_data);
284 debug_assert!(any_data.type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32);
285 std::hint::assert_unchecked(
288 any_data.type_index >= TypeIndex::kTVMFFIStaticObjectBegin as i32,
289 );
290
291 if B::check_any_strict(&any_data) {
292 Self::move_to_any(self, &mut any_data);
295 Ok(B::move_from_any_after_check(&mut any_data))
296 } else {
297 let msg = format!(
298 "Cannot convert from type `{}` to `{}`",
299 B::get_mismatch_type_info(&any_data),
300 B::type_str()
301 );
302 Err(crate::error::Error::new(crate::error::TYPE_ERROR, &msg, ""))
303 }
304 }
305 }
306}
307
308impl<T: ObjectRefCore + AnyCompatible> ObjectRefCast for T {}
309
310#[repr(C)]
314#[derive(ObjectRef, Clone)]
315pub struct ObjectRef {
316 data: ObjectArc<Object>,
317}
318
319#[doc(hidden)]
321pub mod unsafe_ {
322 use tvm_ffi_sys::{
323 COMBINED_REF_COUNT_BOTH_ONE, COMBINED_REF_COUNT_MASK_U32, COMBINED_REF_COUNT_STRONG_ONE,
324 COMBINED_REF_COUNT_WEAK_ONE,
325 };
326
327 use std::ffi::c_void;
328 use std::sync::atomic::{fence, Ordering};
329 use tvm_ffi_sys::TVMFFIObject;
330 use tvm_ffi_sys::TVMFFIObjectDeleterFlagBitMask::{
331 kTVMFFIObjectDeleterFlagBitMaskBoth, kTVMFFIObjectDeleterFlagBitMaskStrong,
332 kTVMFFIObjectDeleterFlagBitMaskWeak,
333 };
334
335 #[inline]
342 pub unsafe fn inc_ref(handle: *mut TVMFFIObject) {
343 let obj = &mut *handle;
344 obj.combined_ref_count.fetch_add(1, Ordering::Relaxed);
345 }
346
347 #[inline]
354 pub(crate) unsafe fn dec_ref(handle: *mut TVMFFIObject) {
355 let obj = &mut *handle;
356 let old_combined_count = obj
357 .combined_ref_count
358 .fetch_sub(COMBINED_REF_COUNT_STRONG_ONE, Ordering::Relaxed);
359 if old_combined_count == COMBINED_REF_COUNT_BOTH_ONE {
360 if let Some(deleter) = obj.deleter {
361 fence(Ordering::Acquire);
362 deleter(
363 obj as *mut TVMFFIObject as *mut c_void,
364 kTVMFFIObjectDeleterFlagBitMaskBoth as i32,
365 );
366 }
367 } else if (old_combined_count & COMBINED_REF_COUNT_MASK_U32)
368 == COMBINED_REF_COUNT_STRONG_ONE
369 {
370 fence(Ordering::Acquire);
373 if let Some(deleter) = obj.deleter {
374 deleter(
375 obj as *mut TVMFFIObject as *mut c_void,
376 kTVMFFIObjectDeleterFlagBitMaskStrong as i32,
377 );
378 }
379 let old_weak_count = obj
380 .combined_ref_count
381 .fetch_sub(COMBINED_REF_COUNT_WEAK_ONE, Ordering::Release);
382 if old_weak_count == COMBINED_REF_COUNT_WEAK_ONE {
383 fence(Ordering::Acquire);
384 if let Some(deleter) = obj.deleter {
385 deleter(
386 obj as *mut TVMFFIObject as *mut c_void,
387 kTVMFFIObjectDeleterFlagBitMaskWeak as i32,
388 );
389 }
390 }
391 }
392 }
393
394 #[inline]
395 pub(crate) unsafe fn strong_count(handle: *mut TVMFFIObject) -> usize {
396 let obj = &mut *handle;
397 (obj.combined_ref_count.load(Ordering::Relaxed) & COMBINED_REF_COUNT_MASK_U32) as usize
398 }
399
400 #[inline]
401 pub(crate) unsafe fn weak_count(handle: *mut TVMFFIObject) -> usize {
402 let obj = &mut *handle;
403 (obj.combined_ref_count.load(Ordering::Relaxed) >> 32) as usize
404 }
405
406 pub(crate) unsafe extern "C" fn object_deleter_for_new<T>(ptr: *mut c_void, flags: i32)
408 where
409 T: super::ObjectCore,
410 {
411 let obj = ptr as *mut T;
412 if flags & kTVMFFIObjectDeleterFlagBitMaskStrong as i32 != 0 {
413 std::ptr::drop_in_place(obj);
414 }
415 if flags & kTVMFFIObjectDeleterFlagBitMaskWeak as i32 != 0 {
416 std::alloc::dealloc(ptr as *mut u8, std::alloc::Layout::new::<T>());
417 }
418 }
419
420 pub(crate) unsafe extern "C" fn object_deleter_for_new_with_extra_items<T, U>(
421 ptr: *mut c_void,
422 flags: i32,
423 ) where
424 T: super::ObjectCoreWithExtraItems<ExtraItem = U>,
425 {
426 let obj = ptr as *mut T;
427 if flags == kTVMFFIObjectDeleterFlagBitMaskBoth as i32 {
428 let extra_items_count = T::extra_items_count(&(*obj));
429 std::ptr::drop_in_place(obj);
430 let layout = std::alloc::Layout::from_size_align(
431 std::mem::size_of::<T>() + extra_items_count * std::mem::size_of::<U>(),
432 std::mem::align_of::<T>(),
433 )
434 .unwrap();
435 std::alloc::dealloc(ptr as *mut u8, layout);
436 } else {
437 assert_eq!(std::mem::size_of::<T>() % std::mem::size_of::<u64>(), 0);
438 if flags & kTVMFFIObjectDeleterFlagBitMaskStrong as i32 != 0 {
439 let extra_items_count = T::extra_items_count(&(*obj));
440 std::ptr::drop_in_place(obj);
441 std::ptr::write(obj as *mut u64, extra_items_count as u64);
442 }
443 if flags & kTVMFFIObjectDeleterFlagBitMaskWeak as i32 != 0 {
444 let extra_items_count = std::ptr::read(obj as *mut u64) as usize;
445 let layout = std::alloc::Layout::from_size_align(
446 std::mem::size_of::<T>() + extra_items_count * std::mem::size_of::<U>(),
447 std::mem::align_of::<T>(),
448 )
449 .unwrap();
450 std::alloc::dealloc(ptr as *mut u8, layout);
451 }
452 }
453 }
454}
455
456impl Object {
461 pub fn new() -> Self {
462 Self {
463 header: TVMFFIObject::new(),
464 }
465 }
466}
467
468unsafe impl ObjectCore for Object {
469 const TYPE_KEY: &'static str = "ffi.Object";
470 const TYPE_DEPTH: i32 = 0;
471 #[inline]
472 fn type_index() -> i32 {
473 TypeIndex::kTVMFFIStaticObjectBegin as i32
474 }
475 #[inline]
476 unsafe fn object_header_mut(this: &mut Self) -> &mut TVMFFIObject {
477 &mut this.header
478 }
479}
480
481impl<T: ObjectCore> ObjectArc<T> {
486 pub fn new(data: T) -> Self {
487 unsafe {
488 let layout = std::alloc::Layout::new::<T>();
489 let raw_data_ptr = std::alloc::alloc(layout);
490 if raw_data_ptr.is_null() {
491 std::alloc::handle_alloc_error(layout);
492 }
493 let ptr = raw_data_ptr as *mut T;
494 std::ptr::write(ptr, data);
495 std::ptr::write(
497 ptr as *mut TVMFFIObject,
498 TVMFFIObject {
499 combined_ref_count: AtomicU64::new(COMBINED_REF_COUNT_BOTH_ONE),
500 type_index: T::type_index(),
501 __padding: 0,
502 deleter: Some(unsafe_::object_deleter_for_new::<T>),
503 },
504 );
505 Self {
507 ptr: std::ptr::NonNull::new_unchecked(ptr as *mut T),
508 _phantom: std::marker::PhantomData,
509 }
510 }
511 }
512 pub fn new_with_extra_items<U>(data: T) -> Self
513 where
514 T: ObjectCoreWithExtraItems<ExtraItem = U>,
515 {
516 unsafe {
517 assert_eq!(std::mem::align_of::<T>() % std::mem::align_of::<U>(), 0);
520 assert_eq!(std::mem::size_of::<T>() % std::mem::align_of::<U>(), 0);
521 let extra_items_count = T::extra_items_count(&data);
522 let layout = std::alloc::Layout::from_size_align(
523 std::mem::size_of::<T>() + extra_items_count * std::mem::size_of::<U>(),
524 std::mem::align_of::<T>(),
525 )
526 .unwrap();
527 let raw_data_ptr = std::alloc::alloc(layout);
528 if raw_data_ptr.is_null() {
529 std::alloc::handle_alloc_error(layout);
530 }
531 let ptr = raw_data_ptr as *mut T;
532 std::ptr::write(ptr, data);
533 std::ptr::write(
535 ptr as *mut TVMFFIObject,
536 TVMFFIObject {
537 combined_ref_count: AtomicU64::new(COMBINED_REF_COUNT_BOTH_ONE),
538 type_index: T::type_index(),
539 __padding: 0,
540 deleter: Some(unsafe_::object_deleter_for_new_with_extra_items::<T, U>),
541 },
542 );
543 Self {
545 ptr: std::ptr::NonNull::new_unchecked(ptr as *mut T),
546 _phantom: std::marker::PhantomData,
547 }
548 }
549 }
550
551 #[inline]
560 pub unsafe fn from_raw(ptr: *const T) -> Self {
561 Self {
562 ptr: std::ptr::NonNull::new_unchecked(ptr as *mut T),
563 _phantom: std::marker::PhantomData,
564 }
565 }
566
567 #[inline]
575 pub unsafe fn into_raw(this: Self) -> *const T {
576 let droped_this = std::mem::ManuallyDrop::new(this);
577 droped_this.ptr.as_ptr() as *const T
578 }
579
580 #[inline]
591 pub unsafe fn as_raw(this: &Self) -> *const T {
592 this.ptr.as_ptr() as *const T
593 }
594
595 #[inline]
605 pub unsafe fn as_raw_mut(this: &mut Self) -> *mut T {
606 this.ptr.as_mut()
607 }
608
609 #[inline]
617 pub fn strong_count(this: &Self) -> usize {
618 unsafe {
619 unsafe_::strong_count(this.ptr.as_ref() as *const T as *mut T as *mut TVMFFIObject)
620 }
621 }
622
623 #[inline]
631 pub fn weak_count(this: &Self) -> usize {
632 unsafe { unsafe_::weak_count(this.ptr.as_ref() as *const T as *mut T as *mut TVMFFIObject) }
633 }
634}
635
636impl<T: ObjectCore> Deref for ObjectArc<T> {
638 type Target = T;
639 #[inline]
640 fn deref(&self) -> &Self::Target {
641 unsafe { self.ptr.as_ref() }
642 }
643}
644
645impl<T: ObjectCore> DerefMut for ObjectArc<T> {
647 #[inline]
648 fn deref_mut(&mut self) -> &mut Self::Target {
649 unsafe { self.ptr.as_mut() }
650 }
651}
652
653impl<T: ObjectCore> Drop for ObjectArc<T> {
655 fn drop(&mut self) {
656 unsafe { unsafe_::dec_ref(self.ptr.as_mut() as *mut T as *mut TVMFFIObject) }
657 }
658}
659
660impl<T: ObjectCore> Clone for ObjectArc<T> {
662 #[inline]
663 fn clone(&self) -> Self {
664 unsafe { unsafe_::inc_ref(self.ptr.as_ref() as *const T as *mut T as *mut TVMFFIObject) }
665 Self {
666 ptr: self.ptr,
667 _phantom: std::marker::PhantomData,
668 }
669 }
670}