//! Utility types needed for coap-message

/// Reference that is annotated with a type ID corresponding to a 'static version of the type
///
/// How the ID corresponds to `T` is up to the type `T`. Any type may use it internally without
/// documented stability guarantees (being itself responsible for upholding whatever it relies on).
/// Code outside of the crate defining `T` should not construct it or rely on its properties; if
/// really needed, that crates should provide own wrapper methods that define their precise
/// unsafety criteria.
pub struct RefWithStaticType<'a, T: ?Sized>(&'a T, core::any::TypeId);

impl<'a, T: ?Sized> RefWithStaticType<'a, T> {
    /// State that the given `id` is a type ID corresponding to T
    ///
    /// # Safety
    ///
    /// When it is safe to construct this depends on the semantics `T` ascribes to it.
    pub unsafe fn new(reference: &'a T, id: core::any::TypeId) -> Self {
        Self(reference, id)
    }

    /// Split into the contained data
    pub fn into_inner(&self) -> (&'a T, core::any::TypeId) {
        (self.0, self.1)
    }
}

/// Exclusive reference that is annotated with a type ID corresponding to a 'static version of the
/// type
///
/// How the ID corresponds to `T` is up to the type `T`. Any type may use it internally without
/// documented stability guarantees (being itself responsible for upholding whatever it relies on).
/// Code outside of the crate defining `T` should not construct it or rely on its properties; if
/// really needed, that crates should provide own wrapper methods that define their precise
/// unsafety criteria.
pub struct RefMutWithStaticType<'a, T: ?Sized>(&'a mut T, core::any::TypeId);

impl<'a, T: ?Sized> RefMutWithStaticType<'a, T> {
    /// State that the given `id` is a type ID corresponding to T
    ///
    /// # Safety
    ///
    /// When it is safe to construct this depends on the semantics `T` ascribes to it.
    pub unsafe fn new(reference: &'a mut T, id: core::any::TypeId) -> Self {
        Self(reference, id)
    }

    /// Split into the contained data
    pub fn into_inner(self) -> (&'a mut T, core::any::TypeId) {
        (self.0, self.1)
    }
}
