1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use alloc::fmt::{Display, Formatter, Result as FmtResult};
#[cfg(feature = "std")]
use std::error::Error;

pub(crate) mod boxed;

/// An error returned when the slice or string is longer than the header is able to encode.
///
/// The headers have a limit of how large lengths they can encode which is usually smaller than
/// what the whole `usize` can hold (at least on 64bit platforms). If they are asked to encode
/// something larger, this error is returned.
///
/// Note that the limits are usually above practical usability limits and if strings of over 4GB
/// are actually needed, the usefulness of this library is questionable (it optimizes for many
/// small strings/slices, the overhead is negligible on these large behemoths).
#[derive(Copy, Clone, Debug)]
pub struct TooLong;

impl Display for TooLong {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        write!(fmt, "Too long")
    }
}

#[cfg(feature = "std")]
impl Error for TooLong {}

/// Description of the header encoding a length.
///
/// This is responsible to hold both a reference count (if applicable) and the length of the slice.
///
/// Note that it is not a trait consumers of this library would use directly and most common
/// implementations should be provided, so it is unlikely one would need to interact with it,
/// except for picking the right one as the type parameter of the [`OwnedSlice`][crate::OwnedSlice]
/// or similar type.
///
/// # Safety
///
/// The trait must correctly decode the same length as was encoded.
///
/// The reference counting must properly "pair" ‒ it must not ask for destruction while someone
/// still holds a reference count.
pub unsafe trait Header {
    /// How many extra bytes are needed for encoding this length.
    ///
    /// Returns the amount of bytes needed, or signals that the length is too long for encoding.
    fn extra_needed(len: usize) -> Result<usize, TooLong>;

    /// Creates a new header and encodes the length.
    ///
    /// Will be called with as many bytes as the [`extra_needed`][Header::extra_needed] designated,
    /// passed as a pointer in the `extra` parameter.
    ///
    /// It shall encode a reference count of 1.
    ///
    /// # Safety
    ///
    /// The `extra` must point to at least as many bytes as asked for by
    /// [`extra_needed`][Header::extra_needed].
    unsafe fn encode_len(len: usize, extra: *mut u8) -> Self;

    /// Decodes the previously encoded length.
    ///
    /// The extra bytes are provided back to it. Note that it is up to the header to know how many
    /// bytes there are.
    ///
    /// # Safety
    ///
    /// The `extra` must point to the bytes previously passed to
    /// [`encode_len`][Header::encode_len].
    unsafe fn decode_len(&self, extra: *const u8) -> usize;

    /// Increment the reference count.
    ///
    /// Returns a success flag. If the reference count exceeds what the header can hold, a false is
    /// returned to signal that it was *not* incremented. In that case, the
    /// [`OwnedSlice`][crate::OwnedSlice] gets fully cloned instead.
    fn inc(&self) -> bool;

    /// Decrements a reference count.
    ///
    /// Returns if the reference count dropped to 0 and the slice should be destroyed.
    fn dec(&self) -> bool;
}