///|
/// Compatibility direction requested by the caller.
pub(all) enum CompatibilityMode {
Backward
Forward
Full
} derive(Eq, Debug)
///|
/// Importance assigned to an evolution finding.
pub(all) enum Severity {
Breaking
Warning
Info
} derive(Eq, Debug)
///|
/// A concrete payload showing why a compatibility rule fails.
pub(all) struct Witness {
payload : String
accepted_by : String
rejected_by : String
reason : String
} derive(Eq, Debug)
///|
/// One stable, path-addressable contract evolution finding.
pub(all) struct Change {
code : String
severity : Severity
direction : String
path : String
message : String
hint : String
witness : Witness?
} derive(Eq, Debug)
///|
/// Complete analysis result for two contract versions.
pub(all) struct AnalysisReport {
contract_name : String
old_version : String
new_version : String
mode : CompatibilityMode
changes : Array[Change]
} derive(Eq, Debug)
///|
pub fn CompatibilityMode::render(self : CompatibilityMode) -> String {
match self {
Backward => "backward"
Forward => "forward"
Full => "full"
}
}
///|
pub fn Severity::render(self : Severity) -> String {
match self {
Breaking => "breaking"
Warning => "warning"
Info => "info"
}
}
///|
pub fn AnalysisReport::breaking_count(self : AnalysisReport) -> Int {
self.changes.count_if(change => change.severity == Breaking)
}
///|
pub fn AnalysisReport::warning_count(self : AnalysisReport) -> Int {
self.changes.count_if(change => change.severity == Warning)
}
///|
pub fn AnalysisReport::info_count(self : AnalysisReport) -> Int {
self.changes.count_if(change => change.severity == Info)
}
///|
pub fn AnalysisReport::is_compatible(self : AnalysisReport) -> Bool {
self.breaking_count() == 0
}
///|
pub fn AnalysisReport::verdict(self : AnalysisReport) -> String {
if self.is_compatible() {
"compatible"
} else {
"incompatible"
}
}
///|
fn breaking_change(
code : String,
direction : String,
path : String,
message : String,
hint : String,
witness : Witness,
) -> Change {
{
code,
severity: Breaking,
direction,
path,
message,
hint,
witness: Some(witness),
}
}
///|
fn info_change(
code : String,
direction : String,
path : String,
message : String,
hint : String,
) -> Change {
{ code, severity: Info, direction, path, message, hint, witness: None }
}