//! Interfaces to storage buffers for messages.

#[cfg(doc)]
use super::*;

use core::marker::PhantomData;

/// Marker that indicates that all lifetimes in `T` are just relevant for the type itself, but not
/// for interactions. In particular, constructing it promises that:
///
/// * The type is covariant in all lifetimes: Any `InputToT<'a>` could be turned into an
///   `InputToT<'b>` for a shorter `'b`.
///
///   In practice, this means that no public interfaces of the type take input that needs to
///   outlive the type (e.g. some `fn set_title(self, title: &'a str) { self.title = title }`).
///
/// * It can not be observed through the type's public interfaces how much longer its lifetime is
///   than the reference that is passed in.
///
///   In practice, this means that there can be a `fn title(&self) -> &str`, but no `fn
///   title(&self) -> &'a str`.
///
/// Those properties are required to implement downcasting of generic messages into expected types,
/// see [`Message::downcast_from()`].
///
/// In the type system, we can not convey information about incomplete types. Thus, the statement
/// is encoded in a `'static` concrete type `T`, but applies to the related types that vary by
/// lifetimes.
pub struct LifetimesMatterLittle<T>(PhantomData<T>);

impl<T> LifetimesMatterLittle<T> {
    /// Creates a new zero-sized marker.
    ///
    /// # Safety
    ///
    /// This must only be used if `T` has the properties required by this type.
    #[allow(
        unsafe_code,
        reason = "this does not *do* anything unsafe, it just declares that *calling it* is unsafe (because it encodes promises)"
    )]
    #[must_use]
    pub unsafe fn new() -> Self {
        Self(PhantomData)
    }
}

/// A trait that can implemented on in-memory encoded CoAP messages; then, an [`Message`] struct
/// can be placed around the implementer to implement [`ReadableMessage`].
///
/// Implementations must not alter the content returned by the accessors. As this trait is safe to
/// implement, the content of the returned slice might change between calls even when the encoded
/// message was owned or exclusively referenced (e.g. when backed by a
/// [`RefCell`][core::cell::RefCell]). Therefore, neither this crate nor others can rely on
/// the content upholding any unsafe guarantees -- but it may (and should) panic rater than erring
/// if the expectation of stable content is violated.
pub trait MessageBuffer {
    /// The code of the message
    fn code(&self) -> u8;

    /// The memory area containing the encoded options, payload marker and payload
    fn tail(&self) -> &[u8];

    #[must_use]
    fn static_variant() -> Option<LifetimesMatterLittle<impl 'static + MessageBuffer>> {
        None::<LifetimesMatterLittle<core::convert::Infallible>>
    }
}

/// Data backing a [`MessageMut`].
///
/// This is to [`MessageBuffer`] like [`AsMut`] is to [`AsRef`].
pub trait MessageBufferMut: MessageBuffer {
    fn code_mut(&mut self) -> &mut u8;
    fn tail_mut(&mut self) -> &mut [u8];

    #[must_use]
    fn static_mut_variant() -> Option<LifetimesMatterLittle<impl 'static + MessageBufferMut>> {
        None::<LifetimesMatterLittle<core::convert::Infallible>>
    }
}
