diff options
Diffstat (limited to 'src/document/signatures.rs')
| -rw-r--r-- | src/document/signatures.rs | 37 |
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 |
