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 $aux:ident $name: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 $aux:ident $name:ident) => {
57 $crate::__support::hash!($pattern ($__prefix) ($name $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 $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
210 $crate::__declare_macro!($vis $ident $generic_macro ($($args)*));
211 $crate::__section_parse!(@generate #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
212 };
213 (@generate #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __in_section_helper_macro_generic) => {
214 $crate::__section_parse!(@generate #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, __base_case__);
215
216 impl ::core::iter::IntoIterator for $ident {
217 type Item = &'static $generic_ty;
218 type IntoIter = ::core::slice::Iter<'static, $generic_ty>;
219 fn into_iter(self) -> Self::IntoIter {
220 $ident.as_slice().iter()
221 }
222 }
223 };
224 (@generate #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, $generic_macro:ident) => {
225 $(#[$meta])*
226 #[allow(non_camel_case_types)]
227 $vis struct $ident;
228
229 impl $crate::__support::SectionFactory for $ident {
230 type SectionType = $crate::__support::Section< $ty, $generic_ty >;
231 type ItemType = $generic_ty;
232 }
233
234 impl $crate::__support::SectionItemType for $ident {
235 type Item = $generic_ty;
236 }
237
238 impl ::core::fmt::Debug for $ident {
239 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
240 ::core::ops::Deref::deref(self).fmt(f)
241 }
242 }
243
244 $crate::__section_parse!(@deref #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, __base_case__);
245 };
246 (@deref #[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __base_case__) => {
247 impl ::core::ops::Deref for $ident {
248 type Target = $ty;
249 fn deref(&self) -> &Self::Target {
250 static SECTION: $crate::__support::Section< $ty, $generic_ty > = {
251 let section = $crate::__support::get_section!(name=$ident, type=$generic_ty, aux=);
252 let name = $crate::__section_name!(
253 raw data bare $ident
254 );
255 $crate::__support::Section::new(
256 name, section.0, section.1
257 )
258 };
259 &SECTION
260 }
261 }
262 };
263 (@deref #[section(aux=$aux:ident)] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __base_case__) => {
264 impl ::core::ops::Deref for $ident {
265 type Target = $ty;
266 fn deref(&self) -> &Self::Target {
267 static SECTION: $crate::__support::Section< $ty, $generic_ty > = {
268 let section = $crate::__support::get_section!(name=$ident, type=$generic_ty, aux=$aux);
269 let name = $crate::__section_name!(
270 raw data bare $ident $aux
271 );
272 $crate::__support::Section::new(
273 name, section.0, section.1
274 )
275 };
276 &SECTION
277 }
278 }
279 };
280 }
281
282 #[cfg(miri)]
283 #[doc(hidden)]
284 #[macro_export]
285 macro_rules! __get_section {
286 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
287 {
289 (std::ptr::null_mut(), std::ptr::null_mut())
290 }
291 };
292 }
293
294 #[cfg(all(not(miri), target_family = "wasm"))]
295 #[doc(hidden)]
296 #[macro_export]
297 macro_rules! __get_section {
298 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
299 {
300 static __START: ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>> = unsafe {
301 ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>>::new(::core::ptr::null_mut())
302 };
303 static __END: ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>> = unsafe {
304 ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>>::new(::core::ptr::null_mut())
305 };
306
307 $crate::__support::ident_concat!((#[no_mangle]pub extern "C" fn) (register_link_section_ $ident) ((data_ptr: *const u8, data_len: usize) {
308 unsafe {
309 __START.store(data_ptr as *mut ::core::marker::PhantomData<$generic_ty>, ::core::sync::atomic::Ordering::Relaxed);
310 __END.store(data_ptr.add(data_len) as *mut ::core::marker::PhantomData<$generic_ty>, ::core::sync::atomic::Ordering::Relaxed);
311 }
312 }));
313
314 (&__START, &__END)
315 }
316 }
317 }
318
319 #[cfg(all(not(miri), target_vendor = "pc"))]
320 #[doc(hidden)]
321 #[macro_export]
322 macro_rules! __get_section {
323 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
324 {
325 $crate::__support::add_section_link_attribute!(
326 data start $ident $($aux)?
327 #[link_section = __]
328 static __START: [$generic_ty; 0] = [];
329 );
330 $crate::__support::add_section_link_attribute!(
331 data end $ident $($aux)?
332 #[link_section = __]
333 static __END: [$generic_ty; 0] = [];
334 );
335
336 (
337 unsafe { &raw const __START as $crate::__support::SectionPtr<$generic_ty> },
338 unsafe { &raw const __END as $crate::__support::SectionPtr<$generic_ty> },
339 )
340 }
341 }
342 }
343
344 #[cfg(all(not(miri), not(target_family = "wasm"), not(target_vendor = "pc")))]
345 #[doc(hidden)]
346 #[macro_export]
347 macro_rules! __get_section {
348 (name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
349 {
350 extern "C" {
351 $crate::__support::add_section_link_attribute!(
352 data start $ident $($aux)?
353 #[link_name = __]
354 static __START: $crate::__support::SectionPtr<$generic_ty>;
355 );
356 }
357 extern "C" {
358 $crate::__support::add_section_link_attribute!(
359 data end $ident $($aux)?
360 #[link_name = __]
361 static __END: $crate::__support::SectionPtr<$generic_ty>;
362 );
363 }
364
365 (
366 unsafe { &raw const __START as $crate::__support::SectionPtr<$generic_ty> },
367 unsafe { &raw const __END as $crate::__support::SectionPtr<$generic_ty> },
368 )
369 }
370 }
371 }
372
373 #[macro_export]
375 #[doc(hidden)]
376 macro_rules! __in_section_parse {
377 (#[in_section( $($path:tt)* )] $($item:tt)*) => {
384 $crate::__support::in_section_parse!(path=[$($path)*] #[in_section($($path)*)] $($item)*);
385 };
386 (path=[$orig_path:path] #[in_section($name:ident)] $($item:tt)*) => {
387 $orig_path ! (
388 (v=0 (name=$name (path=[$orig_path] (item=($($item)*) ()))))
389 );
390 };
391 (path=[$orig_path:path] #[in_section(:: $($path:ident)::*)] $($item:tt)*) => {
392 $crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
393 };
394 (path=[$orig_path:path] #[in_section($prefix:ident :: $($path:ident)::*)] $($item:tt)*) => {
395 $crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
396 };
397 }
398
399 #[macro_export]
400 #[doc(hidden)]
401 macro_rules! __in_section_helper_macro_generic {
402 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt))))) => {
403 $crate::__support::in_section_crate!($ident,, $path, generic, $item);
404 };
405 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) ((aux=$aux:ident)) )=> {
406 $crate::__support::in_section_crate!($ident, $aux, $path, generic, $item);
407 };
408 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) () )=> {
409 $crate::__support::in_section_crate!($ident,, $path, generic, $item);
410 };
411 (v=$v:literal $rest:tt) => {
412 const _: () = {
413 compile_error!(concat!(
414 "link-section: Unsupported version: `",
415 stringify!($v),
416 "`: ",
417 stringify!($rest)
418 ));
419 };
420 };
421 }
422
423 #[macro_export]
424 #[doc(hidden)]
425 macro_rules! __in_section_helper_macro_no_generic {
426 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt))))) => {
427 $crate::__support::in_section_crate!($ident,, $path, no_generic, $item);
428 };
429 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) ((aux=$aux:ident)) )=> {
430 $crate::__support::in_section_crate!($ident, $aux, $path, no_generic, $item);
431 };
432 ((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) () )=> {
433 $crate::__support::in_section_crate!($ident,, $path, no_generic, $item);
434 };
435 (v=$v:literal $rest:tt) => {
436 const _: () = {
437 compile_error!(concat!(
438 "link-section: Unsupported version: `",
439 stringify!($v),
440 "`: ",
441 stringify!($rest)
442 ));
443 };
444 };
445 }
446
447 #[macro_export]
448 #[doc(hidden)]
449 #[allow(unknown_lints, edition_2024_expr_fragment_specifier)]
450 macro_rules! __in_section_crate {
451 ($ident:ident, $($aux:ident)?, $path:path, generic, ($(#[$meta:meta])* $vis:vis fn $ident_fn:ident($($args:tt)*) $(-> $ret:ty)? $body:block)) => {
452 $crate::__add_section_link_attribute!(
453 data section $ident $($aux)?
454 #[link_section = __]
455 $(#[$meta])*
457 #[used]
458 #[allow(non_upper_case_globals)]
459 $vis static $ident_fn: <$path as $crate::__support::SectionItemType>::Item =
460 {
461 fn $ident_fn($($args)*) $(-> $ret)? $body
462 $ident_fn as _
463 };
464 );
465 };
466 ($ident:ident, $($aux:ident)?, $path:path, generic, ($(#[$meta:meta])* $vis:vis static _ : $ty:ty = $value:expr;)) => {
467 const _: () = {
468 $crate::__add_section_link_attribute!(
469 data section $ident $($aux)?
470 #[link_section = __]
471 $(#[$meta])* #[used] $vis static ANONYMOUS: <$path as $crate::__support::SectionItemType>::Item = $value;
472 );
473 };
474 };
475 ($ident:ident, $($aux:ident)?, $path:path, generic, ($(#[$meta:meta])* $vis:vis static $ident_static:ident : $ty:ty = $value:expr;)) => {
476 $crate::__add_section_link_attribute!(
477 data section $ident $($aux)?
478 #[link_section = __]
479 $(#[$meta])* #[used] $vis static $ident_static: <$path as $crate::__support::SectionItemType>::Item = $value;
480 );
481 };
482 ($ident:ident, $($aux:ident)?, $path:path, no_generic, ($(#[$meta:meta])* $vis:vis fn $ident_fn:ident($($args:tt)*) $(-> $ret:ty)? $body:block)) => {
483 $crate::__add_section_link_attribute!(
484 data section $ident $($aux)?
485 #[link_section = __]
486 $(#[$meta])*
487 #[used]
488 #[allow(non_upper_case_globals)]
489 $vis static $ident_fn: fn($($args)*) $(-> $ret)? =
490 {
491 $crate::__section_name!(
492 (#[link_section = __] fn $ident_fn($($args)*) $(-> $ret)? $body)
493 code section $ident
494 );
495 $ident_fn
496 };
497 );
498 };
499 ($ident:ident, $($aux:ident)?, $path:path, no_generic, ($(#[$meta:meta])* $item:item)) => {
500 $crate::__add_section_link_attribute!(
501 data section $ident $($aux)?
502 #[link_section = __]
503 $(#[$meta])* #[used] $item
504 );
505 };
506 }
507
508 pub trait SectionItemType {
509 type Item;
510 }
511
512 pub trait SectionFactory {
513 type SectionType;
514 type ItemType;
515 }
516
517 #[repr(C)]
518 pub struct Section<T: sealed::FromRawSection, S: 'static> {
519 name: &'static str,
520 start: SectionPtr<S>,
521 end: SectionPtr<S>,
522 _t: ::core::marker::PhantomData<T>,
523 }
524
525 impl<T> SectionItemType for super::TypedSection<T> {
526 type Item = T;
527 }
528
529 impl<T: sealed::FromRawSection, S> Section<T, S> {
530 pub const fn new(name: &'static str, start: SectionPtr<S>, end: SectionPtr<S>) -> Self {
531 Self {
532 name,
533 start,
534 end,
535 _t: ::core::marker::PhantomData,
536 }
537 }
538 }
539
540 impl<'a, T: sealed::FromRawSection, S> ::core::iter::IntoIterator for &'a Section<T, S>
541 where
542 for<'b> &'b T: ::core::iter::IntoIterator,
543 {
544 type Item = <&'a T as ::core::iter::IntoIterator>::Item;
545 type IntoIter = <&'a T as ::core::iter::IntoIterator>::IntoIter;
546 fn into_iter(self) -> Self::IntoIter {
547 ::core::ops::Deref::deref(self).into_iter()
548 }
549 }
550
551 impl<T: sealed::FromRawSection, S> ::core::ops::Deref for Section<T, S> {
552 type Target = T;
553 fn deref(&self) -> &Self::Target {
554 unsafe { ::core::mem::transmute(self) }
556 }
557 }
558
559 impl<T: sealed::FromRawSection + ::core::fmt::Debug, S> ::core::fmt::Debug for Section<T, S> {
560 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
561 ::core::fmt::Debug::fmt(::core::ops::Deref::deref(self), f)
562 }
563 }
564
565 unsafe impl<T: sealed::FromRawSection, S> Sync for Section<T, S> {}
566 unsafe impl<T: sealed::FromRawSection, S> Send for Section<T, S> {}
567
568 #[cfg(all(not(target_vendor = "pc"), not(target_family = "wasm")))]
571 pub type SectionPtr<T> = *const ::core::marker::PhantomData<T>;
572 #[cfg(target_vendor = "pc")]
576 pub type SectionPtr<T> = *const [T; 0];
577 #[cfg(target_family = "wasm")]
579 pub type SectionPtr<T> =
580 &'static ::core::sync::atomic::AtomicPtr<::core::marker::PhantomData<T>>;
581
582 mod sealed {
583 pub trait FromRawSection {}
584
585 impl FromRawSection for crate::Section {}
586
587 impl<T> FromRawSection for crate::TypedSection<T> {}
588 }
589}
590
591#[cfg(feature = "proc_macro")]
606pub use ::link_section_proc_macro::section;
607
608#[cfg(feature = "proc_macro")]
615pub use ::link_section_proc_macro::in_section;
616
617#[repr(C)]
620pub struct Section {
621 name: &'static str,
622 start: __support::SectionPtr<()>,
623 end: __support::SectionPtr<()>,
624}
625
626#[cfg(target_family = "wasm")]
627impl Section {
628 pub fn start_ptr(&self) -> *const () {
630 let ptr = self.start.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 pub fn end_ptr(&self) -> *const () {
641 let ptr = self.end.load(::core::sync::atomic::Ordering::Relaxed) as *const ();
642 if ptr.is_null() {
643 panic!(
644 "Section {} was not initialized by the host environment",
645 self.name
646 );
647 }
648 ptr
649 }
650 pub fn byte_len(&self) -> usize {
652 unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
653 }
654}
655
656#[cfg(not(target_family = "wasm"))]
657impl Section {
658 pub const fn start_ptr(&self) -> *const () {
660 self.start as *const ()
661 }
662 pub const fn end_ptr(&self) -> *const () {
664 self.end as *const ()
665 }
666 pub const fn byte_len(&self) -> usize {
668 unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
669 }
670}
671
672impl ::core::fmt::Debug for Section {
673 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
674 f.debug_struct("Section")
675 .field("name", &self.name)
676 .field("start", &self.start_ptr())
677 .field("end", &self.end_ptr())
678 .field("byte_len", &self.byte_len())
679 .finish()
680 }
681}
682
683unsafe impl Sync for Section {}
684unsafe impl Send for Section {}
685
686#[repr(C)]
689pub struct TypedSection<T: 'static> {
690 name: &'static str,
691 start: __support::SectionPtr<T>,
692 end: __support::SectionPtr<T>,
693 _phantom: ::core::marker::PhantomData<T>,
694}
695
696#[cfg(target_family = "wasm")]
697impl<T: 'static> TypedSection<T> {
698 pub fn start_ptr(&self) -> *const T {
700 let ptr = self.start.load(::core::sync::atomic::Ordering::Relaxed) as *const T;
701 if ptr.is_null() {
702 panic!(
703 "TypedSection {} was not initialized by the host environment",
704 self.name
705 );
706 }
707 ptr
708 }
709
710 pub fn end_ptr(&self) -> *const T {
712 let ptr = self.end.load(::core::sync::atomic::Ordering::Relaxed) as *const T;
713 if ptr.is_null() {
714 panic!(
715 "TypedSection {} was not initialized by the host environment",
716 self.name
717 );
718 }
719 ptr
720 }
721
722 pub fn byte_len(&self) -> usize {
724 unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
725 }
726
727 pub fn len(&self) -> usize {
729 self.byte_len() / self.stride()
730 }
731
732 pub fn is_empty(&self) -> bool {
734 self.len() == 0
735 }
736
737 pub fn as_slice(&self) -> &[T] {
739 if self.is_empty() {
740 &[]
741 } else {
742 unsafe { ::core::slice::from_raw_parts(self.start_ptr(), self.len()) }
743 }
744 }
745}
746
747#[cfg(not(target_family = "wasm"))]
748impl<T: 'static> TypedSection<T> {
749 pub const fn start_ptr(&self) -> *const T {
751 self.start as *const T
752 }
753
754 pub const fn end_ptr(&self) -> *const T {
756 self.end as *const T
757 }
758
759 pub const fn byte_len(&self) -> usize {
761 unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
762 }
763
764 pub const fn len(&self) -> usize {
766 self.byte_len() / self.stride()
767 }
768
769 pub const fn is_empty(&self) -> bool {
771 self.len() == 0
772 }
773
774 pub const fn as_slice(&self) -> &[T] {
776 if self.is_empty() {
777 &[]
778 } else {
779 unsafe { ::core::slice::from_raw_parts(self.start_ptr(), self.len()) }
780 }
781 }
782}
783
784impl<T: 'static> TypedSection<T> {
786 pub const fn stride(&self) -> usize {
788 assert!(
789 ::core::mem::size_of::<T>() > 0
790 && ::core::mem::size_of::<T>() * 2 == ::core::mem::size_of::<[T; 2]>()
791 );
792 ::core::mem::size_of::<T>()
793 }
794
795 pub fn offset_of(&self, item: &T) -> Option<usize> {
797 let ptr = item as *const T;
798 if ptr < self.start_ptr() || ptr >= self.end_ptr() {
799 None
800 } else {
801 Some(unsafe { ptr.offset_from(self.start_ptr()) as usize })
802 }
803 }
804
805 #[allow(clippy::mut_from_ref)]
812 pub unsafe fn as_mut_slice(&self) -> &mut [T] {
813 if self.is_empty() {
814 &mut []
815 } else {
816 unsafe { ::core::slice::from_raw_parts_mut(self.start_ptr() as *mut T, self.len()) }
817 }
818 }
819}
820
821impl<'a, T> ::core::iter::IntoIterator for &'a TypedSection<T> {
822 type Item = &'a T;
823 type IntoIter = ::core::slice::Iter<'a, T>;
824 fn into_iter(self) -> Self::IntoIter {
825 self.as_slice().iter()
826 }
827}
828
829impl<T> ::core::ops::Deref for TypedSection<T> {
830 type Target = [T];
831 fn deref(&self) -> &Self::Target {
832 self.as_slice()
833 }
834}
835
836impl<T> ::core::fmt::Debug for TypedSection<T> {
837 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
838 f.debug_struct("TypedSection")
839 .field("name", &self.name)
840 .field("start", &self.start_ptr())
841 .field("end", &self.end_ptr())
842 .field("len", &self.len())
843 .field("stride", &self.stride())
844 .finish()
845 }
846}
847
848unsafe impl<T> Sync for TypedSection<T> where T: Sync {}
849unsafe impl<T> Send for TypedSection<T> where T: Send {}