use alloc::vec::Vec;
use core::sync::atomic::{AtomicU16, Ordering};
use bytes::BufMut;
use crate::{
Error,
protocol::codec::Encode,
tcp::{Header, UnitId},
};
#[must_use]
#[derive(Default)]
pub struct Encoder(AtomicU16);
impl Encoder {
pub const fn with_next_transaction_id(transaction_id: u16) -> Self {
Self(AtomicU16::new(transaction_id))
}
pub fn encode<P: Encode>(
&self,
unit_id: UnitId,
payload: &P,
to: &mut impl BufMut,
) -> Result<u16, Error> {
let mut request_bytes = Vec::new();
payload.encode(&mut request_bytes);
let transaction_id = self.0.fetch_add(1, Ordering::Relaxed);
let header = {
let length = u16::try_from(request_bytes.len() + 1)
.map_err(|_| Error::PayloadSizeExceeded(request_bytes.len()))?;
Header { unit_id, transaction_id, length, protocol_id: Header::PROTOCOL_ID }
};
header.encode(to);
to.put(&*request_bytes);
Ok(transaction_id)
}
}