Files
PlantCtrl/rust/src/mcutie_3_0_0/buffer.rs
Empire Phoenix e05f3d768f Add mcutie MQTT client implementation and improve library structure
- Integrated `mcutie` library as a core MQTT client for device communication.
- Added support for Home Assistant entities (binary sensor, button) via MQTT.
- Implemented buffer management, async operations, and packet encoding/decoding.
- Introduced structured error handling and device registration features.
- Updated `Cargo.toml` with new dependencies and enabled feature flags for `serde` and `log`.
- Enhanced logging macros with configurable options (`defmt` or `log`).
- Organized codebase into modules (buffer, components, IO, publish, etc.) for better maintainability.

fix legacy dependecencies and compatiblity with mcutie vendored lib

fix shit i hate this
2026-05-04 01:48:22 +02:00

125 lines
3.3 KiB
Rust

use core::{cmp, fmt, ops::Deref};
use embedded_io::{SliceWriteError, Write};
use mqttrs::{encode_slice, Packet};
use crate::Error;
/// A stack allocated buffer that can be written to and then read back from.
/// Dereferencing as a [`u8`] slice allows access to previously written data.
///
/// Can be written to with [`write!`] and supports [`embedded_io::Write`] and
/// [`embedded_io_async::Write`].
pub struct Buffer<const N: usize> {
bytes: [u8; N],
cursor: usize,
}
impl<const N: usize> Default for Buffer<N> {
fn default() -> Self {
Self::new()
}
}
impl<const N: usize> Buffer<N> {
/// Creates a new buffer.
pub(crate) const fn new() -> Self {
Self {
bytes: [0; N],
cursor: 0,
}
}
/// Creates a new buffer and writes the given data into it.
pub(crate) fn from(buf: &[u8]) -> Result<Self, Error> {
let mut buffer = Self::new();
match buffer.write_all(buf) {
Ok(()) => Ok(buffer),
Err(_) => Err(Error::TooLarge),
}
}
pub(crate) fn encode_packet(&mut self, packet: &Packet<'_>) -> Result<(), mqttrs::Error> {
let len = encode_slice(packet, &mut self.bytes[self.cursor..])?;
self.cursor += len;
Ok(())
}
#[cfg(feature = "serde")]
/// Serializes a value into this buffer using JSON.
pub(crate) fn serialize_json<T: serde::Serialize>(
&mut self,
value: &T,
) -> Result<(), serde_json_core::ser::Error> {
let len = serde_json_core::to_slice(value, &mut self.bytes[self.cursor..])?;
self.cursor += len;
Ok(())
}
#[cfg(feature = "serde")]
/// Deserializes this buffer using JSON into the given type.
pub fn deserialize_json<'a, T: serde::Deserialize<'a>>(
&'a self,
) -> Result<T, serde_json_core::de::Error> {
let (result, _) = serde_json_core::from_slice(self)?;
Ok(result)
}
/// The number of bytes available for writing into this buffer.
pub fn available(&self) -> usize {
N - self.cursor
}
}
impl<const N: usize> Deref for Buffer<N> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.bytes[0..self.cursor]
}
}
impl<const N: usize> fmt::Write for Buffer<N> {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.write_all(s.as_bytes()).map_err(|_| fmt::Error)
}
}
impl<const N: usize> embedded_io::ErrorType for Buffer<N> {
type Error = SliceWriteError;
}
impl<const N: usize> embedded_io::Write for Buffer<N> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
if buf.is_empty() {
return Ok(0);
}
let writable = cmp::min(self.available(), buf.len());
if writable == 0 {
Err(SliceWriteError::Full)
} else {
self.bytes[self.cursor..self.cursor + writable].copy_from_slice(buf);
self.cursor += writable;
Ok(writable)
}
}
fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
impl<const N: usize> embedded_io_async::Write for Buffer<N> {
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
<Self as embedded_io::Write>::write(self, buf)
}
async fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}