1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
use ptr_meta::Pointee;
/// Trait which can be implemented by any pointer-like ('Pointee')types,
/// as long as their metadata might be made smaller.
///
/// As such, it is implemented for:
/// - Zero-sized types (no metadata and actually also no pointer)
/// - Statically-sized types (no metadata)
/// - Dynamically-sized types (metadata indicates length which can be made smaller if the length fits in the smaller int)
///
/// It is _not_ implemented for trait objects, because their metadata is itself a pointer!
///
/// # Safety
///
/// In a perfect world, we would have hade a `SlimmerMetadata: Into<Self as Pointee>::Metadata` bound on this trait.
/// However, since pointer sizes differ on different compilation targets,
/// current Rust never implements this conversion.
///
/// As such, this trait functions under the assumption that
/// ```ignore
/// let slim_meta = meta.try_into();
/// let recovered_meta = slim_meta.try_into().unwrap();
/// ```
/// will never fail.
///
/// This assumption is very reasonable and in all likelyhood fulfilled by any pointer metadata type
/// you ever throw at it.
/// But since we cannot trust arbitrary safe code to do 'the right thing', this trait needs to be unsafe.
pub unsafe trait SlimmerPointee<SlimmerMetadata>: Pointee
where
<Self as Pointee>::Metadata: Clone,
SlimmerMetadata: TryFrom<<Self as Pointee>::Metadata> + TryInto<<Self as Pointee>::Metadata>,
{
}
/// Trivial blanket implementation for sized types, as they do not have any metadata.
unsafe impl<T: Sized> SlimmerPointee<()> for T {}
/// Implementation that will behave identical to `Box<[T]>` on any architecture
unsafe impl<T> SlimmerPointee<usize> for [T] {}
/// Store at most 255 elements
unsafe impl<T> SlimmerPointee<u8> for [T] {}
/// Store at most 65535 elements
unsafe impl<T> SlimmerPointee<u16> for [T] {}
/// Store at most 4294967295 elements
unsafe impl<T> SlimmerPointee<u32> for [T] {}
/// Store at most 18446744073709551615 elements
unsafe impl<T> SlimmerPointee<u64> for [T] {}
/// Implementation that will behave identical to `Box<[T]>` on any architecture
unsafe impl SlimmerPointee<usize> for str {}
/// Store at most 15 bytes
unsafe impl SlimmerPointee<u8> for str {}
/// Store at most 65535 bytes == 64KiB
unsafe impl SlimmerPointee<u16> for str {}
/// Store at most 4294967295 bytes == 4GiB
unsafe impl SlimmerPointee<u32> for str {}
/// Store at most 18446744073709551615 bytes == 16 EiB
unsafe impl SlimmerPointee<u64> for str {}
#[cfg(feature = "std")]
unsafe impl SlimmerPointee<usize> for ::std::ffi::CStr {}
#[cfg(feature = "std")]
unsafe impl SlimmerPointee<usize> for ::std::ffi::OsStr {}
#[cfg(feature = "std")]
unsafe impl SlimmerPointee<u8> for ::std::ffi::CStr {}
#[cfg(feature = "std")]
unsafe impl SlimmerPointee<u8> for ::std::ffi::OsStr {}
#[cfg(feature = "std")]
unsafe impl SlimmerPointee<u16> for ::std::ffi::CStr {}
#[cfg(feature = "std")]
unsafe impl SlimmerPointee<u16> for ::std::ffi::OsStr {}
#[cfg(feature = "std")]
unsafe impl SlimmerPointee<u32> for ::std::ffi::CStr {}
#[cfg(feature = "std")]
unsafe impl SlimmerPointee<u32> for ::std::ffi::OsStr {}
#[cfg(feature = "std")]
unsafe impl SlimmerPointee<u64> for ::std::ffi::CStr {}
#[cfg(feature = "std")]
unsafe impl SlimmerPointee<u64> for ::std::ffi::OsStr {}