From 389b11b597b6bf60f120b190002bbb76fff28dbf Mon Sep 17 00:00:00 2001 From: tv Date: Sat, 7 Nov 2026 22:35:21 +0100 Subject: access: screening received changes access::screen: a batch of received changes judged change by change, those that change what rules read applied before the next is judged; a refused change stays out with whatever builds on it, kept aside for operators; changes missing dependencies wait. Auth plan M6. --- src/document/changes.rs | 27 +++++++++++++++++++++++++++ src/document/mod.rs | 3 ++- 2 files changed, 29 insertions(+), 1 deletion(-) (limited to 'src/document') diff --git a/src/document/changes.rs b/src/document/changes.rs index 57e2bf7..eef7dbc 100644 --- a/src/document/changes.rs +++ b/src/document/changes.rs @@ -240,6 +240,33 @@ pub(crate) fn misplaced_author(mut data: &[u8]) -> Option { None } +/// The changes in `data`, chunks as sync messages and downloads carry them: changes, +/// compressed or not, bundles, documents. None if a chunk doesn't load. +pub(crate) fn changes_in(mut data: &[u8]) -> Option> { + const MAGIC: [u8; 4] = [0x85, 0x6f, 0x4a, 0x83]; + const HEADER: usize = 9; + let mut changes = Vec::new(); + while !data.is_empty() { + if data.len() <= HEADER || data[..4] != MAGIC { + return None; + } + let kind = data[8]; + let (length, read) = uleb128(&data[HEADER..])?; + let end = HEADER + .checked_add(read)? + .checked_add(usize::try_from(length).ok()?)?; + let chunk = data.get(..end)?; + data = &data[end..]; + match kind { + 1 | 2 => changes.push(Change::try_from(chunk).ok()?), + 3 => changes.extend(automerge::Bundle::try_from(chunk).ok()?.to_changes().ok()?), + 0 => changes.extend(Document::load(chunk).ok()?.get_changes(&[])), + _ => return None, + } + } + Some(changes) +} + /// `change`, if it names an author but isn't its actor's first (`misplaced_author`). fn misplaced_in(change: &Change) -> Option { let author = change.author()?; diff --git a/src/document/mod.rs b/src/document/mod.rs index 7f59942..c183537 100644 --- a/src/document/mod.rs +++ b/src/document/mod.rs @@ -9,7 +9,8 @@ /// Only `document` and `remake` use Automerge itself (`architecture.md`, The document). pub(crate) use automerge::transaction::{Transactable, Transaction}; pub(crate) use automerge::{ - ActorId, Automerge as Document, Change, ChangeHash, ReadDoc, ScalarValue, + ActorId, Automerge as Document, Change, ChangeHash, ExpandedChange, PatchLog, ReadDoc, + ScalarValue, }; /// The whole document as bytes, as the engine saves it: a backup, the document -- cgit v1.3.1