Skip to main content

wire_repr/codec/
prefix.rs

1//! Prefix codec contract.
2
3use core::num::NonZeroUsize;
4
5use super::EncodePlan;
6
7/// The nonzero extent occupied by a validated encoded prefix.
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
9pub struct PrefixExtent {
10    encoded_len: NonZeroUsize,
11}
12
13impl PrefixExtent {
14    /// Creates an extent from a nonzero encoded length.
15    #[must_use]
16    pub const fn new(encoded_len: NonZeroUsize) -> Self {
17        Self { encoded_len }
18    }
19
20    /// Returns the number of bytes occupied by the encoded prefix.
21    #[must_use]
22    pub const fn encoded_len(self) -> NonZeroUsize {
23        self.encoded_len
24    }
25
26    /// Splits input into its encoded prefix and remaining suffix.
27    #[inline]
28    #[must_use]
29    pub fn split_input<'input>(&self, input: &'input [u8]) -> Option<(&'input [u8], &'input [u8])> {
30        let encoded_len = self.encoded_len.get();
31        if encoded_len > input.len() {
32            None
33        } else {
34            Some(input.split_at(encoded_len))
35        }
36    }
37}
38
39/// A codec whose encoded representation occupies a variable-length prefix.
40///
41/// [`Self::validate_prefix`] performs structural validation and discovers the exact
42/// nonzero extent from available input. A successful extent must not exceed the
43/// supplied input. Callers must enforce that implementor law with
44/// [`PrefixExtent::split_input`] or an equivalent check before slicing, because custom
45/// implementations can violate it.
46///
47/// [`Self::decode`] receives exactly the encoded bytes for which validation succeeded
48/// and whose length equals the reported extent. It decodes semantically without
49/// rediscovering a suffix. Calling it on other bytes is a contract violation and may
50/// panic. Legal noncanonical input remains the caller's exact bytes; canonicality
51/// belongs to [`Self::plan`]. Every successful plan must report a nonzero encoded
52/// length and write a complete canonical representation for which
53/// [`Self::validate_prefix`] returns that same extent. Decoding those bytes must recover
54/// the same semantic value supplied to [`Self::plan`]. A codec that violates these
55/// requirements is contract-invalid. All fallible planning completes before a caller
56/// buffer is mutated.
57pub trait PrefixCodec {
58    /// Semantic value represented by the codec, which may borrow decode input.
59    type Value<'wire>
60    where
61        Self: 'wire;
62
63    /// Error returned while structurally validating a prefix.
64    type DecodeError: core::fmt::Debug;
65
66    /// Error returned while preparing an encoded value.
67    type EncodeError: core::fmt::Debug;
68
69    /// Prepared canonical encoded bytes, which may borrow the input value.
70    type Plan<'value>: EncodePlan
71    where
72        Self: 'value;
73
74    /// Structurally validates a prefix and reports its exact encoded extent.
75    fn validate_prefix(bytes: &[u8]) -> Result<PrefixExtent, Self::DecodeError>;
76
77    /// Decodes exact bytes which have already been successfully prefix-validated.
78    ///
79    /// `bytes` must be the encoded span selected by the returned [`PrefixExtent`], not
80    /// the input that may also contain a suffix. Calling this with other bytes is a
81    /// contract violation and may panic.
82    fn decode<'wire>(bytes: &'wire [u8]) -> Self::Value<'wire>;
83
84    /// Prepares the complete canonical encoding without mutating a caller buffer.
85    fn plan<'value>(value: Self::Value<'value>) -> Result<Self::Plan<'value>, Self::EncodeError>;
86}