aboutsummaryrefslogtreecommitdiffstats
path: root/src/document/signatures.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/document/signatures.rs')
-rw-r--r--src/document/signatures.rs37
1 files changed, 36 insertions, 1 deletions
diff --git a/src/document/signatures.rs b/src/document/signatures.rs
index e92cf9c..c8af89a 100644
--- a/src/document/signatures.rs
+++ b/src/document/signatures.rs
@@ -154,13 +154,42 @@ impl<'de> serde::Deserialize<'de> for SignEvery {
#[derive(Debug, Default)]
pub(crate) struct Signatures {
by_change: HashMap<ChangeHash, [u8; 64]>,
+ /// The changes signed, in the order their signatures came: the document file
+ /// appends those after the ones it wrote (`since`).
+ order: Vec<ChangeHash>,
/// This node's latest change, if no signature vouches for it yet (`SignEvery`).
unsigned: Option<ChangeHash>,
}
impl Signatures {
+ /// Signatures kept before, as `since` gave them (the document file).
+ pub(crate) fn from_kept(kept: Vec<(ChangeHash, [u8; 64])>) -> Self {
+ let mut signatures = Self::default();
+ for (hash, signature) in kept {
+ signatures.insert(hash, signature);
+ }
+ signatures
+ }
+
pub(crate) fn insert(&mut self, hash: ChangeHash, signature: [u8; 64]) {
- self.by_change.insert(hash, signature);
+ if self.by_change.insert(hash, signature).is_none() {
+ self.order.push(hash);
+ }
+ }
+
+ /// How many signatures there are.
+ pub(crate) fn count(&self) -> usize {
+ self.order.len()
+ }
+
+ /// The signatures after the first `count` (`count`), in the order they came.
+ pub(crate) fn since(&self, count: usize) -> Vec<(ChangeHash, [u8; 64])> {
+ self.order
+ .get(count..)
+ .unwrap_or_default()
+ .iter()
+ .map(|hash| (*hash, self.by_change[hash]))
+ .collect()
}
/// Signs `hash`, this node's latest change, with `key` and keeps the signature: it
@@ -286,6 +315,12 @@ mod tests {
signatures.left_unsigned(a);
signatures.sign(b, &key);
assert!(!signatures.sign_latest(&key));
+ // Kept in the order they came, each once.
+ assert_eq!(signatures.count(), 2);
+ assert_eq!(signatures.since(1)[0].0, b);
+ assert!(signatures.since(5).is_empty());
+ let again = Signatures::from_kept(signatures.since(0));
+ assert_eq!(again.since(0), signatures.since(0));
}
/// Protocol data, listed paths (within or above them) and asked-for writes are