de16adbcc5
Transactions with no ops in them are generally undesirable. They take up space in the change log but do nothing else. They are not useless though, it may occasionally be necessary to create an empty change in order to list all the current heads of the document as dependents of the empty change. The current API makes no distinction between empty changes and non-empty changes. If the user calls `Transaction::commit` a change is created regardless of whether there are ops to commit. To provide a more useful API modify `commit` so that if there is a no-op transaction then no changes are created, but provide explicit methods to create an empty change via `Transaction::empty_change`, `Automerge::empty_change` and `Autocommit::empty_change`. Also make these APIs available in Javascript and C. |
||
---|---|---|
.. | ||
cmake | ||
examples | ||
img | ||
src | ||
test | ||
.gitignore | ||
build.rs | ||
Cargo.toml | ||
cbindgen.toml | ||
CMakeLists.txt | ||
README.md |
Methods we need to support
Basic management
AMcreate()
AMclone(doc)
AMfree(doc)
AMconfig(doc, key, val)
// set actoractor = get_actor(doc)
Transactions
AMpendingOps(doc)
AMcommit(doc, message, time)
AMrollback(doc)
Write
AMset{Map|List}(doc, obj, prop, value)
AMinsert(doc, obj, index, value)
AMpush(doc, obj, value)
AMdel{Map|List}(doc, obj, prop)
AMinc{Map|List}(doc, obj, prop, value)
AMspliceText(doc, obj, start, num_del, text)
Read (the heads argument is optional and can be on an at
variant)
AMkeys(doc, obj, heads)
AMlength(doc, obj, heads)
AMlistRange(doc, obj, heads)
AMmapRange(doc, obj, heads)
AMvalues(doc, obj, heads)
AMtext(doc, obj, heads)
Sync
AMgenerateSyncMessage(doc, state)
AMreceiveSyncMessage(doc, state, message)
AMinitSyncState()
Save / Load
AMload(data)
AMloadIncremental(doc, data)
AMsave(doc)
AMsaveIncremental(doc)
Low Level Access
AMapplyChanges(doc, changes)
AMgetChanges(doc, deps)
AMgetChangesAdded(doc1, doc2)
AMgetHeads(doc)
AMgetLastLocalChange(doc)
AMgetMissingDeps(doc, heads)
Encode/Decode
AMencodeChange(change)
AMdecodeChange(change)
AMencodeSyncMessage(change)
AMdecodeSyncMessage(change)
AMencodeSyncState(change)
AMdecodeSyncState(change)
Open Question - Memory management
Most of these calls return one or more items of arbitrary length. Doing memory management in C is tricky. This is my proposed solution...
// returns 1 or zero opids
n = automerge_set(doc, "_root", "hello", datatype, value);
if (n) {
automerge_pop(doc, &obj, len);
}
// returns n values
n = automerge_values(doc, "_root", "hello");
for (i = 0; i<n ;i ++) {
automerge_pop_value(doc, &value, &datatype, len);
}
There would be one pop method per object type. Users allocs and frees the buffers. Multiple return values would result in multiple pops. Too small buffers would error and allow retry.
Formats
Actors - We could do (bytes,len) or a hex encoded string?.
ObjIds - We could do flat bytes of the ExId struct but lets do human readable strings for now - the struct would be faster but opque
Heads - Might as well make it a flat buffer (n, hash, hash, ...)
Changes - Put them all in a flat concatenated buffer
Encode/Decode - to json strings?