#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DataflowFailure {
Transfer,
Join,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum DataflowEvent<N, E, C> {
Visit(N),
Propagate {
edge: E,
class: EdgeClass<C>,
},
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct DataflowUsage {
pub work: usize,
pub observations: usize,
pub depth: usize,
pub output: usize,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum DataflowError<N, E, L> {
UnknownSeed(N),
ContinuationMismatch {
changed: ContinuationFingerprint,
expected: ValueFingerprint,
actual: ValueFingerprint,
},
BudgetExceeded {
kind: BudgetKind,
limit: usize,
attempted: usize,
node: Option<N>,
edge: Option<E>,
location: L,
target_location: Option<L>,
},
NodeFailure {
failure: DataflowFailure,
node: N,
location: L,
},
EdgeFailure {
failure: DataflowFailure,
edge: E,
location: L,
target_location: L,
},
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ContinuationFingerprint {
Graph,
Policy,
Dependencies,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct CausalPredecessor<N, E> {
pub node: N,
pub edge: Option<E>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DataflowExplanation<N, E> {
predecessors: Box<[CausalPredecessor<N, E>]>,
omitted: usize,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
struct CausalRecord<N, E> {
retained: Vec<CausalPredecessor<N, E>>,
omitted: usize,
}
impl<N, E> DataflowExplanation<N, E> {
pub fn predecessors(&self) -> &[CausalPredecessor<N, E>] {
&self.predecessors
}
pub const fn truncated(&self) -> bool {
self.omitted != 0
}
pub const fn omitted(&self) -> usize {
self.omitted
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DataflowContinuation<N, E, C, S> {
token: ContinuationToken,
graph: ValueFingerprint,
policy: ValueFingerprint,
dependencies: ValueFingerprint,
states: BTreeMap<N, S>,
pending: BTreeSet<N>,
events: Vec<DataflowEvent<N, E, C>>,
causes: BTreeMap<N, CausalRecord<N, E>>,
cause_limit: usize,
usage: DataflowUsage,
}
impl<N, E, C, S> DataflowContinuation<N, E, C, S> {
pub const fn token(&self) -> ContinuationToken {
self.token
}
pub const fn graph_fingerprint(&self) -> ValueFingerprint {
self.graph
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum DataflowProgress<N, E, C, S> {
Complete(DataflowSolution<N, E, C, S>),
Suspended(DataflowContinuation<N, E, C, S>),
}
pub type DataflowProgressResult<N, E, L, C, S> =
Result<DataflowProgress<N, E, C, S>, DataflowError<N, E, L>>;
#[derive(Clone, Copy)]
struct ContinuationIdentity {
graph: ValueFingerprint,
policy: ValueFingerprint,
dependencies: ValueFingerprint,
}
pub type DataflowResult<N, E, L, C, S> =
Result<DataflowSolution<N, E, C, S>, DataflowError<N, E, L>>;
pub type CompletionProofResult<N, E, L, C, S> =
Result<DataflowCompletionProof<N, E, C, S>, DataflowError<N, E, L>>;
struct ChargeLocation<N, E, L> {
node: Option<N>,
edge: Option<E>,
location: L,
target_location: Option<L>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DataflowSolution<N, E, C, S> {
states: BTreeMap<N, S>,
events: Vec<DataflowEvent<N, E, C>>,
usage: DataflowUsage,
causes: BTreeMap<N, CausalRecord<N, E>>,
}
pub const DATAFLOW_PROOF_SCHEMA_REVISION: u64 = 1;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DataflowCompletionProof<N, E, C, S> {
identity: ValueFingerprint,
graph: ValueFingerprint,
lattice: ValueFingerprint,
policy: ValueFingerprint,
boundaries: ValueFingerprint,
limits: ValueFingerprint,
dependencies: ValueFingerprint,
seed_fingerprints: BTreeMap<N, ValueFingerprint>,
observations: Box<[(N, E, N)]>,
node_fingerprints: BTreeMap<N, ValueFingerprint>,
solution: DataflowSolution<N, E, C, S>,
}
impl<N: Ord, E, C, S> DataflowCompletionProof<N, E, C, S> {
pub const fn identity(&self) -> ValueFingerprint {
self.identity
}
pub fn observations(&self) -> &[(N, E, N)] {
&self.observations
}
pub fn node_fingerprints(&self) -> &BTreeMap<N, ValueFingerprint> {
&self.node_fingerprints
}
pub const fn solution(&self) -> &DataflowSolution<N, E, C, S> {
&self.solution
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CompletionProofMismatch {
Graph,
Lattice,
Policy,
Limits,
Dependencies,
}
impl<N: Ord, E, C, S> DataflowSolution<N, E, C, S> {
pub fn state(&self, node: &N) -> Option<&S> {
self.states.get(node)
}
pub fn states(&self) -> impl ExactSizeIterator<Item = (&N, &S)> {
self.states.iter()
}
pub fn events(&self) -> &[DataflowEvent<N, E, C>] {
&self.events
}
pub const fn usage(&self) -> DataflowUsage {
self.usage
}
pub fn explain(&self, node: &N, limit: usize) -> Option<DataflowExplanation<N, E>>
where
N: Clone,
E: Clone,
{
let causes = self.causes.get(node)?;
let retained = causes
.retained
.iter()
.take(limit)
.cloned()
.collect::<Vec<_>>();
Some(DataflowExplanation {
omitted: causes
.omitted
.saturating_add(causes.retained.len().saturating_sub(retained.len())),
predecessors: retained.into_boxed_slice(),
})
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct FixpointEngine;