mod accept;
mod findings;
mod read;
mod write;
pub use accept::{Refusal, accept, accept_stale};
pub use findings::{Reconciled, TestFile, TestFiles, TraceFinding, TraceRule, reconcile};
pub use read::{FILE_FIELDS, LINK_FIELDS, TEST_FIELDS, read};
pub use write::write;
use std::collections::HashMap;
use std::fmt;
use crate::attributes::VerificationFate;
use crate::canonical::Digest;
use crate::codec::Problem;
use crate::document::Document;
use crate::identity::Key;
use crate::ids::NodeId;
use crate::node::Node;
use crate::yaml::{Location, Position};
pub const TRACE: &str = "loft.trace.yaml";
pub const FORMAT: &str = "loft-trace/1";
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Trace {
pub links: Vec<Link>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Link {
pub node: Key,
pub reviewed: Option<Digest>,
pub evidence: Evidence,
pub position: Option<Position>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Evidence {
Tests(Vec<Test>),
Unverified(String),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Test {
pub file: String,
pub name: String,
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub struct TraceError {
pub location: Option<Location>,
pub problem: Problem,
}
impl fmt::Display for TraceError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.location {
Some(location) => write!(formatter, "{TRACE}:{location}: {}", self.problem),
None => write!(formatter, "{TRACE}: {}", self.problem),
}
}
}
#[derive(Debug, Clone, Copy)]
struct Place {
index: usize,
id: NodeId,
in_scope: bool,
}
fn places(document: &Document) -> HashMap<Key, Place> {
let mut places = HashMap::new();
document.walk(&mut |node| {
if let Some(id) = node.id() {
let index = places.len();
let in_scope = in_scope(node);
places.insert(
id.key(),
Place {
index,
id,
in_scope,
},
);
}
});
places
}
fn in_scope(node: Node<'_>) -> bool {
let proved = |fate: Option<VerificationFate>| fate == Some(VerificationFate::Proved);
match node {
Node::Criterion(_) => true,
Node::Constraint(constraint) => proved(constraint.verification_fate),
Node::QualityAttribute(quality) => proved(quality.verification_fate),
_ => false,
}
}
fn order(places: &HashMap<Key, Place>, key: Key) -> (usize, Key) {
(
places.get(&key).map_or(usize::MAX, |place| place.index),
key,
)
}