1#![doc = include_str!("../README.md")]
2#![allow(unsafe_code)]
3
4#[doc(hidden)]
5pub mod __support {
6 pub use crate::__in_section_crate as in_section_crate;
7 pub use crate::__in_section_parse as in_section_parse;
8 pub use crate::__section_name as section_name;
9 pub use crate::__section_parse as section_parse;
10
11 pub use link_section_proc_macro::hash;
12 pub use link_section_proc_macro::ident_concat;
13
14 #[cfg(target_vendor = "apple")]
15 #[macro_export]
16 #[doc(hidden)]
17 macro_rules! __section_name {
18 ($pattern:tt data $($rest:tt)*) => {
19 $crate::__support::section_name!(__ $pattern symbol "__DATA" $($rest)*);
20 };
21 ($pattern:tt code $($rest:tt)*) => {
22 $crate::__support::section_name!(__ $pattern symbol "__TEXT" $($rest)*);
23 };
24 ($pattern:tt $unknown_section:ident $($rest:tt)*) => {
25 const _: () = {
26 compile_error!("Unknown section type: `{}`", stringify!($unknown_section));
27 };
28 };
29
30 (__ $pattern:tt symbol $section_prefix:literal bare $name:ident) => {
31 $crate::__support::section_name!(__ $pattern hash ($section_prefix ",") () $name);
32 };
33 (__ $pattern:tt symbol $section_prefix:literal section $name:ident) => {
34 $crate::__support::section_name!(__ $pattern hash ($section_prefix ",") (",regular,no_dead_strip") $name);
35 };
36 (__ $pattern:tt symbol $section_prefix:literal start $name:ident) => {
37 $crate::__support::section_name!(__ $pattern hash ("\x01section$start$" $section_prefix "$") () $name);
39 };
40 (__ $pattern:tt symbol $section_prefix:literal end $name:ident) => {
41 $crate::__support::section_name!(__ $pattern hash ("\x01section$end$" $section_prefix "$") ()$name);
42 };
43
44 (__ $pattern:tt hash $prefix:tt $suffix:tt $name:ident) => {
45 $crate::__support::hash!($pattern $name $prefix $suffix 6 16 "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
46 };
47 }
48
49 #[cfg(target_family = "wasm")]
50 #[macro_export]
51 #[doc(hidden)]
52 macro_rules! __section_name {
53 ($pattern:tt data $($rest:tt)*) => {
54 $crate::__support::section_name!(__ $pattern symbol ".data" $($rest)*);
55 };
56 ($pattern:tt code $($rest:tt)*) => {
57 $crate::__support::section_name!(__ $pattern symbol ".text" $($rest)*);
58 };
59 ($pattern:tt $unknown_section:ident $($rest:tt)*) => {
60 const _: () = {
61 compile_error!("Unknown section type: `{}`", stringify!($unknown_section));
62 };
63 };
64
65 (__ $pattern:tt symbol $section_prefix:literal bare $name:ident) => {
66 $crate::__support::section_name!(__ $pattern hash ($section_prefix ".link_section.") () $name);
67 };
68 (__ $pattern:tt symbol $section_prefix:literal section $name:ident) => {
69 $crate::__support::section_name!(__ $pattern hash ($section_prefix ".link_section.") () $name);
70 };
71
72 (__ $pattern:tt hash $prefix:tt $suffix:tt $name:ident) => {
73 $crate::__support::hash!($pattern $name $prefix $suffix 6 16 "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
74 };
75 }
76
77 #[cfg(all(
78 not(target_vendor = "apple"),
79 not(target_vendor = "pc"),
80 not(target_family = "wasm")
81 ))]
82 #[macro_export]
83 #[doc(hidden)]
84 macro_rules! __section_name {
85 ($pattern:tt data $($rest:tt)*) => {
86 $crate::__support::section_name!(__ $pattern symbol "_data" $($rest)*);
87 };
88 ($pattern:tt code $($rest:tt)*) => {
89 $crate::__support::section_name!(__ $pattern symbol "_text" $($rest)*);
90 };
91 ($pattern:tt $unknown_section:ident $($rest:tt)*) => {
92 const _: () = {
93 compile_error!("Unknown section type: `{}`", stringify!($unknown_section));
94 };
95 };
96
97 (__ $pattern:tt symbol $section_prefix:literal bare $name:ident) => {
100 $crate::__support::section_name!(__ $pattern hash ($section_prefix "_link_section_") () $name);
101 };
102 (__ $pattern:tt symbol $section_prefix:literal section $name:ident) => {
103 $crate::__support::section_name!(__ $pattern hash ($section_prefix "_link_section_") () $name);
104 };
105 (__ $pattern:tt symbol $section_prefix:literal start $name:ident) => {
106 $crate::__support::section_name!(__ $pattern hash ("__start_" $section_prefix "_link_section_") () $name);
107 };
108 (__ $pattern:tt symbol $section_prefix:literal end $name:ident) => {
109 $crate::__support::section_name!(__ $pattern hash ("__stop_" $section_prefix "_link_section_") () $name);
110 };
111
112 (__ $pattern:tt hash $prefix:tt $suffix:tt $name:ident) => {
113 $crate::__support::hash!($pattern $name $prefix $suffix 10 64 "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
114 };
115 }
116
117 #[cfg(target_vendor = "pc")]
118 #[macro_export]
119 #[doc(hidden)]
120 macro_rules! __section_name {
121 ($pattern:tt data $($rest:tt)*) => {
122 $crate::__support::section_name!(__ $pattern symbol ".data" $($rest)*);
123 };
124 ($pattern:tt code $($rest:tt)*) => {
125 $crate::__support::section_name!(__ $pattern symbol ".text" $($rest)*);
126 };
127 ($pattern:tt $unknown_section:ident $($rest:tt)*) => {
128 const _: () = {
129 compile_error!("Unknown section type: `{}`", stringify!($unknown_section));
130 };
131 };
132
133 (__ $pattern:tt symbol $section_prefix:literal bare $name:ident) => {
134 $crate::__support::section_name!(__ $pattern hash ($section_prefix "$") () $name);
135 };
136 (__ $pattern:tt symbol $section_prefix:literal section $name:ident) => {
137 $crate::__support::section_name!(__ $pattern hash ($section_prefix "$") ("$b") $name);
138 };
139 (__ $pattern:tt symbol $section_prefix:literal start $name:ident) => {
140 $crate::__support::section_name!(__ $pattern hash ($section_prefix "$") ("$a") $name);
141 };
142 (__ $pattern:tt symbol $section_prefix:literal end $name:ident) => {
143 $crate::__support::section_name!(__ $pattern hash ($section_prefix "$") ("$c") $name);
144 };
145
146 (__ $pattern:tt hash $prefix:tt $suffix:tt $name:ident) => {
147 $crate::__support::hash!($pattern $name $prefix $suffix 10 64 "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
148 };
149 }
150
151 #[macro_export]
153 #[doc(hidden)]
154 macro_rules! __section_parse {
155 (#[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* < $($generic:tt)*) => {
157 $crate::__section_parse!(#[section] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* < $($generic)*) ( $($generic)* ) generic);
158 };
159 (#[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* ;) => {
161 $crate::__section_parse!(#[section] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* ;) ( () > ; ) no_generic);
162 };
163 (#[section] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic:ident) => {
165 macro_rules! $ident {
167 (v=0 (item=$item:tt $rest:tt)) => {
168 $crate::__support::in_section_crate!($ident $generic $ty, $item);
169 };
170 (v=$v:literal $rest:tt) => {
171 const _: () = { compile_error!(concat!("link-section: Unsupported version: `", stringify!($v), "`")); };
172 };
173 }
174
175 $(#[$meta])*
176 #[used]
177 #[cfg(target_family = "wasm")]
178 $vis static $ident: $crate::__support::Section< $ty, $generic_ty > = {
179 static __START: ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>> = unsafe {
180 ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>>::new(::core::ptr::null_mut())
181 };
182 static __END: ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>> = unsafe {
183 ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>>::new(::core::ptr::null_mut())
184 };
185
186 $crate::__support::ident_concat!((#[no_mangle]pub extern "C" fn) (register_link_section_ $ident) ((data_ptr: *const u8, data_len: usize) {
187 unsafe {
188 __START.store(data_ptr as *mut ::core::marker::PhantomData<$generic_ty>, ::core::sync::atomic::Ordering::Relaxed);
189 __END.store(data_ptr.add(data_len) as *mut ::core::marker::PhantomData<$generic_ty>, ::core::sync::atomic::Ordering::Relaxed);
190 }
191 }));
192
193 $crate::__support::Section::new(
194 stringify!($ident),
195 &__START,
196 &__END,
197 )
198 };
199
200 $(#[$meta])*
201 #[used]
202 #[cfg(not(target_family = "wasm"))]
203 $vis static $ident: $crate::__support::Section< $ty, $generic_ty > = $crate::__support::Section::new(
204 {
205 $crate::__support::section_name!(
206 (const fn section_name() -> &'static str { __ })
207 data bare $ident
208 );
209
210 section_name()
211 },
212 {
213 #[cfg(not(target_vendor = "pc"))]
214 $crate::__support::section_name!(
215 (
216 extern "C" {
217 #[link_name = __] static __START: $crate::__support::SectionPtr<$generic_ty>;
218 }
219 )
220 data start $ident
221 );
222
223 #[cfg(target_vendor = "pc")]
225 $crate::__support::section_name!(
226 (
227 #[link_section = __]
228 #[used]
229 static __START: [$generic_ty; 0] = [];
230 )
231 data start $ident
232 );
233
234 unsafe { &raw const __START as $crate::__support::SectionPtr<$generic_ty> }
235 },
236 {
237 #[cfg(not(target_vendor = "pc"))]
238 $crate::__support::section_name!(
239 (
240 extern "C" {
241 #[link_name = __] static __END: $crate::__support::SectionPtr<$generic_ty>;
242 }
243 )
244 data end $ident
245 );
246
247 #[cfg(target_vendor = "pc")]
248 $crate::__support::section_name!(
249 (
250 #[link_section = __]
251 #[used]
252 static __END: [$generic_ty; 0] = [];
253 )
254 data end $ident
255 );
256
257 unsafe { &raw const __END as $crate::__support::SectionPtr<$generic_ty> }
258 },
259 );
260 };
261 }
262
263 #[macro_export]
265 #[doc(hidden)]
266 macro_rules! __in_section_parse {
267 (#[in_section($name:path)] $($item:tt)*) => {
268 $name ! (
269 v=0 (item=($($item)*) ())
270 );
271 };
272 }
273
274 #[macro_export]
275 #[doc(hidden)]
276 #[allow(unknown_lints, edition_2024_expr_fragment_specifier)]
277 macro_rules! __in_section_crate {
278 ($ident:ident generic $section_ty:ty, ($(#[$meta:meta])* $vis:vis fn $ident_fn:ident($($args:tt)*) $(-> $ret:ty)? $body:block)) => {
279 $crate::__support::section_name!(
280 (
281 $(#[$meta])*
283 #[used]
284 #[link_section = __]
285 #[allow(non_upper_case_globals)]
286 $vis static $ident_fn: <$section_ty as $crate::__support::SectionItemType>::Item =
287 {
288 fn $ident_fn($($args)*) $(-> $ret)? $body
289 $ident_fn as <$section_ty as $crate::__support::SectionItemType>::Item
290 };
291 )
292 data section $ident
293 );
294 };
295 ($ident:ident generic $section_ty:ty, ($(#[$meta:meta])* $vis:vis static $ident_static:ident : $ty:ty = $value:expr;)) => {
296 $crate::__support::section_name!(
297 ($(#[$meta])* #[link_section = __] #[used] $vis static $ident_static: <$section_ty as $crate::__support::SectionItemType>::Item = $value;)
298 data section $ident
299 );
300 };
301 ($ident:ident no_generic $section_ty:ty, ($(#[$meta:meta])* $vis:vis fn $ident_fn:ident($($args:tt)*) $(-> $ret:ty)? $body:block)) => {
302 $crate::__support::section_name!(
303 (
304 $(#[$meta])*
305 #[link_section = __]
306 #[used]
307 #[allow(non_upper_case_globals)]
308 $vis static $ident_fn: fn($($args)*) $(-> $ret)? =
309 {
310 $crate::__support::section_name!(
311 (#[link_section = __] fn $ident_fn($($args)*) $(-> $ret)? $body)
312 code section $ident
313 );
314 $ident_fn
315 };
316 )
317 data section $ident
318 );
319 };
320 ($ident:ident no_generic $section_ty:ty, ($(#[$meta:meta])* $item:item)) => {
321 $crate::__support::section_name!(
322 ($(#[$meta])* #[link_section = __] #[used] $item)
323 data section $ident
324 );
325 };
326 }
327
328 pub trait SectionItemType {
329 type Item;
330 }
331
332 #[repr(C)]
333 pub struct Section<T: sealed::FromRawSection, S: 'static> {
334 name: &'static str,
335 start: SectionPtr<S>,
336 end: SectionPtr<S>,
337 _t: ::core::marker::PhantomData<T>,
338 }
339
340 impl<T> SectionItemType for super::TypedSection<T> {
341 type Item = T;
342 }
343
344 impl<T: sealed::FromRawSection, S> Section<T, S> {
345 pub const fn new(name: &'static str, start: SectionPtr<S>, end: SectionPtr<S>) -> Self {
346 Self {
347 name,
348 start,
349 end,
350 _t: ::core::marker::PhantomData,
351 }
352 }
353 }
354
355 impl<'a, T: sealed::FromRawSection, S> ::core::iter::IntoIterator for &'a Section<T, S>
356 where
357 for<'b> &'b T: ::core::iter::IntoIterator,
358 {
359 type Item = <&'a T as ::core::iter::IntoIterator>::Item;
360 type IntoIter = <&'a T as ::core::iter::IntoIterator>::IntoIter;
361 fn into_iter(self) -> Self::IntoIter {
362 ::core::ops::Deref::deref(self).into_iter()
363 }
364 }
365
366 impl<T: sealed::FromRawSection, S> ::core::ops::Deref for Section<T, S> {
367 type Target = T;
368 fn deref(&self) -> &Self::Target {
369 unsafe { ::core::mem::transmute(self) }
371 }
372 }
373
374 impl<T: sealed::FromRawSection + ::core::fmt::Debug, S> ::core::fmt::Debug for Section<T, S> {
375 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
376 ::core::fmt::Debug::fmt(::core::ops::Deref::deref(self), f)
377 }
378 }
379
380 unsafe impl<T: sealed::FromRawSection, S> Sync for Section<T, S> {}
381 unsafe impl<T: sealed::FromRawSection, S> Send for Section<T, S> {}
382
383 #[cfg(all(not(target_vendor = "pc"), not(target_family = "wasm")))]
386 pub type SectionPtr<T> = *const ::core::marker::PhantomData<T>;
387 #[cfg(target_vendor = "pc")]
391 pub type SectionPtr<T> = *const [T; 0];
392 #[cfg(target_family = "wasm")]
394 pub type SectionPtr<T> =
395 &'static ::core::sync::atomic::AtomicPtr<::core::marker::PhantomData<T>>;
396
397 mod sealed {
398 pub trait FromRawSection {}
399
400 impl FromRawSection for crate::Section {}
401
402 impl<T> FromRawSection for crate::TypedSection<T> {}
403 }
404}
405
406pub use ::link_section_proc_macro::section;
421
422pub use ::link_section_proc_macro::in_section;
429
430#[repr(C)]
433pub struct Section {
434 name: &'static str,
435 start: __support::SectionPtr<()>,
436 end: __support::SectionPtr<()>,
437}
438
439#[cfg(target_family = "wasm")]
440impl Section {
441 pub fn start_ptr(&self) -> *const () {
443 let ptr = self.start.load(::core::sync::atomic::Ordering::Relaxed) as *const ();
444 if ptr.is_null() {
445 panic!(
446 "Section {} was not initialized by the host environment",
447 self.name
448 );
449 }
450 ptr
451 }
452 pub fn end_ptr(&self) -> *const () {
454 let ptr = self.end.load(::core::sync::atomic::Ordering::Relaxed) as *const ();
455 if ptr.is_null() {
456 panic!(
457 "Section {} was not initialized by the host environment",
458 self.name
459 );
460 }
461 ptr
462 }
463 pub fn byte_len(&self) -> usize {
465 unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
466 }
467}
468
469#[cfg(not(target_family = "wasm"))]
470impl Section {
471 pub const fn start_ptr(&self) -> *const () {
473 self.start as *const ()
474 }
475 pub const fn end_ptr(&self) -> *const () {
477 self.end as *const ()
478 }
479 pub const fn byte_len(&self) -> usize {
481 unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
482 }
483}
484
485impl ::core::fmt::Debug for Section {
486 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
487 f.debug_struct("Section")
488 .field("name", &self.name)
489 .field("start", &self.start_ptr())
490 .field("end", &self.end_ptr())
491 .field("byte_len", &self.byte_len())
492 .finish()
493 }
494}
495
496unsafe impl Sync for Section {}
497unsafe impl Send for Section {}
498
499#[repr(C)]
502pub struct TypedSection<T: 'static> {
503 name: &'static str,
504 start: __support::SectionPtr<T>,
505 end: __support::SectionPtr<T>,
506 _phantom: ::core::marker::PhantomData<T>,
507}
508
509#[cfg(target_family = "wasm")]
510impl<T: 'static> TypedSection<T> {
511 pub const fn stride(&self) -> usize {
513 #[repr(C)]
516 struct Sizer<T> {
517 t1: T,
518 t2: T,
519 t3: T,
520 }
521
522 let sizer = ::core::mem::MaybeUninit::<Sizer<T>>::uninit();
523 let ptr: *const Sizer<T> = sizer.as_ptr();
524 let start = ptr as *const u8;
525 let end = unsafe { ::core::ptr::addr_of!((*ptr).t3) } as *const u8;
526 unsafe { end.offset_from(start) as usize / 2 }
527 }
528
529 pub fn start_ptr(&self) -> *const T {
531 let ptr = self.start.load(::core::sync::atomic::Ordering::Relaxed) as *const T;
532 if ptr.is_null() {
533 panic!(
534 "TypedSection {} was not initialized by the host environment",
535 self.name
536 );
537 }
538 ptr
539 }
540
541 pub fn end_ptr(&self) -> *const T {
543 let ptr = self.end.load(::core::sync::atomic::Ordering::Relaxed) as *const T;
544 if ptr.is_null() {
545 panic!(
546 "TypedSection {} was not initialized by the host environment",
547 self.name
548 );
549 }
550 ptr
551 }
552
553 pub fn byte_len(&self) -> usize {
555 unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
556 }
557
558 pub fn len(&self) -> usize {
560 self.byte_len() / self.stride()
561 }
562
563 pub fn is_empty(&self) -> bool {
565 self.len() == 0
566 }
567
568 pub fn as_slice(&self) -> &[T] {
570 if self.is_empty() {
571 &[]
572 } else {
573 unsafe { ::core::slice::from_raw_parts(self.start_ptr(), self.len()) }
574 }
575 }
576}
577
578#[cfg(not(target_family = "wasm"))]
579impl<T: 'static> TypedSection<T> {
580 pub const fn stride(&self) -> usize {
582 #[repr(C)]
585 struct Sizer<T> {
586 t1: T,
587 t2: T,
588 t3: T,
589 }
590
591 let sizer = ::core::mem::MaybeUninit::<Sizer<T>>::uninit();
592 let ptr: *const Sizer<T> = sizer.as_ptr();
593 let start = ptr as *const u8;
594 let end = unsafe { ::core::ptr::addr_of!((*ptr).t3) } as *const u8;
595 unsafe { end.offset_from(start) as usize / 2 }
596 }
597
598 pub const fn start_ptr(&self) -> *const T {
600 self.start as *const T
601 }
602
603 pub const fn end_ptr(&self) -> *const T {
605 self.end as *const T
606 }
607
608 pub const fn byte_len(&self) -> usize {
610 unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
611 }
612
613 pub const fn len(&self) -> usize {
615 self.byte_len() / self.stride()
616 }
617
618 pub const fn is_empty(&self) -> bool {
620 self.len() == 0
621 }
622
623 pub const fn as_slice(&self) -> &[T] {
625 if self.is_empty() {
626 &[]
627 } else {
628 unsafe { ::core::slice::from_raw_parts(self.start_ptr(), self.len()) }
629 }
630 }
631}
632
633impl<'a, T> ::core::iter::IntoIterator for &'a TypedSection<T> {
634 type Item = &'a T;
635 type IntoIter = ::core::slice::Iter<'a, T>;
636 fn into_iter(self) -> Self::IntoIter {
637 self.as_slice().iter()
638 }
639}
640
641impl<T> ::core::ops::Deref for TypedSection<T> {
642 type Target = [T];
643 fn deref(&self) -> &Self::Target {
644 self.as_slice()
645 }
646}
647
648impl<T> ::core::fmt::Debug for TypedSection<T> {
649 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
650 f.debug_struct("TypedSection")
651 .field("name", &self.name)
652 .field("start", &self.start_ptr())
653 .field("end", &self.end_ptr())
654 .field("len", &self.len())
655 .field("stride", &self.stride())
656 .finish()
657 }
658}
659
660unsafe impl<T> Sync for TypedSection<T> where T: Sync {}
661unsafe impl<T> Send for TypedSection<T> where T: Send {}