use crate::diagnostics::Diagnostic;
#[cfg(feature = "compiler")]
use crate::diagnostics::{CompileError, DiagnosticPhase, Severity};
use std::fmt;
pub type ContractViolation = Diagnostic;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ContractValidationError {
pub violations: Vec<ContractViolation>,
}
impl ContractValidationError {
pub(crate) fn single(
code: impl Into<String>,
path: impl Into<String>,
message: impl Into<String>,
) -> Self {
Self {
violations: vec![Diagnostic::violation(code, path, message)],
}
}
pub(crate) fn resource_limit(resource: &str, limit: usize, observed: usize) -> Self {
Self {
violations: vec![Diagnostic::resource_violation(
resource,
crate::limits::portable_count(limit),
crate::limits::portable_count(observed),
)],
}
}
#[cfg(feature = "compiler")]
pub(crate) fn into_compile_error(self, phase: DiagnosticPhase) -> CompileError {
CompileError {
diagnostics: self
.violations
.into_iter()
.map(|violation| {
let message = match &violation.path {
Some(path) => format!("{}: {}", path, violation.message),
None => violation.message.clone(),
};
Diagnostic {
phase: Some(phase.clone()),
severity: Some(Severity::Error),
message,
..violation
}
})
.collect(),
}
}
}
impl fmt::Display for ContractValidationError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
formatter,
"Contract validation failed with {} violation(s)",
self.violations.len()
)
}
}
impl std::error::Error for ContractValidationError {}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ContractJsonError {
MalformedJson(String),
InvalidContract(ContractValidationError),
}
impl fmt::Display for ContractJsonError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::MalformedJson(message) => write!(formatter, "Malformed Contract JSON: {message}"),
Self::InvalidContract(error) => error.fmt(formatter),
}
}
}
impl std::error::Error for ContractJsonError {}