use std::fmt::Display;
use crate::{Binding, Certificate, Certification, Delegation, Edge, Network};
#[derive(Debug)]
pub struct ReduceError(pub String);
impl Display for ReduceError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl std::error::Error for ReduceError {}
pub trait ResidualNetworkTrait {
fn new(network: &Network, anchors: &[TrustAnchor]) -> Self;
fn search(&self, target: &Binding) -> Option<(Path, u8)>;
fn reduce(&mut self, path: &Path, reduce_amount: u8) -> Result<(), ReduceError>;
fn anchor_capacity(&self, anchor: &Certificate) -> Option<u8>;
fn outbound_capacity(&self, cert: &Certificate) -> u8;
fn used_flow_between(&self, issuer: &Certificate, target: &Certificate) -> u8;
}
pub trait WotSearchTrait {
fn new(network: Network, anchors: Vec<TrustAnchor>, target: Binding) -> Self;
fn search(&mut self, target_trust_amount: usize) -> Paths;
}
#[derive(Debug)]
pub struct Paths {
paths: Vec<(Path, u8)>,
}
impl Paths {
pub fn new() -> Self {
Self {
paths: Default::default(),
}
}
pub fn new_with_paths(paths: Vec<(Path, u8)>) -> Self {
Self { paths }
}
pub fn get(&self) -> &[(Path, u8)] {
&self.paths
}
pub fn add(&mut self, path: Path, effective_amount: u8) {
assert!(
effective_amount <= path.standalone_amount(),
"Effective amount cannot exceed the standalone amount of the path."
);
self.paths.push((path, effective_amount));
}
pub fn total_effective_amount(&self) -> usize {
self.paths
.iter()
.map(|(_, effective)| *effective as usize)
.sum()
}
}
impl Default for Paths {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub struct Path {
pub start: Certificate,
pub delegations: Vec<Delegation>,
pub certification: Certification,
}
impl Path {
pub fn new(
start: Certificate,
delegations: Vec<Delegation>,
certification: Certification,
) -> Self {
Self {
start,
delegations,
certification,
}
}
pub fn first(&self) -> &Certificate {
&self.start
}
pub fn delegations(&self) -> &[Delegation] {
&self.delegations
}
pub fn binding(&self) -> &Certification {
&self.certification
}
pub(crate) fn standalone_amount(&self) -> u8 {
self.delegations
.iter()
.map(|d| d.trust_amount)
.min()
.unwrap_or(120) }
pub fn certificates(&self) -> Vec<&Certificate> {
let mut certs = vec![self.first()];
for edge in self.delegations() {
certs.push(edge.target())
}
certs.push(&self.certification.target.cert);
certs
}
pub fn length(&self) -> usize {
self.delegations.len() + 2
}
pub fn edges(&self) -> impl Iterator<Item = Edge> + '_ {
self.delegations()
.iter()
.map(|d| Edge::Delegation(d.clone()))
.chain([Edge::Certification(self.binding().clone())])
}
}
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub struct TrustAnchor {
pub cert: Certificate,
pub trust_amount: u8,
}
impl TrustAnchor {
pub fn new(cert: Certificate, trust_amount: u8) -> Self {
assert!(trust_amount <= 120);
Self { cert, trust_amount }
}
pub fn cert(&self) -> &Certificate {
&self.cert
}
pub fn amount(&self) -> u8 {
self.trust_amount
}
}