diff options
| author | tv <tv@krebsco.de> | 2026-11-07 22:35:21 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-07 22:35:21 +0100 |
| commit | 389b11b597b6bf60f120b190002bbb76fff28dbf (patch) | |
| tree | 94a9c9aac6aac510218bb454bc90bdd3a6dc920c /src/document | |
| parent | 1a5b5ea02909e6c176ebd85d395e47fe15fcdba0 (diff) | |
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.
Diffstat (limited to 'src/document')
| -rw-r--r-- | src/document/changes.rs | 27 | ||||
| -rw-r--r-- | src/document/mod.rs | 3 |
2 files changed, 29 insertions, 1 deletions
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<MisplacedAuthor> { 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<Vec<Change>> { + 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<MisplacedAuthor> { 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 |
