Skip to main content

coap_message_implementations/inmemory/
buffer_traits.rs

1//! Interfaces to storage buffers for messages.
2
3#[cfg(doc)]
4use super::*;
5
6use core::marker::PhantomData;
7
8/// Marker that indicates that all lifetimes in `T` are just relevant for the type itself, but not
9/// for interactions. In particular, constructing it promises that:
10///
11/// * The type is covariant in all lifetimes: Any `InputToT<'a>` could be turned into an
12///   `InputToT<'b>` for a shorter `'b`.
13///
14///   In practice, this means that no public interfaces of the type take input that needs to
15///   outlive the type (e.g. some `fn set_title(self, title: &'a str) { self.title = title }`).
16///
17/// * It can not be observed through the type's public interfaces how much longer its lifetime is
18///   than the reference that is passed in.
19///
20///   In practice, this means that there can be a `fn title(&self) -> &str`, but no `fn
21///   title(&self) -> &'a str`.
22///
23/// Those properties are required to implement downcasting of generic messages into expected types,
24/// see [`Message::downcast_from()`].
25///
26/// In the type system, we can not convey information about incomplete types. Thus, the statement
27/// is encoded in a `'static` concrete type `T`, but applies to the related types that vary by
28/// lifetimes.
29pub struct LifetimesMatterLittle<T>(PhantomData<T>);
30
31impl<T> LifetimesMatterLittle<T> {
32    /// Creates a new zero-sized marker.
33    ///
34    /// # Safety
35    ///
36    /// This must only be used if `T` has the properties required by this type.
37    #[allow(
38        unsafe_code,
39        reason = "this does not *do* anything unsafe, it just declares that *calling it* is unsafe (because it encodes promises)"
40    )]
41    #[must_use]
42    pub unsafe fn new() -> Self {
43        Self(PhantomData)
44    }
45}
46
47/// A trait that can implemented on in-memory encoded CoAP messages; then, an [`Message`] struct
48/// can be placed around the implementer to implement [`ReadableMessage`].
49///
50/// Implementations must not alter the content returned by the accessors. As this trait is safe to
51/// implement, the content of the returned slice might change between calls even when the encoded
52/// message was owned or exclusively referenced (e.g. when backed by a
53/// [`RefCell`][core::cell::RefCell]). Therefore, neither this crate nor others can rely on
54/// the content upholding any unsafe guarantees -- but it may (and should) panic rater than erring
55/// if the expectation of stable content is violated.
56pub trait MessageBuffer {
57    /// The code of the message
58    fn code(&self) -> u8;
59
60    /// The memory area containing the encoded options, payload marker and payload
61    fn tail(&self) -> &[u8];
62
63    #[must_use]
64    fn static_variant() -> Option<LifetimesMatterLittle<impl 'static + MessageBuffer>> {
65        None::<LifetimesMatterLittle<core::convert::Infallible>>
66    }
67}
68
69/// Data backing a [`MessageMut`].
70///
71/// This is to [`MessageBuffer`] like [`AsMut`] is to [`AsRef`].
72pub trait MessageBufferMut: MessageBuffer {
73    fn code_mut(&mut self) -> &mut u8;
74    fn tail_mut(&mut self) -> &mut [u8];
75
76    #[must_use]
77    fn static_mut_variant() -> Option<LifetimesMatterLittle<impl 'static + MessageBufferMut>> {
78        None::<LifetimesMatterLittle<core::convert::Infallible>>
79    }
80}