Skip to main content

modkit_canonical_errors/
context.rs

1use serde::Serialize;
2
3// ---------------------------------------------------------------------------
4// Shared inner types
5// ---------------------------------------------------------------------------
6
7#[derive(Debug, Clone, Serialize)]
8pub struct FieldViolationV1 {
9    pub field: String,
10    pub description: String,
11    pub reason: String,
12}
13
14impl FieldViolationV1 {
15    #[must_use]
16    pub fn new(
17        field: impl Into<String>,
18        description: impl Into<String>,
19        reason: impl Into<String>,
20    ) -> Self {
21        Self {
22            field: field.into(),
23            description: description.into(),
24            reason: reason.into(),
25        }
26    }
27}
28
29pub type FieldViolation = FieldViolationV1;
30
31#[derive(Debug, Clone, Serialize)]
32pub struct QuotaViolationV1 {
33    pub subject: String,
34    pub description: String,
35}
36
37impl QuotaViolationV1 {
38    #[must_use]
39    pub fn new(subject: impl Into<String>, description: impl Into<String>) -> Self {
40        Self {
41            subject: subject.into(),
42            description: description.into(),
43        }
44    }
45}
46
47pub type QuotaViolation = QuotaViolationV1;
48
49#[derive(Debug, Clone, Serialize)]
50pub struct PreconditionViolationV1 {
51    #[serde(rename = "type")]
52    pub type_: String,
53    pub subject: String,
54    pub description: String,
55}
56
57impl PreconditionViolationV1 {
58    #[must_use]
59    pub fn new(
60        type_: impl Into<String>,
61        subject: impl Into<String>,
62        description: impl Into<String>,
63    ) -> Self {
64        Self {
65            type_: type_.into(),
66            subject: subject.into(),
67            description: description.into(),
68        }
69    }
70}
71
72pub type PreconditionViolation = PreconditionViolationV1;
73
74// ---------------------------------------------------------------------------
75// Per-category context types
76// ---------------------------------------------------------------------------
77
78// 01 Cancelled — context: Cancelled
79#[derive(Debug, Clone, Serialize)]
80#[allow(clippy::empty_structs_with_brackets)]
81pub struct CancelledV1 {}
82
83impl CancelledV1 {
84    #[must_use]
85    pub fn new() -> Self {
86        Self {}
87    }
88}
89
90impl Default for CancelledV1 {
91    fn default() -> Self {
92        Self::new()
93    }
94}
95
96pub type Cancelled = CancelledV1;
97
98// 02 Unknown — context: Unknown
99#[derive(Debug, Clone, Serialize)]
100pub struct UnknownV1 {
101    #[serde(skip)]
102    pub description: String,
103}
104
105impl UnknownV1 {
106    #[must_use]
107    pub fn new(description: impl Into<String>) -> Self {
108        Self {
109            description: description.into(),
110        }
111    }
112}
113
114pub type Unknown = UnknownV1;
115
116// 03 InvalidArgument — context: InvalidArgument (enum with 3 variants)
117#[derive(Debug, Clone, Serialize)]
118#[serde(untagged)]
119pub enum InvalidArgumentV1 {
120    FieldViolations {
121        field_violations: Vec<FieldViolation>,
122    },
123    Format {
124        format: String,
125    },
126    Constraint {
127        constraint: String,
128    },
129}
130
131impl InvalidArgumentV1 {
132    #[must_use]
133    pub fn fields(violations: impl Into<Vec<FieldViolation>>) -> Self {
134        Self::FieldViolations {
135            field_violations: violations.into(),
136        }
137    }
138
139    #[must_use]
140    pub fn format(msg: impl Into<String>) -> Self {
141        Self::Format { format: msg.into() }
142    }
143
144    #[must_use]
145    pub fn constraint(msg: impl Into<String>) -> Self {
146        Self::Constraint {
147            constraint: msg.into(),
148        }
149    }
150}
151
152pub type InvalidArgument = InvalidArgumentV1;
153
154// 04 DeadlineExceeded — context: DeadlineExceeded
155#[derive(Debug, Clone, Serialize)]
156#[allow(clippy::empty_structs_with_brackets)]
157pub struct DeadlineExceededV1 {}
158
159impl DeadlineExceededV1 {
160    #[must_use]
161    pub fn new() -> Self {
162        Self {}
163    }
164}
165
166impl Default for DeadlineExceededV1 {
167    fn default() -> Self {
168        Self::new()
169    }
170}
171
172pub type DeadlineExceeded = DeadlineExceededV1;
173
174// 05 NotFound — context: NotFound
175#[derive(Debug, Clone, Serialize)]
176#[allow(clippy::empty_structs_with_brackets)]
177pub struct NotFoundV1 {}
178
179impl NotFoundV1 {
180    #[must_use]
181    pub fn new() -> Self {
182        Self {}
183    }
184}
185
186impl Default for NotFoundV1 {
187    fn default() -> Self {
188        Self::new()
189    }
190}
191
192pub type NotFound = NotFoundV1;
193
194// 06 AlreadyExists — context: AlreadyExists
195#[derive(Debug, Clone, Serialize)]
196#[allow(clippy::empty_structs_with_brackets)]
197pub struct AlreadyExistsV1 {}
198
199impl AlreadyExistsV1 {
200    #[must_use]
201    pub fn new() -> Self {
202        Self {}
203    }
204}
205
206impl Default for AlreadyExistsV1 {
207    fn default() -> Self {
208        Self::new()
209    }
210}
211
212pub type AlreadyExists = AlreadyExistsV1;
213
214// 07 PermissionDenied — context: PermissionDenied
215#[derive(Debug, Clone, Serialize)]
216pub struct PermissionDeniedV1 {
217    pub reason: String,
218}
219
220impl PermissionDeniedV1 {
221    #[must_use]
222    pub fn new(reason: impl Into<String>) -> Self {
223        Self {
224            reason: reason.into(),
225        }
226    }
227}
228
229pub type PermissionDenied = PermissionDeniedV1;
230
231// 08 ResourceExhausted — context: ResourceExhausted
232#[derive(Debug, Clone, Serialize)]
233pub struct ResourceExhaustedV1 {
234    pub violations: Vec<QuotaViolation>,
235}
236
237impl ResourceExhaustedV1 {
238    #[must_use]
239    pub fn new(violations: impl Into<Vec<QuotaViolation>>) -> Self {
240        Self {
241            violations: violations.into(),
242        }
243    }
244}
245
246pub type ResourceExhausted = ResourceExhaustedV1;
247
248// 09 FailedPrecondition — context: FailedPrecondition
249#[derive(Debug, Clone, Serialize)]
250pub struct FailedPreconditionV1 {
251    pub violations: Vec<PreconditionViolation>,
252}
253
254impl FailedPreconditionV1 {
255    #[must_use]
256    pub fn new(violations: impl Into<Vec<PreconditionViolation>>) -> Self {
257        Self {
258            violations: violations.into(),
259        }
260    }
261}
262
263pub type FailedPrecondition = FailedPreconditionV1;
264
265// 10 Aborted — context: Aborted
266#[derive(Debug, Clone, Serialize)]
267pub struct AbortedV1 {
268    pub reason: String,
269}
270
271impl AbortedV1 {
272    #[must_use]
273    pub fn new(reason: impl Into<String>) -> Self {
274        Self {
275            reason: reason.into(),
276        }
277    }
278}
279
280pub type Aborted = AbortedV1;
281
282// 11 OutOfRange — context: OutOfRange
283#[derive(Debug, Clone, Serialize)]
284pub struct OutOfRangeV1 {
285    pub field_violations: Vec<FieldViolation>,
286}
287
288impl OutOfRangeV1 {
289    #[must_use]
290    pub fn new(violations: impl Into<Vec<FieldViolation>>) -> Self {
291        Self {
292            field_violations: violations.into(),
293        }
294    }
295}
296
297pub type OutOfRange = OutOfRangeV1;
298
299// 12 Unimplemented — context: Unimplemented
300#[derive(Debug, Clone, Serialize)]
301#[allow(clippy::empty_structs_with_brackets)]
302pub struct UnimplementedV1 {}
303
304impl UnimplementedV1 {
305    #[must_use]
306    pub fn new() -> Self {
307        Self {}
308    }
309}
310
311impl Default for UnimplementedV1 {
312    fn default() -> Self {
313        Self::new()
314    }
315}
316
317pub type Unimplemented = UnimplementedV1;
318
319// 13 Internal — context: Internal
320#[derive(Debug, Clone, Serialize)]
321pub struct InternalV1 {
322    #[serde(skip)]
323    pub description: String,
324}
325
326impl InternalV1 {
327    #[must_use]
328    pub fn new(description: impl Into<String>) -> Self {
329        Self {
330            description: description.into(),
331        }
332    }
333}
334
335pub type Internal = InternalV1;
336
337// 14 ServiceUnavailable — context: ServiceUnavailable
338#[derive(Debug, Clone, Serialize)]
339pub struct ServiceUnavailableV1 {
340    #[serde(skip_serializing_if = "Option::is_none")]
341    pub retry_after_seconds: Option<u64>,
342}
343
344impl ServiceUnavailableV1 {
345    #[must_use]
346    pub fn new(retry_after_seconds: Option<u64>) -> Self {
347        Self {
348            retry_after_seconds,
349        }
350    }
351}
352
353pub type ServiceUnavailable = ServiceUnavailableV1;
354
355// 15 DataLoss — context: DataLoss
356#[derive(Debug, Clone, Serialize)]
357#[allow(clippy::empty_structs_with_brackets)]
358pub struct DataLossV1 {}
359
360impl DataLossV1 {
361    #[must_use]
362    pub fn new() -> Self {
363        Self {}
364    }
365}
366
367impl Default for DataLossV1 {
368    fn default() -> Self {
369        Self::new()
370    }
371}
372
373pub type DataLoss = DataLossV1;
374
375// 16 Unauthenticated — context: Unauthenticated
376#[derive(Debug, Clone, Serialize)]
377pub struct UnauthenticatedV1 {
378    #[serde(skip_serializing_if = "Option::is_none")]
379    pub reason: Option<String>,
380}
381
382impl UnauthenticatedV1 {
383    #[must_use]
384    pub fn new() -> Self {
385        Self { reason: None }
386    }
387
388    #[must_use]
389    pub fn with_reason(mut self, reason: impl Into<String>) -> Self {
390        self.reason = Some(reason.into());
391        self
392    }
393}
394
395impl Default for UnauthenticatedV1 {
396    fn default() -> Self {
397        Self::new()
398    }
399}
400
401pub type Unauthenticated = UnauthenticatedV1;