1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
//! Error types for AAD parsing and validation.
use std::fmt;
use thiserror::Error;
/// All possible errors during AAD parsing, validation, and canonicalization.
#[derive(Debug, Error)]
pub enum AadError {
/// Integer value exceeds the safe range (0 to 2^53-1).
#[error("field '{field}' integer out of range: {value} exceeds maximum safe value {max}")]
IntegerOutOfRange {
/// The field whose value was out of range
field: String,
/// The value that was out of range
value: u64,
/// The maximum allowed value (2^53-1)
max: u64,
},
/// Negative integer encountered where unsigned was expected.
#[error("field '{field}' negative integer not allowed: {value}")]
NegativeInteger {
/// The field that received the negative value
field: String,
/// The negative value encountered
value: i64,
},
/// Field key is empty.
#[error("field key cannot be empty")]
EmptyFieldKey,
/// Field key contains invalid characters.
#[error("invalid field key '{key}': {reason}")]
InvalidFieldKey {
/// The invalid key
key: String,
/// Explanation of why it's invalid
reason: String,
},
/// Attempted to use a reserved key name as an extension.
#[error("reserved key '{key}' cannot be used as extension field")]
ReservedKeyAsExtension {
/// The reserved key that was misused
key: String,
},
/// Extension key does not match required pattern `x_<app>_<field>`.
#[error("invalid extension key format '{key}': expected pattern {expected_pattern}")]
InvalidExtensionKeyFormat {
/// The invalid extension key
key: String,
/// The expected pattern description
expected_pattern: &'static str,
},
/// String field is shorter than minimum length.
#[error("field '{field}' too short: minimum {min_bytes} bytes, got {actual_bytes}")]
FieldTooShort {
/// The field name
field: &'static str,
/// Minimum required bytes
min_bytes: usize,
/// Actual bytes provided
actual_bytes: usize,
},
/// String field exceeds maximum length.
#[error("field '{field}' too long: maximum {max_bytes} bytes, got {actual_bytes}")]
FieldTooLong {
/// The field name
field: &'static str,
/// Maximum allowed bytes
max_bytes: usize,
/// Actual bytes provided
actual_bytes: usize,
},
/// NUL byte (0x00) found in string value.
#[error("field '{field}' contains NUL byte (0x00)")]
NulByteInValue {
/// The field containing the NUL byte
field: &'static str,
},
/// Required field is missing from the AAD object.
#[error("missing required field: {field}")]
MissingRequiredField {
/// The name of the missing field
field: &'static str,
},
/// Duplicate key found in JSON object.
#[error("duplicate key: '{key}'")]
DuplicateKey {
/// The duplicated key
key: String,
},
/// Unknown field for the specified schema version.
#[error("unknown field '{field}' for schema version {version}")]
UnknownField {
/// The unknown field name
field: String,
/// The schema version
version: u64,
},
/// Unsupported schema version.
#[error("unsupported schema version: {version}")]
UnsupportedVersion {
/// The unsupported version number
version: u64,
},
/// Field has wrong type (e.g., string instead of integer).
#[error("field '{field}' has wrong type: expected {expected}, got {actual}")]
WrongFieldType {
/// The field with wrong type
field: &'static str,
/// The expected type
expected: &'static str,
/// The actual type found
actual: JsonType,
},
/// Serialized AAD exceeds the 16 KiB limit.
#[error("serialized AAD too large: maximum {max_bytes} bytes, got {actual_bytes}")]
SerializedTooLarge {
/// Maximum allowed bytes (16384)
max_bytes: usize,
/// Actual serialized size
actual_bytes: usize,
},
/// Invalid JSON syntax or structure.
#[error("invalid JSON: {message}")]
InvalidJson {
/// Description of the JSON error
message: String,
},
/// Non-integer or non-finite float where an integer was required.
#[error("field '{field}' is not a valid integer: {reason}")]
InvalidFloat {
/// The field name
field: String,
/// `"NaN"`, `"Infinity"`, `"negative"`, `"fractional"`, or `"exceeds MAX_SAFE_INTEGER"`
reason: &'static str,
},
}
/// JSON value type for error reporting.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum JsonType {
/// JSON null value
Null,
/// JSON boolean value
Bool,
/// JSON number value
Number,
/// JSON string value
String,
/// JSON array value
Array,
/// JSON object value
Object,
}
impl fmt::Display for JsonType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Null => write!(f, "null"),
Self::Bool => write!(f, "boolean"),
Self::Number => write!(f, "number"),
Self::String => write!(f, "string"),
Self::Array => write!(f, "array"),
Self::Object => write!(f, "object"),
}
}
}
impl From<&serde_json::Value> for JsonType {
fn from(value: &serde_json::Value) -> Self {
match value {
serde_json::Value::Null => Self::Null,
serde_json::Value::Bool(_) => Self::Bool,
serde_json::Value::Number(_) => Self::Number,
serde_json::Value::String(_) => Self::String,
serde_json::Value::Array(_) => Self::Array,
serde_json::Value::Object(_) => Self::Object,
}
}
}