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.
57///
58/// When a layout builder derives a region length through
59/// `Self::Value<'static>: TryFrom<usize>`, the complete conversion and codec round trip
60/// must preserve that length: converting the decoded planned representation back to
61/// `usize` must produce the original region length.
62pub trait PrefixCodec {
63 /// Semantic value represented by the codec, which may borrow decode input.
64 type Value<'wire>
65 where
66 Self: 'wire;
67
68 /// Error returned while structurally validating a prefix.
69 type DecodeError: core::fmt::Debug;
70
71 /// Error returned while preparing an encoded value.
72 type EncodeError: core::fmt::Debug;
73
74 /// Prepared canonical encoded bytes, which may borrow the input value.
75 type Plan<'value>: EncodePlan
76 where
77 Self: 'value;
78
79 /// Structurally validates a prefix and reports its exact encoded extent.
80 fn validate_prefix(bytes: &[u8]) -> Result<PrefixExtent, Self::DecodeError>;
81
82 /// Decodes exact bytes which have already been successfully prefix-validated.
83 ///
84 /// `bytes` must be the encoded span selected by the returned [`PrefixExtent`], not
85 /// the input that may also contain a suffix. Calling this with other bytes is a
86 /// contract violation and may panic.
87 fn decode<'wire>(bytes: &'wire [u8]) -> Self::Value<'wire>;
88
89 /// Prepares the complete canonical encoding without mutating a caller buffer.
90 fn plan<'value>(value: Self::Value<'value>) -> Result<Self::Plan<'value>, Self::EncodeError>;
91}