Skip to main content

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}