1#![allow(clippy::mutable_key_type)]
2#![allow(clippy::type_complexity)]
3use std::{
47 any::Any,
48 cell::{OnceCell, RefCell},
49 collections::HashMap,
50 fmt,
51 hash::{Hash, Hasher},
52 marker::PhantomData,
53 ops::{Deref, DerefMut},
54 rc::Rc,
55 sync::OnceLock,
56};
57
58use crate::sync::*;
59
60fn fmt_var_debug<T: fmt::Debug + Send + Sync + 'static>(slot: &Slot, generation: u64, struct_name: &str, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 let mut ds = f.debug_struct(struct_name);
62
63 if slot.generation.load(Ordering::Acquire) != generation {
64 return ds.field("status", &"dropped").finish_non_exhaustive();
65 }
66
67 let Some(guard) = slot.value.try_read() else {
68 return ds.field("status", &"locked").finish_non_exhaustive();
69 };
70
71 if let Some(any_val) = guard.as_ref() {
72 if let Some(value) = any_val.downcast_ref::<T>() {
73 ds.field("value", value).finish_non_exhaustive()
74 } else {
75 ds.field("status", &"type_mismatch")
76 .field("expected", &std::any::type_name::<T>())
77 .finish_non_exhaustive()
78 }
79 } else {
80 ds.field("status", &"dropped").finish_non_exhaustive()
81 }
82}
83
84#[derive(Debug, Clone, Copy)]
85pub(crate) struct VarKey {
86 slot: &'static Slot,
87 generation: u64,
88}
89
90impl Eq for VarKey {}
91impl PartialEq for VarKey {
92 fn eq(&self, other: &Self) -> bool {
93 std::ptr::eq(self.slot, other.slot) && self.generation == other.generation
94 }
95}
96
97impl Hash for VarKey {
98 fn hash<H: Hasher>(&self, state: &mut H) {
99 std::ptr::hash(self.slot, state);
100 self.generation.hash(state);
101 }
102}
103
104pub struct Var<T: Send + Sync + 'static>(pub(crate) WeakVar<T>);
117
118impl<T: Send + Sync + 'static> Deref for Var<T> {
119 type Target = WeakVar<T>;
120
121 fn deref(&self) -> &Self::Target {
122 &self.0
123 }
124}
125
126impl<T: Send + Sync + 'static> Drop for Var<T> {
127 fn drop(&mut self) {
128 let registry = self.0.registry;
129 let slot = self.0.slot;
130 let prev = slot.generation.fetch_add(1, Ordering::Release);
131 registry.write_count.fetch_add(1, Ordering::Release);
132
133 slot.attempt_cleanup(registry, prev + 1);
135 }
136}
137
138impl<T: Send + Sync + 'static> From<T> for Var<T> {
139 fn from(value: T) -> Self {
140 Self::new(value)
141 }
142}
143
144impl<T: Send + Sync + Default + 'static> Default for Var<T> {
145 fn default() -> Self {
146 Self::new(T::default())
147 }
148}
149
150impl<T: fmt::Debug + Send + Sync + 'static> fmt::Debug for Var<T> {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 fmt_var_debug::<T>(self.slot, self.generation, "Var", f)
154 }
155}
156
157impl<T: Send + Sync + 'static> Var<T> {
158 pub fn new(value: T) -> Self {
160 Self::new_in(Registry::global(), value)
161 }
162
163 pub(crate) fn new_in(registry: &'static Registry, value: T) -> Self {
165 let (slot, generation) = registry.alloc_slot();
166 *slot.value.write() = Some(Box::new(value));
167 slot.version.store(0, Ordering::Release);
168
169 Var(WeakVar {
170 registry,
171 slot,
172 generation,
173 ty: PhantomData,
174 })
175 }
176
177 pub fn read<'a>(&'a self) -> VarReadGuard<'a, T> {
179 WeakVar::read(self).unwrap() }
181
182 pub fn write<'a>(&'a self) -> VarWriteGuard<'a, T> {
186 WeakVar::write(self).unwrap() }
188
189 pub fn get_version(&self) -> u64 {
191 WeakVar::get_version(self).unwrap() }
193
194 pub fn get(&self) -> T
196 where
197 T: Clone,
198 {
199 WeakVar::get(self).unwrap() }
201
202 pub fn set(&self, new: T)
204 where
205 T: PartialEq,
206 {
207 WeakVar::set(self, new).unwrap() }
209
210 pub fn replace(&self, new: T) -> T {
212 WeakVar::replace(self, new).unwrap() }
214
215 pub fn take(&self) -> T
217 where
218 T: Default,
219 {
220 WeakVar::take(self).unwrap() }
222
223 pub fn downgrade(&self) -> WeakVar<T> {
229 self.0
230 }
231}
232
233pub struct WeakVar<T: Send + Sync + 'static> {
237 pub(crate) registry: &'static Registry,
238 pub(crate) slot: &'static Slot,
239 pub(crate) generation: u64,
240 pub(crate) ty: PhantomData<T>,
241}
242
243impl<T: Send + Sync + 'static> Copy for WeakVar<T> {}
245impl<T: Send + Sync + 'static> Clone for WeakVar<T> {
246 fn clone(&self) -> Self {
247 *self
248 }
249}
250
251impl<T: Send + Sync + 'static> Eq for WeakVar<T> {}
252impl<T: Send + Sync + 'static> PartialEq for WeakVar<T> {
253 fn eq(&self, other: &Self) -> bool {
254 std::ptr::eq(self.slot, other.slot) && self.generation == other.generation
255 }
256}
257
258impl<T: fmt::Debug + Send + Sync + 'static> fmt::Debug for WeakVar<T> {
259 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261 fmt_var_debug::<T>(self.slot, self.generation, "WeakVar", f)
262 }
263}
264
265impl<T: Send + Sync + 'static> WeakVar<T> {
266 pub(crate) fn get_key(&self) -> VarKey {
268 VarKey {
269 slot: self.slot,
270 generation: self.generation,
271 }
272 }
273
274 pub fn is_alive(&self) -> bool {
276 self.slot.generation.load(Ordering::Acquire) == self.generation
277 }
278
279 pub fn get_version(&self) -> Option<u64> {
281 if self.is_alive() {
282 Some(self.slot.version.load(Ordering::Acquire))
283 } else {
284 None
285 }
286 }
287
288 pub fn read<'a>(&'a self) -> Option<VarReadGuard<'a, T>> {
292 let guard = self.slot.value.read();
293
294 if self.slot.generation.load(Ordering::Acquire) != self.generation {
295 drop(guard);
296 self.slot.attempt_cleanup(self.registry, self.generation + 1);
297 return None;
298 }
299
300 let guard = RwLockReadGuard::try_map(guard, |opt: &Option<Box<dyn Any + Send + Sync>>| {
301 let boxed = opt.as_ref()?;
302 (boxed.as_ref() as &dyn Any).downcast_ref::<T>()
303 })
304 .ok()?;
305
306 Some(VarReadGuard {
307 meta: VarGuardMeta {
308 registry: self.registry,
309 slot: self.slot,
310 generation: self.generation,
311 },
312 guard: Some(guard),
313 armed: true,
314 _marker: PhantomData,
315 })
316 }
317
318 pub fn write<'a>(&'a self) -> Option<VarWriteGuard<'a, T>> {
324 let guard = self.slot.value.write();
325
326 if self.slot.generation.load(Ordering::Acquire) != self.generation {
327 drop(guard);
328 self.slot.attempt_cleanup(self.registry, self.generation + 1);
329 return None;
330 }
331
332 let guard = RwLockWriteGuard::try_map(guard, |opt: &mut Option<Box<dyn Any + Send + Sync>>| {
333 let boxed = opt.as_mut()?;
334 (boxed.as_mut() as &mut dyn Any).downcast_mut::<T>()
335 })
336 .ok()?;
337
338 Some(VarWriteGuard {
339 meta: VarGuardMeta {
340 registry: self.registry,
341 slot: self.slot,
342 generation: self.generation,
343 },
344 guard: Some(guard),
345 changed: true,
346 armed: true,
347 _marker: PhantomData,
348 })
349 }
350
351 pub fn get(&self) -> Option<T>
353 where
354 T: Clone,
355 {
356 self.read().map(|guard| (*guard).clone())
357 }
358
359 pub fn get_or(&self, default: T) -> T
364 where
365 T: Clone,
366 {
367 self.get().unwrap_or(default)
368 }
369
370 pub fn get_or_else(&self, default: impl FnOnce() -> T) -> T
374 where
375 T: Clone,
376 {
377 if let Some(val) = self.get() { val } else { default() }
378 }
379
380 pub fn set(&self, new: T) -> Option<()>
384 where
385 T: PartialEq,
386 {
387 let mut guard = self.write()?;
388 if *guard != new {
389 *guard = new;
390 } else {
391 guard.cancel_change();
392 }
393 Some(())
394 }
395
396 pub fn replace(&self, new: T) -> Option<T> {
398 let mut guard = self.write()?;
399 Some(std::mem::replace(&mut *guard, new))
400 }
401
402 pub fn take(&self) -> Option<T>
404 where
405 T: Default,
406 {
407 let mut guard = self.write()?;
408 Some(std::mem::take(&mut *guard))
409 }
410
411 pub fn mark_read(&self) {
415 if self.is_alive() {
416 let key = self.get_key();
417 let version = self.slot.version.load(Ordering::Acquire);
418 notify_scopes(key, version);
419 }
420 }
421}
422
423#[derive(Debug, Default, Clone)]
427pub struct DependencyMap {
428 pub(crate) deps: HashMap<VarKey, u64>,
429}
430
431impl DependencyMap {
432 pub(crate) fn record(&mut self, key: VarKey, version: u64) {
433 self.deps.entry(key).and_modify(|v| *v = std::cmp::max(*v, version)).or_insert(version);
434 }
435
436 pub fn clear(&mut self) {
438 self.deps.clear();
439 }
440
441 pub fn cleared(mut self) -> Self {
443 self.deps.clear();
444 self
445 }
446
447 pub fn any_changed(&self) -> bool {
451 for (key, last_seen) in self.deps.iter() {
452 let current = key.slot.version.load(Ordering::Acquire);
453 if key.slot.generation.load(Ordering::Acquire) != key.generation {
454 return true;
455 }
456 if current != *last_seen {
457 return true;
458 }
459 }
460 false
461 }
462
463 pub fn any_changed_update(&mut self) -> bool {
467 let mut changed = false;
468
469 self.deps.retain(|key, last_seen| {
470 if key.slot.generation.load(Ordering::Acquire) != key.generation {
472 changed = true;
473 return false;
474 }
475
476 let current = key.slot.version.load(Ordering::Acquire);
478 if current != *last_seen {
479 changed = true;
480 *last_seen = current;
481 }
482
483 true
484 });
485
486 changed
487 }
488
489 pub fn mark_read(&self) {
491 for key in self.deps.keys() {
492 if key.slot.generation.load(Ordering::Acquire) == key.generation {
494 let version = key.slot.version.load(Ordering::Acquire);
495 notify_scopes(*key, version);
496 }
497 }
498 }
499
500 pub fn read_scope(self, func: impl FnMut()) -> Self {
506 scopes_with(|stack| stack.borrow_mut().push(self));
507
508 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(func));
510
511 let deps = scopes_with(|stack| stack.borrow_mut().pop().unwrap()); if let Err(panic) = result {
514 std::panic::resume_unwind(panic);
515 }
516
517 deps
518 }
519}
520
521#[derive(Clone, Copy)]
526struct VarGuardMeta {
527 registry: &'static Registry,
528 slot: &'static Slot,
529 generation: u64,
530}
531
532impl VarGuardMeta {
533 #[inline]
534 fn key(&self) -> VarKey {
535 VarKey {
536 slot: self.slot,
537 generation: self.generation,
538 }
539 }
540}
541
542pub struct VarReadGuard<'a, T: ?Sized + Send + Sync + 'static> {
551 meta: VarGuardMeta,
552 guard: Option<MappedRwLockReadGuard<'a, T>>,
553 armed: bool,
554 _marker: PhantomData<*const ()>, }
556
557impl<'a, T: ?Sized + Send + Sync + 'static> Deref for VarReadGuard<'a, T> {
558 type Target = T;
559 fn deref(&self) -> &Self::Target {
560 self.guard.as_ref().unwrap() }
562}
563
564impl<'a, T: ?Sized + Send + Sync + 'static> Drop for VarReadGuard<'a, T> {
565 fn drop(&mut self) {
566 if !self.armed {
567 return;
568 }
569
570 let version = self.meta.slot.version.load(Ordering::Acquire);
571 drop(self.guard.take());
572 notify_scopes(self.meta.key(), version);
573 if self.meta.slot.generation.load(Ordering::Acquire) != self.meta.generation {
574 self.meta.slot.attempt_cleanup(self.meta.registry, self.meta.generation + 1);
575 }
576 }
577}
578
579impl<'a, T: ?Sized + Send + Sync + 'static> VarReadGuard<'a, T> {
580 pub fn map<U: ?Sized + Send + Sync + 'static>(mut this: Self, f: impl FnOnce(&T) -> &U) -> VarReadGuard<'a, U> {
584 let meta = this.meta;
585 let guard = this.guard.take().expect("mapped guard is missing");
586
587 let guard = MappedRwLockReadGuard::map(guard, f);
589
590 this.armed = false;
592
593 VarReadGuard {
594 meta,
595 guard: Some(guard),
596 armed: true,
597 _marker: PhantomData,
598 }
599 }
600
601 pub fn try_map<U: ?Sized + Send + Sync + 'static>(mut this: Self, f: impl FnOnce(&T) -> Option<&U>) -> Result<VarReadGuard<'a, U>, VarReadGuard<'a, T>> {
605 let meta = this.meta;
606 let guard = this.guard.take().expect("mapped guard is missing");
607
608 match MappedRwLockReadGuard::try_map(guard, f) {
609 Ok(mapped) => {
610 this.armed = false;
612
613 Ok(VarReadGuard {
614 meta,
615 guard: Some(mapped),
616 armed: true,
617 _marker: PhantomData,
618 })
619 }
620 Err(original) => {
621 this.guard = Some(original);
623 Err(this)
624 }
625 }
626 }
627
628 pub fn try_map_or_err<U: ?Sized + Send + Sync + 'static, E>(
632 mut this: Self,
633 f: impl FnOnce(&T) -> Result<&U, E>,
634 ) -> Result<VarReadGuard<'a, U>, (VarReadGuard<'a, T>, E)> {
635 let meta = this.meta;
636 let guard = this.guard.take().expect("mapped guard is missing");
637
638 let mut err: Option<E> = None;
639
640 let mapped = MappedRwLockReadGuard::try_map(guard, |t| match f(t) {
641 Ok(r) => Some(r),
642 Err(e) => {
643 err = Some(e);
644 None
645 }
646 });
647
648 match mapped {
649 Ok(mapped) => {
650 this.armed = false;
652
653 Ok(VarReadGuard {
654 meta,
655 guard: Some(mapped),
656 armed: true,
657 _marker: PhantomData,
658 })
659 }
660 Err(original) => {
661 this.guard = Some(original);
663 let e = err.expect("try_map_or_err failed without producing an error");
664 Err((this, e))
665 }
666 }
667 }
668}
669
670pub struct VarWriteGuard<'a, T: ?Sized + Send + Sync + 'static> {
684 meta: VarGuardMeta,
685 guard: Option<MappedRwLockWriteGuard<'a, T>>,
686 changed: bool,
687 armed: bool,
688 _marker: PhantomData<*const ()>, }
690
691impl<'a, T: ?Sized + Send + Sync + 'static> Deref for VarWriteGuard<'a, T> {
692 type Target = T;
693 fn deref(&self) -> &Self::Target {
694 self.guard.as_ref().unwrap() }
696}
697
698impl<'a, T: ?Sized + Send + Sync + 'static> DerefMut for VarWriteGuard<'a, T> {
699 fn deref_mut(&mut self) -> &mut Self::Target {
700 self.guard.as_mut().unwrap() }
702}
703
704impl<'a, T: ?Sized + Send + Sync + 'static> Drop for VarWriteGuard<'a, T> {
705 fn drop(&mut self) {
706 if !self.armed {
707 return;
708 }
709
710 let version = if self.changed {
711 self.meta.registry.write_count.fetch_add(1, Ordering::Release);
712 self.meta.slot.version.fetch_add(1, Ordering::Release) + 1
713 } else {
714 self.meta.slot.version.load(Ordering::Acquire)
715 };
716
717 drop(self.guard.take());
718 notify_scopes(self.meta.key(), version);
719 if self.meta.slot.generation.load(Ordering::Acquire) != self.meta.generation {
720 self.meta.slot.attempt_cleanup(self.meta.registry, self.meta.generation + 1);
721 }
722 }
723}
724
725impl<'a, T: ?Sized + Send + Sync + 'static> VarWriteGuard<'a, T> {
726 pub fn cancel_change(&mut self) {
730 self.changed = false;
731 }
732
733 pub fn map<U: ?Sized + Send + Sync + 'static>(mut this: Self, f: impl FnOnce(&mut T) -> &mut U) -> VarWriteGuard<'a, U> {
737 let meta = this.meta;
738 let changed = this.changed;
739 let guard = this.guard.take().expect("mapped guard is missing");
740
741 let guard = MappedRwLockWriteGuard::map(guard, f);
743
744 this.armed = false;
746
747 VarWriteGuard {
748 meta,
749 guard: Some(guard),
750 changed,
751 armed: true,
752 _marker: PhantomData,
753 }
754 }
755
756 pub fn try_map<U: ?Sized + Send + Sync + 'static>(
760 mut this: Self,
761 f: impl FnOnce(&mut T) -> Option<&mut U>,
762 ) -> Result<VarWriteGuard<'a, U>, VarWriteGuard<'a, T>> {
763 let meta = this.meta;
764 let changed = this.changed;
765 let guard = this.guard.take().expect("mapped guard is missing");
766
767 match MappedRwLockWriteGuard::try_map(guard, f) {
768 Ok(mapped) => {
769 this.armed = false;
771
772 Ok(VarWriteGuard {
773 meta,
774 guard: Some(mapped),
775 changed,
776 armed: true,
777 _marker: PhantomData,
778 })
779 }
780 Err(original) => {
781 this.guard = Some(original);
783 Err(this)
784 }
785 }
786 }
787
788 pub fn try_map_or_err<U: ?Sized + Send + Sync + 'static, E>(
792 mut this: Self,
793 f: impl FnOnce(&mut T) -> Result<&mut U, E>,
794 ) -> Result<VarWriteGuard<'a, U>, (VarWriteGuard<'a, T>, E)> {
795 let meta = this.meta;
796 let changed = this.changed;
797 let guard = this.guard.take().expect("mapped guard is missing");
798
799 let mut err: Option<E> = None;
800
801 let mapped = MappedRwLockWriteGuard::try_map(guard, |t| match f(t) {
802 Ok(r) => Some(r),
803 Err(e) => {
804 err = Some(e);
805 None
806 }
807 });
808
809 match mapped {
810 Ok(mapped) => {
811 this.armed = false;
813
814 Ok(VarWriteGuard {
815 meta,
816 guard: Some(mapped),
817 changed,
818 armed: true,
819 _marker: PhantomData,
820 })
821 }
822 Err(original) => {
823 this.guard = Some(original);
825 let e = err.expect("try_map_or_err failed without producing an error");
826 Err((this, e))
827 }
828 }
829 }
830}
831
832#[derive(Debug)]
833pub(crate) struct Slot {
834 pub(crate) generation: AtomicU64,
835 pub(crate) version: AtomicU64,
836 pub(crate) value: RwLock<Option<Box<dyn Any + Send + Sync>>>,
837}
838
839impl Slot {
840 fn new() -> Self {
841 Self {
842 generation: AtomicU64::new(0),
843 version: AtomicU64::new(0),
844 value: RwLock::new(None),
845 }
846 }
847
848 fn attempt_cleanup(&'static self, registry: &'static Registry, expected_gen: u64) {
849 if let Some(mut guard) = self.value.try_write()
851 && self.generation.load(Ordering::Acquire) == expected_gen
852 && guard.is_some()
853 {
854 let value = guard.take();
855 drop(guard);
856
857 struct RecycleGuard {
858 registry: &'static Registry,
859 slot: &'static Slot,
860 }
861
862 impl Drop for RecycleGuard {
863 fn drop(&mut self) {
864 self.registry.recycle_slot(self.slot);
865 }
866 }
867
868 let _recycle_guard = RecycleGuard { registry, slot: self };
869 drop(value);
870 }
871 }
872}
873
874#[cfg(not(loom))]
875std::thread_local! {
876 static READ_SCOPES: OnceCell<Rc<RefCell<Vec<DependencyMap>>>> = const { OnceCell::new() };
878}
879
880#[cfg(loom)]
882loom::thread_local! {
883 static READ_SCOPES: OnceCell<Rc<RefCell<Vec<DependencyMap>>>> = OnceCell::new();
884}
885
886fn notify_scopes(key: VarKey, version: u64) {
888 scopes_with(|stack| {
889 for vars in stack.borrow_mut().iter_mut() {
890 vars.record(key, version);
891 }
892 });
893}
894
895fn scopes_with<F, R>(f: F) -> R
897where
898 F: FnOnce(&Rc<RefCell<Vec<DependencyMap>>>) -> R,
899{
900 READ_SCOPES.with(|once| f(once.get_or_init(|| Rc::new(RefCell::new(Vec::new())))))
901}
902
903#[doc(hidden)]
906pub fn read_scopes_rc() -> Rc<RefCell<Vec<DependencyMap>>> {
907 scopes_with(|stack| stack.clone())
908}
909
910#[doc(hidden)]
913pub fn try_init_read_scopes(rc: Rc<RefCell<Vec<DependencyMap>>>) -> bool {
914 READ_SCOPES.with(|cell| cell.set(rc).is_ok())
915}
916
917#[doc(hidden)]
919pub struct Registry {
920 free_slots: Mutex<Vec<&'static Slot>>,
921 write_count: AtomicU64,
922}
923
924static GLOBAL_REGISTRY: OnceLock<&'static Registry> = OnceLock::new();
925
926impl Default for Registry {
927 fn default() -> Self {
928 Self {
929 free_slots: Mutex::new(Vec::new()),
930 write_count: AtomicU64::new(0),
931 }
932 }
933}
934
935impl Registry {
936 pub fn global() -> &'static Self {
938 GLOBAL_REGISTRY.get_or_init(|| Box::leak(Box::new(Self::default())))
939 }
940
941 pub fn set_global(&'static self) -> bool {
943 GLOBAL_REGISTRY.set(self).is_ok()
944 }
945
946 pub fn write_count(&self) -> u64 {
948 self.write_count.load(Ordering::Acquire)
949 }
950
951 fn alloc_slot(&self) -> (&'static Slot, u64) {
953 let mut free = self.free_slots.lock();
954 if let Some(slot) = free.pop() {
955 let next_gen = slot.generation.fetch_add(1, Ordering::Release) + 1;
956 (slot, next_gen)
957 } else {
958 let slot = Box::leak(Box::new(Slot::new()));
959 (slot, 0)
960 }
961 }
962
963 fn recycle_slot(&self, slot: &'static Slot) {
965 let mut free = self.free_slots.lock();
966 free.push(slot);
967 }
968}
969
970#[cfg(feature = "serde")]
971pub mod serde_impl {
972 use super::*;
973 use serde::{Deserialize, Deserializer, Serialize, Serializer, de, ser};
974 use std::cell::RefCell;
975
976 type SlotId = u64;
977
978 struct DeEntry {
979 slot: &'static Slot,
980 pending_generation: u64,
981 initialized: bool,
982 }
983
984 struct SerdeContext {
985 ser_map: HashMap<VarKey, SlotId>,
986 de_map: HashMap<SlotId, DeEntry>,
987 next_id: SlotId,
988 }
989
990 impl SerdeContext {
991 fn new() -> Self {
992 Self {
993 ser_map: HashMap::new(),
994 de_map: HashMap::new(),
995 next_id: 1, }
997 }
998
999 fn cleanup_uninitialized(self) {
1000 let registry = Registry::global();
1001
1002 for entry in self.de_map.into_values() {
1003 if entry.initialized {
1004 continue;
1005 }
1006
1007 entry.slot.generation.store(entry.pending_generation + 1, Ordering::Release);
1008 *entry.slot.value.write() = None;
1009 entry.slot.version.store(0, Ordering::Release);
1010 registry.recycle_slot(entry.slot);
1011 }
1012 }
1013 }
1014
1015 thread_local! {
1016 static CONTEXT: RefCell<Option<SerdeContext>> = const { RefCell::new(None) };
1017 }
1018
1019 pub fn serde_scope<R>(f: impl FnOnce() -> R) -> R {
1021 CONTEXT.with(|ctx| {
1022 let mut borrow = ctx.borrow_mut();
1023 if borrow.is_some() {
1024 panic!("nested serde_scope is not supported");
1025 }
1026 *borrow = Some(SerdeContext::new());
1027 });
1028
1029 struct ScopeGuard;
1030 impl Drop for ScopeGuard {
1031 fn drop(&mut self) {
1032 CONTEXT.with(|ctx| {
1033 let mut borrow = ctx.borrow_mut();
1034 if let Some(ctx) = borrow.take() {
1035 ctx.cleanup_uninitialized();
1036 }
1037 });
1038 }
1039 }
1040
1041 let _guard = ScopeGuard;
1042 f()
1043 }
1044
1045 fn resolve_id<S: Serializer, T>(v: &WeakVar<T>) -> Result<SlotId, S::Error>
1046 where
1047 T: Send + Sync + 'static,
1048 {
1049 if !v.is_alive() {
1050 return Ok(0);
1051 }
1052
1053 CONTEXT.with(|cell| {
1054 let mut borrow = cell.borrow_mut();
1055 let ctx = borrow.as_mut().ok_or_else(|| ser::Error::custom("Serialize called outside of a scope"))?;
1056
1057 let key = v.get_key();
1058 Ok(*ctx.ser_map.entry(key).or_insert_with(|| {
1059 let id = ctx.next_id;
1060 ctx.next_id += 1;
1061 id
1062 }))
1063 })
1064 }
1065
1066 fn resolve_handle<'de, D: Deserializer<'de>, T>(id: SlotId) -> Result<WeakVar<T>, D::Error>
1067 where
1068 T: Send + Sync + 'static,
1069 {
1070 let registry = Registry::global();
1071
1072 if id == 0 {
1073 static DEAD_SLOT: OnceLock<Slot> = OnceLock::new();
1074 let slot = DEAD_SLOT.get_or_init(|| Slot {
1075 generation: AtomicU64::new(1),
1076 version: AtomicU64::new(0),
1077 value: RwLock::new(None),
1078 });
1079
1080 return Ok(WeakVar {
1081 registry,
1082 slot,
1083 generation: 0,
1084 ty: PhantomData,
1085 });
1086 }
1087
1088 let (slot, pending_generation) = CONTEXT.with(|cell| {
1089 let mut borrow = cell.borrow_mut();
1090 let ctx = borrow.as_mut().ok_or_else(|| de::Error::custom("Deserialize called outside of a scope"))?;
1091
1092 if let Some(entry) = ctx.de_map.get(&id) {
1093 Ok((entry.slot, entry.pending_generation))
1094 } else {
1095 let (slot, generation) = registry.alloc_slot();
1096 let pending_generation = generation + 1;
1097
1098 ctx.de_map.insert(
1099 id,
1100 DeEntry {
1101 slot,
1102 pending_generation,
1103 initialized: false,
1104 },
1105 );
1106
1107 Ok((slot, pending_generation))
1108 }
1109 })?;
1110
1111 Ok(WeakVar {
1112 registry,
1113 slot,
1114 generation: pending_generation,
1115 ty: PhantomData,
1116 })
1117 }
1118
1119 impl<T> Serialize for Var<T>
1120 where
1121 T: Serialize + Send + Sync + 'static,
1122 {
1123 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1124 where
1125 S: Serializer,
1126 {
1127 if let Some(guard) = self.0.read() {
1128 let id = resolve_id::<S, T>(&self.0)?;
1129 (id, Some(&*guard)).serialize(serializer)
1130 } else {
1131 (0u64, Option::<T>::None).serialize(serializer)
1132 }
1133 }
1134 }
1135
1136 impl<'de, T> Deserialize<'de> for Var<T>
1137 where
1138 T: Deserialize<'de> + Send + Sync + 'static,
1139 {
1140 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1141 where
1142 D: Deserializer<'de>,
1143 {
1144 let (id, maybe_value) = <(SlotId, Option<T>)>::deserialize(deserializer)?;
1145
1146 let Some(val) = maybe_value else {
1147 let handle = resolve_handle::<D, T>(0)?;
1148 return Ok(Var(handle));
1149 };
1150
1151 let handle = resolve_handle::<D, T>(id)?;
1152 *handle.slot.value.write() = Some(Box::new(val));
1153 handle.slot.version.store(0, Ordering::Release);
1154 handle.slot.generation.store(handle.generation, Ordering::Release);
1155
1156 CONTEXT.with(|cell| {
1157 let mut borrow = cell.borrow_mut();
1158 let ctx = borrow.as_mut().expect("Deserialize called outside of a scope");
1159 if let Some(entry) = ctx.de_map.get_mut(&id) {
1160 entry.initialized = true;
1161 }
1162 });
1163
1164 Ok(Var(handle))
1165 }
1166 }
1167
1168 impl<T> Serialize for WeakVar<T>
1169 where
1170 T: Send + Sync + 'static,
1171 {
1172 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1173 where
1174 S: Serializer,
1175 {
1176 resolve_id::<S, T>(self)?.serialize(serializer)
1177 }
1178 }
1179
1180 impl<'de, T> Deserialize<'de> for WeakVar<T>
1181 where
1182 T: Send + Sync + 'static,
1183 {
1184 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1185 where
1186 D: Deserializer<'de>,
1187 {
1188 let id = SlotId::deserialize(deserializer)?;
1189 resolve_handle::<D, T>(id)
1190 }
1191 }
1192}