base_web_content/rejected.rs
1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4use crate::{ContentError, Violation};
5use std::fmt;
6
7/// Content that was refused, with every handle the caller gave the parser, so that provisional uploads can be removed.
8#[non_exhaustive]
9pub struct Rejected<H> {
10 /// Why the content was refused.
11 pub reason: Rejection,
12 /// The handle of every upload the caller stored, including those a later upload replaced.
13 pub handles: Vec<H>,
14}
15
16/// Shows the reason and the number of handles, since a handle may name what was submitted.
17impl<H> fmt::Debug for Rejected<H> {
18 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
19 formatter
20 .debug_struct("Rejected")
21 .field("reason", &self.reason)
22 .field("handles", &self.handles.len())
23 .finish()
24 }
25}
26
27/// Why content was refused: the two kinds of failure `design/errors.md` defines. It is exhaustive, so that an application can match it without a wildcard; adding a kind is a breaking change.
28#[derive(Clone, Debug, PartialEq, Eq)]
29pub enum Rejection {
30 /// Parsing stopped with a fatal error.
31 Error(ContentError),
32 /// The body parsed, but some declared fields could not be accepted: every one, in declaration order.
33 Violations(Vec<Violation>),
34}
35
36impl fmt::Display for Rejection {
37 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
38 match self {
39 Self::Error(error) => error.fmt(formatter),
40 Self::Violations(violations) => {
41 let violations: Vec<String> = violations.iter().map(Violation::to_string).collect();
42 write!(
43 formatter,
44 "content has invalid fields: {}",
45 violations.join(", ")
46 )
47 }
48 }
49 }
50}