Add lifetimes to transact_with and fixup watch example

This commit is contained in:
Andrew Jeffery 2022-04-18 15:44:06 +01:00
parent b6fd7ac26e
commit 702a0ec172
4 changed files with 65 additions and 50 deletions
automerge-wasm/src
automerge

View file

@ -442,7 +442,7 @@ impl Automerge {
js_set(&patch, "conflict", conflict)?;
}
Patch::Insert(obj, index, value) => {
Patch::Insert { obj, index, value } => {
js_set(&patch, "action", "insert")?;
js_set(&patch, "obj", obj.to_string())?;
js_set(&patch, "key", index as f64)?;
@ -458,7 +458,7 @@ impl Automerge {
};
}
Patch::Delete(obj, key) => {
Patch::Delete { obj, key } => {
js_set(&patch, "action", "delete")?;
js_set(&patch, "obj", obj.to_string())?;
js_set(&patch, "key", key)?;

View file

@ -1,18 +1,25 @@
use automerge::transaction::CommitOptions;
use automerge::transaction::Transactable;
use automerge::Automerge;
use automerge::ChangeHash;
use automerge::ObjId;
use automerge::AutomergeError;
use automerge::Patch;
use automerge::VecOpObserver;
use automerge::ROOT;
fn main() {
let mut doc = Automerge::new();
let heads1 = doc.get_heads();
let mut observer = VecOpObserver::default();
// a simple scalar change in the root object
let mut tx = doc.transaction();
tx.put(ROOT, "hello", "world").unwrap();
let heads2 = tx.commit();
get_changes(&heads1, &doc);
doc.transact_with::<_, _, AutomergeError, _, _>(
|_result| CommitOptions::default().with_op_observer(&mut observer),
|tx| {
tx.put(ROOT, "hello", "world").unwrap();
Ok(())
},
)
.unwrap();
get_changes(&doc, observer.take_patches());
let mut tx = doc.transaction();
let map = tx
@ -23,47 +30,48 @@ fn main() {
let list = tx
.put_object(&map, "my list", automerge::ObjType::List)
.unwrap();
// tx.insert(&list, 0, "yay").unwrap();
tx.insert(&list, 0, "yay").unwrap();
let m = tx.insert_object(&list, 0, automerge::ObjType::Map).unwrap();
tx.put(&m, "hi", 2).unwrap();
tx.insert(&list, 1, "woo").unwrap();
let m = tx.insert_object(&list, 2, automerge::ObjType::Map).unwrap();
tx.put(&m, "hi", 2).unwrap();
let _heads3 = tx.commit();
get_changes(&[heads2], &doc);
// now if a peer were to send us a change that added a key in map we wouldn't know the path to
// the change or we might not have a reference to the map objid.
let _heads3 = tx.commit_with(CommitOptions::default().with_op_observer(&mut observer));
get_changes(&doc, observer.take_patches());
}
fn get_changes(heads: &[ChangeHash], doc: &Automerge) {
let changes = doc.get_changes(heads);
// changes should be in topological order
for change in changes {
let change = change.decode();
for op in change.operations {
// get the object that it changed
let obj = doc.import(&op.obj.to_string()).unwrap();
// get the prop too
let prop = format!("{:?}", op.key);
println!("{:?}", op);
println!(
"{} {:?} in obj {:?}, object path {:?}",
if op.insert { "inserted" } else { "changed" },
prop,
fn get_changes(doc: &Automerge, patches: Vec<Patch>) {
for patch in patches {
match patch {
Patch::Put {
obj,
get_path_for_obj(doc, &obj)
);
key,
value,
conflict: _,
} => {
println!(
"put {:?} at {:?} in obj {:?}, object path {:?}",
value,
key,
obj,
doc.path_to_object(&obj)
)
}
Patch::Insert { obj, index, value } => {
println!(
"insert {:?} at {:?} in obj {:?}, object path {:?}",
value,
index,
obj,
doc.path_to_object(&obj)
)
}
Patch::Delete { obj, key } => println!(
"delete {:?} in obj {:?}, object path {:?}",
key,
obj,
doc.path_to_object(&obj)
),
}
}
}
fn get_path_for_obj(doc: &Automerge, obj: &ObjId) -> String {
let mut s = String::new();
let mut obj = obj.clone();
while let Some((parent, key)) = doc.parent_object(obj) {
s = format!("{}/{}", key, s);
obj = parent;
}
s
}

View file

@ -154,11 +154,11 @@ impl Automerge {
}
/// Like [`Self::transact`] but with a function for generating the commit options.
pub fn transact_with<F, O, E, C, Obs>(&mut self, c: C, f: F) -> transaction::Result<O, E>
pub fn transact_with<'a, F, O, E, C, Obs>(&mut self, c: C, f: F) -> transaction::Result<O, E>
where
F: FnOnce(&mut Transaction) -> Result<O, E>,
C: FnOnce(&O) -> CommitOptions<Obs>,
Obs: OpObserver,
C: FnOnce(&O) -> CommitOptions<'a, Obs>,
Obs: 'a + OpObserver,
{
let mut tx = self.transaction();
let result = f(&mut tx);

View file

@ -52,8 +52,11 @@ impl VecOpObserver {
impl OpObserver for VecOpObserver {
fn insert(&mut self, obj_id: ExId, index: usize, (value, id): (Value, ExId)) {
self.patches
.push(Patch::Insert(obj_id, index, (value.into_owned(), id)));
self.patches.push(Patch::Insert {
obj: obj_id,
index,
value: (value.into_owned(), id),
});
}
fn put(&mut self, objid: ExId, key: Prop, (value, id): (Value, ExId), conflict: bool) {
@ -66,7 +69,7 @@ impl OpObserver for VecOpObserver {
}
fn delete(&mut self, objid: ExId, key: Prop) {
self.patches.push(Patch::Delete(objid, key))
self.patches.push(Patch::Delete { obj: objid, key })
}
}
@ -81,7 +84,11 @@ pub enum Patch {
conflict: bool,
},
/// Inserting a new element into a list/text
Insert(ExId, usize, (Value<'static>, ExId)),
Insert {
obj: ExId,
index: usize,
value: (Value<'static>, ExId),
},
/// Deleting an element from a list/text
Delete(ExId, Prop),
Delete { obj: ExId, key: Prop },
}