Skip to main content

bnb/
builder.rs

1//! Support types for `#[derive(BitsBuilder)]` and `#[bin]`.
2
3use alloc::string::String;
4use core::fmt;
5
6/// The error a generated builder's `build()` returns.
7///
8/// Two cases:
9/// - [`MissingField`](BuilderError::MissingField) — a **required** field was
10///   never set. "Required" is the default; a field is only optional if it carries
11///   `#[builder(default)]` (or `#[builder(default = expr)]`). This is what lets the
12///   builder *call out* an unset bit/byte instead of silently defaulting it to
13///   zero (the gap in the infix `with_*` API).
14/// - [`Invalid`](BuilderError::Invalid) — a `#[bin(validate = …)]` soundness
15///   check rejected the built value. The string is the validator's error,
16///   stringified, so any `Display` error type composes without coupling the
17///   builder to a protocol-specific error type.
18///
19/// # Examples
20///
21/// ```
22/// use bnb::{bitfield, u4, BitsBuilder, BuilderError};
23///
24/// #[bitfield(u8, bits = msb)]
25/// #[derive(BitsBuilder, Clone, Copy, Debug)]
26/// struct Nibbles { hi: u4, lo: u4 }
27///
28/// let err = Nibbles::builder().hi(u4::new(0xA)).build().unwrap_err();
29/// assert_eq!(err, BuilderError::MissingField("lo"));
30/// assert_eq!(err.field(), Some("lo"));
31/// assert_eq!(err.to_string(), "required field `lo` was not set");
32/// ```
33#[derive(Clone, Debug, PartialEq, Eq)]
34pub enum BuilderError {
35    /// A required field was not set; carries the field name.
36    MissingField(&'static str),
37    /// A soundness validator rejected the value; carries its message.
38    Invalid(String),
39}
40
41impl BuilderError {
42    /// Constructs the "required field not set" error for `field`.
43    pub fn missing_field(field: &'static str) -> Self {
44        Self::MissingField(field)
45    }
46
47    /// Constructs a soundness-failure error from a validator's message.
48    pub fn invalid(message: impl Into<String>) -> Self {
49        Self::Invalid(message.into())
50    }
51
52    /// The name of the field that was not set, or `None` for an
53    /// [`Invalid`](BuilderError::Invalid) error.
54    pub fn field(&self) -> Option<&'static str> {
55        match self {
56            Self::MissingField(field) => Some(field),
57            Self::Invalid(_) => None,
58        }
59    }
60}
61
62impl fmt::Display for BuilderError {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        match self {
65            Self::MissingField(field) => write!(f, "required field `{field}` was not set"),
66            Self::Invalid(message) => write!(f, "soundness check failed: {message}"),
67        }
68    }
69}
70
71impl core::error::Error for BuilderError {}