#![doc = include_str!("../docs/BUILD.md")]
#![doc = include_str!("../docs/PREAMBLE.md")]
#![allow(unsafe_code)]
#![cfg_attr(linktime_used_linker, doc(test(attr(feature(used_with_arg)))))]
#![no_std]
#[doc = include_str!("../docs/LIFE_BEFORE_MAIN.md")]
pub mod life_before_main {}
#[cfg(target_family = "wasm")]
mod wasm;
#[cfg(target_family = "wasm")]
extern crate alloc;
pub mod declarative {
pub use crate::__in_section_parse as in_section;
pub use crate::__section_parse as section;
}
#[doc(hidden)]
pub mod __support {
pub use crate::__add_section_link_attribute as add_section_link_attribute;
pub use crate::__def_section_name as def_section_name;
pub use crate::__get_section as get_section;
pub use crate::__in_section_crate as in_section_crate;
pub use crate::__in_section_parse as in_section_parse;
pub use crate::__section_parse as section_parse;
#[cfg(feature = "proc_macro")]
pub use linktime_proc_macro::hash;
#[cfg(feature = "proc_macro")]
pub use linktime_proc_macro::ident_concat;
#[cfg(target_family = "wasm")]
extern "C" {
pub(crate) fn read_custom_section(
name: *const u8,
name_length: usize,
target_address: *mut u8,
target_address_length: usize,
) -> usize;
}
#[cfg(target_family = "wasm")]
pub use crate::wasm::{register_wasm_link_section_item, LinkSectionRawInfo};
#[cfg(all(not(miri), target_os = "windows"))]
pub use section::Alignment;
#[macro_export]
#[doc(hidden)]
macro_rules! __def_section_name {
(
{$(
$__section:ident $__type:ident => $__prefix:tt __ $__suffix:tt;
)*}
AUXILIARY = $__aux_sep:literal;
MAX_LENGTH = $__max_length:literal;
HASH_LENGTH = $__hash_length:literal;
VALID_SECTION_CHARS = $__valid_section_chars:literal;
) => {
#[macro_export]
#[doc(hidden)]
macro_rules! __section_name {
$(
(raw $__section $__type $name:ident) => {
concat!(concat! $__prefix, stringify!($name), concat! $__suffix);
};
(raw $__section $__type $name:ident $aux:ident) => {
concat!(concat! $__prefix, stringify!($name), $__aux_sep, stringify!($aux), concat! $__suffix);
};
($pattern:tt $__section $__type $name:ident) => {
$crate::__support::hash!($pattern ($__prefix) $name ($__suffix) $__hash_length $__max_length $__valid_section_chars);
};
($pattern:tt $__section $__type $name:ident $aux:ident) => {
$crate::__support::hash!($pattern ($__prefix) ($name $__aux_sep $aux) ($__suffix) $__hash_length $__max_length $__valid_section_chars);
};
)*
($pattern:tt $unknown_section:ident $unknown_type:ident $name:ident) => {
const _: () = {
compile_error!(concat!("Unknown section type: `", stringify!($unknown_section), "/", stringify!($unknown_type), "`"));
};
};
}
};
}
#[cfg(not(linktime_used_linker))]
#[doc(hidden)]
#[macro_export]
macro_rules! __add_used {
(
$section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
$(#[$meta:meta])*
$vis:vis static $ident:ident : $($static:tt)*
) => {
$crate::__add_section_link_attribute_impl!(
$section $type $name $($aux)? #[$attr = __]
$(#[$meta])*
#[used]
#[cfg_attr(target_os = "aix", export_name = concat!("_", env!("CARGO_PKG_NAME"), "_",
::core::module_path!(), "_",
stringify!($ident),
"_L", line!(), "C", column!()))]
$vis static $ident : $($static)*
);
};
}
#[cfg(linktime_used_linker)]
#[doc(hidden)]
#[macro_export]
macro_rules! __add_used {
(
$section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
$(#[$meta:meta])*
$vis:vis static $ident:ident : $($static:tt)*
) => {
$crate::__add_section_link_attribute_impl!(
$section $type $name $($aux)? #[$attr = __]
$(#[$meta])*
#[used(linker)]
#[cfg_attr(target_os = "aix", export_name = concat!("_", env!("CARGO_PKG_NAME"), "_",
::core::module_path!(), "_",
stringify!($ident),
"_L", line!(), "C", column!()))]
$vis static $ident : $($static)*
);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __add_section_link_attribute(
($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
$(#[$meta:meta])*
$vis:vis static $($static:tt)*
) => {
$crate::__add_used!(
$section $type $name $($aux)? #[$attr = __]
$(#[$meta])*
$vis static $($static)*
);
};
($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
extern "C" {
$(#[$meta:meta])*
$vis:vis static $($static:tt)*
}
) => {
extern "C" {
$crate::__add_section_link_attribute_impl!(
$section $type $name $($aux)? #[$attr = __]
$(#[$meta])*
#[allow(unsafe_code)]
$vis static $($static)*
);
}
};
($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __]
$($item:tt)*) => {
$crate::__add_section_link_attribute_impl!(
$section $type $name $($aux)? #[$attr = __]
#[allow(unsafe_code)]
$($item)*
);
};
);
#[cfg(feature = "proc_macro")]
#[doc(hidden)]
#[macro_export]
macro_rules! __add_section_link_attribute_impl(
($section:ident $type:ident $name:ident $($aux:ident)? #[$attr:ident = __] $($item:tt)*) => {
$crate::__section_name!(
(#[$attr = __] #[allow(unsafe_code)] $($item)*)
$section $type $name $($aux)?
);
}
);
#[cfg(not(feature = "proc_macro"))]
#[doc(hidden)]
#[macro_export]
macro_rules! __add_section_link_attribute_impl(
($section:ident $type:ident $name:ident #[$attr:ident = __] $($item:tt)*) => {
#[$attr = $crate::__section_name!(
raw $section $type $name
)] $($item)*
}
);
#[cfg(target_vendor = "apple")]
def_section_name! {
{
data bare => ("__DATA,") __ ();
code bare => ("__TEXT,") __ ();
data section => ("__DATA,") __ (",regular,no_dead_strip");
code section => ("__TEXT,") __ (",regular,pure_instructions");
data start => ("\x01section$start$__DATA$") __ ();
data end => ("\x01section$end$__DATA$") __ ();
}
AUXILIARY = "_";
MAX_LENGTH = 16;
HASH_LENGTH = 6;
VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
}
#[cfg(target_family = "wasm")]
def_section_name! {
{
data bare => (".data", ".link_section.") __ ();
data section => (".data", ".link_section.") __ ();
code bare => (".text", ".link_section.") __ ();
code section => (".text", ".link_section.") __ ();
data bounds => (".data", ".link_section.") __ (".bounds");
}
AUXILIARY = ".";
MAX_LENGTH = 16;
HASH_LENGTH = 6;
VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
}
#[cfg(all(
not(target_vendor = "apple"),
not(target_os = "windows"),
not(target_family = "wasm")
))]
def_section_name! {
{
data bare => ("_data", "_link_section_") __ ();
data section => ("_data", "_link_section_") __ ();
data start => ("__start_", "_data", "_link_section_") __ ();
data end => ("__stop_", "_data", "_link_section_") __ ();
code bare => ("_text", "_link_section_") __ ();
code section => ("_text", "_link_section_") __ ();
code start => ("__start_", "_text", "_link_section_") __ ();
code end => ("__stop_", "_text", "_link_section_") __ ();
}
AUXILIARY = "_";
MAX_LENGTH = 64;
HASH_LENGTH = 10;
VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
}
#[cfg(target_os = "windows")]
def_section_name! {
{
data bare => (".data", "$") __ ();
data section => (".data", "$") __ ("$b");
data start => (".data", "$") __ ("$a");
data end => (".data", "$") __ ("$c");
code bare => (".text", "$") __ ();
code section => (".text", "$") __ ("$b");
code start => (".text", "$") __ ("$a");
code end => (".text", "$") __ ("$c");
}
AUXILIARY = "$d$";
MAX_LENGTH = 64;
HASH_LENGTH = 10;
VALID_SECTION_CHARS = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
}
#[cfg(not(feature = "proc_macro"))]
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_macro {
($vis:vis $ident:ident $generic_macro:ident $args:tt) => {
#[doc(hidden)]
$vis use $crate::$generic_macro as $ident;
};
}
#[cfg(feature = "proc_macro")]
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_macro {
($vis:vis $ident:ident $generic_macro:ident $args:tt) => {
$crate::__support::ident_concat!(
(#[macro_export]
#[doc(hidden)]
macro_rules!) (__ $ident __link_section_private_macro__) ({
($passthru:tt) => {
$crate::$generic_macro!($passthru $args);
};
})
);
$crate::__support::ident_concat!(
(#[doc(hidden)] pub use) (__ $ident __link_section_private_macro__) (as $ident;)
);
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! __section_parse {
(#[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* < $($generic:tt)*) => {
$crate::__section_parse!(@parsed #[section $($args)*] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* < $($generic)*) ( $($generic)* ) __in_section_helper_macro_generic);
};
(#[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $(:: $path_prefix:ident ::)? $($path:ident)::* ;) => {
$crate::__section_parse!(@parsed #[section $($args)*] $(#[$meta])* $vis static $ident: ( $(:: $path_prefix ::)? $($path)::* ;) ( () > ; ) __in_section_helper_macro_no_generic);
};
(@parsed #[section(aux = $name:ident, no_macro)] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
$crate::__section_parse!(@generate #[section(aux = $name)] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
};
(@parsed #[section(no_macro)] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
$crate::__section_parse!(@generate #[section] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
};
(@parsed #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : ($ty:ty ;) ( $generic_ty:ty > ; ) $generic_macro:ident) => {
$crate::__declare_macro!($vis $ident $generic_macro ($($args)*));
$crate::__section_parse!(@generate #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, $generic_macro);
};
(@generate #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __in_section_helper_macro_generic) => {
$crate::__section_parse!(@generate #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, __base_case__);
impl ::core::iter::IntoIterator for $ident {
type Item = &'static $generic_ty;
type IntoIter = ::core::slice::Iter<'static, $generic_ty>;
fn into_iter(self) -> Self::IntoIter {
$ident.as_slice().iter()
}
}
};
(@generate #[section $($args:tt)*] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, $generic_macro:ident) => {
$(#[$meta])*
#[allow(non_camel_case_types)]
$vis struct $ident;
impl $crate::__support::SectionItemType for $ident {
type Item = $generic_ty;
}
impl ::core::fmt::Debug for $ident {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
::core::ops::Deref::deref(self).fmt(f)
}
}
impl ::core::ops::Deref for $ident {
type Target = $ty;
fn deref(&self) -> &Self::Target {
self.const_deref()
}
}
$crate::__section_parse!(@deref #[section $($args)*] $(#[$meta])* $vis static $ident: $ty, $generic_ty, __base_case__);
};
(@deref #[section] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __base_case__) => {
impl $ident {
pub const fn const_deref(&self) -> &$ty {
static SECTION: $ty = {
let section = $crate::__support::get_section!(name=$ident, type=$generic_ty, aux=);
let name = $crate::__section_name!(
raw data bare $ident
);
unsafe { <$ty>::new(name, section) }
};
&SECTION
}
}
};
(@deref #[section(aux=$aux:ident)] $(#[$meta:meta])* $vis:vis static $ident:ident : $ty:ty, $generic_ty:ty, __base_case__) => {
impl $ident {
pub const fn const_deref(&self) -> &$ty {
static SECTION: $ty = {
let section = $crate::__support::get_section!(name=$ident, type=$generic_ty, aux=$aux);
let name = $crate::__section_name!(
raw data bare $aux $ident );
unsafe { <$ty>::new(name, section) }
};
&SECTION
}
}
};
}
#[cfg(miri)]
mod section {
#[doc(hidden)]
#[macro_export]
macro_rules! __get_section {
(name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {{
$crate::__support::PtrBounds::new(core::ptr::null_mut(), core::ptr::null_mut())
}};
}
pub type Bounds = crate::__support::PtrBounds;
}
#[cfg(all(not(miri), target_family = "wasm"))]
mod section {
#[doc(hidden)]
#[macro_export]
macro_rules! __get_section {
(name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
{
static __LINK_SECTION_NAME: &'static str = $crate::__section_name!(
raw data bare $ident $($aux)?
);
$crate::__support::add_section_link_attribute!(
data bounds $ident $($aux)?
#[export_name = __]
#[used]
static __LINK_SECTION_INFO: $crate::__support::LinkSectionRawInfo = $crate::__support::LinkSectionRawInfo::new::<$generic_ty>(__LINK_SECTION_NAME);
);
unsafe { $crate::__support::Bounds::new(&raw const __LINK_SECTION_INFO) }
}
}
}
pub use crate::wasm::Bounds;
}
#[cfg(all(not(miri), target_os = "windows"))]
mod section {
#[doc(hidden)]
#[macro_export]
macro_rules! __get_section {
(name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
{
use $crate::__support::Alignment;
use $crate::__support::PtrBounds;
use $crate::__support::add_section_link_attribute;
use core::mem;
add_section_link_attribute!(
data start $ident $($aux)?
#[link_section = __]
static __START: Alignment<$generic_ty> = Alignment::new();
);
add_section_link_attribute!(
data end $ident $($aux)?
#[link_section = __]
static __END: Alignment<$generic_ty> = Alignment::new();
);
PtrBounds::new(
unsafe {
let start = &raw const __START;
start.cast::<u8>().add(mem::size_of::<Alignment<$generic_ty>>()) as *const()
},
unsafe { &raw const __END as *const () },
)
}
}
}
#[repr(C)]
pub struct Alignment<T> {
_align: [T; 0],
_padding: u8,
}
#[allow(clippy::new_without_default)]
impl<T> Alignment<T> {
pub const fn new() -> Self {
Self {
_align: [],
_padding: 0,
}
}
}
pub type Bounds = crate::__support::PtrBounds;
}
#[cfg(all(not(miri), not(target_family = "wasm"), not(target_os = "windows")))]
mod section {
#[doc(hidden)]
#[macro_export]
macro_rules! __get_section {
(name=$ident:ident, type=$generic_ty:ty, aux=$($aux:ident)?) => {
{
$crate::__support::add_section_link_attribute!(
data start $ident $($aux)?
#[link_name = __]
extern "C" {
static __START: u8;
}
);
$crate::__support::add_section_link_attribute!(
data end $ident $($aux)?
#[link_name = __]
extern "C" {
static __END: u8;
}
);
$crate::__support::PtrBounds::new(
unsafe { &raw const __START as *const () },
unsafe { &raw const __END as *const () },
)
}
}
}
pub type Bounds = crate::__support::PtrBounds;
}
#[macro_export]
#[doc(hidden)]
macro_rules! __in_section_parse {
(#[in_section(unsafe, type = $stored_ty:ty, name = $ident:ident $( , aux = $aux:ident)?)] $($item:tt)*) => {
$crate::__support::in_section_crate!((type = $stored_ty), $ident, $($aux)?, $ident, ($($item)*));
};
(#[in_section(unsafe, name = $ident:ident $( , aux = $aux:ident)?)] $($item:tt)*) => {
$crate::__support::in_section_crate!(data, $ident, $($aux)?, $ident, ($($item)*));
};
(#[in_section( $($path:tt)* )] $($item:tt)*) => {
$crate::__support::in_section_parse!(path=[$($path)*] #[in_section($($path)*)] $($item)*);
};
(path=[$orig_path:path] #[in_section($name:ident)] $($item:tt)*) => {
$orig_path ! (
(v=0 (name=$name (path=[$orig_path] (item=($($item)*) ()))))
);
};
(path=[$orig_path:path] #[in_section(:: $($path:ident)::*)] $($item:tt)*) => {
$crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
};
(path=[$orig_path:path] #[in_section($prefix:ident :: $($path:ident)::*)] $($item:tt)*) => {
$crate::__support::in_section_parse!(path=[$orig_path] #[in_section($($path)::*)] $($item)*);
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __in_section_helper_macro_generic {
((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt))))) => {
$crate::__support::in_section_crate!(section, $ident,, $path, $item);
};
((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) ((aux=$aux:ident)) )=> {
$crate::__support::in_section_crate!(section, $ident, $aux, $path, $item);
};
((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) () )=> {
$crate::__support::in_section_crate!(section, $ident,, $path, $item);
};
((v=$v:literal $rest:tt)) => {
const _: () = {
compile_error!(concat!(
"link-section: Unsupported version: `",
stringify!($v),
"`: ",
stringify!($rest)
));
};
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __in_section_helper_macro_no_generic {
((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt))))) => {
$crate::__support::in_section_crate!(data, $ident,, $path, $item);
};
((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) ((aux=$aux:ident)) )=> {
$crate::__support::in_section_crate!(data, $ident, $aux, $path, $item);
};
((v=0 (name=$ident:ident (path=[$path:path] (item=$item:tt $rest:tt)))) () )=> {
$crate::__support::in_section_crate!(data, $ident,, $path, $item);
};
((v=$v:literal $rest:tt)) => {
const _: () = {
compile_error!(concat!(
"link-section: Unsupported version: `",
stringify!($v),
"`: ",
stringify!($rest)
));
};
};
}
#[macro_export]
#[doc(hidden)]
#[allow(unknown_lints, edition_2024_expr_fragment_specifier)]
macro_rules! __in_section_crate {
(@type_select section $path:path, $item_ty:ty) => {
<$path as $crate::__support::SectionItemType>::Item
};
(@type_select data $path:path, $item_ty:ty) => {
$item_ty
};
(@type_select (type = $stored_ty:ty) $path:path, $item_ty:ty) => {
$stored_ty
};
($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis fn $ident_fn:ident($($args:tt)*) $(-> $ret:ty)? $body:block)) => {
$crate::__in_section_crate!($type_source, $ident, $($aux)?, $path, (
const _: fn($($args)*) $(-> $ret)? = $ident_fn;
));
$crate::__add_section_link_attribute!(
code section $ident $($aux)?
#[link_section = __]
$(#[$meta])*
$vis fn $ident_fn($($args)*) $(-> $ret)? $body
);
};
($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis static _ : $ty:ty = $value:expr;)) => {
$crate::__in_section_crate!($type_source, $ident, $($aux)?, $path, (
$(#[$meta])*
const _: fn($($args)*) $(-> $ret)? = $ident_fn;
));
};
($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis static $ident_static:ident : $ty:ty = $value:expr;)) => {
#[cfg(target_family = "wasm")]
compile_error!("static items are not supported on WASM: use const items instead");
#[cfg(not(target_family = "wasm"))]
$crate::__add_section_link_attribute!(
data section $ident $($aux)?
#[link_section = __]
$(#[$meta])*
$vis static $ident_static: $crate::__in_section_crate!(@type_select $type_source $path, $ty) = $value;
);
};
($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis const $name:ident: $ty:ty = $value:expr;)) => {
$(#[$meta])* $vis const $name: $ty = {
type __InSecStoredTy = $crate::__in_section_crate!(@type_select $type_source $path, $ty);
const __LINK_SECTION_CONST_ITEM_VALUE: __InSecStoredTy = $value;
#[cfg(target_family = "wasm")]
{
$crate::__add_section_link_attribute!(
data section $ident $($aux)?
#[link_section = __]
$vis static __LINK_SECTION_CONST_ITEM: u8 = 0;
);
$crate::__add_section_link_attribute!(
data bounds $ident $($aux)?
#[link_name = __]
extern "C" {
static __LINK_SECTION_INFO: $crate::__support::LinkSectionRawInfo;
}
);
#[link_section = ".init_array.0"]
static __LINK_SECTION_ITEM_FN_REF: extern "C" fn() = {
extern "C" fn __LINK_SECTION_ITEM_FN() {
static DISARMED: ::core::sync::atomic::AtomicBool = ::core::sync::atomic::AtomicBool::new(false);
if DISARMED.swap(true, ::core::sync::atomic::Ordering::Relaxed) {
return;
}
unsafe {
let ptr = $crate::__support::register_wasm_link_section_item(&raw const __LINK_SECTION_INFO);
::core::ptr::write(ptr as *mut __InSecStoredTy, __LINK_SECTION_CONST_ITEM_VALUE);
}
}
__LINK_SECTION_ITEM_FN
};
}
#[cfg(not(target_family = "wasm"))]
$crate::__add_section_link_attribute!(
data section $ident $($aux)?
#[link_section = __]
$(#[$meta])*
$vis static __LINK_SECTION_CONST_ITEM: __InSecStoredTy = __LINK_SECTION_CONST_ITEM_VALUE;
);
__LINK_SECTION_CONST_ITEM_VALUE
};
};
($type_source:tt, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $vis:vis const _: $ty:ty = $value:expr;)) => {
$(#[$meta])* $vis const _: () = {
type __InSecStoredTy = $crate::__in_section_crate!(@type_select $type_source $path, $ty);
$crate::__add_section_link_attribute!(
data section $ident $($aux)?
#[link_section = __]
$(#[$meta])*
$vis static __LINK_SECTION_CONST_ITEM: __InSecStoredTy = $value;
);
};
};
(data, $ident:ident, $($aux:ident)?, $path:path, ($(#[$meta:meta])* $item:item)) => {
$crate::__add_section_link_attribute!(
data section $ident $($aux)?
#[link_section = __]
$(#[$meta])*
$item
);
};
}
pub trait SectionItemType {
type Item;
}
impl<T> SectionItemType for super::TypedSection<T> {
type Item = T;
}
pub struct PtrBounds {
pub start: *const (),
pub end: *const (),
}
impl PtrBounds {
pub const fn new(start: *const (), end: *const ()) -> Self {
Self { start, end }
}
#[inline(always)]
pub const fn start_ptr(&self) -> *const () {
self.start
}
#[inline(always)]
pub const fn end_ptr(&self) -> *const () {
self.end
}
#[inline(always)]
pub const fn byte_len(&self) -> usize {
unsafe { (self.end.cast::<u8>()).offset_from(self.start.cast::<u8>()) as usize }
}
}
pub use section::Bounds;
}
#[cfg(feature = "proc_macro")]
pub use ::linktime_proc_macro::section;
#[cfg(feature = "proc_macro")]
pub use ::linktime_proc_macro::in_section;
#[repr(C)]
pub struct Section {
name: &'static str,
bounds: __support::Bounds,
}
impl Section {
#[doc(hidden)]
pub const unsafe fn new(name: &'static str, bounds: __support::Bounds) -> Self {
Self { name, bounds }
}
#[inline]
pub fn byte_len(&self) -> usize {
self.bounds.byte_len()
}
#[inline]
pub fn start_ptr(&self) -> *const () {
self.bounds.start_ptr()
}
#[inline]
pub fn end_ptr(&self) -> *const () {
self.bounds.end_ptr()
}
}
impl ::core::fmt::Debug for Section {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.debug_struct("Section")
.field("name", &self.name)
.field("start", &self.start_ptr())
.field("end", &self.end_ptr())
.field("byte_len", &self.byte_len())
.finish()
}
}
unsafe impl Sync for Section {}
unsafe impl Send for Section {}
#[repr(C)]
pub struct TypedSection<T: 'static> {
name: &'static str,
bounds: __support::Bounds,
_phantom: ::core::marker::PhantomData<T>,
}
impl<T: 'static> TypedSection<T> {
#[doc(hidden)]
pub const unsafe fn new(name: &'static str, bounds: __support::Bounds) -> Self {
Self {
name,
bounds,
_phantom: ::core::marker::PhantomData,
}
}
#[inline(always)]
pub fn start_ptr(&self) -> *const T {
self.bounds.start_ptr() as *const T
}
#[inline(always)]
pub fn end_ptr(&self) -> *const T {
self.bounds.end_ptr() as *const T
}
#[inline]
pub fn start_ptr_mut(&self) -> *mut T {
self.bounds.start_ptr() as *mut T
}
#[inline]
pub fn end_ptr_mut(&self) -> *mut T {
self.bounds.end_ptr() as *mut T
}
#[inline(always)]
pub const fn stride(&self) -> usize {
assert!(
::core::mem::size_of::<T>() > 0
&& ::core::mem::size_of::<T>() * 2 == ::core::mem::size_of::<[T; 2]>()
);
::core::mem::size_of::<T>()
}
#[inline]
pub fn byte_len(&self) -> usize {
self.bounds.byte_len()
}
#[inline]
pub fn len(&self) -> usize {
self.byte_len() / self.stride()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn as_slice(&self) -> &[T] {
if self.is_empty() {
&[]
} else {
unsafe { ::core::slice::from_raw_parts(self.start_ptr(), self.len()) }
}
}
#[inline]
pub fn offset_of(&self, item: &T) -> Option<usize> {
let ptr = item as *const T;
if ptr < self.start_ptr() || ptr >= self.end_ptr() {
None
} else {
Some(unsafe { ptr.offset_from(self.start_ptr()) as usize })
}
}
#[allow(clippy::mut_from_ref)]
#[inline]
pub unsafe fn as_mut_slice(&self) -> &mut [T] {
if self.is_empty() {
&mut []
} else {
unsafe { ::core::slice::from_raw_parts_mut(self.start_ptr() as *mut T, self.len()) }
}
}
}
impl<'a, T> ::core::iter::IntoIterator for &'a TypedSection<T> {
type Item = &'a T;
type IntoIter = ::core::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.as_slice().iter()
}
}
impl<T> ::core::ops::Deref for TypedSection<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<T> ::core::fmt::Debug for TypedSection<T> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.debug_struct("TypedSection")
.field("name", &self.name)
.field("start", &self.start_ptr())
.field("end", &self.end_ptr())
.field("len", &self.len())
.field("stride", &self.stride())
.finish()
}
}
unsafe impl<T> Sync for TypedSection<T> where T: Sync {}
unsafe impl<T> Send for TypedSection<T> where T: Send {}