Skip to main content

bacnet_bip_codec/
sink.rs

1//! Byte sinks for [`Bvll::encode_to_sink`](crate::Bvll::encode_to_sink) and
2//! [`Bvll6::encode_to_sink`](crate::ipv6::Bvll6::encode_to_sink).
3
4use core::fmt;
5
6/// A destination for encoded BVLL octets, shared by the B/IP and the
7/// B/IPv6 encoders.
8///
9/// The encoders ask for
10/// [`remaining_capacity`](BvllSink::remaining_capacity) first. A sink that
11/// reports one is never handed a message that does not fit, so the fixed
12/// sinks in this crate never hold part of a message. A sink that reports
13/// `None` can grow, and is written without that check: if one of its writes
14/// fails after an earlier one succeeded, the earlier octets stay in it, and
15/// the caller has to discard them.
16pub trait BvllSink {
17    /// Octets of room left, or `None` when the sink grows as needed.
18    fn remaining_capacity(&self) -> Option<usize>;
19
20    /// Append `bytes`, or fail without appending any of them.
21    fn write(&mut self, bytes: &[u8]) -> Result<(), SinkFull>;
22}
23
24/// A [`BvllSink`] had no room for a write.
25///
26/// Each encoder reports it as its own error's `BufferExhausted`.
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub struct SinkFull {
29    /// Octets the write needed.
30    pub needed: usize,
31    /// Room the sink had.
32    pub available: usize,
33}
34
35impl fmt::Display for SinkFull {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        write!(
38            f,
39            "sink full: need {}, have {}",
40            self.needed, self.available
41        )
42    }
43}
44
45impl core::error::Error for SinkFull {}
46
47/// Writes at the front of the slice and advances it past what was written,
48/// so after a successful encode the slice holds the unused tail.
49impl BvllSink for &mut [u8] {
50    fn remaining_capacity(&self) -> Option<usize> {
51        Some(self.len())
52    }
53
54    fn write(&mut self, bytes: &[u8]) -> Result<(), SinkFull> {
55        if self.len() < bytes.len() {
56            return Err(SinkFull {
57                needed: bytes.len(),
58                available: self.len(),
59            });
60        }
61        let (head, tail) = core::mem::take(self).split_at_mut(bytes.len());
62        head.copy_from_slice(bytes);
63        *self = tail;
64        Ok(())
65    }
66}
67
68#[cfg(feature = "heapless")]
69impl<const N: usize> BvllSink for heapless::Vec<u8, N> {
70    fn remaining_capacity(&self) -> Option<usize> {
71        Some(N - self.len())
72    }
73
74    fn write(&mut self, bytes: &[u8]) -> Result<(), SinkFull> {
75        let available = N - self.len();
76        self.extend_from_slice(bytes).map_err(|_| SinkFull {
77            needed: bytes.len(),
78            available,
79        })
80    }
81}
82
83#[cfg(feature = "alloc")]
84impl BvllSink for alloc::vec::Vec<u8> {
85    fn remaining_capacity(&self) -> Option<usize> {
86        None
87    }
88
89    fn write(&mut self, bytes: &[u8]) -> Result<(), SinkFull> {
90        self.extend_from_slice(bytes);
91        Ok(())
92    }
93}
94
95#[cfg(feature = "bytes")]
96impl BvllSink for bytes::BytesMut {
97    fn remaining_capacity(&self) -> Option<usize> {
98        None
99    }
100
101    fn write(&mut self, bytes: &[u8]) -> Result<(), SinkFull> {
102        self.extend_from_slice(bytes);
103        Ok(())
104    }
105}