Skip to main content

verit_core/
error.rs

1use std::fmt;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub enum Error {
5    /// Message does not start with the "VRT" magic family at all — not a
6    /// Veritate message.
7    BadMagic,
8    /// A Veritate message ("VRT" prefix) whose version byte this decoder does
9    /// not implement. `found` is the version digit in the magic; `supported`
10    /// is what this build understands. Guarantees a vN message can never be
11    /// silently misread as vM.
12    UnsupportedVersion { found: u8, supported: u8 },
13    /// The fixed header is structurally invalid for this version: an unknown
14    /// flag bit, or a reserved field that is not zero.
15    MalformedHeader(&'static str),
16    /// Buffer too short for the fixed header or a declared region.
17    Truncated,
18    /// An offset or length points outside the message buffer.
19    OutOfBounds,
20    /// List element index past the end of the list.
21    IndexOutOfBounds,
22    /// A string field holds invalid UTF-8.
23    BadUtf8,
24    /// The (inline) schema bytes are malformed or non-canonical.
25    BadSchema(String),
26    /// A value's type does not match the schema field type (write path),
27    /// or a typed getter was used on a differently-typed field (read path).
28    TypeMismatch { expected: String, got: String },
29    /// Writer and reader schema cannot be resolved (e.g. int narrowing).
30    Incompatible(String),
31    /// A value referenced a field ID that is not in the schema.
32    UnknownFieldId(u16),
33    /// The same field ID appeared twice in one struct value.
34    DuplicateField(u16),
35    /// The same key appeared twice in one map value.
36    DuplicateMapKey,
37    /// A `union` value or wire tag selected a variant index that does not exist.
38    BadUnionTag(u32),
39    /// A dense struct was encoded without one of its (mandatory) fields.
40    MissingField(u16),
41    /// The message's schema id does not match the resolver's writer schema
42    /// (or the inline schema bytes hash to something else).
43    SchemaIdMismatch { message: u128, expected: u128 },
44    /// dump_json needs an inline schema but the message was hash-only.
45    NoInlineSchema,
46    /// Recursion (nested structs/lists) exceeded the safety depth limit — the
47    /// message may contain an offset cycle or hostile nesting.
48    DepthLimitExceeded,
49    /// A bounded read exhausted its traversal budget: the message followed
50    /// offsets that would touch more bytes than the budget allows (an
51    /// amplification guard for untrusted input — see `Budget` / the wire spec §5.2).
52    TraversalBudgetExceeded,
53    /// Message would exceed the 4 GiB u32-offset limit.
54    MessageTooLarge,
55    /// A `.vertc` container file is malformed: bad magic/version, an index
56    /// pointing out of bounds, a misaligned or overlapping record, etc.
57    BadContainer(&'static str),
58    /// Internal invariant violation (a bug in this library).
59    Internal(&'static str),
60}
61
62impl fmt::Display for Error {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        match self {
65            Error::BadMagic => write!(f, "not a Veritate message (bad magic)"),
66            Error::UnsupportedVersion { found, supported } => write!(
67                f,
68                "unsupported Veritate wire version: message is v{}, this build implements v{}",
69                *found as char, *supported as char
70            ),
71            Error::MalformedHeader(s) => write!(f, "malformed message header: {s}"),
72            Error::Truncated => write!(f, "message truncated"),
73            Error::OutOfBounds => write!(f, "offset out of bounds"),
74            Error::IndexOutOfBounds => write!(f, "list index out of bounds"),
75            Error::BadUtf8 => write!(f, "string field is not valid UTF-8"),
76            Error::BadSchema(s) => write!(f, "bad schema: {s}"),
77            Error::TypeMismatch { expected, got } => {
78                write!(f, "type mismatch: expected {expected}, got {got}")
79            }
80            Error::Incompatible(s) => write!(f, "schemas incompatible: {s}"),
81            Error::UnknownFieldId(id) => write!(f, "field id {id} not in schema"),
82            Error::DuplicateField(id) => write!(f, "field id {id} set twice"),
83            Error::DuplicateMapKey => write!(f, "the same map key was set twice"),
84            Error::BadUnionTag(t) => write!(f, "union tag {t} is not a valid variant index"),
85            Error::MissingField(id) => {
86                write!(f, "dense struct requires field id {id}, which was not set")
87            }
88            Error::SchemaIdMismatch { message, expected } => write!(
89                f,
90                "schema id mismatch: message has {message:#034x}, expected {expected:#034x}"
91            ),
92            Error::NoInlineSchema => write!(f, "message carries no inline schema"),
93            Error::DepthLimitExceeded => {
94                write!(f, "nesting depth limit exceeded (possible offset cycle)")
95            }
96            Error::TraversalBudgetExceeded => {
97                write!(
98                    f,
99                    "traversal budget exceeded (possible amplification attack)"
100                )
101            }
102            Error::MessageTooLarge => write!(f, "message exceeds 4 GiB limit"),
103            Error::BadContainer(s) => write!(f, "bad container: {s}"),
104            Error::Internal(s) => write!(f, "internal error: {s}"),
105        }
106    }
107}
108
109impl std::error::Error for Error {}
110
111pub type Result<T> = std::result::Result<T, Error>;