diff options
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 |
