Skip to main content

c2pa_structured_text/
error.rs

1// Copyright 2026 WritersLogic. All rights reserved.
2// Licensed under the Apache License, Version 2.0 or the MIT license,
3// at your option.
4
5use std::fmt;
6
7#[derive(Debug)]
8pub enum Error {
9    /// No `-----BEGIN/END C2PA MANIFEST-----` block was located.
10    NotFound,
11    /// More than one manifest block was found. Per the specification the asset
12    /// shall then be treated as if no manifests were located.
13    MultipleBlocks,
14    /// The block is present but the reference between the delimiters is empty.
15    EmptyReference,
16    /// The reference is neither a resolvable URI nor a `data:` URI.
17    MalformedReference(String),
18    /// The text uses bare CR (0x0D) line endings, which are unsupported by the
19    /// structured-text binding method because they make line boundaries
20    /// ambiguous. Convert to LF or CRLF before embedding or validating.
21    BareCarriageReturn,
22    /// A `data:application/c2pa;base64,` reference could not be Base64-decoded.
23    ManifestDecode(crate::codec::DecodeError),
24    /// The exclusion ranges of a data hash assertion are malformed: negative,
25    /// out of order, overlapping, or extending past the end of the asset.
26    /// Corresponds to `assertion.dataHash.malformed`.
27    MalformedExclusion,
28    /// The recomputed data hash did not match the value in the assertion.
29    /// Corresponds to `assertion.dataHash.mismatch`.
30    HashMismatch,
31    /// A hash algorithm identifier outside the C2PA allowed list was requested.
32    /// Corresponds to `algorithm.unsupported`.
33    UnsupportedAlgorithm(String),
34}
35
36impl fmt::Display for Error {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        match self {
39            Self::NotFound => write!(f, "no manifest block found"),
40            Self::MultipleBlocks => write!(f, "multiple manifest blocks found"),
41            Self::EmptyReference => write!(f, "empty manifest reference"),
42            Self::MalformedReference(s) => write!(f, "malformed manifest reference: {s}"),
43            Self::BareCarriageReturn => {
44                write!(
45                    f,
46                    "bare CR line endings are not supported; convert to LF or CRLF"
47                )
48            }
49            Self::ManifestDecode(e) => write!(f, "manifest data URI is not valid base64: {e}"),
50            Self::MalformedExclusion => write!(f, "data hash exclusion range is malformed"),
51            Self::HashMismatch => write!(f, "data hash does not match the asset content"),
52            Self::UnsupportedAlgorithm(a) => write!(f, "unsupported hash algorithm: {a}"),
53        }
54    }
55}
56
57impl std::error::Error for Error {
58    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
59        match self {
60            Self::ManifestDecode(e) => Some(e),
61            _ => None,
62        }
63    }
64}