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>;