cesr/core/matter/code/cesr_code.rs
1use super::matter_code::MatterCode;
2use super::sealed::Sealed;
3use crate::core::matter::error::ValidationError;
4use crate::core::matter::sizage::Sizage;
5#[cfg(feature = "alloc")]
6use crate::core::matter::sizage::SizeType;
7#[cfg(feature = "alloc")]
8#[allow(
9 unused_imports,
10 reason = "alloc prelude items; used only by the `placeholder` default method"
11)]
12use alloc::string::{String, ToString};
13
14/// Placeholder character for a self-addressing field before its digest is
15/// computed and back-patched.
16///
17/// `#` is deliberately outside the Base64 alphabet, so a placeholder value is
18/// never mistaken for a real qb64 primitive.
19pub const DUMMY_CHAR: char = '#';
20
21/// Sealed trait that all CESR typed codes must implement.
22///
23/// Provides the ability to convert to the untyped `MatterCode`, retrieve
24/// the Base64 string representation, and look up the `Sizage` and raw byte size.
25#[allow(
26 private_bounds,
27 reason = "Sealed trait pattern restricts implementors to this crate"
28)]
29pub trait CesrCode: Sealed + Copy + Eq + core::fmt::Debug {
30 /// Converts this typed code to the untyped [`MatterCode`].
31 fn to_matter_code(&self) -> MatterCode;
32 /// Returns the canonical Base64 string representation of this code.
33 fn as_str(&self) -> &'static str;
34
35 /// Returns the [`Sizage`] descriptor for this code.
36 fn get_sizage(&self) -> Sizage {
37 self.to_matter_code().get_sizage()
38 }
39
40 /// Returns the expected raw byte size for this code.
41 ///
42 /// # Errors
43 ///
44 /// Returns a `ValidationError` for variable-size codes.
45 fn raw_size(&self) -> Result<usize, ValidationError> {
46 self.to_matter_code().raw_size()
47 }
48
49 /// Returns a placeholder qb64 string of this code's full character width,
50 /// filled with [`DUMMY_CHAR`].
51 ///
52 /// Reserves a self-addressing field's exact byte span before its digest is
53 /// computed and back-patched over the placeholder. The width equals the
54 /// code's fixed full size (`fs`).
55 ///
56 /// # Errors
57 ///
58 /// Returns [`ValidationError::InvalidSizingOperation`] for variable-size
59 /// codes, which have no fixed placeholder width.
60 #[cfg(feature = "alloc")]
61 fn placeholder(&self) -> Result<String, ValidationError> {
62 match self.get_sizage().fs {
63 SizeType::Fixed(n) => Ok(core::iter::repeat_n(DUMMY_CHAR, usize::from(n)).collect()),
64 SizeType::Small | SizeType::Large => Err(ValidationError::InvalidSizingOperation(
65 self.to_matter_code().to_string(),
66 )),
67 }
68 }
69}