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