1use core::cell::Cell;
2use core::fmt;
3use core::mem::{replace, ManuallyDrop};
4use core::ptr::{self, addr_of, NonNull};
5
6use crate::alloc::clone::TryClone;
7use crate::alloc::{self, Box};
8use crate::{Any, Hash};
9
10use super::{
11 Access, AccessError, AnyObjVtable, AnyTypeInfo, BorrowMut, BorrowRef, FromValue, Handover, Mut,
12 RawAccessGuard, RawAnyGuard, Ref, RefVtable, RuntimeError, Shared, Snapshot, ToValue, TypeInfo,
13 Value,
14};
15
16pub struct AnyObj {
18 shared: NonNull<AnyObjData>,
19}
20
21impl AnyObj {
22 #[inline]
28 pub(super) const unsafe fn from_raw(shared: NonNull<AnyObjData>) -> Self {
29 Self { shared }
30 }
31
32 #[inline]
50 pub fn new<T>(data: T) -> alloc::Result<Self>
51 where
52 T: Any,
53 {
54 let shared = AnyObjData {
55 access: Access::new(),
56 count: Cell::new(1),
57 vtable: AnyObjVtable::owned::<T>(),
58 data,
59 };
60
61 let shared = NonNull::from(Box::leak(Box::try_new(shared)?)).cast();
62 Ok(Self { shared })
63 }
64
65 #[inline]
72 pub(crate) unsafe fn from_ref<T>(data: *const T) -> alloc::Result<Self>
73 where
74 T: Any,
75 {
76 let shared = AnyObjData {
77 access: Access::new(),
78 count: Cell::new(1),
79 vtable: AnyObjVtable::from_ref::<T>(),
80 data: NonNull::new_unchecked(data.cast_mut()),
81 };
82
83 let shared = NonNull::from(Box::leak(Box::try_new(shared)?)).cast();
84 Ok(Self { shared })
85 }
86
87 #[inline]
94 pub(crate) unsafe fn from_mut<T>(data: *mut T) -> alloc::Result<Self>
95 where
96 T: Any,
97 {
98 let shared = AnyObjData {
99 access: Access::new(),
100 count: Cell::new(1),
101 vtable: AnyObjVtable::from_mut::<T>(),
102 data: NonNull::new_unchecked(data),
103 };
104
105 let shared = NonNull::from(Box::leak(Box::try_new(shared)?)).cast();
106 Ok(Self { shared })
107 }
108
109 #[inline]
123 pub(crate) fn is_last_owner(&self) -> bool {
124 unsafe { vtable(self).is_owned() && self.shared.as_ref().count.get() == 1 }
127 }
128
129 pub(crate) fn dismantle(&self, out: &mut Handover<'_>) {
141 if !self.is_last_owner() {
142 return;
143 }
144
145 let Some(dismantle) = vtable(self).dismantle else {
146 return;
147 };
148
149 unsafe {
153 let Ok(_guard) = self.shared.as_ref().access.exclusive() else {
154 return;
155 };
156
157 dismantle(self.shared, out)
158 }
159 }
160
161 pub(crate) fn into_shared<T>(self) -> Result<Shared<T>, AnyObjError>
163 where
164 T: Any,
165 {
166 let vtable = vtable(&self);
167
168 if !vtable.is::<T>() {
169 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
170 T::ANY_TYPE_INFO,
171 vtable.type_info(),
172 )));
173 }
174
175 unsafe { Ok(self.unsafe_into_shared()) }
177 }
178
179 #[inline]
185 pub(crate) unsafe fn unsafe_into_shared<T>(self) -> Shared<T>
186 where
187 T: Any,
188 {
189 let this = ManuallyDrop::new(self);
190 Shared::from_raw(this.shared.cast())
191 }
192
193 pub(crate) fn downcast<T>(self) -> Result<T, AnyObjError>
195 where
196 T: Any,
197 {
198 let vtable = vtable(&self);
199
200 if !vtable.is::<T>() {
201 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
202 T::ANY_TYPE_INFO,
203 vtable.type_info(),
204 )));
205 }
206
207 if !vtable.is_owned() {
208 return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
209 vtable.type_info(),
210 )));
211 }
212
213 unsafe {
215 self.shared.as_ref().access.try_take()?;
216 let data = vtable.as_ptr::<T>(self.shared);
217 Ok(data.read())
218 }
219 }
220
221 pub(crate) fn drop(self) -> Result<(), AnyObjError> {
223 let vtable = vtable(&self);
224
225 if !vtable.is_owned() {
226 return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
227 vtable.type_info(),
228 )));
229 }
230
231 unsafe {
233 self.shared.as_ref().access.try_take()?;
234
235 if let Some(drop_value) = vtable.drop_value {
236 drop_value(self.shared);
237 }
238
239 Ok(())
240 }
241 }
242
243 pub fn take(self) -> Result<Self, AnyObjError> {
245 let vtable = vtable(&self);
246
247 unsafe {
249 self.shared.as_ref().access.try_take()?;
250 Ok((vtable.clone)(self.shared)?)
251 }
252 }
253
254 pub(crate) fn into_ref<T>(self) -> Result<Ref<T>, AnyObjError>
261 where
262 T: Any,
263 {
264 let vtable = vtable(&self);
265
266 if !vtable.is::<T>() {
267 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
268 T::ANY_TYPE_INFO,
269 vtable.type_info(),
270 )));
271 }
272
273 if !vtable.is_owned() {
274 return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
275 vtable.type_info(),
276 )));
277 }
278
279 unsafe {
281 self.shared.as_ref().access.try_shared()?;
282 let this = ManuallyDrop::new(self);
283 let data = vtable.as_ptr(this.shared);
284
285 let vtable = &RefVtable {
286 drop: |shared: NonNull<()>| {
287 let shared = shared.cast::<AnyObjData>();
288 shared.as_ref().access.release();
289 AnyObjData::dec(shared)
290 },
291 into_value: Some(|shared: NonNull<()>| {
295 let shared = shared.cast::<AnyObjData>();
296 shared.as_ref().access.release();
297 Value::from(AnyObj::from_raw(shared))
298 }),
299 };
300
301 let guard = RawAnyGuard::new(this.shared.cast(), vtable);
302 Ok(Ref::new(data, guard))
303 }
304 }
305
306 pub(crate) fn into_mut<T>(self) -> Result<Mut<T>, AnyObjError>
313 where
314 T: Any,
315 {
316 let vtable = vtable(&self);
317
318 if !vtable.is::<T>() {
319 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
320 T::ANY_TYPE_INFO,
321 vtable.type_info(),
322 )));
323 }
324
325 if !vtable.is_owned() {
326 return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
327 vtable.type_info(),
328 )));
329 }
330
331 unsafe {
333 self.shared.as_ref().access.try_exclusive()?;
334 let this = ManuallyDrop::new(self);
335 let data = vtable.as_ptr(this.shared);
336
337 let vtable = &RefVtable {
338 drop: |shared: NonNull<()>| {
339 let shared = shared.cast::<AnyObjData>();
340 shared.as_ref().access.release();
341 AnyObjData::dec(shared)
342 },
343 into_value: Some(|shared: NonNull<()>| {
347 let shared = shared.cast::<AnyObjData>();
348 shared.as_ref().access.release();
349 Value::from(AnyObj::from_raw(shared))
350 }),
351 };
352
353 let guard = RawAnyGuard::new(this.shared.cast(), vtable);
354 Ok(Mut::new(data, guard))
355 }
356 }
357
358 pub fn borrow_ref<T>(&self) -> Result<BorrowRef<'_, T>, AnyObjError>
363 where
364 T: Any,
365 {
366 let vtable = vtable(self);
367
368 if !vtable.is::<T>() {
369 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
370 T::ANY_TYPE_INFO,
371 vtable.type_info(),
372 )));
373 }
374
375 unsafe {
377 let guard = self.shared.as_ref().access.shared()?;
378 let data = vtable.as_ptr(self.shared);
379 Ok(BorrowRef::new(data, guard.into_raw()))
380 }
381 }
382
383 pub fn try_borrow_ref<T>(&self) -> Result<Option<BorrowRef<'_, T>>, AccessError>
391 where
392 T: Any,
393 {
394 let vtable = vtable(self);
395
396 if !vtable.is::<T>() {
397 return Ok(None);
398 }
399
400 unsafe {
402 let guard = self.shared.as_ref().access.shared()?;
403 let data = vtable.as_ptr(self.shared);
404 Ok(Some(BorrowRef::new(data, guard.into_raw())))
405 }
406 }
407
408 pub fn try_borrow_mut<T>(&self) -> Result<Option<BorrowMut<'_, T>>, AccessError>
416 where
417 T: Any,
418 {
419 let vtable = vtable(self);
420
421 if !vtable.is::<T>() {
422 return Ok(None);
423 }
424
425 unsafe {
427 let guard = self.shared.as_ref().access.exclusive()?;
428 let data = vtable.as_ptr(self.shared);
429 Ok(Some(BorrowMut::new(data, guard.into_raw())))
430 }
431 }
432
433 pub fn borrow_mut<T>(&self) -> Result<BorrowMut<'_, T>, AnyObjError>
435 where
436 T: Any,
437 {
438 let vtable = vtable(self);
439
440 if !vtable.is::<T>() || !vtable.is_mutable() {
441 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
442 T::ANY_TYPE_INFO,
443 vtable.type_info(),
444 )));
445 }
446
447 unsafe {
449 let guard = self.shared.as_ref().access.exclusive()?;
450 let data = vtable.as_ptr(self.shared);
451 Ok(BorrowMut::new(data, guard.into_raw()))
452 }
453 }
454
455 pub(crate) fn borrow_ref_ptr<T>(self) -> Result<(NonNull<T>, RawAnyObjGuard), AnyObjError>
460 where
461 T: Any,
462 {
463 let vtable = vtable(&self);
464
465 if !vtable.is::<T>() {
466 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
467 T::ANY_TYPE_INFO,
468 vtable.type_info(),
469 )));
470 }
471
472 unsafe {
474 let guard = self.shared.as_ref().access.shared()?.into_raw();
475 let this = ManuallyDrop::new(self);
476
477 let data = vtable.as_ptr(this.shared);
478
479 let guard = RawAnyObjGuard {
480 guard,
481 dec_shared: AnyObjDecShared {
482 shared: this.shared,
483 },
484 };
485
486 Ok((data, guard))
487 }
488 }
489
490 pub(crate) fn borrow_mut_ptr<T>(self) -> Result<(NonNull<T>, RawAnyObjGuard), AnyObjError>
492 where
493 T: Any,
494 {
495 let vtable = vtable(&self);
496
497 if !vtable.is::<T>() || !vtable.is_mutable() {
498 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
499 T::ANY_TYPE_INFO,
500 vtable.type_info(),
501 )));
502 }
503
504 unsafe {
506 let guard = self.shared.as_ref().access.exclusive()?.into_raw();
507 let this = ManuallyDrop::new(self);
508
509 let data = vtable.as_ptr(this.shared);
510
511 let guard = RawAnyObjGuard {
512 guard,
513 dec_shared: AnyObjDecShared {
514 shared: this.shared,
515 },
516 };
517
518 Ok((data, guard))
519 }
520 }
521
522 pub(crate) unsafe fn into_drop_guard(self) -> (Self, AnyObjDrop) {
530 AnyObjData::inc(self.shared);
533
534 let guard = AnyObjDrop {
535 shared: self.shared,
536 };
537
538 (self, guard)
539 }
540
541 pub(crate) fn is_readable(&self) -> bool {
543 unsafe { self.shared.as_ref().access.is_shared() }
546 }
547
548 pub(crate) fn is_writable(&self) -> bool {
550 unsafe {
551 let shared = self.shared.as_ref();
552 shared.vtable.is_mutable() && shared.access.is_exclusive()
553 }
554 }
555
556 pub(crate) fn snapshot(&self) -> Snapshot {
558 unsafe { self.shared.as_ref().access.snapshot() }
559 }
560
561 pub(crate) fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
563 vtable(self).debug(f)
564 }
565
566 pub fn type_hash(&self) -> Hash {
568 vtable(self).type_hash()
569 }
570
571 pub fn type_info(&self) -> TypeInfo {
573 vtable(self).type_info()
574 }
575}
576
577impl Clone for AnyObj {
578 #[inline]
579 fn clone(&self) -> Self {
580 unsafe {
582 AnyObjData::inc(self.shared);
583 }
584
585 Self {
586 shared: self.shared,
587 }
588 }
589
590 #[inline]
591 fn clone_from(&mut self, source: &Self) {
592 if ptr::eq(self.shared.as_ptr(), source.shared.as_ptr()) {
593 return;
594 }
595
596 let old = replace(&mut self.shared, source.shared);
597
598 unsafe {
600 AnyObjData::dec(old);
601 AnyObjData::inc(self.shared);
602 }
603 }
604}
605
606impl TryClone for AnyObj {
607 #[inline]
608 fn try_clone(&self) -> alloc::Result<Self> {
609 Ok(self.clone())
610 }
611
612 #[inline]
613 fn try_clone_from(&mut self, source: &Self) -> alloc::Result<()> {
614 self.clone_from(source);
615 Ok(())
616 }
617}
618
619impl fmt::Debug for AnyObj {
620 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
621 self.debug(f)
622 }
623}
624
625impl Drop for AnyObj {
626 fn drop(&mut self) {
627 unsafe {
629 AnyObjData::dec(self.shared);
630 }
631 }
632}
633
634impl FromValue for AnyObj {
635 #[inline]
636 fn from_value(value: Value) -> Result<Self, RuntimeError> {
637 value.into_any_obj()
638 }
639}
640
641impl ToValue for AnyObj {
642 #[inline]
643 fn to_value(self) -> Result<Value, RuntimeError> {
644 Ok(Value::from(self))
645 }
646}
647
648#[repr(C)]
649pub(super) struct AnyObjData<T = ()> {
650 pub(super) access: Access,
652 pub(super) count: Cell<usize>,
654 pub(super) vtable: &'static AnyObjVtable,
656 pub(super) data: T,
658}
659
660impl AnyObjData {
661 #[inline]
663 pub(super) unsafe fn inc(this: NonNull<Self>) {
664 let count_ref = &*addr_of!((*this.as_ptr()).count);
665 let count = count_ref.get();
666
667 debug_assert_ne!(
668 count, 0,
669 "Reference count of zero should only happen if Shared is incorrectly implemented"
670 );
671
672 if count == usize::MAX {
673 crate::alloc::abort();
674 }
675
676 count_ref.set(count + 1);
677 }
678
679 #[inline]
686 pub(super) unsafe fn dec(this: NonNull<Self>) {
687 let count_ref = &*addr_of!((*this.as_ptr()).count);
688 let count = count_ref.get();
689
690 debug_assert_ne!(
691 count, 0,
692 "Reference count of zero should only happen if Shared is incorrectly implemented"
693 );
694
695 let count = count - 1;
696 count_ref.set(count);
697
698 if count == 0 {
699 let vtable = *addr_of!((*this.as_ptr()).vtable);
700
701 if let Some(drop_value) = vtable.drop_value {
702 let access = &*addr_of!((*this.as_ptr()).access);
703
704 if !access.is_taken() {
705 drop_value(this);
706 }
707 }
708
709 (vtable.drop)(this);
710 }
711 }
712}
713
714#[derive(Debug)]
715#[cfg_attr(test, derive(PartialEq))]
716pub(super) enum AnyObjErrorKind {
717 Alloc(alloc::Error),
718 Cast(AnyTypeInfo, TypeInfo),
719 AccessError(AccessError),
720 NotOwned(TypeInfo),
721}
722
723#[cfg_attr(test, derive(PartialEq))]
725pub struct AnyObjError {
726 kind: AnyObjErrorKind,
727}
728
729impl AnyObjError {
730 #[inline]
731 pub(super) fn new(kind: AnyObjErrorKind) -> Self {
732 Self { kind }
733 }
734
735 #[inline]
736 pub(super) fn into_kind(self) -> AnyObjErrorKind {
737 self.kind
738 }
739}
740
741impl core::error::Error for AnyObjError {}
742
743impl fmt::Display for AnyObjError {
744 #[inline]
745 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
746 match &self.kind {
747 AnyObjErrorKind::Alloc(error) => error.fmt(f),
748 AnyObjErrorKind::Cast(expected, actual) => {
749 write!(f, "Failed to cast `{actual}` to `{expected}`")
750 }
751 AnyObjErrorKind::AccessError(error) => error.fmt(f),
752 AnyObjErrorKind::NotOwned(type_info) => {
753 write!(f, "Cannot use owned operations for {type_info}")
754 }
755 }
756 }
757}
758
759impl fmt::Debug for AnyObjError {
760 #[inline]
761 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
762 self.kind.fmt(f)
763 }
764}
765
766impl From<alloc::Error> for AnyObjError {
767 #[inline]
768 fn from(error: alloc::Error) -> Self {
769 Self::new(AnyObjErrorKind::Alloc(error))
770 }
771}
772
773impl From<AccessError> for AnyObjError {
774 #[inline]
775 fn from(error: AccessError) -> Self {
776 Self::new(AnyObjErrorKind::AccessError(error))
777 }
778}
779
780pub(super) struct AnyObjDecShared {
782 pub(super) shared: NonNull<AnyObjData>,
783}
784
785impl Drop for AnyObjDecShared {
786 fn drop(&mut self) {
787 unsafe {
789 AnyObjData::dec(self.shared);
790 }
791 }
792}
793
794pub(crate) struct AnyObjDrop {
796 #[allow(unused)]
797 pub(super) shared: NonNull<AnyObjData>,
798}
799
800impl Drop for AnyObjDrop {
801 #[inline]
802 fn drop(&mut self) {
803 unsafe {
805 self.shared.as_ref().access.take();
806 AnyObjData::dec(self.shared);
807 }
808 }
809}
810
811pub(crate) struct RawAnyObjGuard {
813 #[allow(unused)]
814 pub(super) guard: RawAccessGuard,
815 #[allow(unused)]
816 pub(super) dec_shared: AnyObjDecShared,
817}
818
819#[inline]
820fn vtable(any: &AnyObj) -> &'static AnyObjVtable {
821 unsafe { addr_of!((*any.shared.as_ptr()).vtable).read() }
822}