This is achieved by liberal use of feature flags. Main additions are:
* Build the OpSet more efficiently when loading from compressed
document storage using a DocObserver as implemented in
`automerge::op_tree::load`
* Reimplement the parsing login in the various types in
`automerge::sync`
There are numerous other small changes required to get the types to line
up.
Signed-off-by: Alex Good <alex@memoryandthought.me>
The representation of changes in storage-v2 is different to the existing
representation so add accessor methods to the fields of `Change` and
make all accesses go through them. This allows the change representation
in storage-v2 to be a drop-in.
Signed-off-by: Alex Good <alex@memoryandthought.me>
The ordering of opids in the successor and predecessors of an op is
relevant when encoding because inconsistent ordering changes the
hashgraph. This means we must maintain the invariant that opids are
encoded in ascending lamport order. We have been maintaining this
invariant in the encoding implementation - however, this is not ideal
because it requires allocating for every op in the change when we commit
a transaction.
Add `types::OpIds` and use it in place of `Vec<OpId>` for `Op::succ` and
`Op::pred`. `OpIds` maintains the invariant that the IDs it contains
must be ordered with respect to some comparator function - which is
always `OpSetMetadata::lamport_cmp`. Remove the sorting of opids in
SuccEncoder::append.
There is easy confusion when calling parents with the id of a scalar,
wanting it to get the parent object first but that is not implemented.
To get the parent object of a scalar id would mean searching every
object for the OpId which may get too expensive when lots of objects are
around, this may be reconsidered later but the result would still be
useful to indicate when the id doesn't exist in the document vs has no
parents.
This allows users to have the convenience of getting all of the parents
of an object, whilst allowing them to terminate early when they have
found what they need.
- Commit now returns just a single hash rather than a vec. Since the
change we create from committing has all of the heads as deps there
can only be one hash/head after committing.
- Apply changes now takes a Vec rather than a slice. This avoids having
to clone them inside.
- transact_with now passes the result of the closure to the commit
options function
- Remove patch struct
- Change receive_sync_message to return a () instead of the
`Option<Patch>`
- Change `Transaction*` structs to just `*` and use the transaction
module
- Make CommitOptions fields public