#![doc = concat!("```rust\n", include_str!("../examples/sorted_referenced_slice.rs"), "\n```\n")]
use link_section::TypedMovableSection;
pub type Ref<T> = link_section::MovableRef<T>;
#[doc = include_str!("../examples/sorted_referenced_slice.rs")]
pub struct ScatteredSortedReferencedSlice<T: Ord + 'static> {
data: &'static TypedMovableSection<T>,
_marker: core::marker::PhantomData<T>,
}
impl<T: Ord + 'static> ScatteredSortedReferencedSlice<T> {
#[doc(hidden)]
#[allow(unsafe_code)]
pub const unsafe fn new(data: &'static TypedMovableSection<T>) -> Self {
Self {
data,
_marker: core::marker::PhantomData,
}
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn offset_of(
this: &Self,
item: impl link_section::SectionItemLocation<T>,
) -> Option<usize> {
TypedMovableSection::offset_of(this.data, item)
}
}
impl<T: Ord + 'static> ::core::ops::Deref for ScatteredSortedReferencedSlice<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.data.as_slice()
}
}
impl<T: Ord + 'static> ::core::iter::IntoIterator for &'static ScatteredSortedReferencedSlice<T> {
type Item = &'static T;
type IntoIter = ::core::slice::Iter<'static, T>;
fn into_iter(self) -> Self::IntoIter {
self.data.as_slice().iter()
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __sorted_referenced_slice {
(@gather $unique:ident $(#[$meta:meta])* $vis:vis static $name:ident: ($($collection:tt)*) < $ty:ty >;) => {
$(#[$meta])*
$vis static $name: $($collection)* <$ty> = const {
$crate::__support::link_section::declarative::section!(
#[section(unsafe, type = movable, name = $name :: $unique)]
static $name: $crate::__support::link_section::TypedMovableSection<$ty>;
);
$crate::__support::ctor::declarative::ctor!(
#[ctor(unsafe, anonymous, priority = 0)]
fn __sorted_referenced_slice_init() {
unsafe {
$name.sort_unstable();
}
}
);
unsafe {
$crate::sorted_referenced_slice::ScatteredSortedReferencedSlice::new($name.const_deref())
}
};
};
(@scatter [$collection_name:ident :: $unique:ident] $types:tt ([$($meta:tt)*] => $(#[$imeta:meta])* $vis:vis static $name:ident: $ty:ty = $expr:expr;)) => {
$crate::__support::link_section::declarative::in_section!(
#[in_section(unsafe, name = $collection_name :: $unique, type = movable)]
$(#[$imeta])*
$vis static $name: $ty = $expr;
);
};
}
#[cfg(all(test, not(miri)))]
mod tests {
use crate::sorted_referenced_slice::{Ref, ScatteredSortedReferencedSlice};
__sorted_referenced_slice!(@gather A pub static TEST_SORT_REF: (ScatteredSortedReferencedSlice)<u32>;);
__sorted_referenced_slice!(@scatter [TEST_SORT_REF::A] [u32] ([TEST_SORT_REF] => pub static SORT_REF_ITEM_A: u32 = 1;));
__sorted_referenced_slice!(@scatter [TEST_SORT_REF::A] [u32] ([TEST_SORT_REF] => pub static SORT_REF_ITEM_B: u32 = 3;));
__sorted_referenced_slice!(@scatter [TEST_SORT_REF::A] [u32] ([TEST_SORT_REF] => pub static SORT_REF_ITEM_C: u32 = 2;));
#[test]
fn test_scattered_sorted_referenced_slice() {
assert_eq!(TEST_SORT_REF.len(), 3);
assert_eq!(&*TEST_SORT_REF, [1, 2, 3].as_slice());
let a: &Ref<u32> = &SORT_REF_ITEM_A;
assert_eq!(**a, 1);
assert_eq!(*SORT_REF_ITEM_B, 3);
assert_eq!(*SORT_REF_ITEM_C, 2);
}
__sorted_referenced_slice!(@gather B pub static EMPTY_SORT_REF: (ScatteredSortedReferencedSlice)<u32>;);
#[test]
fn test_empty_scattered_sorted_referenced_slice() {
assert_eq!(EMPTY_SORT_REF.len(), 0);
assert!(EMPTY_SORT_REF.is_empty());
assert_eq!(&*EMPTY_SORT_REF, &[] as &[u32]);
}
}