use crate::operation::{
OperationExecutionContext, OperationNodeId, OperationNodeKind, OperationPlanError,
OperationStage,
};
pub struct Projection<'a>(crate::xml::dom::benchmark::Projection<'a>);
impl<'a> Projection<'a> {
pub fn new(
input: &'a str,
backend: crate::XmlBackend,
) -> Result<Self, crate::xml::dom::ParseError> {
Ok(Self(crate::xml::dom::benchmark::Projection::new(
input, backend,
)?))
}
pub fn project(&self) -> Result<crate::xml::dom::Document<'a>, crate::xml::dom::ParseError> {
self.0.project()
}
}
pub struct Plan {
context: OperationExecutionContext<(), ()>,
order: Vec<OperationNodeId>,
}
impl Plan {
pub fn new(references: usize) -> Self {
assert!((1..=64).contains(&references), "bounded benchmark graph");
let mut context = OperationExecutionContext::new((), (), None);
let root = context.add_node(OperationNodeKind::Document, OperationStage::Parse, None);
let mut order = vec![root];
for index in 0..references {
let node = context.add_node(
OperationNodeKind::Digest { index },
OperationStage::Digest,
None,
);
context
.add_dependency(node, root)
.expect("forward dependency");
order.push(node);
}
let crypto = context.add_node(OperationNodeKind::Crypto, OperationStage::Crypto, None);
for &node in &order[1..] {
context
.add_dependency(crypto, node)
.expect("forward dependency");
}
order.push(crypto);
let evidence =
context.add_node(OperationNodeKind::Evidence, OperationStage::Evidence, None);
context
.add_dependency(evidence, crypto)
.expect("forward dependency");
order.push(evidence);
Self { context, order }
}
pub fn compile(&mut self) {
self.context.compile().expect("valid benchmark plan");
}
pub fn execute(&self) {
for &node in &self.order {
self.context
.run(node, || Ok::<_, OperationPlanError>(()))
.expect("dependency order");
}
}
}