thinnable 0.3.3

Thin references to unsized types.
use core::{
    convert::TryInto,
    marker::{PhantomData, Unsize},
    ptr,
};

pub type Metadata<U> = <U as ptr::Pointee>::Metadata;

/// A failure on conversion of DST `U`'s metadata to type `M`.
pub type MetadataCreationFailure<U, M> = <Metadata<U> as TryInto<M>>::Error;
pub type MetadataRecoveryFailure<U, M> = <M as TryInto<Metadata<U>>>::Error;

pub(crate) struct MetadataFor<U: ?Sized, M> {
    for_type: PhantomData<U>,
    metadata: M,
}

impl<U, M> MetadataFor<U, M>
where
    U: ?Sized,
{
    #[inline(always)]
    pub fn try_new<T: Unsize<U>>(data: &T) -> Result<Self, MetadataCreationFailure<U, M>>
    where
        Metadata<U>: TryInto<M>,
    {
        Ok(Self {
            for_type: PhantomData,
            metadata: ptr::metadata(data as &U).try_into()?,
        })
    }

    #[inline(always)]
    pub fn try_get(&self) -> Result<Metadata<U>, MetadataRecoveryFailure<U, M>>
    where
        M: Copy + TryInto<Metadata<U>>,
    {
        self.metadata.try_into()
    }
}