squash/header/
mod.rs

1use alloc::fmt::{Display, Formatter, Result as FmtResult};
2#[cfg(feature = "std")]
3use std::error::Error;
4
5pub(crate) mod boxed;
6
7/// An error returned when the slice or string is longer than the header is able to encode.
8///
9/// The headers have a limit of how large lengths they can encode which is usually smaller than
10/// what the whole `usize` can hold (at least on 64bit platforms). If they are asked to encode
11/// something larger, this error is returned.
12///
13/// Note that the limits are usually above practical usability limits and if strings of over 4GB
14/// are actually needed, the usefulness of this library is questionable (it optimizes for many
15/// small strings/slices, the overhead is negligible on these large behemoths).
16#[derive(Copy, Clone, Debug)]
17pub struct TooLong;
18
19impl Display for TooLong {
20    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
21        write!(fmt, "Too long")
22    }
23}
24
25#[cfg(feature = "std")]
26impl Error for TooLong {}
27
28/// Description of the header encoding a length.
29///
30/// This is responsible to hold both a reference count (if applicable) and the length of the slice.
31///
32/// Note that it is not a trait consumers of this library would use directly and most common
33/// implementations should be provided, so it is unlikely one would need to interact with it,
34/// except for picking the right one as the type parameter of the [`OwnedSlice`][crate::OwnedSlice]
35/// or similar type.
36///
37/// # Safety
38///
39/// The trait must correctly decode the same length as was encoded.
40///
41/// The reference counting must properly "pair" ‒ it must not ask for destruction while someone
42/// still holds a reference count.
43pub unsafe trait Header {
44    /// How many extra bytes are needed for encoding this length.
45    ///
46    /// Returns the amount of bytes needed, or signals that the length is too long for encoding.
47    fn extra_needed(len: usize) -> Result<usize, TooLong>;
48
49    /// Creates a new header and encodes the length.
50    ///
51    /// Will be called with as many bytes as the [`extra_needed`][Header::extra_needed] designated,
52    /// passed as a pointer in the `extra` parameter.
53    ///
54    /// It shall encode a reference count of 1.
55    ///
56    /// # Safety
57    ///
58    /// The `extra` must point to at least as many bytes as asked for by
59    /// [`extra_needed`][Header::extra_needed].
60    unsafe fn encode_len(len: usize, extra: *mut u8) -> Self;
61
62    /// Decodes the previously encoded length.
63    ///
64    /// The extra bytes are provided back to it. Note that it is up to the header to know how many
65    /// bytes there are.
66    ///
67    /// # Safety
68    ///
69    /// The `extra` must point to the bytes previously passed to
70    /// [`encode_len`][Header::encode_len].
71    unsafe fn decode_len(&self, extra: *const u8) -> usize;
72
73    /// Increment the reference count.
74    ///
75    /// Returns a success flag. If the reference count exceeds what the header can hold, a false is
76    /// returned to signal that it was *not* incremented. In that case, the
77    /// [`OwnedSlice`][crate::OwnedSlice] gets fully cloned instead.
78    fn inc(&self) -> bool;
79
80    /// Decrements a reference count.
81    ///
82    /// Returns if the reference count dropped to 0 and the slice should be destroyed.
83    fn dec(&self) -> bool;
84}