//! Implementations of storage buffers for messages that require `alloc`.

extern crate alloc;
use super::*;

/// An owned (heap allocated) CoAP message buffer.
///
/// This is mostly practical for testing to have something similar to [`SliceBuffer`] /
/// [`SliceBufferMut`] that is distinct from them, and shows how the
/// [`MessageBuffer`]/[`…Mut`][MessageBufferMut] traits generalize over ownership.
pub struct BoxBuffer {
    code: u8,
    data: alloc::boxed::Box<[u8]>,
}

impl BoxBuffer {
    /// Creates a new instance with a given fixed length available for options and payload.
    pub fn new(length: usize) -> Self {
        Self {
            code: 0,
            data: alloc::vec![0; length].into_boxed_slice(),
        }
    }
}

impl MessageBuffer for BoxBuffer {
    fn code(&self) -> u8 {
        self.code
    }

    fn tail(&self) -> &[u8] {
        &self.data
    }

    #[cfg(feature = "downcast")]
    fn static_variant() -> Option<LifetimesMatterLittle<impl 'static + MessageBuffer>> {
        // SAFETY: This is the type used here, and it is already 'static
        Some(unsafe { LifetimesMatterLittle::<Self>::new() })
    }
}

impl MessageBufferMut for BoxBuffer {
    fn code_mut(&mut self) -> &mut u8 {
        &mut self.code
    }

    fn tail_mut(&mut self) -> &mut [u8] {
        &mut self.data
    }

    #[cfg(feature = "downcast")]
    fn static_mut_variant() -> Option<LifetimesMatterLittle<impl 'static + MessageBufferMut>> {
        // SAFETY: This is the type used here, and it is already 'static
        Some(unsafe { LifetimesMatterLittle::<Self>::new() })
    }
}
