use super::MatterPart;
use crate::b64::error::Error as CesrUtilError;
#[cfg(feature = "alloc")]
#[allow(
unused_imports,
reason = "alloc prelude items; subset used per cfg/feature combination"
)]
use alloc::string::String;
use base64::DecodeError;
use core::str::Utf8Error;
use thiserror::Error as ThisError;
#[derive(Debug, ThisError, PartialEq, Eq)]
pub enum ParsingError {
#[error("Input stream is empty.")]
EmptyStream,
#[error("Input stream is too short; more bytes were expected to complete parsing of `{0}`.")]
StreamTooShort(MatterPart),
#[error("Unrecognized code: '{0}' does not correspond to a known Matter code.")]
UnknownMatterCode(String),
#[error("Malformed code: the {part} component was invalid. Found '{found}'.")]
MalformedCode {
part: MatterPart,
found: String,
},
#[error("The character '{0}' is not a valid lead character for a variable-sized primitive.")]
InvalidVariableSizeLead(char),
#[error("Attempted to apply variable-length logic to the fixed-size code '{0}'.")]
MismatchedSizingLogic(String),
#[error("A low-level conversion error occurred")]
Conversion(#[from] CesrUtilError),
#[error("Invalid UTF-8 sequence encountered during parsing.")]
InvalidUtf8(#[from] Utf8Error),
#[error("Base64 decoding failed.")]
Base64(DecodeError),
}
impl From<DecodeError> for ParsingError {
fn from(e: DecodeError) -> Self {
Self::Base64(e)
}
}
#[derive(Debug, ThisError, PartialEq, Eq)]
pub enum ValidationError {
#[error("Unrecognized code: '{0}' does not correspond to a known Matter code.")]
UnknownMatterCode(String),
#[error("Malformed code: the {part} component was invalid. Found '{found}'.")]
MalformedCode {
part: MatterPart,
found: String,
},
#[error("The code '{code}' requires a 'soft' component, but it was not provided.")]
MissingSoft {
code: String,
},
#[error(
"The 'soft' component has an incorrect length for code '{code}': expected {expected}, but found {found}."
)]
IncorrectSoftLength {
code: String,
expected: usize,
found: usize,
},
#[error("The 'soft' component for code '{code}' contains invalid Base64 characters.")]
InvalidSoftFormat {
code: String,
},
#[error("The code '{code}' requires a raw data payload, but it was not provided.")]
MissingRaw {
code: String,
},
#[error("The code '{code}' must not have a raw data payload.")]
UnexpectedRaw {
code: String,
},
#[error("Incorrect raw data size for code '{code}': expected {expected}, but found {found}.")]
IncorrectRawSize {
code: String,
expected: usize,
found: usize,
},
#[error(
"The code '{0}' is a fixed-size code and cannot be promoted to a variable-size equivalent."
)]
IncompatiblePromotion(String),
#[error(
"The requested promotion for code '{code}' with a lead size of {lead} is not a valid CESR transformation."
)]
InvalidPromotionTarget {
code: String,
lead: usize,
},
#[error("Promotion from '{from}' to '{to}' resulted in an invalid or unknown code.")]
InvalidPromotionResult {
from: String,
to: String,
},
#[error("Cannot get a fixed raw size for the variable-sized code '{0}'.")]
InvalidSizingOperation(String),
#[error("Non-canonical encoding: non-zero bits were found in the '{0}' padding section.")]
NonCanonicalEncoding(MatterPart),
#[error(
"Structural integrity error: the parsed components do not match the expected total length of the primitive."
)]
StructuralIntegrityError,
#[error(
"Declared variable size is too large: computing the primitive's full size overflowed the address space."
)]
SizeOverflow,
}
#[derive(Debug, ThisError, PartialEq, Eq)]
pub enum MatterBuildError {
#[error(transparent)]
Parsing(#[from] ParsingError),
#[error(transparent)]
Validation(#[from] ValidationError),
}
#[cfg(test)]
mod build_error_tests {
use super::{MatterBuildError, ParsingError, ValidationError};
use alloc::string::ToString;
#[test]
fn from_parsing_error_lands_in_parsing_variant() {
let e: MatterBuildError = ParsingError::EmptyStream.into();
assert_eq!(e, MatterBuildError::Parsing(ParsingError::EmptyStream));
}
#[test]
fn from_validation_error_lands_in_validation_variant() {
let e: MatterBuildError = ValidationError::StructuralIntegrityError.into();
assert_eq!(
e,
MatterBuildError::Validation(ValidationError::StructuralIntegrityError)
);
}
#[test]
fn display_is_transparent_to_source() {
let e: MatterBuildError = ParsingError::EmptyStream.into();
assert_eq!(e.to_string(), ParsingError::EmptyStream.to_string());
}
#[test]
fn validation_display_is_transparent_to_source() {
let e: MatterBuildError = ValidationError::StructuralIntegrityError.into();
assert_eq!(
e.to_string(),
ValidationError::StructuralIntegrityError.to_string()
);
}
}