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}