Skip to main content

link_section/
lib.rs

1#![doc = include_str!("../README.md")]
2#![allow(unsafe_code)]
3
4/// Declarative forms of the `#[section]` and `#[in_section(...)]` macros.
5///
6/// The declarative forms wrap and parse a proc_macro-like syntax like so, and
7/// are identical in expansion to the undecorated procedural macros. The
8/// declarative forms support the same attribute parameters as the procedural
9/// macros.
10pub 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::__in_section_crate as in_section_crate;
20    pub use crate::__in_section_parse as in_section_parse;
21    pub use crate::__section_parse as section_parse;
22
23    #[cfg(feature = "proc_macro")]
24    pub use link_section_proc_macro::hash;
25    #[cfg(feature = "proc_macro")]
26    pub use link_section_proc_macro::ident_concat;
27
28    /// Declares the section_name macro.
29    #[macro_export]
30    #[doc(hidden)]
31    macro_rules! __def_section_name {
32        (
33            {$(
34                $__section:ident $__type:ident => $__prefix:tt __ $__suffix:tt;
35            )*}
36
37            MAX_LENGTH = $__max_length:literal;
38            HASH_LENGTH = $__hash_length:literal;
39            VALID_SECTION_CHARS = $__valid_section_chars:literal;
40        ) => {
41            /// Internal macro for generating a section name.
42            #[macro_export]
43            #[doc(hidden)]
44            macro_rules! __section_name {
45                $(
46                    (raw $__section $__type $name:ident) => {
47                        concat!(concat! $__prefix, stringify!($name), concat! $__suffix);
48                    };
49                    ($pattern:tt $__section $__type $name:ident) => {
50                        $crate::__support::hash!($pattern $name ($__prefix) ($__suffix) $__hash_length $__max_length $__valid_section_chars);
51                    };
52                )*
53                ($pattern:tt $unknown_section:ident $unknown_type:ident $name:ident) => {
54                    const _: () = {
55                        compile_error!("Unknown section type: `{}`/`{}`", stringify!($unknown_section), stringify!($unknown_type));
56                    };
57                };
58            }
59        };
60    }
61
62    #[cfg(feature = "proc_macro")]
63    #[doc(hidden)]
64    #[macro_export]
65    macro_rules! __add_section_link_attribute(
66        ($section:ident $type:ident $name:ident #[$attr:ident = __] $item:item) => {
67            $crate::__section_name!(
68                (#[$attr = __] #[allow(unsafe_code)] $item)
69                $section $type $name
70            );
71        }
72    );
73
74    #[cfg(not(feature = "proc_macro"))]
75    #[doc(hidden)]
76    #[macro_export]
77    macro_rules! __add_section_link_attribute(
78        ($section:ident $type:ident $name:ident #[$attr:ident = __] $item:item) => {
79            #[$attr = $crate::__section_name!(
80                raw $section $type $name
81            )] $item
82        }
83    );
84
85    // \x01: "do not mangle" (ref https://github.com/rust-lang/rust-bindgen/issues/2935)
86    #[cfg(target_vendor = "apple")]
87    def_section_name! {
88        {
89            data bare => ("__DATA,") __ ();
90            code bare => ("__TEXT,") __ ();
91            data section => ("__DATA,") __ (",regular,no_dead_strip");
92            code section => ("__TEXT,") __ (",regular,no_dead_strip");
93            data start => ("\x01section$start$__DATA$") __ ();
94            data end => ("\x01section$end$__DATA$") __ ();
95        }
96        MAX_LENGTH = 16;
97        HASH_LENGTH = 6;
98        VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
99    }
100
101    #[cfg(target_family = "wasm")]
102    def_section_name! {
103        {
104            data bare => (".data", ".link_section.") __ ();
105            data section => (".data", ".link_section.") __ ();
106            code bare => (".text", ".link_section.") __ ();
107            code section => (".text", ".link_section.") __ ();
108        }
109        MAX_LENGTH = 16;
110        HASH_LENGTH = 6;
111        VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
112    }
113
114    #[cfg(all(
115        not(target_vendor = "apple"),
116        not(target_vendor = "pc"),
117        not(target_family = "wasm")
118    ))]
119    def_section_name! {
120        {
121            data bare => ("_data", "_link_section_") __ ();
122            data section => ("_data", "_link_section_") __ ();
123            data start => ("__start_", "_data", "_link_section_") __ ();
124            data end => ("__stop_", "_data", "_link_section_") __ ();
125            code bare => ("_text", "_link_section_") __ ();
126            code section => ("_text", "_link_section_") __ ();
127            code start => ("__start_", "_text", "_link_section_") __ ();
128            code end => ("__stop_", "_text", "_link_section_") __ ();
129        }
130        MAX_LENGTH = 64;
131        HASH_LENGTH = 10;
132        VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
133    }
134
135    #[cfg(target_vendor = "pc")]
136    def_section_name! {
137        {
138            data bare => (".data", "$") __ ();
139            data section => (".data", "$") __ ("$b");
140            data start => (".data", "$") __ ("$a");
141            data end => (".data", "$") __ ("$c");
142            code bare => (".text", "$") __ ();
143            code section => (".text", "$") __ ("$b");
144            code start => (".text", "$") __ ("$a");
145            code end => (".text", "$") __ ("$c");
146        }
147        MAX_LENGTH = 64;
148        HASH_LENGTH = 10;
149        VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
150    }
151
152    /// Define a link section.
153    #[macro_export]
154    #[doc(hidden)]
155    macro_rules! __section_parse {
156        // Has a generic (note that $generic eats the trailing semicolon)
157        (#[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* < $($generic:tt)*) => {
158            $crate::__section_parse!(@parsed #[section] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* < $($generic)*) ( $($generic)* ) __in_section_helper_macro_generic);
159        };
160        // No generic
161        (#[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* ;) => {
162            $crate::__section_parse!(@parsed #[section] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* ;) ( () > ; ) __in_section_helper_macro_no_generic);
163        };
164        // Both end up here...
165        (@parsed #[section] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
166            /// Internal macro for parsing the section. This is exported with
167            /// the same name as the type below.
168            #[doc(hidden)]
169            $vis use $crate::$generic_macro as $ident;
170
171            $crate::__section_parse!(@generate #[section] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
172        };
173        (@generate #[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __in_section_helper_macro_generic) => {
174            $crate::__section_parse!(@generate #[section] $(#[$meta])* $vis static $ident: $ty, $generic_ty, __base_case__);
175
176            impl ::core::iter::IntoIterator for $ident {
177                type Item = &'static $generic_ty;
178                type IntoIter = ::core::slice::Iter<'static, $generic_ty>;
179                fn into_iter(self) -> Self::IntoIter {
180                    $ident.as_slice().iter()
181                }
182            }
183        };
184        (@generate #[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, $generic_macro:ident) => {
185            $(#[$meta])*
186            #[allow(non_camel_case_types)]
187            $vis struct $ident;
188
189            impl $crate::__support::SectionFactory for $ident {
190                type SectionType = $crate::__support::Section< $ty, $generic_ty >;
191                type ItemType = $generic_ty;
192            }
193
194            impl $crate::__support::SectionItemType for $ident {
195                type Item = $generic_ty;
196            }
197
198            impl ::core::fmt::Debug for $ident {
199                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
200                    ::core::ops::Deref::deref(self).fmt(f)
201                }
202            }
203
204            impl ::core::ops::Deref for $ident {
205                type Target = $ty;
206                fn deref(&self) -> &Self::Target {
207                    // Disable link sections for miri (`extern static `␁section$start$__DATA$CTOR` is not supported by Miri`)
208                    #[cfg(miri)]
209                    static SECTION: $crate::__support::Section< $ty, $generic_ty > = {
210                        $crate::__support::Section::new(
211                            {
212                                let name = $crate::__section_name!(
213                                    raw data bare $ident
214                                );
215                                name
216                            },
217                            std::ptr::null_mut(),
218                            std::ptr::null_mut(),
219                        )
220                    };
221
222                    #[cfg(all(not(miri), target_family = "wasm"))]
223                    static SECTION: $crate::__support::Section< $ty, $generic_ty > = {
224                        static __START: ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>> = unsafe {
225                            ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>>::new(::core::ptr::null_mut())
226                        };
227                        static __END: ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>> = unsafe {
228                            ::core::sync::atomic::AtomicPtr::<::core::marker::PhantomData<$generic_ty>>::new(::core::ptr::null_mut())
229                        };
230
231                        $crate::__support::ident_concat!((#[no_mangle]pub extern "C" fn) (register_link_section_ $ident) ((data_ptr: *const u8, data_len: usize) {
232                            unsafe {
233                                __START.store(data_ptr as *mut ::core::marker::PhantomData<$generic_ty>, ::core::sync::atomic::Ordering::Relaxed);
234                                __END.store(data_ptr.add(data_len) as *mut ::core::marker::PhantomData<$generic_ty>, ::core::sync::atomic::Ordering::Relaxed);
235                            }
236                        }));
237
238                        $crate::__support::Section::new(
239                            {
240                                let name = $crate::__section_name!(
241                                    raw data bare $ident
242                                );
243                                name
244                            },
245                            &__START,
246                            &__END,
247                        )
248                    };
249
250                    #[cfg(all(not(miri), not(target_family = "wasm")))]
251                    static SECTION: $crate::__support::Section< $ty, $generic_ty > = $crate::__support::Section::new(
252                        {
253                            let name = $crate::__section_name!(
254                                raw data bare $ident
255                            );
256                            name
257                        },
258                        {
259                            #[cfg(not(target_vendor = "pc"))]
260                            extern "C" {
261                                $crate::__support::add_section_link_attribute!(
262                                    data start $ident
263                                    #[link_name = __]
264                                    static __START: $crate::__support::SectionPtr<$generic_ty>;
265                                );
266                            }
267
268                            // Windows always sorts, so we can use alphabetical order
269                            #[cfg(target_vendor = "pc")]
270                            $crate::__support::add_section_link_attribute!(
271                                data start $ident
272                                #[link_section = __]
273                                static __START: [$generic_ty; 0] = [];
274                            );
275
276                            unsafe { &raw const __START as $crate::__support::SectionPtr<$generic_ty> }
277                        },
278                        {
279                            #[cfg(not(target_vendor = "pc"))]
280                            extern "C" {
281                                $crate::__support::add_section_link_attribute!(
282                                    data end $ident
283                                    #[link_name = __]
284                                    static __END: $crate::__support::SectionPtr<$generic_ty>;
285                                );
286                            }
287
288                            #[cfg(target_vendor = "pc")]
289                            $crate::__support::add_section_link_attribute!(
290                                data end $ident
291                                #[link_section = __]
292                                static __END: [$generic_ty; 0] = [];
293                            );
294
295                            unsafe { &raw const __END as $crate::__support::SectionPtr<$generic_ty> }
296                        },
297                    );
298
299                    &SECTION
300                }
301            }
302
303        };
304    }
305
306    /// Export a symbol into a link section.
307    #[macro_export]
308    #[doc(hidden)]
309    macro_rules! __in_section_parse {
310        // Needs to handle:
311        //  <name>
312        //  :: <name>
313        //  <path> :: <name>
314        //  :: <path> :: <name>
315        //  etc...
316        (#[in_section( $($path:tt)* )] $($item:tt)*) => {
317            $crate::__support::in_section_parse!(path=[$($path)*] #[in_section($($path)*)] $($item)*);
318        };
319        (path=[$orig_path:path] #[in_section($name:ident)] $($item:tt)*) => {
320            $orig_path ! (
321                v=0 (name=$name (path=[$orig_path] (item=($($item)*) ())))
322            );
323        };
324        (path=[$orig_path:path] #[in_section(:: $($path:ident)::*)] $($item:tt)*) => {
325            $crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
326        };
327        (path=[$orig_path:path] #[in_section($prefix:ident :: $($path:ident)::*)] $($item:tt)*) => {
328            $crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
329        };
330    }
331
332    #[macro_export]
333    #[doc(hidden)]
334    macro_rules! __in_section_helper_macro_generic {
335        (v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) => {
336            $crate::__support::in_section_crate!($ident, $path, generic, $item);
337        };
338        (v=$v:literal $rest:tt) => {
339            const _: () = {
340                compile_error!(concat!(
341                    "link-section: Unsupported version: `",
342                    stringify!($v),
343                    "`: ",
344                    stringify!($rest)
345                ));
346            };
347        };
348    }
349
350    #[macro_export]
351    #[doc(hidden)]
352    macro_rules! __in_section_helper_macro_no_generic {
353        (v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) => {
354            $crate::__support::in_section_crate!($ident, $path, no_generic, $item);
355        };
356        (v=$v:literal $rest:tt) => {
357            const _: () = {
358                compile_error!(concat!(
359                    "link-section: Unsupported version: `",
360                    stringify!($v),
361                    "`: ",
362                    stringify!($rest)
363                ));
364            };
365        };
366    }
367
368    #[macro_export]
369    #[doc(hidden)]
370    #[allow(unknown_lints, edition_2024_expr_fragment_specifier)]
371    macro_rules! __in_section_crate {
372        ($ident:ident, $path:path, generic, ($(#[$meta:meta])* $vis:vis fn $ident_fn:ident($($args:tt)*) $(-> $ret:ty)? $body:block)) => {
373            $crate::__add_section_link_attribute!(
374                data section $ident
375                #[link_section = __]
376                // Split the function into a static item and a function pointer
377                $(#[$meta])*
378                #[used]
379                #[allow(non_upper_case_globals)]
380                $vis static $ident_fn: <$path as $crate::__support::SectionItemType>::Item =
381                    {
382                        fn $ident_fn($($args)*) $(-> $ret)? $body
383                        $ident_fn as _
384                    };
385            );
386        };
387        ($ident:ident, $path:path, generic, ($(#[$meta:meta])* $vis:vis static _ : $ty:ty = $value:expr;)) => {
388            const _: () = {
389                $crate::__add_section_link_attribute!(
390                    data section $ident
391                    #[link_section = __]
392                    $(#[$meta])* #[used] $vis static ANONYMOUS: <$path as $crate::__support::SectionItemType>::Item = $value;
393                );
394            };
395        };
396        ($ident:ident, $path:path, generic, ($(#[$meta:meta])* $vis:vis static $ident_static:ident : $ty:ty = $value:expr;)) => {
397            $crate::__add_section_link_attribute!(
398                data section $ident
399                #[link_section = __]
400                $(#[$meta])* #[used] $vis static $ident_static: <$path as $crate::__support::SectionItemType>::Item = $value;
401            );
402        };
403        ($ident:ident, $path:path, no_generic, ($(#[$meta:meta])* $vis:vis fn $ident_fn:ident($($args:tt)*) $(-> $ret:ty)? $body:block)) => {
404            $crate::__add_section_link_attribute!(
405                data section $ident
406                #[link_section = __]
407                $(#[$meta])*
408                #[used]
409                #[allow(non_upper_case_globals)]
410                $vis static $ident_fn: fn($($args)*) $(-> $ret)? =
411                    {
412                        $crate::__section_name!(
413                            (#[link_section = __] fn $ident_fn($($args)*) $(-> $ret)? $body)
414                            code section $ident
415                        );
416                        $ident_fn
417                    };
418            );
419        };
420        ($ident:ident, $path:path, no_generic, ($(#[$meta:meta])* $item:item)) => {
421            $crate::__add_section_link_attribute!(
422                data section $ident
423                #[link_section = __]
424                $(#[$meta])* #[used] $item
425            );
426        };
427    }
428
429    pub trait SectionItemType {
430        type Item;
431    }
432
433    pub trait SectionFactory {
434        type SectionType;
435        type ItemType;
436    }
437
438    #[repr(C)]
439    pub struct Section<T: sealed::FromRawSection, S: 'static> {
440        name: &'static str,
441        start: SectionPtr<S>,
442        end: SectionPtr<S>,
443        _t: ::core::marker::PhantomData<T>,
444    }
445
446    impl<T> SectionItemType for super::TypedSection<T> {
447        type Item = T;
448    }
449
450    impl<T: sealed::FromRawSection, S> Section<T, S> {
451        pub const fn new(name: &'static str, start: SectionPtr<S>, end: SectionPtr<S>) -> Self {
452            Self {
453                name,
454                start,
455                end,
456                _t: ::core::marker::PhantomData,
457            }
458        }
459    }
460
461    impl<'a, T: sealed::FromRawSection, S> ::core::iter::IntoIterator for &'a Section<T, S>
462    where
463        for<'b> &'b T: ::core::iter::IntoIterator,
464    {
465        type Item = <&'a T as ::core::iter::IntoIterator>::Item;
466        type IntoIter = <&'a T as ::core::iter::IntoIterator>::IntoIter;
467        fn into_iter(self) -> Self::IntoIter {
468            ::core::ops::Deref::deref(self).into_iter()
469        }
470    }
471
472    impl<T: sealed::FromRawSection, S> ::core::ops::Deref for Section<T, S> {
473        type Target = T;
474        fn deref(&self) -> &Self::Target {
475            // SAFETY: all sections are repr(C)
476            unsafe { ::core::mem::transmute(self) }
477        }
478    }
479
480    impl<T: sealed::FromRawSection + ::core::fmt::Debug, S> ::core::fmt::Debug for Section<T, S> {
481        fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
482            ::core::fmt::Debug::fmt(::core::ops::Deref::deref(self), f)
483        }
484    }
485
486    unsafe impl<T: sealed::FromRawSection, S> Sync for Section<T, S> {}
487    unsafe impl<T: sealed::FromRawSection, S> Send for Section<T, S> {}
488
489    /// On Apple platforms, the linker provides a pointer to the start and end
490    /// of the section regardless of the section's name.
491    #[cfg(all(not(target_vendor = "pc"), not(target_family = "wasm")))]
492    pub type SectionPtr<T> = *const ::core::marker::PhantomData<T>;
493    /// On LLVM/GCC/MSVC platforms, we cannot use start/end symbols for sections
494    /// without C-compatible names, so instead we drop a [T; 0] at the start and
495    /// end of the section.
496    #[cfg(target_vendor = "pc")]
497    pub type SectionPtr<T> = *const [T; 0];
498    /// On WASM, we use an atomic pointer to the start and end of the section.
499    #[cfg(target_family = "wasm")]
500    pub type SectionPtr<T> =
501        &'static ::core::sync::atomic::AtomicPtr<::core::marker::PhantomData<T>>;
502
503    mod sealed {
504        pub trait FromRawSection {}
505
506        impl FromRawSection for crate::Section {}
507
508        impl<T> FromRawSection for crate::TypedSection<T> {}
509    }
510}
511
512/// Define a link section.
513///
514/// # Example
515/// ```rust
516/// use link_section::{in_section, section};
517///
518/// #[section]
519/// pub static DATA_SECTION: link_section::Section;
520///
521/// #[in_section(DATA_SECTION)]
522/// pub fn data_function() {
523///     println!("data_function");
524/// }
525/// ```
526#[cfg(feature = "proc_macro")]
527pub use ::link_section_proc_macro::section;
528
529/// Place an item into a link section.
530///
531/// # Functions and typed sections
532///
533/// As a special case, since function declarations by themselves are not sized,
534/// functions in typed sections are split and stored as function pointers.
535#[cfg(feature = "proc_macro")]
536pub use ::link_section_proc_macro::in_section;
537
538/// An untyped link section that can be used to store any type. The underlying
539/// data is not enumerable.
540#[repr(C)]
541pub struct Section {
542    name: &'static str,
543    start: __support::SectionPtr<()>,
544    end: __support::SectionPtr<()>,
545}
546
547#[cfg(target_family = "wasm")]
548impl Section {
549    /// The start address of the section.
550    pub fn start_ptr(&self) -> *const () {
551        let ptr = self.start.load(::core::sync::atomic::Ordering::Relaxed) as *const ();
552        if ptr.is_null() {
553            panic!(
554                "Section {} was not initialized by the host environment",
555                self.name
556            );
557        }
558        ptr
559    }
560    /// The end address of the section.
561    pub fn end_ptr(&self) -> *const () {
562        let ptr = self.end.load(::core::sync::atomic::Ordering::Relaxed) as *const ();
563        if ptr.is_null() {
564            panic!(
565                "Section {} was not initialized by the host environment",
566                self.name
567            );
568        }
569        ptr
570    }
571    /// The byte length of the section.
572    pub fn byte_len(&self) -> usize {
573        unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
574    }
575}
576
577#[cfg(not(target_family = "wasm"))]
578impl Section {
579    /// The start address of the section.
580    pub const fn start_ptr(&self) -> *const () {
581        self.start as *const ()
582    }
583    /// The end address of the section.
584    pub const fn end_ptr(&self) -> *const () {
585        self.end as *const ()
586    }
587    /// The byte length of the section.
588    pub const fn byte_len(&self) -> usize {
589        unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
590    }
591}
592
593impl ::core::fmt::Debug for Section {
594    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
595        f.debug_struct("Section")
596            .field("name", &self.name)
597            .field("start", &self.start_ptr())
598            .field("end", &self.end_ptr())
599            .field("byte_len", &self.byte_len())
600            .finish()
601    }
602}
603
604unsafe impl Sync for Section {}
605unsafe impl Send for Section {}
606
607/// A typed link section that can be used to store any sized type. The
608/// underlying data is enumerable.
609#[repr(C)]
610pub struct TypedSection<T: 'static> {
611    name: &'static str,
612    start: __support::SectionPtr<T>,
613    end: __support::SectionPtr<T>,
614    _phantom: ::core::marker::PhantomData<T>,
615}
616
617#[cfg(target_family = "wasm")]
618impl<T: 'static> TypedSection<T> {
619    /// The stride of the typed section.
620    pub const fn stride(&self) -> usize {
621        assert!(
622            ::core::mem::size_of::<T>() > 0
623                && ::core::mem::size_of::<T>() * 2 == ::core::mem::size_of::<[T; 2]>()
624        );
625        ::core::mem::size_of::<T>()
626    }
627
628    /// The start address of the section.
629    pub fn start_ptr(&self) -> *const T {
630        let ptr = self.start.load(::core::sync::atomic::Ordering::Relaxed) as *const T;
631        if ptr.is_null() {
632            panic!(
633                "TypedSection {} was not initialized by the host environment",
634                self.name
635            );
636        }
637        ptr
638    }
639
640    /// The end address of the section.
641    pub fn end_ptr(&self) -> *const T {
642        let ptr = self.end.load(::core::sync::atomic::Ordering::Relaxed) as *const T;
643        if ptr.is_null() {
644            panic!(
645                "TypedSection {} was not initialized by the host environment",
646                self.name
647            );
648        }
649        ptr
650    }
651
652    /// The byte length of the section.
653    pub fn byte_len(&self) -> usize {
654        unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
655    }
656
657    /// The number of elements in the section.
658    pub fn len(&self) -> usize {
659        self.byte_len() / self.stride()
660    }
661
662    /// True if the section is empty.
663    pub fn is_empty(&self) -> bool {
664        self.len() == 0
665    }
666
667    /// The section as a slice.
668    pub fn as_slice(&self) -> &[T] {
669        if self.is_empty() {
670            &[]
671        } else {
672            unsafe { ::core::slice::from_raw_parts(self.start_ptr(), self.len()) }
673        }
674    }
675}
676
677#[cfg(not(target_family = "wasm"))]
678impl<T: 'static> TypedSection<T> {
679    /// The stride of the typed section.
680    pub const fn stride(&self) -> usize {
681        assert!(
682            ::core::mem::size_of::<T>() > 0
683                && ::core::mem::size_of::<T>() * 2 == ::core::mem::size_of::<[T; 2]>()
684        );
685        ::core::mem::size_of::<T>()
686    }
687
688    /// The start address of the section.
689    pub const fn start_ptr(&self) -> *const T {
690        self.start as *const T
691    }
692
693    /// The end address of the section.
694    pub const fn end_ptr(&self) -> *const T {
695        self.end as *const T
696    }
697
698    /// The byte length of the section.
699    pub const fn byte_len(&self) -> usize {
700        unsafe { (self.end_ptr() as *const u8).offset_from(self.start_ptr() as *const u8) as usize }
701    }
702
703    /// The number of elements in the section.
704    pub const fn len(&self) -> usize {
705        self.byte_len() / self.stride()
706    }
707
708    /// True if the section is empty.
709    pub const fn is_empty(&self) -> bool {
710        self.len() == 0
711    }
712
713    /// The section as a slice.
714    pub const fn as_slice(&self) -> &[T] {
715        if self.is_empty() {
716            &[]
717        } else {
718            unsafe { ::core::slice::from_raw_parts(self.start_ptr(), self.len()) }
719        }
720    }
721
722    /// The section as a mutable slice.
723    ///
724    /// # Safety
725    ///
726    /// This cannot be safely used and is _absolutely unsound_ if any other
727    /// slices are live.
728    #[allow(clippy::mut_from_ref)]
729    pub unsafe fn as_mut_slice(&self) -> &mut [T] {
730        if self.is_empty() {
731            &mut []
732        } else {
733            unsafe { ::core::slice::from_raw_parts_mut(self.start_ptr() as *mut T, self.len()) }
734        }
735    }
736}
737
738impl<'a, T> ::core::iter::IntoIterator for &'a TypedSection<T> {
739    type Item = &'a T;
740    type IntoIter = ::core::slice::Iter<'a, T>;
741    fn into_iter(self) -> Self::IntoIter {
742        self.as_slice().iter()
743    }
744}
745
746impl<T> ::core::ops::Deref for TypedSection<T> {
747    type Target = [T];
748    fn deref(&self) -> &Self::Target {
749        self.as_slice()
750    }
751}
752
753impl<T> ::core::fmt::Debug for TypedSection<T> {
754    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
755        f.debug_struct("TypedSection")
756            .field("name", &self.name)
757            .field("start", &self.start_ptr())
758            .field("end", &self.end_ptr())
759            .field("len", &self.len())
760            .field("stride", &self.stride())
761            .finish()
762    }
763}
764
765unsafe impl<T> Sync for TypedSection<T> where T: Sync {}
766unsafe impl<T> Send for TypedSection<T> where T: Send {}