Skip to main content

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}