use core::hint;
use core::mem;
use core::ops::Deref;
use core::slice;
use crate::__private::Slice;
pub struct DistributedSlice<T: ?Sized + Slice> {
name: &'static str,
section_start: StaticPtr<T::Element>,
section_stop: StaticPtr<T::Element>,
dupcheck_start: StaticPtr<usize>,
dupcheck_stop: StaticPtr<usize>,
}
struct StaticPtr<T> {
ptr: *const T,
}
unsafe impl<T> Send for StaticPtr<T> {}
unsafe impl<T> Sync for StaticPtr<T> {}
impl<T> Copy for StaticPtr<T> {}
impl<T> Clone for StaticPtr<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> DistributedSlice<[T]> {
#[doc(hidden)]
#[cfg(any(
target_os = "none",
target_os = "linux",
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "illumos",
target_os = "freebsd"
))]
pub const unsafe fn private_new(
name: &'static str,
section_start: *const T,
section_stop: *const T,
dupcheck_start: *const usize,
dupcheck_stop: *const usize,
) -> Self {
DistributedSlice {
name,
section_start: StaticPtr { ptr: section_start },
section_stop: StaticPtr { ptr: section_stop },
dupcheck_start: StaticPtr {
ptr: dupcheck_start,
},
dupcheck_stop: StaticPtr { ptr: dupcheck_stop },
}
}
#[doc(hidden)]
#[cfg(target_os = "windows")]
pub const unsafe fn private_new(
name: &'static str,
section_start: *const [T; 0],
section_stop: *const [T; 0],
dupcheck_start: *const (),
dupcheck_stop: *const (),
) -> Self {
DistributedSlice {
name,
section_start: StaticPtr {
ptr: section_start as *const T,
},
section_stop: StaticPtr {
ptr: section_stop as *const T,
},
dupcheck_start: StaticPtr {
ptr: dupcheck_start as *const usize,
},
dupcheck_stop: StaticPtr {
ptr: dupcheck_stop as *const usize,
},
}
}
#[doc(hidden)]
#[inline]
pub unsafe fn private_typecheck(self, element: T) {
mem::forget(element);
}
}
impl<T> DistributedSlice<[T]> {
pub fn static_slice(self) -> &'static [T] {
if self.dupcheck_start.ptr.wrapping_add(1) < self.dupcheck_stop.ptr {
panic!("duplicate #[distributed_slice] with name \"{}\"", self.name);
}
let stride = mem::size_of::<T>();
let start = self.section_start.ptr;
let stop = self.section_stop.ptr;
let byte_offset = stop as usize - start as usize;
let len = match byte_offset.checked_div(stride) {
Some(len) => len,
None => unsafe { hint::unreachable_unchecked() },
};
unsafe { slice::from_raw_parts(start, len) }
}
}
impl<T> Copy for DistributedSlice<[T]> {}
impl<T> Clone for DistributedSlice<[T]> {
fn clone(&self) -> Self {
*self
}
}
impl<T: 'static> Deref for DistributedSlice<[T]> {
type Target = [T];
fn deref(&self) -> &'static Self::Target {
self.static_slice()
}
}
impl<T: 'static> IntoIterator for DistributedSlice<[T]> {
type Item = &'static T;
type IntoIter = slice::Iter<'static, T>;
fn into_iter(self) -> Self::IntoIter {
self.static_slice().iter()
}
}