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, 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 pub(crate) fn into_shared<T>(self) -> Result<Shared<T>, AnyObjError>
111 where
112 T: Any,
113 {
114 let vtable = vtable(&self);
115
116 if !vtable.is::<T>() {
117 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
118 T::ANY_TYPE_INFO,
119 vtable.type_info(),
120 )));
121 }
122
123 unsafe { Ok(self.unsafe_into_shared()) }
125 }
126
127 #[inline]
133 pub(crate) unsafe fn unsafe_into_shared<T>(self) -> Shared<T>
134 where
135 T: Any,
136 {
137 let this = ManuallyDrop::new(self);
138 Shared::from_raw(this.shared.cast())
139 }
140
141 pub(crate) fn downcast<T>(self) -> Result<T, AnyObjError>
143 where
144 T: Any,
145 {
146 let vtable = vtable(&self);
147
148 if !vtable.is::<T>() {
149 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
150 T::ANY_TYPE_INFO,
151 vtable.type_info(),
152 )));
153 }
154
155 if !vtable.is_owned() {
156 return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
157 vtable.type_info(),
158 )));
159 }
160
161 unsafe {
163 self.shared.as_ref().access.try_take()?;
164 let data = vtable.as_ptr::<T>(self.shared);
165 Ok(data.read())
166 }
167 }
168
169 pub(crate) fn drop(self) -> Result<(), AnyObjError> {
171 let vtable = vtable(&self);
172
173 if !vtable.is_owned() {
174 return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
175 vtable.type_info(),
176 )));
177 }
178
179 unsafe {
181 self.shared.as_ref().access.try_take()?;
182
183 if let Some(drop_value) = vtable.drop_value {
184 drop_value(self.shared);
185 }
186
187 Ok(())
188 }
189 }
190
191 pub fn take(self) -> Result<Self, AnyObjError> {
193 let vtable = vtable(&self);
194
195 unsafe {
197 self.shared.as_ref().access.try_take()?;
198 Ok((vtable.clone)(self.shared)?)
199 }
200 }
201
202 pub(crate) fn into_ref<T>(self) -> Result<Ref<T>, AnyObjError>
209 where
210 T: Any,
211 {
212 let vtable = vtable(&self);
213
214 if !vtable.is::<T>() {
215 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
216 T::ANY_TYPE_INFO,
217 vtable.type_info(),
218 )));
219 }
220
221 if !vtable.is_owned() {
222 return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
223 vtable.type_info(),
224 )));
225 }
226
227 unsafe {
229 self.shared.as_ref().access.try_shared()?;
230 let this = ManuallyDrop::new(self);
231 let data = vtable.as_ptr(this.shared);
232
233 let vtable = &RefVtable {
234 drop: |shared: NonNull<()>| {
235 let shared = shared.cast::<AnyObjData>();
236 shared.as_ref().access.release();
237 AnyObjData::dec(shared)
238 },
239 };
240
241 let guard = RawAnyGuard::new(this.shared.cast(), vtable);
242 Ok(Ref::new(data, guard))
243 }
244 }
245
246 pub(crate) fn into_mut<T>(self) -> Result<Mut<T>, AnyObjError>
253 where
254 T: Any,
255 {
256 let vtable = vtable(&self);
257
258 if !vtable.is::<T>() {
259 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
260 T::ANY_TYPE_INFO,
261 vtable.type_info(),
262 )));
263 }
264
265 if !vtable.is_owned() {
266 return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
267 vtable.type_info(),
268 )));
269 }
270
271 unsafe {
273 self.shared.as_ref().access.try_exclusive()?;
274 let this = ManuallyDrop::new(self);
275 let data = vtable.as_ptr(this.shared);
276
277 let vtable = &RefVtable {
278 drop: |shared: NonNull<()>| {
279 let shared = shared.cast::<AnyObjData>();
280 shared.as_ref().access.release();
281 AnyObjData::dec(shared)
282 },
283 };
284
285 let guard = RawAnyGuard::new(this.shared.cast(), vtable);
286 Ok(Mut::new(data, guard))
287 }
288 }
289
290 pub fn borrow_ref<T>(&self) -> Result<BorrowRef<'_, T>, AnyObjError>
295 where
296 T: Any,
297 {
298 let vtable = vtable(self);
299
300 if !vtable.is::<T>() {
301 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
302 T::ANY_TYPE_INFO,
303 vtable.type_info(),
304 )));
305 }
306
307 unsafe {
309 let guard = self.shared.as_ref().access.shared()?;
310 let data = vtable.as_ptr(self.shared);
311 Ok(BorrowRef::new(data, guard.into_raw()))
312 }
313 }
314
315 pub fn try_borrow_ref<T>(&self) -> Result<Option<BorrowRef<'_, T>>, AccessError>
323 where
324 T: Any,
325 {
326 let vtable = vtable(self);
327
328 if !vtable.is::<T>() {
329 return Ok(None);
330 }
331
332 unsafe {
334 let guard = self.shared.as_ref().access.shared()?;
335 let data = vtable.as_ptr(self.shared);
336 Ok(Some(BorrowRef::new(data, guard.into_raw())))
337 }
338 }
339
340 pub fn try_borrow_mut<T>(&self) -> Result<Option<BorrowMut<'_, T>>, AccessError>
348 where
349 T: Any,
350 {
351 let vtable = vtable(self);
352
353 if !vtable.is::<T>() {
354 return Ok(None);
355 }
356
357 unsafe {
359 let guard = self.shared.as_ref().access.exclusive()?;
360 let data = vtable.as_ptr(self.shared);
361 Ok(Some(BorrowMut::new(data, guard.into_raw())))
362 }
363 }
364
365 pub fn borrow_mut<T>(&self) -> Result<BorrowMut<'_, T>, AnyObjError>
367 where
368 T: Any,
369 {
370 let vtable = vtable(self);
371
372 if !vtable.is::<T>() || !vtable.is_mutable() {
373 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
374 T::ANY_TYPE_INFO,
375 vtable.type_info(),
376 )));
377 }
378
379 unsafe {
381 let guard = self.shared.as_ref().access.exclusive()?;
382 let data = vtable.as_ptr(self.shared);
383 Ok(BorrowMut::new(data, guard.into_raw()))
384 }
385 }
386
387 pub(crate) fn borrow_ref_ptr<T>(self) -> Result<(NonNull<T>, RawAnyObjGuard), AnyObjError>
392 where
393 T: Any,
394 {
395 let vtable = vtable(&self);
396
397 if !vtable.is::<T>() {
398 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
399 T::ANY_TYPE_INFO,
400 vtable.type_info(),
401 )));
402 }
403
404 unsafe {
406 let guard = self.shared.as_ref().access.shared()?.into_raw();
407 let this = ManuallyDrop::new(self);
408
409 let data = vtable.as_ptr(this.shared);
410
411 let guard = RawAnyObjGuard {
412 guard,
413 dec_shared: AnyObjDecShared {
414 shared: this.shared,
415 },
416 };
417
418 Ok((data, guard))
419 }
420 }
421
422 pub(crate) fn borrow_mut_ptr<T>(self) -> Result<(NonNull<T>, RawAnyObjGuard), AnyObjError>
424 where
425 T: Any,
426 {
427 let vtable = vtable(&self);
428
429 if !vtable.is::<T>() || !vtable.is_mutable() {
430 return Err(AnyObjError::new(AnyObjErrorKind::Cast(
431 T::ANY_TYPE_INFO,
432 vtable.type_info(),
433 )));
434 }
435
436 unsafe {
438 let guard = self.shared.as_ref().access.exclusive()?.into_raw();
439 let this = ManuallyDrop::new(self);
440
441 let data = vtable.as_ptr(this.shared);
442
443 let guard = RawAnyObjGuard {
444 guard,
445 dec_shared: AnyObjDecShared {
446 shared: this.shared,
447 },
448 };
449
450 Ok((data, guard))
451 }
452 }
453
454 pub(crate) unsafe fn into_drop_guard(self) -> (Self, AnyObjDrop) {
462 AnyObjData::inc(self.shared);
465
466 let guard = AnyObjDrop {
467 shared: self.shared,
468 };
469
470 (self, guard)
471 }
472
473 pub(crate) fn is_readable(&self) -> bool {
475 unsafe { self.shared.as_ref().access.is_shared() }
478 }
479
480 pub(crate) fn is_writable(&self) -> bool {
482 unsafe {
483 let shared = self.shared.as_ref();
484 shared.vtable.is_mutable() && shared.access.is_exclusive()
485 }
486 }
487
488 pub(crate) fn snapshot(&self) -> Snapshot {
490 unsafe { self.shared.as_ref().access.snapshot() }
491 }
492
493 pub(crate) fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
495 vtable(self).debug(f)
496 }
497
498 pub fn type_hash(&self) -> Hash {
500 vtable(self).type_hash()
501 }
502
503 pub fn type_info(&self) -> TypeInfo {
505 vtable(self).type_info()
506 }
507}
508
509impl Clone for AnyObj {
510 #[inline]
511 fn clone(&self) -> Self {
512 unsafe {
514 AnyObjData::inc(self.shared);
515 }
516
517 Self {
518 shared: self.shared,
519 }
520 }
521
522 #[inline]
523 fn clone_from(&mut self, source: &Self) {
524 if ptr::eq(self.shared.as_ptr(), source.shared.as_ptr()) {
525 return;
526 }
527
528 let old = replace(&mut self.shared, source.shared);
529
530 unsafe {
532 AnyObjData::dec(old);
533 AnyObjData::inc(self.shared);
534 }
535 }
536}
537
538impl TryClone for AnyObj {
539 #[inline]
540 fn try_clone(&self) -> alloc::Result<Self> {
541 Ok(self.clone())
542 }
543
544 #[inline]
545 fn try_clone_from(&mut self, source: &Self) -> alloc::Result<()> {
546 self.clone_from(source);
547 Ok(())
548 }
549}
550
551impl fmt::Debug for AnyObj {
552 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
553 self.debug(f)
554 }
555}
556
557impl Drop for AnyObj {
558 fn drop(&mut self) {
559 unsafe {
561 AnyObjData::dec(self.shared);
562 }
563 }
564}
565
566impl FromValue for AnyObj {
567 #[inline]
568 fn from_value(value: Value) -> Result<Self, RuntimeError> {
569 value.into_any_obj()
570 }
571}
572
573impl ToValue for AnyObj {
574 #[inline]
575 fn to_value(self) -> Result<Value, RuntimeError> {
576 Ok(Value::from(self))
577 }
578}
579
580#[repr(C)]
581pub(super) struct AnyObjData<T = ()> {
582 pub(super) access: Access,
584 pub(super) count: Cell<usize>,
586 pub(super) vtable: &'static AnyObjVtable,
588 pub(super) data: T,
590}
591
592impl AnyObjData {
593 #[inline]
595 pub(super) unsafe fn inc(this: NonNull<Self>) {
596 let count_ref = &*addr_of!((*this.as_ptr()).count);
597 let count = count_ref.get();
598
599 debug_assert_ne!(
600 count, 0,
601 "Reference count of zero should only happen if Shared is incorrectly implemented"
602 );
603
604 if count == usize::MAX {
605 crate::alloc::abort();
606 }
607
608 count_ref.set(count + 1);
609 }
610
611 #[inline]
618 pub(super) unsafe fn dec(this: NonNull<Self>) {
619 let count_ref = &*addr_of!((*this.as_ptr()).count);
620 let count = count_ref.get();
621
622 debug_assert_ne!(
623 count, 0,
624 "Reference count of zero should only happen if Shared is incorrectly implemented"
625 );
626
627 let count = count - 1;
628 count_ref.set(count);
629
630 if count == 0 {
631 let vtable = *addr_of!((*this.as_ptr()).vtable);
632
633 if let Some(drop_value) = vtable.drop_value {
634 let access = &*addr_of!((*this.as_ptr()).access);
635
636 if !access.is_taken() {
637 drop_value(this);
638 }
639 }
640
641 (vtable.drop)(this);
642 }
643 }
644}
645
646#[derive(Debug)]
647#[cfg_attr(test, derive(PartialEq))]
648pub(super) enum AnyObjErrorKind {
649 Alloc(alloc::Error),
650 Cast(AnyTypeInfo, TypeInfo),
651 AccessError(AccessError),
652 NotOwned(TypeInfo),
653}
654
655#[cfg_attr(test, derive(PartialEq))]
657pub struct AnyObjError {
658 kind: AnyObjErrorKind,
659}
660
661impl AnyObjError {
662 #[inline]
663 pub(super) fn new(kind: AnyObjErrorKind) -> Self {
664 Self { kind }
665 }
666
667 #[inline]
668 pub(super) fn into_kind(self) -> AnyObjErrorKind {
669 self.kind
670 }
671}
672
673impl core::error::Error for AnyObjError {}
674
675impl fmt::Display for AnyObjError {
676 #[inline]
677 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
678 match &self.kind {
679 AnyObjErrorKind::Alloc(error) => error.fmt(f),
680 AnyObjErrorKind::Cast(expected, actual) => {
681 write!(f, "Failed to cast `{actual}` to `{expected}`")
682 }
683 AnyObjErrorKind::AccessError(error) => error.fmt(f),
684 AnyObjErrorKind::NotOwned(type_info) => {
685 write!(f, "Cannot use owned operations for {type_info}")
686 }
687 }
688 }
689}
690
691impl fmt::Debug for AnyObjError {
692 #[inline]
693 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
694 self.kind.fmt(f)
695 }
696}
697
698impl From<alloc::Error> for AnyObjError {
699 #[inline]
700 fn from(error: alloc::Error) -> Self {
701 Self::new(AnyObjErrorKind::Alloc(error))
702 }
703}
704
705impl From<AccessError> for AnyObjError {
706 #[inline]
707 fn from(error: AccessError) -> Self {
708 Self::new(AnyObjErrorKind::AccessError(error))
709 }
710}
711
712pub(super) struct AnyObjDecShared {
714 pub(super) shared: NonNull<AnyObjData>,
715}
716
717impl Drop for AnyObjDecShared {
718 fn drop(&mut self) {
719 unsafe {
721 AnyObjData::dec(self.shared);
722 }
723 }
724}
725
726pub(crate) struct AnyObjDrop {
728 #[allow(unused)]
729 pub(super) shared: NonNull<AnyObjData>,
730}
731
732impl Drop for AnyObjDrop {
733 #[inline]
734 fn drop(&mut self) {
735 unsafe {
737 self.shared.as_ref().access.take();
738 AnyObjData::dec(self.shared);
739 }
740 }
741}
742
743pub(crate) struct RawAnyObjGuard {
745 #[allow(unused)]
746 pub(super) guard: RawAccessGuard,
747 #[allow(unused)]
748 pub(super) dec_shared: AnyObjDecShared,
749}
750
751#[inline]
752fn vtable(any: &AnyObj) -> &'static AnyObjVtable {
753 unsafe { addr_of!((*any.shared.as_ptr()).vtable).read() }
754}