Skip to main content

structured_cades/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![doc = include_str!("../README.md")]
3
4extern crate alloc;
5
6pub mod baseline;
7pub mod basic;
8pub mod counters;
9pub mod credential;
10pub mod material;
11pub mod participants;
12pub mod prepare;
13pub mod preservation;
14pub mod properties;
15pub mod source;
16pub mod timestamp;
17
18/// Terminal processing refusal, distinct from a completed format finding.
19#[derive(Debug)]
20pub enum Error {
21    /// Original common CMS failure, preserving all underlying diagnostics.
22    Cms(structured_cms::Error),
23    /// Original ASN.1 failure, without changing its coordinates or cause.
24    Encoding {
25        /// Original protocol field whose decoding refused.
26        field: &'static str,
27        /// Original ASN.1 cause, including its retained diagnostic path.
28        cause: structured_asn1::Error,
29    },
30    /// Shared PKIX schema/DER refusal, preserving its field and location.
31    Pkix(structured_pkix::Error),
32    /// Format schema failure at an actual original value.
33    Syntax {
34        /// Exact format/schema category.
35        code: structured_cms::ErrorCode,
36        /// Original protocol field.
37        field: &'static str,
38        /// Original source offset.
39        at: u64,
40    },
41    /// Current work/storage refused before use at this original position.
42    Resource {
43        /// Actual original source position.
44        at: u64,
45        /// Exact refusal, never converted to missing material.
46        cause: structured_asn1::memory::MemoryError,
47        /// Original operation field.
48        field: &'static str,
49    },
50    /// A receipt or selected model belongs to another original source.
51    Foreign {
52        /// Actual selecting position, never a fabricated decode offset.
53        at: u64,
54    },
55}
56
57impl Error {
58    pub(crate) fn resource(
59        cause: structured_asn1::memory::MemoryError,
60        field: &'static str,
61        at: u64,
62    ) -> Self {
63        Self::Resource { at, cause, field }
64    }
65    pub(crate) fn encoding(cause: structured_asn1::Error, field: &'static str) -> Self {
66        Self::Encoding { cause, field }
67    }
68    /// A refusal of the run, rather than a recoverable document finding.
69    #[must_use]
70    pub fn is_terminal(&self) -> bool {
71        match self {
72            Self::Cms(error) => error.is_terminal(),
73            Self::Encoding { cause, .. } => {
74                cause.is_resource() || cause.code() == structured_asn1::ErrorCode::TagTooLarge
75            }
76            Self::Pkix(error) => {
77                error.is_resource() || error.code() == structured_pkix::ErrorCode::ForeignReader
78            }
79            Self::Resource { .. } | Self::Foreign { .. } => true,
80            Self::Syntax { .. } => false,
81        }
82    }
83    /// Original source position of the failure.
84    #[must_use]
85    pub fn offset(&self) -> u64 {
86        match self {
87            Self::Cms(error) => error.offset(),
88            Self::Encoding { cause, .. } => cause.offset(),
89            Self::Pkix(error) => error.offset(),
90            Self::Resource { at, .. } | Self::Foreign { at } | Self::Syntax { at, .. } => *at,
91        }
92    }
93    /// Original protocol field, when this failure originates in document
94    /// processing. A foreign receipt is caller misuse and has no invented field.
95    #[must_use]
96    pub fn field(&self) -> Option<&'static str> {
97        match self {
98            Self::Cms(cause) => Some(cause.field()),
99            Self::Pkix(cause) => Some(cause.field()),
100            Self::Encoding { field, .. }
101            | Self::Syntax { field, .. }
102            | Self::Resource { field, .. } => Some(*field),
103            Self::Foreign { .. } => None,
104        }
105    }
106}
107
108impl From<structured_cms::Error> for Error {
109    fn from(cause: structured_cms::Error) -> Self {
110        Self::Cms(cause)
111    }
112}
113
114/// Complete operation or terminal processing refusal; never a successful prefix.
115pub type Result<T> = core::result::Result<T, Error>;
116
117/// Explicitly requested format profile, never inferred from unsigned attributes.
118#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
119pub enum Level {
120    /// Mandatory signed baseline fields and signer association.
121    Basic,
122    /// Basic plus the complete signature-timestamp obligations.
123    Timestamped,
124    /// Timestamped plus all required incorporated validation material.
125    LongTerm,
126    /// Long-term plus every original archive's protected validation material.
127    Archival,
128}
129
130/// Issuer of source-derived `CAdES` receipts in the format-neutral LTV core.
131/// Only this crate constructs it, after selecting the original CMS source.
132#[derive(Debug, Clone, Copy)]
133pub struct Cades(());
134
135pub(crate) const ISSUER: Cades = Cades(());