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)]
315#[derive(ObjectRef, Clone)]
316pub struct ObjectRef {
317 data: ObjectArc<Object>,
318}
319
320#[doc(hidden)]
322pub mod unsafe_ {
323 use tvm_ffi_sys::{
324 COMBINED_REF_COUNT_BOTH_ONE, COMBINED_REF_COUNT_MASK_U32, COMBINED_REF_COUNT_STRONG_ONE,
325 COMBINED_REF_COUNT_WEAK_ONE,
326 };
327
328 use std::ffi::c_void;
329 use std::sync::atomic::{fence, Ordering};
330 use tvm_ffi_sys::TVMFFIObject;
331 use tvm_ffi_sys::TVMFFIObjectDeleterFlagBitMask::{
332 kTVMFFIObjectDeleterFlagBitMaskBoth, kTVMFFIObjectDeleterFlagBitMaskStrong,
333 kTVMFFIObjectDeleterFlagBitMaskWeak,
334 };
335
336 #[inline]
343 pub unsafe fn inc_ref(handle: *mut TVMFFIObject) {
344 let obj = &mut *handle;
345 obj.combined_ref_count.fetch_add(1, Ordering::Relaxed);
346 }
347
348 #[inline]
355 pub(crate) unsafe fn dec_ref(handle: *mut TVMFFIObject) {
356 let obj = &mut *handle;
357 let old_combined_count = obj
358 .combined_ref_count
359 .fetch_sub(COMBINED_REF_COUNT_STRONG_ONE, Ordering::Relaxed);
360 if old_combined_count == COMBINED_REF_COUNT_BOTH_ONE {
361 if let Some(deleter) = obj.deleter {
362 fence(Ordering::Acquire);
363 deleter(
364 obj as *mut TVMFFIObject as *mut c_void,
365 kTVMFFIObjectDeleterFlagBitMaskBoth as i32,
366 );
367 }
368 } else if (old_combined_count & COMBINED_REF_COUNT_MASK_U32)
369 == COMBINED_REF_COUNT_STRONG_ONE
370 {
371 fence(Ordering::Acquire);
374 if let Some(deleter) = obj.deleter {
375 deleter(
376 obj as *mut TVMFFIObject as *mut c_void,
377 kTVMFFIObjectDeleterFlagBitMaskStrong as i32,
378 );
379 }
380 let old_weak_count = obj
381 .combined_ref_count
382 .fetch_sub(COMBINED_REF_COUNT_WEAK_ONE, Ordering::Release);
383 if old_weak_count == COMBINED_REF_COUNT_WEAK_ONE {
384 fence(Ordering::Acquire);
385 if let Some(deleter) = obj.deleter {
386 deleter(
387 obj as *mut TVMFFIObject as *mut c_void,
388 kTVMFFIObjectDeleterFlagBitMaskWeak as i32,
389 );
390 }
391 }
392 }
393 }
394
395 #[inline]
396 pub(crate) unsafe fn strong_count(handle: *mut TVMFFIObject) -> usize {
397 let obj = &mut *handle;
398 (obj.combined_ref_count.load(Ordering::Relaxed) & COMBINED_REF_COUNT_MASK_U32) as usize
399 }
400
401 #[inline]
402 pub(crate) unsafe fn weak_count(handle: *mut TVMFFIObject) -> usize {
403 let obj = &mut *handle;
404 (obj.combined_ref_count.load(Ordering::Relaxed) >> 32) as usize
405 }
406
407 pub(crate) unsafe extern "C" fn object_deleter_for_new<T>(ptr: *mut c_void, flags: i32)
409 where
410 T: super::ObjectCore,
411 {
412 let obj = ptr as *mut T;
413 if flags & kTVMFFIObjectDeleterFlagBitMaskStrong as i32 != 0 {
414 std::ptr::drop_in_place(obj);
415 }
416 if flags & kTVMFFIObjectDeleterFlagBitMaskWeak as i32 != 0 {
417 std::alloc::dealloc(ptr as *mut u8, std::alloc::Layout::new::<T>());
418 }
419 }
420
421 pub(crate) unsafe extern "C" fn object_deleter_for_new_with_extra_items<T, U>(
422 ptr: *mut c_void,
423 flags: i32,
424 ) where
425 T: super::ObjectCoreWithExtraItems<ExtraItem = U>,
426 {
427 let obj = ptr as *mut T;
428 if flags == kTVMFFIObjectDeleterFlagBitMaskBoth as i32 {
429 let extra_items_count = T::extra_items_count(&(*obj));
430 std::ptr::drop_in_place(obj);
431 let layout = std::alloc::Layout::from_size_align(
432 std::mem::size_of::<T>() + extra_items_count * std::mem::size_of::<U>(),
433 std::mem::align_of::<T>(),
434 )
435 .unwrap();
436 std::alloc::dealloc(ptr as *mut u8, layout);
437 } else {
438 assert_eq!(std::mem::size_of::<T>() % std::mem::size_of::<u64>(), 0);
439 if flags & kTVMFFIObjectDeleterFlagBitMaskStrong as i32 != 0 {
440 let extra_items_count = T::extra_items_count(&(*obj));
441 std::ptr::drop_in_place(obj);
442 std::ptr::write(obj as *mut u64, extra_items_count as u64);
443 }
444 if flags & kTVMFFIObjectDeleterFlagBitMaskWeak as i32 != 0 {
445 let extra_items_count = std::ptr::read(obj as *mut u64) as usize;
446 let layout = std::alloc::Layout::from_size_align(
447 std::mem::size_of::<T>() + extra_items_count * std::mem::size_of::<U>(),
448 std::mem::align_of::<T>(),
449 )
450 .unwrap();
451 std::alloc::dealloc(ptr as *mut u8, layout);
452 }
453 }
454 }
455}
456
457impl Object {
462 pub fn new() -> Self {
463 Self {
464 header: TVMFFIObject::new(),
465 }
466 }
467}
468
469unsafe impl ObjectCore for Object {
470 const TYPE_KEY: &'static str = "ffi.Object";
471 const TYPE_DEPTH: i32 = 0;
472 #[inline]
473 fn type_index() -> i32 {
474 TypeIndex::kTVMFFIStaticObjectBegin as i32
475 }
476 #[inline]
477 unsafe fn object_header_mut(this: &mut Self) -> &mut TVMFFIObject {
478 &mut this.header
479 }
480}
481
482impl<T: ObjectCore> ObjectArc<T> {
487 pub fn new(data: T) -> Self {
488 unsafe {
489 let layout = std::alloc::Layout::new::<T>();
490 let raw_data_ptr = std::alloc::alloc(layout);
491 if raw_data_ptr.is_null() {
492 std::alloc::handle_alloc_error(layout);
493 }
494 let ptr = raw_data_ptr as *mut T;
495 std::ptr::write(ptr, data);
496 std::ptr::write(
498 ptr as *mut TVMFFIObject,
499 TVMFFIObject {
500 combined_ref_count: AtomicU64::new(COMBINED_REF_COUNT_BOTH_ONE),
501 type_index: T::type_index(),
502 __padding: 0,
503 deleter: Some(unsafe_::object_deleter_for_new::<T>),
504 },
505 );
506 Self {
508 ptr: std::ptr::NonNull::new_unchecked(ptr as *mut T),
509 _phantom: std::marker::PhantomData,
510 }
511 }
512 }
513 pub fn new_with_extra_items<U>(data: T) -> Self
514 where
515 T: ObjectCoreWithExtraItems<ExtraItem = U>,
516 {
517 unsafe {
518 assert_eq!(std::mem::align_of::<T>() % std::mem::align_of::<U>(), 0);
521 assert_eq!(std::mem::size_of::<T>() % std::mem::align_of::<U>(), 0);
522 let extra_items_count = T::extra_items_count(&data);
523 let layout = std::alloc::Layout::from_size_align(
524 std::mem::size_of::<T>() + extra_items_count * std::mem::size_of::<U>(),
525 std::mem::align_of::<T>(),
526 )
527 .unwrap();
528 let raw_data_ptr = std::alloc::alloc(layout);
529 if raw_data_ptr.is_null() {
530 std::alloc::handle_alloc_error(layout);
531 }
532 let ptr = raw_data_ptr as *mut T;
533 std::ptr::write(ptr, data);
534 std::ptr::write(
536 ptr as *mut TVMFFIObject,
537 TVMFFIObject {
538 combined_ref_count: AtomicU64::new(COMBINED_REF_COUNT_BOTH_ONE),
539 type_index: T::type_index(),
540 __padding: 0,
541 deleter: Some(unsafe_::object_deleter_for_new_with_extra_items::<T, U>),
542 },
543 );
544 Self {
546 ptr: std::ptr::NonNull::new_unchecked(ptr as *mut T),
547 _phantom: std::marker::PhantomData,
548 }
549 }
550 }
551
552 #[inline]
561 pub unsafe fn from_raw(ptr: *const T) -> Self {
562 Self {
563 ptr: std::ptr::NonNull::new_unchecked(ptr as *mut T),
564 _phantom: std::marker::PhantomData,
565 }
566 }
567
568 #[inline]
576 pub unsafe fn into_raw(this: Self) -> *const T {
577 let droped_this = std::mem::ManuallyDrop::new(this);
578 droped_this.ptr.as_ptr() as *const T
579 }
580
581 #[inline]
592 pub unsafe fn as_raw(this: &Self) -> *const T {
593 this.ptr.as_ptr() as *const T
594 }
595
596 #[inline]
606 pub unsafe fn as_raw_mut(this: &mut Self) -> *mut T {
607 this.ptr.as_mut()
608 }
609
610 #[inline]
618 pub fn strong_count(this: &Self) -> usize {
619 unsafe {
620 unsafe_::strong_count(this.ptr.as_ref() as *const T as *mut T as *mut TVMFFIObject)
621 }
622 }
623
624 #[inline]
632 pub fn weak_count(this: &Self) -> usize {
633 unsafe { unsafe_::weak_count(this.ptr.as_ref() as *const T as *mut T as *mut TVMFFIObject) }
634 }
635}
636
637impl<T: ObjectCore> Deref for ObjectArc<T> {
639 type Target = T;
640 #[inline]
641 fn deref(&self) -> &Self::Target {
642 unsafe { self.ptr.as_ref() }
643 }
644}
645
646impl<T: ObjectCore> DerefMut for ObjectArc<T> {
648 #[inline]
649 fn deref_mut(&mut self) -> &mut Self::Target {
650 unsafe { self.ptr.as_mut() }
651 }
652}
653
654impl<T: ObjectCore> Drop for ObjectArc<T> {
656 fn drop(&mut self) {
657 unsafe { unsafe_::dec_ref(self.ptr.as_mut() as *mut T as *mut TVMFFIObject) }
658 }
659}
660
661impl<T: ObjectCore> Clone for ObjectArc<T> {
663 #[inline]
664 fn clone(&self) -> Self {
665 unsafe { unsafe_::inc_ref(self.ptr.as_ref() as *const T as *mut T as *mut TVMFFIObject) }
666 Self {
667 ptr: self.ptr,
668 _phantom: std::marker::PhantomData,
669 }
670 }
671}