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}