#![doc = concat!("```rust\n", include_str!("../examples/slice.rs"), "\n```\n")]
use link_section::TypedSection;
#[doc = concat!("```rust\n", include_str!("../examples/slice.rs"), "\n```\n")]
pub struct ScatteredSlice<T: 'static> {
section: &'static TypedSection<T>,
}
impl<T> ScatteredSlice<T> {
#[doc(hidden)]
#[allow(unsafe_code)]
pub const unsafe fn new(section: &'static TypedSection<T>) -> Self {
Self { section }
}
}
impl<T> ::core::ops::Deref for ScatteredSlice<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.section
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! __slice {
(@gather $(#[$meta:meta])* $vis:vis static $name:ident: $collection:ident < $ty:ty >;) => {
#[doc(hidden)]
#[allow(unused)]
$vis use $crate::__slice as $name;
$(#[$meta])*
$vis static $name: $collection<$ty> = {
$crate::__support::link_section::declarative::section!(
#[section(typed)]
static $name: $crate::__support::link_section::TypedSection<$ty>;
);
unsafe { $crate::slice::ScatteredSlice::new(
$name.const_deref()
) }
};
};
(@scatter [$($meta:tt)*] $(#[$imeta:meta])* $vis:vis $type:ident $name:tt: $ty:ty = $expr:expr;) => {
$crate::__support::link_section::declarative::in_section!(
#[in_section(unsafe, name = $($meta)*, type = typed)]
$(#[$imeta])*
$vis $type $name: $ty = $expr;
);
};
(($collection:ident => $(#[$imeta:meta])* $vis:vis $type:ident $name:tt: $ty:ty = $expr:expr;)) => {
$crate::__slice!(
@scatter [$collection]
$(#[$imeta])*
$vis $type $name: $ty = $expr;
);
};
}
#[cfg(all(test, not(miri)))]
mod tests {
pub use super::ScatteredSlice;
__slice!(@gather pub static TEST_SLICE: ScatteredSlice<u32>;);
__slice!(@scatter [TEST_SLICE] const _: u32 = 1;);
__slice!(@scatter [TEST_SLICE] const _: u32 = 3;);
__slice!(@scatter [TEST_SLICE] const _: u32 = 2;);
#[test]
fn test_scattered_slice() {
assert_eq!(TEST_SLICE.len(), 3);
assert!(TEST_SLICE.contains(&1));
assert!(TEST_SLICE.contains(&2));
assert!(TEST_SLICE.contains(&3));
}
}