Skip to main content

bc_envelope/extension/edge/
edges.rs

1use std::collections::HashMap;
2
3use bc_components::{Digest, DigestProvider};
4
5use crate::{Envelope, Result};
6
7/// A container for edge envelopes on a document.
8///
9/// `Edges` stores pre-constructed edge envelopes keyed by their digest,
10/// mirroring the `Attachments` container but for edges as defined in
11/// BCR-2026-003.
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct Edges {
14    envelopes: HashMap<Digest, Envelope>,
15}
16
17impl Default for Edges {
18    fn default() -> Self { Self::new() }
19}
20
21impl Edges {
22    /// Creates a new empty edges container.
23    pub fn new() -> Self { Self { envelopes: HashMap::new() } }
24
25    /// Adds a pre-constructed edge envelope.
26    pub fn add(&mut self, edge_envelope: Envelope) {
27        let digest = edge_envelope.digest();
28        self.envelopes.insert(digest, edge_envelope);
29    }
30
31    /// Retrieves an edge by its digest.
32    pub fn get(&self, digest: Digest) -> Option<&Envelope> {
33        self.envelopes.get(&digest)
34    }
35
36    /// Removes an edge by its digest.
37    pub fn remove(&mut self, digest: Digest) -> Option<Envelope> {
38        self.envelopes.remove(&digest)
39    }
40
41    /// Removes all edges from the container.
42    pub fn clear(&mut self) { self.envelopes.clear(); }
43
44    /// Returns whether the container has any edges.
45    pub fn is_empty(&self) -> bool { self.envelopes.is_empty() }
46
47    /// Returns the number of edges in the container.
48    pub fn len(&self) -> usize { self.envelopes.len() }
49
50    /// Returns an iterator over all edge envelopes.
51    pub fn iter(&self) -> impl Iterator<Item = (&Digest, &Envelope)> {
52        self.envelopes.iter()
53    }
54
55    /// Adds all edges as `'edge'` assertion envelopes to the given envelope.
56    pub fn add_to_envelope(&self, envelope: Envelope) -> Envelope {
57        let mut new_envelope = envelope;
58        for (_digest, edge_envelope) in self.envelopes.iter() {
59            new_envelope = new_envelope
60                .add_assertion(known_values::EDGE, edge_envelope.clone());
61        }
62        new_envelope
63    }
64
65    /// Extracts edges from an envelope's `'edge'` assertions.
66    pub fn try_from_envelope(envelope: &Envelope) -> Result<Edges> {
67        let edge_envelopes = envelope.edges()?;
68        let mut edges = Edges::new();
69        for edge in edge_envelopes {
70            let digest = edge.digest();
71            edges.envelopes.insert(digest, edge);
72        }
73        Ok(edges)
74    }
75}
76
77/// A trait for types that can have edges.
78///
79/// `Edgeable` provides a consistent interface for working with edges.
80/// Types implementing this trait can store and retrieve edge envelopes
81/// representing verifiable claims as defined in BCR-2026-003.
82#[allow(dead_code)]
83pub trait Edgeable {
84    /// Returns a reference to the edges container.
85    fn edges(&self) -> &Edges;
86
87    /// Returns a mutable reference to the edges container.
88    fn edges_mut(&mut self) -> &mut Edges;
89
90    /// Adds a pre-constructed edge envelope.
91    fn add_edge(&mut self, edge_envelope: Envelope) {
92        self.edges_mut().add(edge_envelope);
93    }
94
95    /// Retrieves an edge by its digest.
96    fn get_edge(&self, digest: Digest) -> Option<&Envelope> {
97        self.edges().get(digest)
98    }
99
100    /// Removes an edge by its digest.
101    fn remove_edge(&mut self, digest: Digest) -> Option<Envelope> {
102        self.edges_mut().remove(digest)
103    }
104
105    /// Removes all edges.
106    fn clear_edges(&mut self) { self.edges_mut().clear(); }
107
108    /// Returns whether the object has any edges.
109    fn has_edges(&self) -> bool { !self.edges().is_empty() }
110}
111
112use crate::known_values;