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