1use core::{
2 alloc::Layout,
3 marker::PhantomData,
4 ops::{Deref, DerefMut},
5 ptr::{NonNull, addr_of},
6};
7
8use crate::scope::{ActiveScope, Scope};
9
10#[doc(hidden)]
11pub struct Item {
12 pub layout: Layout,
13 pub init: fn(NonNull<()>),
14 pub drop: fn(NonNull<()>),
15}
16
17pub(crate) struct Registry;
18
19impl Deref for Registry {
20 type Target = [Item];
21
22 fn deref(&self) -> &Self::Target {
23 unsafe extern "Rust" {
24 static __start_scope_local: Item;
25 static __stop_scope_local: Item;
26 }
27 let start = addr_of!(__start_scope_local) as usize;
28 let len = (addr_of!(__stop_scope_local) as usize - start) / core::mem::size_of::<Item>();
29 unsafe { core::slice::from_raw_parts(start as *const Item, len) }
30 }
31}
32
33impl Item {
34 #[inline]
35 pub(crate) fn index(&'static self) -> usize {
36 unsafe { (self as *const Item).offset_from_unsigned(Registry.as_ptr()) }
37 }
38}
39
40pub struct LocalItem<T> {
42 item: &'static Item,
43 _p: PhantomData<T>,
44}
45
46impl<T> LocalItem<T> {
47 #[doc(hidden)]
48 #[inline]
49 pub const fn new(item: &'static Item) -> Self {
50 Self {
51 item,
52 _p: PhantomData,
53 }
54 }
55
56 pub fn scope<'scope>(&self, scope: &'scope Scope) -> ScopeItem<'scope, T> {
58 ScopeItem {
59 item: self.item,
60 scope,
61 _p: PhantomData,
62 }
63 }
64
65 pub fn scope_mut<'scope>(&self, scope: &'scope mut Scope) -> ScopeItemMut<'scope, T> {
67 ScopeItemMut {
68 item: self.item,
69 scope,
70 _p: PhantomData,
71 }
72 }
73}
74
75impl<T> Deref for LocalItem<T> {
76 type Target = T;
77
78 #[inline]
79 fn deref(&self) -> &Self::Target {
80 ActiveScope::get(self.item).as_ref()
81 }
82}
83
84pub struct ScopeItem<'scope, T> {
88 item: &'static Item,
89 scope: &'scope Scope,
90 _p: PhantomData<T>,
91}
92
93impl<'scope, T> Deref for ScopeItem<'scope, T> {
94 type Target = T;
95
96 #[inline]
97 fn deref(&self) -> &Self::Target {
98 self.scope.get(self.item).as_ref()
99 }
100}
101
102pub struct ScopeItemMut<'scope, T> {
106 item: &'static Item,
107 scope: &'scope mut Scope,
108 _p: PhantomData<T>,
109}
110
111impl<'scope, T> Deref for ScopeItemMut<'scope, T> {
112 type Target = T;
113
114 #[inline]
115 fn deref(&self) -> &Self::Target {
116 self.scope.get(self.item).as_ref()
117 }
118}
119
120impl<'scope, T> DerefMut for ScopeItemMut<'scope, T> {
121 #[inline]
122 fn deref_mut(&mut self) -> &mut Self::Target {
123 self.scope.get_mut(self.item).as_mut()
124 }
125}
126
127#[macro_export]
142macro_rules! scope_local {
143 ( $( $(#[$attr:meta])* $vis:vis static $name:ident: $ty:ty = $default:expr; )+ ) => {
144 $(
145 $(#[$attr])*
146 $vis static $name: $crate::LocalItem<$ty> = {
147 #[unsafe(link_section = "scope_local")]
148 static ITEM: $crate::Item = $crate::Item {
149 layout: core::alloc::Layout::new::<$ty>(),
150 init: |ptr| {
151 let val: $ty = $default;
152 unsafe { ptr.cast().write(val) }
153 },
154 drop: |ptr| unsafe {
155 ptr.cast::<$ty>().drop_in_place();
156 },
157 };
158
159 $crate::LocalItem::new(&ITEM)
160 };
161 )+
162 }
163}