1#![doc = include_str!("../README.md")]
2#![allow(unsafe_code)]
3
4pub mod declarative {
11 pub use crate::__in_section_parse as in_section;
12 pub use crate::__section_parse as section;
13}
14
15#[doc(hidden)]
16pub mod __support {
17 pub use crate::__add_section_link_attribute as add_section_link_attribute;
18 pub use crate::__def_section_name as def_section_name;
19 pub use crate::__get_section as get_section;
20 pub use crate::__in_section_crate as in_section_crate;
21 pub use crate::__in_section_parse as in_section_parse;
22 pub use crate::__section_parse as section_parse;
23
24 #[cfg(feature = "proc_macro")]
25 pub use link_section_proc_macro::hash;
26 #[cfg(feature = "proc_macro")]
27 pub use link_section_proc_macro::ident_concat;
28
29 #[macro_export]
31 #[doc(hidden)]
32 macro_rules! __def_section_name {
33 (
34 {$(
35 $__section:ident $__type:ident => $__prefix:tt __ $__suffix:tt;
36 )*}
37 AUXILIARY = $__aux_sep:literal;
38 MAX_LENGTH = $__max_length:literal;
39 HASH_LENGTH = $__hash_length:literal;
40 VALID_SECTION_CHARS = $__valid_section_chars:literal;
41 ) => {
42 #[macro_export]
44 #[doc(hidden)]
45 macro_rules! __section_name {
46 $(
47 (raw $__section $__type $name:ident) => {
48 concat!(concat! $__prefix, stringify!($name), concat! $__suffix);
49 };
50 (raw $__section $__type $name:ident $aux:ident) => {
51 concat!(concat! $__prefix, stringify!($name), $__aux_sep, stringify!($aux), concat! $__suffix);
52 };
53 ($pattern:tt $__section $__type $name:ident) => {
54 $crate::__support::hash!($pattern ($__prefix) $name ($__suffix) $__hash_length $__max_length $__valid_section_chars);
55 };
56 ($pattern:tt $__section $__type $name:ident $aux:ident) => {
57 $crate::__support::hash!($pattern ($__prefix) ($name $__aux_sep $aux) ($__suffix) $__hash_length $__max_length $__valid_section_chars);
58 };
59 )*
60 ($pattern:tt $unknown_section:ident $unknown_type:ident $name:ident) => {
61 const _: () = {
62 compile_error!("Unknown section type: `{}`/`{}`", stringify!($unknown_section), stringify!($unknown_type));
63 };
64 };
65 }
66 };
67 }
68
69 #[cfg(feature = "proc_macro")]
70 #[doc(hidden)]
71 #[macro_export]
72 macro_rules! __add_section_link_attribute(
73 ($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __] $item:item) => {
74 $crate::__section_name!(
75 (#[$attr = __] #[allow(unsafe_code)] $item)
76 $section $type $name $($aux)?
77 );
78 }
79 );
80
81 #[cfg(not(feature = "proc_macro"))]
82 #[doc(hidden)]
83 #[macro_export]
84 macro_rules! __add_section_link_attribute(
85 ($section:ident $type:ident $name:ident #[$attr:ident = __] $item:item) => {
86 #[$attr = $crate::__section_name!(
87 raw $section $type $name
88 )] $item
89 }
90 );
91
92 #[cfg(target_vendor = "apple")]
94 def_section_name! {
95 {
96 data bare => ("__DATA,") __ ();
97 code bare => ("__TEXT,") __ ();
98 data section => ("__DATA,") __ (",regular,no_dead_strip");
99 code section => ("__TEXT,") __ (",regular,no_dead_strip");
100 data start => ("\x01section$start$__DATA$") __ ();
101 data end => ("\x01section$end$__DATA$") __ ();
102 }
103 AUXILIARY = "_";
104 MAX_LENGTH = 16;
105 HASH_LENGTH = 6;
106 VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
107 }
108
109 #[cfg(target_family = "wasm")]
110 def_section_name! {
111 {
112 data bare => (".data", ".link_section.") __ ();
113 data section => (".data", ".link_section.") __ ();
114 code bare => (".text", ".link_section.") __ ();
115 code section => (".text", ".link_section.") __ ();
116 }
117 AUXILIARY = ".";
118 MAX_LENGTH = 16;
119 HASH_LENGTH = 6;
120 VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
121 }
122
123 #[cfg(all(
124 not(target_vendor = "apple"),
125 not(target_vendor = "pc"),
126 not(target_family = "wasm")
127 ))]
128 def_section_name! {
129 {
130 data bare => ("_data", "_link_section_") __ ();
131 data section => ("_data", "_link_section_") __ ();
132 data start => ("__start_", "_data", "_link_section_") __ ();
133 data end => ("__stop_", "_data", "_link_section_") __ ();
134 code bare => ("_text", "_link_section_") __ ();
135 code section => ("_text", "_link_section_") __ ();
136 code start => ("__start_", "_text", "_link_section_") __ ();
137 code end => ("__stop_", "_text", "_link_section_") __ ();
138 }
139 AUXILIARY = "_";
140 MAX_LENGTH = 64;
141 HASH_LENGTH = 10;
142 VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
143 }
144
145 #[cfg(target_vendor = "pc")]
146 def_section_name! {
147 {
148 data bare => (".data", "$") __ ();
149 data section => (".data", "$") __ ("$b");
150 data start => (".data", "$") __ ("$a");
151 data end => (".data", "$") __ ("$c");
152 code bare => (".text", "$") __ ();
153 code section => (".text", "$") __ ("$b");
154 code start => (".text", "$") __ ("$a");
155 code end => (".text", "$") __ ("$c");
156 }
157 AUXILIARY = "$d$";
158 MAX_LENGTH = 64;
159 HASH_LENGTH = 10;
160 VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
161 }
162
163 #[cfg(not(feature = "proc_macro"))]
164 #[doc(hidden)]
165 #[macro_export]
166 macro_rules! __declare_macro {
167 ($vis:vis $ident:ident $generic_macro:ident $args:tt) => {
168 #[doc(hidden)]
171 $vis use $crate::$generic_macro as $ident;
172 };
173 }
174
175 #[cfg(feature = "proc_macro")]
176 #[doc(hidden)]
177 #[macro_export]
178 macro_rules! __declare_macro {
179 ($vis:vis $ident:ident $generic_macro:ident $args:tt) => {
180 $crate::__support::ident_concat!(
181 (#[macro_export]
182 #[doc(hidden)]
183 macro_rules!) (__ $ident __link_section_private_macro__) ({
184 ($passthru:tt) => {
185 $crate::$generic_macro!($passthru $args);
186 };
187 })
188 );
189
190 $crate::__support::ident_concat!(
191 (#[doc(hidden)] pub use) (__ $ident __link_section_private_macro__) (as $ident;)
192 );
193 }
194 }
195
196 #[macro_export]
198 #[doc(hidden)]
199 macro_rules! __section_parse {
200 (#[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* < $($generic:tt)*) => {
202 $crate::__section_parse!(@parsed #[section $($args)*] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* < $($generic)*) ( $($generic)* ) __in_section_helper_macro_generic);
203 };
204 (#[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* ;) => {
206 $crate::__section_parse!(@parsed #[section $($args)*] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* ;) ( () > ; ) __in_section_helper_macro_no_generic);
207 };
208 (@parsed #[section(aux = $name:ident, no_macro)] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
210 $crate::__section_parse!(@generate #[section(aux = $name)] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
211 };
212 (@parsed #[section(no_macro)] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
213 $crate::__section_parse!(@generate #[section] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
214 };
215 (@parsed #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
216 $crate::__declare_macro!($vis $ident $generic_macro ($($args)*));
217 $crate::__section_parse!(@generate #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
218 };
219 (@generate #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __in_section_helper_macro_generic) => {
220 $crate::__section_parse!(@generate #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, __base_case__);
221
222 impl ::core::iter::IntoIterator for $ident {
223 type Item = &'static $generic_ty;
224 type IntoIter = ::core::slice::Iter<'static, $generic_ty>;
225 fn into_iter(self) -> Self::IntoIter {
226 $ident.as_slice().iter()
227 }
228 }
229 };
230 (@generate #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, $generic_macro:ident) => {
231 $(#[$meta])*
232 #[allow(non_camel_case_types)]
233 $vis struct $ident;
234
235 impl $crate::__support::SectionItemType for $ident {
236 type Item = $generic_ty;
237 }
238
239 impl ::core::fmt::Debug for $ident {
240 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
241 ::core::ops::Deref::deref(self).fmt(f)
242 }
243 }
244
245 impl ::core::ops::Deref for $ident {
246 type Target = $ty;
247 fn deref(&self) -> &Self::Target {
248 self.const_deref()
249 }
250 }
251
252 $crate::__section_parse!(@deref #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, __base_case__);
253 };
254 (@deref #[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __base_case__) => {
255 impl $ident {
256 pub const fn const_deref(&self) -> &$ty {
259 static SECTION: $ty = {
260 let section = $crate::__support::get_section!(name=$ident, type=$generic_ty, aux=);
261 let name = $crate::__section_name!(
262 raw data bare $ident
263 );
264 unsafe { <$ty>::new(name, section.0, section.1) }
265 };
266 &SECTION
267 }
268 }
269 };
270 (@deref #[section(aux=$aux:ident)] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __base_case__) => {
271 impl $ident {
272 pub const fn const_deref(&self) -> &$ty {
275 static SECTION: $ty = {
276 let section = $crate::__support::get_section!(name=$ident, type=$generic_ty, aux=$aux);
277 let name = $crate::__section_name!(
278 raw data bare $aux $ident );
280 unsafe { <$ty>::new(name, section.0, section.1) }
281 };
282 &SECTION
283 }
284 }
285 };
286 }
287
288 #[cfg(miri)]
289 mod section {
290 #[doc(hidden)]
291 #[macro_export]
292 macro_rules! __get_section {
293 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {{
294 (std::ptr::null_mut(), std::ptr::null_mut())
295 }};
296 }
297
298 pub type SectionPtr<T> = *const ::core::marker::PhantomData<T>;
301 }
302
303 #[cfg(all(not(miri), target_family = "wasm"))]
304 mod section {
305 #[doc(hidden)]
306 #[macro_export]
307 macro_rules! __get_section {
308 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
309 {
310 static __START: ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>> = unsafe {
311 ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>>::new(::core::ptr::null_mut())
312 };
313 static __END: ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>> = unsafe {
314 ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>>::new(::core::ptr::null_mut())
315 };
316
317 $crate::__support::ident_concat!((#[no_mangle]pub extern "C" fn) (register_link_section_ $ident) ((data_ptr: *const u8, data_len: usize) {
318 unsafe {
319 __START.store(data_ptr as *mut ::core::marker::PhantomData<$generic_ty>, ::core::sync::atomic::Ordering::Relaxed);
320 __END.store(data_ptr.add(data_len) as *mut ::core::marker::PhantomData<$generic_ty>, ::core::sync::atomic::Ordering::Relaxed);
321 }
322 }));
323
324 (&__START, &__END)
325 }
326 }
327 }
328
329 pub type SectionPtr<T> =
333 &'static ::core::sync::atomic::AtomicPtr<::core::marker::PhantomData<T>>;
334 }
335
336 #[cfg(all(not(miri), target_vendor = "pc"))]
337 mod section {
338 #[doc(hidden)]
339 #[macro_export]
340 macro_rules! __get_section {
341 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
342 {
343 $crate::__support::add_section_link_attribute!(
344 data start $ident $($aux)?
345 #[link_section = __]
346 static __START: [$generic_ty; 0] = [];
347 );
348 $crate::__support::add_section_link_attribute!(
349 data end $ident $($aux)?
350 #[link_section = __]
351 static __END: [$generic_ty; 0] = [];
352 );
353
354 (
355 unsafe { &raw const __START as $crate::__support::SectionPtr<$generic_ty> },
356 unsafe { &raw const __END as $crate::__support::SectionPtr<$generic_ty> },
357 )
358 }
359 }
360 }
361
362 pub type SectionPtr<T> = *const [T; 0];
366 }
367
368 #[cfg(all(not(miri), not(target_family = "wasm"), not(target_vendor = "pc")))]
369 mod section {
370 #[doc(hidden)]
371 #[macro_export]
372 macro_rules! __get_section {
373 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
374 {
375 extern "C" {
376 $crate::__support::add_section_link_attribute!(
377 data start $ident $($aux)?
378 #[link_name = __]
379 static __START: $crate::__support::SectionPtr<$generic_ty>;
380 );
381 }
382 extern "C" {
383 $crate::__support::add_section_link_attribute!(
384 data end $ident $($aux)?
385 #[link_name = __]
386 static __END: $crate::__support::SectionPtr<$generic_ty>;
387 );
388 }
389
390 (
391 unsafe { &raw const __START as $crate::__support::SectionPtr<$generic_ty> },
392 unsafe { &raw const __END as $crate::__support::SectionPtr<$generic_ty> },
393 )
394 }
395 }
396 }
397
398 pub type SectionPtr<T> = *const ::core::marker::PhantomData<T>;
401 }
402
403 #[macro_export]
405 #[doc(hidden)]
406 macro_rules! __in_section_parse {
407 (#[in_section(unsafe, type = $stored_ty:ty, name = $ident:ident $( , aux = $aux:ident)?)] $($item:tt)*) => {
414 $crate::__support::in_section_crate!((type = $stored_ty), $ident, $($aux)?, $ident, ($($item)*));
415 };
416 (#[in_section(unsafe, name = $ident:ident $( , aux = $aux:ident)?)] $($item:tt)*) => {
417 $crate::__support::in_section_crate!(data, $ident, $($aux)?, $ident, ($($item)*));
418 };
419 (#[in_section( $($path:tt)* )] $($item:tt)*) => {
420 $crate::__support::in_section_parse!(path=[$($path)*] #[in_section($($path)*)] $($item)*);
421 };
422 (path=[$orig_path:path] #[in_section($name:ident)] $($item:tt)*) => {
423 $orig_path ! (
424 (v=0 (name=$name (path=[$orig_path] (item=($($item)*) ()))))
425 );
426 };
427 (path=[$orig_path:path] #[in_section(:: $($path:ident)::*)] $($item:tt)*) => {
428 $crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
429 };
430 (path=[$orig_path:path] #[in_section($prefix:ident :: $($path:ident)::*)] $($item:tt)*) => {
431 $crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
432 };
433 }
434
435 #[macro_export]
436 #[doc(hidden)]
437 macro_rules! __in_section_helper_macro_generic {
438 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt))))) => {
439 $crate::__support::in_section_crate!(section, $ident,, $path, $item);
440 };
441 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) ((aux=$aux:ident)) )=> {
442 $crate::__support::in_section_crate!(section, $ident, $aux, $path, $item);
443 };
444 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) () )=> {
445 $crate::__support::in_section_crate!(section, $ident,, $path, $item);
446 };
447 (v=$v:literal $rest:tt) => {
448 const _: () = {
449 compile_error!(concat!(
450 "link-section: Unsupported version: `",
451 stringify!($v),
452 "`: ",
453 stringify!($rest)
454 ));
455 };
456 };
457 }
458
459 #[macro_export]
460 #[doc(hidden)]
461 macro_rules! __in_section_helper_macro_no_generic {
462 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt))))) => {
463 $crate::__support::in_section_crate!(data, $ident,, $path, $item);
464 };
465 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) ((aux=$aux:ident)) )=> {
466 $crate::__support::in_section_crate!(data, $ident, $aux, $path, $item);
467 };
468 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) () )=> {
469 $crate::__support::in_section_crate!(data, $ident,, $path, $item);
470 };
471 (v=$v:literal $rest:tt) => {
472 const _: () = {
473 compile_error!(concat!(
474 "link-section: Unsupported version: `",
475 stringify!($v),
476 "`: ",
477 stringify!($rest)
478 ));
479 };
480 };
481 }
482
483 #[macro_export]
484 #[doc(hidden)]
485 #[allow(unknown_lints, edition_2024_expr_fragment_specifier)]
486 macro_rules! __in_section_crate {
487 (@type_select section $path:path, $item_ty:ty) => {
488 <$path as $crate::__support::SectionItemType>::Item
489 };
490 (@type_select data $path:path, $item_ty:ty) => {
491 $item_ty
492 };
493 (@type_select (type = $stored_ty:ty) $path:path, $item_ty:ty) => {
494 $stored_ty
495 };
496 ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis fn $ident_fn:ident($($args:tt)*) $(-> $ret:ty)? $body:block)) => {
497 $crate::__add_section_link_attribute!(
498 data section $ident $($aux)?
499 #[link_section = __]
500 $(#[$meta])*
501 #[used]
502 #[allow(non_upper_case_globals)]
503 $vis static $ident_fn: $crate::__in_section_crate!(@type_select $type_source $path, fn($($args)*) $(-> $ret)?) =
504 {
505 $crate::__add_section_link_attribute!(
506 code section $ident $($aux)?
507 #[link_section = __]
508 fn $ident_fn($($args)*) $(-> $ret)? $body
509 );
510 $ident_fn
511 };
512 );
513 };
514 ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis static _ : $ty:ty = $value:expr;)) => {
515 const _: () = {
516 $crate::__add_section_link_attribute!(
517 data section $ident $($aux)?
518 #[link_section = __]
519 $(#[$meta])* #[used] $vis static ANONYMOUS: $crate::__in_section_crate!(@type_select $type_source $path, $ty) = $value;
520 );
521 };
522 };
523 ($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis static $ident_static:ident : $ty:ty = $value:expr;)) => {
524 $crate::__add_section_link_attribute!(
525 data section $ident $($aux)?
526 #[link_section = __]
527 $(#[$meta])* #[used] $vis static $ident_static: $crate::__in_section_crate!(@type_select $type_source $path, $ty) = $value;
528 );
529 };
530 (data, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $item:item)) => {
531 $crate::__add_section_link_attribute!(
532 data section $ident $($aux)?
533 #[link_section = __]
534 $(#[$meta])* #[used] $item
535 );
536 };
537 }
538
539 pub trait SectionItemType {
540 type Item;
541 }
542
543 impl<T> SectionItemType for super::TypedSection<T> {
544 type Item = T;
545 }
546
547 pub use section::SectionPtr;
548}
549
550#[cfg(feature = "proc_macro")]
577pub use ::link_section_proc_macro::section;
578
579#[cfg(feature = "proc_macro")]
586pub use ::link_section_proc_macro::in_section;
587
588#[repr(C)]
591pub struct Section {
592 name: &'static str,
593 start: __support::SectionPtr<()>,
594 end: __support::SectionPtr<()>,
595}
596
597impl Section {
598 #[doc(hidden)]
599 pub const unsafe fn new(
600 name: &'static str,
601 start: __support::SectionPtr<()>,
602 end: __support::SectionPtr<()>,
603 ) -> Self {
604 Self { name, start, end }
605 }
606
607 pub fn byte_len(&self) -> usize {
609 unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
610 }
611}
612
613#[cfg(target_family = "wasm")]
614impl Section {
615 pub fn start_ptr(&self) -> *const () {
617 let ptr = self.start.load(::core::sync::atomic::Ordering::Relaxed) as *const ();
618 if ptr.is_null() {
619 panic!(
620 "Section {} was not initialized by the host environment",
621 self.name
622 );
623 }
624 ptr
625 }
626 pub fn end_ptr(&self) -> *const () {
628 let ptr = self.end.load(::core::sync::atomic::Ordering::Relaxed) as *const ();
629 if ptr.is_null() {
630 panic!(
631 "Section {} was not initialized by the host environment",
632 self.name
633 );
634 }
635 ptr
636 }
637}
638
639#[cfg(not(target_family = "wasm"))]
640impl Section {
641 pub fn start_ptr(&self) -> *const () {
643 self.start as *const ()
644 }
645 pub fn end_ptr(&self) -> *const () {
647 self.end as *const ()
648 }
649}
650
651impl ::core::fmt::Debug for Section {
652 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
653 f.debug_struct("Section")
654 .field("name", &self.name)
655 .field("start", &self.start_ptr())
656 .field("end", &self.end_ptr())
657 .field("byte_len", &self.byte_len())
658 .finish()
659 }
660}
661
662unsafe impl Sync for Section {}
663unsafe impl Send for Section {}
664
665#[repr(C)]
668pub struct TypedSection<T: 'static> {
669 name: &'static str,
670 start: __support::SectionPtr<T>,
671 end: __support::SectionPtr<T>,
672 _phantom: ::core::marker::PhantomData<T>,
673}
674
675#[cfg(target_family = "wasm")]
676impl<T: 'static> TypedSection<T> {
677 pub fn start_ptr(&self) -> *const T {
679 let ptr = self.start.load(::core::sync::atomic::Ordering::Relaxed) as *const T;
680 if ptr.is_null() {
681 panic!(
682 "TypedSection {} was not initialized by the host environment",
683 self.name
684 );
685 }
686 ptr
687 }
688
689 pub fn end_ptr(&self) -> *const T {
691 let ptr = self.end.load(::core::sync::atomic::Ordering::Relaxed) as *const T;
692 if ptr.is_null() {
693 panic!(
694 "TypedSection {} was not initialized by the host environment",
695 self.name
696 );
697 }
698 ptr
699 }
700}
701
702#[cfg(not(target_family = "wasm"))]
703impl<T: 'static> TypedSection<T> {
704 pub fn start_ptr(&self) -> *const T {
706 self.start as usize as *const T
707 }
708
709 pub fn end_ptr(&self) -> *const T {
711 self.end as *const T
712 }
713}
714
715impl<T: 'static> TypedSection<T> {
717 #[doc(hidden)]
718 pub const unsafe fn new(
719 name: &'static str,
720 start: __support::SectionPtr<T>,
721 end: __support::SectionPtr<T>,
722 ) -> Self {
723 Self {
724 name,
725 start,
726 end,
727 _phantom: ::core::marker::PhantomData,
728 }
729 }
730
731 pub const fn stride(&self) -> usize {
733 assert!(
734 ::core::mem::size_of::<T>() > 0
735 && ::core::mem::size_of::<T>() * 2 == ::core::mem::size_of::<[T; 2]>()
736 );
737 ::core::mem::size_of::<T>()
738 }
739
740 pub fn byte_len(&self) -> usize {
742 unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
743 }
744
745 pub fn len(&self) -> usize {
747 self.byte_len() / self.stride()
748 }
749
750 pub fn is_empty(&self) -> bool {
752 self.len() == 0
753 }
754
755 pub fn as_slice(&self) -> &[T] {
757 if self.is_empty() {
758 &[]
759 } else {
760 unsafe { ::core::slice::from_raw_parts(self.start_ptr(), self.len()) }
761 }
762 }
763
764 pub fn offset_of(&self, item: &T) -> Option<usize> {
766 let ptr = item as *const T;
767 if ptr < self.start_ptr() || ptr >= self.end_ptr() {
768 None
769 } else {
770 Some(unsafe { ptr.offset_from(self.start_ptr()) as usize })
771 }
772 }
773
774 #[allow(clippy::mut_from_ref)]
781 pub unsafe fn as_mut_slice(&self) -> &mut [T] {
782 if self.is_empty() {
783 &mut []
784 } else {
785 unsafe { ::core::slice::from_raw_parts_mut(self.start_ptr() as *mut T, self.len()) }
786 }
787 }
788}
789
790impl<'a, T> ::core::iter::IntoIterator for &'a TypedSection<T> {
791 type Item = &'a T;
792 type IntoIter = ::core::slice::Iter<'a, T>;
793 fn into_iter(self) -> Self::IntoIter {
794 self.as_slice().iter()
795 }
796}
797
798impl<T> ::core::ops::Deref for TypedSection<T> {
799 type Target = [T];
800 fn deref(&self) -> &Self::Target {
801 self.as_slice()
802 }
803}
804
805impl<T> ::core::fmt::Debug for TypedSection<T> {
806 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
807 f.debug_struct("TypedSection")
808 .field("name", &self.name)
809 .field("start", &self.start_ptr())
810 .field("end", &self.end_ptr())
811 .field("len", &self.len())
812 .field("stride", &self.stride())
813 .finish()
814 }
815}
816
817unsafe impl<T> Sync for TypedSection<T> where T: Sync {}
818unsafe impl<T> Send for TypedSection<T> where T: Send {}