const generic expr based fixed length array manipulation crate
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs28
1 files changed, 22 insertions, 6 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 164cd7f..110ef45 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -21,7 +21,11 @@
clippy::use_self,
missing_docs
)]
-use core::{array::from_fn, intrinsics::transmute_unchecked, mem::MaybeUninit as MU};
+use core::{
+ array::from_fn,
+ intrinsics::transmute_unchecked,
+ mem::{offset_of, MaybeUninit as MU},
+};
pub mod pervasive;
mod slice;
mod tuple;
@@ -46,16 +50,28 @@ pub mod prelude {
#[repr(C)]
struct Pair<X, Y>(X, Y);
impl<X, Y> Pair<X, Y> {
- const unsafe fn into(self) -> (X, Y) {
- // SAFETY: this is unsound, as the layout of the tuple may change.
- // crater? you there yet?
- unsafe { transmute_unchecked(self) }
+ const fn tuple() -> bool {
+ (size_of::<(X, Y)>() == size_of::<Self>())
+ & (offset_of!(Self, 0) == offset_of!((X, Y), 0))
+ & (offset_of!(Self, 1) == offset_of!((X, Y), 1))
+ }
+
+ const fn into(self) -> (X, Y) {
+ if Self::tuple() {
+ // SAFETY: we are a tuple!!!
+ unsafe { transmute_unchecked::<Self, (X, Y)>(self) }
+ } else {
+ // SAFETY: this is safe.
+ let out = unsafe { (core::ptr::read(&self.0), core::ptr::read(&self.1)) };
+ core::mem::forget(self);
+ out
+ }
}
const unsafe fn splat<T>(x: T) -> (X, Y) {
assert!(core::mem::size_of::<T>() == core::mem::size_of::<Pair<X, Y>>());
// SAFETY: well.
- unsafe { transmute_unchecked::<_, Self>(x).into() }
+ unsafe { transmute_unchecked::<_, Self>(x) }.into()
}
}