Skip to main content

link_section/
lib.rs

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