Merge pull request #20 from automerge/two-level-objtype
Two level objtype
This commit is contained in:
commit
dd33e528ab
22 changed files with 397 additions and 323 deletions
automerge-backend
src
tests
automerge-frontend
src
tests
automerge-protocol
|
@ -77,12 +77,12 @@ impl ActorMap {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn export_actor(&self, actor: &ActorID) -> amp::ActorID {
|
||||
pub fn export_actor(&self, actor: ActorID) -> amp::ActorID {
|
||||
self.0[actor.0].clone()
|
||||
}
|
||||
|
||||
pub fn export_opid(&self, opid: &OpID) -> amp::OpID {
|
||||
amp::OpID(opid.0, self.export_actor(&opid.1))
|
||||
amp::OpID(opid.0, self.export_actor(opid.1))
|
||||
}
|
||||
|
||||
pub fn export_obj(&self, obj: &ObjectID) -> amp::ObjectID {
|
||||
|
@ -151,7 +151,7 @@ impl ActorMap {
|
|||
}
|
||||
|
||||
pub fn opid_to_string(&self, id: &OpID) -> String {
|
||||
format!("{}@{}", id.0, self.export_actor(&id.1).to_hex_string())
|
||||
format!("{}@{}", id.0, self.export_actor(id.1).to_hex_string())
|
||||
}
|
||||
|
||||
pub fn elementid_to_string(&self, eid: &ElementID) -> String {
|
||||
|
|
|
@ -127,10 +127,10 @@ impl Backend {
|
|||
let internal_key = self.actors.import_key(external_key.clone());
|
||||
let pred = op_set.get_pred(&internal_object_id, &internal_key, insert);
|
||||
let action = match rop.action {
|
||||
amp::OpType::MakeMap => OpType::Make(amp::ObjType::Map),
|
||||
amp::OpType::MakeTable => OpType::Make(amp::ObjType::Table),
|
||||
amp::OpType::MakeList => OpType::Make(amp::ObjType::List),
|
||||
amp::OpType::MakeText => OpType::Make(amp::ObjType::Text),
|
||||
amp::OpType::MakeMap => OpType::Make(amp::ObjType::map()),
|
||||
amp::OpType::MakeTable => OpType::Make(amp::ObjType::table()),
|
||||
amp::OpType::MakeList => OpType::Make(amp::ObjType::list()),
|
||||
amp::OpType::MakeText => OpType::Make(amp::ObjType::text()),
|
||||
amp::OpType::Del => OpType::Del,
|
||||
amp::OpType::Link => OpType::Link(
|
||||
child
|
||||
|
|
|
@ -415,7 +415,7 @@ mod tests {
|
|||
pred: vec![opid3.clone(), opid4.clone()],
|
||||
},
|
||||
Operation {
|
||||
action: OpType::Make(amp::ObjType::List),
|
||||
action: OpType::Make(amp::ObjType::list()),
|
||||
key: key2.clone(),
|
||||
obj: obj2.clone(),
|
||||
insert,
|
||||
|
|
|
@ -229,10 +229,10 @@ impl<'a> Iterator for OperationIterator<'a> {
|
|||
let child = self.chld.next()?;
|
||||
let action = match action {
|
||||
Action::Set => OpType::Set(value),
|
||||
Action::MakeList => OpType::Make(amp::ObjType::List),
|
||||
Action::MakeText => OpType::Make(amp::ObjType::Text),
|
||||
Action::MakeMap => OpType::Make(amp::ObjType::Map),
|
||||
Action::MakeTable => OpType::Make(amp::ObjType::Table),
|
||||
Action::MakeList => OpType::Make(amp::ObjType::list()),
|
||||
Action::MakeText => OpType::Make(amp::ObjType::text()),
|
||||
Action::MakeMap => OpType::Make(amp::ObjType::map()),
|
||||
Action::MakeTable => OpType::Make(amp::ObjType::table()),
|
||||
Action::Del => OpType::Del,
|
||||
Action::Inc => OpType::Inc(value.to_i64()?),
|
||||
Action::Link => OpType::Link(child),
|
||||
|
@ -537,10 +537,10 @@ impl ColumnEncoder {
|
|||
self.val.append_null();
|
||||
self.chld.append_null();
|
||||
match kind {
|
||||
amp::ObjType::List => Action::MakeList,
|
||||
amp::ObjType::Map => Action::MakeMap,
|
||||
amp::ObjType::Table => Action::MakeTable,
|
||||
amp::ObjType::Text => Action::MakeText,
|
||||
amp::ObjType::Sequence(amp::SequenceType::List) => Action::MakeList,
|
||||
amp::ObjType::Map(amp::MapType::Map) => Action::MakeMap,
|
||||
amp::ObjType::Map(amp::MapType::Table) => Action::MakeTable,
|
||||
amp::ObjType::Sequence(amp::SequenceType::Text) => Action::MakeText,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -39,7 +39,7 @@ impl ObjState {
|
|||
|
||||
pub fn is_seq(&self) -> bool {
|
||||
match self.obj_type {
|
||||
amp::ObjType::Text | amp::ObjType::List => true,
|
||||
amp::ObjType::Sequence(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -222,10 +222,14 @@ impl<'de> Deserialize<'de> for Operation {
|
|||
let insert = insert.unwrap_or(false);
|
||||
let value = amp::Value::from(value, datatype);
|
||||
let action = match action {
|
||||
amp::OpType::MakeMap => OpType::Make(amp::ObjType::Map),
|
||||
amp::OpType::MakeTable => OpType::Make(amp::ObjType::Table),
|
||||
amp::OpType::MakeList => OpType::Make(amp::ObjType::List),
|
||||
amp::OpType::MakeText => OpType::Make(amp::ObjType::Text),
|
||||
amp::OpType::MakeMap => OpType::Make(amp::ObjType::Map(amp::MapType::Map)),
|
||||
amp::OpType::MakeTable => OpType::Make(amp::ObjType::Map(amp::MapType::Table)),
|
||||
amp::OpType::MakeList => {
|
||||
OpType::Make(amp::ObjType::Sequence(amp::SequenceType::List))
|
||||
}
|
||||
amp::OpType::MakeText => {
|
||||
OpType::Make(amp::ObjType::Sequence(amp::SequenceType::Text))
|
||||
}
|
||||
amp::OpType::Del => OpType::Del,
|
||||
amp::OpType::Link => {
|
||||
OpType::Link(child.ok_or_else(|| Error::missing_field("pred"))?)
|
||||
|
|
|
@ -46,7 +46,7 @@ pub(crate) struct OpSet {
|
|||
impl OpSet {
|
||||
pub fn init() -> OpSet {
|
||||
let mut objs = im_rc::HashMap::new();
|
||||
objs.insert(ObjectID::Root, Rc::new(ObjState::new(amp::ObjType::Map)));
|
||||
objs.insert(ObjectID::Root, Rc::new(ObjState::new(amp::ObjType::map())));
|
||||
|
||||
OpSet {
|
||||
objs,
|
||||
|
@ -208,6 +208,7 @@ impl OpSet {
|
|||
object_id: &ObjectID,
|
||||
object: &ObjState,
|
||||
actors: &ActorMap,
|
||||
map_type: amp::MapType,
|
||||
) -> Result<amp::Diff, AutomergeError> {
|
||||
let mut props = HashMap::new();
|
||||
|
||||
|
@ -227,7 +228,7 @@ impl OpSet {
|
|||
}
|
||||
Ok(amp::MapDiff {
|
||||
object_id: actors.export_obj(object_id),
|
||||
obj_type: object.obj_type,
|
||||
obj_type: map_type,
|
||||
props,
|
||||
}
|
||||
.into())
|
||||
|
@ -238,6 +239,7 @@ impl OpSet {
|
|||
object_id: &ObjectID,
|
||||
object: &ObjState,
|
||||
actors: &ActorMap,
|
||||
seq_type: amp::SequenceType,
|
||||
) -> Result<amp::Diff, AutomergeError> {
|
||||
let mut edits = Vec::new();
|
||||
let mut props = HashMap::new();
|
||||
|
@ -267,7 +269,7 @@ impl OpSet {
|
|||
}
|
||||
Ok(amp::SeqDiff {
|
||||
object_id: actors.export_obj(object_id),
|
||||
obj_type: object.obj_type,
|
||||
obj_type: seq_type,
|
||||
edits,
|
||||
props,
|
||||
}
|
||||
|
@ -280,10 +282,11 @@ impl OpSet {
|
|||
actors: &ActorMap,
|
||||
) -> Result<amp::Diff, AutomergeError> {
|
||||
let object = self.get_obj(&object_id)?;
|
||||
if object.is_seq() {
|
||||
self.construct_list(object_id, object, actors)
|
||||
} else {
|
||||
self.construct_map(object_id, object, actors)
|
||||
match object.obj_type {
|
||||
amp::ObjType::Map(map_type) => self.construct_map(object_id, object, actors, map_type),
|
||||
amp::ObjType::Sequence(seq_type) => {
|
||||
self.construct_list(object_id, object, actors, seq_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,6 +328,7 @@ impl OpSet {
|
|||
pending: &[PendingDiff],
|
||||
pending_diffs: &mut HashMap<ObjectID, Vec<PendingDiff>>,
|
||||
actors: &ActorMap,
|
||||
seq_type: amp::SequenceType,
|
||||
) -> Result<amp::Diff, AutomergeError> {
|
||||
let mut props = HashMap::new();
|
||||
let edits = pending.iter().filter_map(|p| p.edit()).collect();
|
||||
|
@ -352,7 +356,7 @@ impl OpSet {
|
|||
}
|
||||
Ok(amp::SeqDiff {
|
||||
object_id: actors.export_obj(obj_id),
|
||||
obj_type: obj.obj_type,
|
||||
obj_type: seq_type,
|
||||
edits,
|
||||
props,
|
||||
}
|
||||
|
@ -366,6 +370,7 @@ impl OpSet {
|
|||
pending: &[PendingDiff],
|
||||
pending_diffs: &mut HashMap<ObjectID, Vec<PendingDiff>>,
|
||||
actors: &ActorMap,
|
||||
map_type: amp::MapType,
|
||||
) -> Result<amp::Diff, AutomergeError> {
|
||||
let mut props = HashMap::new();
|
||||
// I may have duplicate keys - I do this to make sure I visit each one only once
|
||||
|
@ -391,7 +396,7 @@ impl OpSet {
|
|||
}
|
||||
Ok(amp::MapDiff {
|
||||
object_id: actors.export_obj(obj_id),
|
||||
obj_type: obj.obj_type,
|
||||
obj_type: map_type,
|
||||
props,
|
||||
}
|
||||
.into())
|
||||
|
@ -405,10 +410,13 @@ impl OpSet {
|
|||
) -> Result<amp::Diff, AutomergeError> {
|
||||
let obj = self.get_obj(obj_id)?;
|
||||
if let Some(pending) = pending_diffs.remove(obj_id) {
|
||||
if obj.is_seq() {
|
||||
self.gen_seq_diff(obj_id, obj, &pending, pending_diffs, actors)
|
||||
} else {
|
||||
self.gen_map_diff(obj_id, obj, &pending, pending_diffs, actors)
|
||||
match obj.obj_type {
|
||||
amp::ObjType::Sequence(seq_type) => {
|
||||
self.gen_seq_diff(obj_id, obj, &pending, pending_diffs, actors, seq_type)
|
||||
}
|
||||
amp::ObjType::Map(map_type) => {
|
||||
self.gen_map_diff(obj_id, obj, &pending, pending_diffs, actors, map_type)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Ok(amp::Diff::Unchanged(amp::ObjDiff {
|
||||
|
|
|
@ -16,10 +16,10 @@ impl Serialize for OpType {
|
|||
S: Serializer,
|
||||
{
|
||||
let s = match self {
|
||||
OpType::Make(amp::ObjType::Map) => "makeMap",
|
||||
OpType::Make(amp::ObjType::Table) => "makeTable",
|
||||
OpType::Make(amp::ObjType::List) => "makeList",
|
||||
OpType::Make(amp::ObjType::Text) => "makeText",
|
||||
OpType::Make(amp::ObjType::Map(amp::MapType::Map)) => "makeMap",
|
||||
OpType::Make(amp::ObjType::Map(amp::MapType::Table)) => "makeTable",
|
||||
OpType::Make(amp::ObjType::Sequence(amp::SequenceType::List)) => "makeList",
|
||||
OpType::Make(amp::ObjType::Sequence(amp::SequenceType::Text)) => "makeText",
|
||||
OpType::Del => "del",
|
||||
OpType::Link(_) => "link",
|
||||
OpType::Inc(_) => "inc",
|
||||
|
|
|
@ -2,8 +2,8 @@ extern crate automerge_backend;
|
|||
use automerge_backend::{AutomergeError, Backend, UnencodedChange};
|
||||
use automerge_backend::{OpType, Operation};
|
||||
use automerge_protocol::{
|
||||
ActorID, Diff, DiffEdit, ElementID, Key, MapDiff, ObjDiff, ObjType, ObjectID, Patch, SeqDiff,
|
||||
Value,
|
||||
ActorID, Diff, DiffEdit, ElementID, Key, MapDiff, MapType, ObjDiff, ObjType, ObjectID, Patch,
|
||||
SeqDiff, SequenceType, Value,
|
||||
};
|
||||
use maplit::hashmap;
|
||||
use std::convert::TryInto;
|
||||
|
@ -39,7 +39,7 @@ fn test_incremental_diffs_in_a_map() {
|
|||
can_redo: false,
|
||||
diffs: Some(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap!( "bird".into() => hashmap!( "1@7b7723afd9e6480397a4d467b7693156".try_into().unwrap() => "magpie".into() ))
|
||||
}.into()),
|
||||
};
|
||||
|
@ -91,7 +91,7 @@ fn test_increment_key_in_map() -> Result<(), AutomergeError> {
|
|||
diffs: Some(
|
||||
MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap!(
|
||||
"counter".into() => hashmap!{
|
||||
"1@cdee6963c1664645920be8b41a933c2b".try_into().unwrap() => Value::Counter(3).into(),
|
||||
|
@ -155,7 +155,7 @@ fn test_conflict_on_assignment_to_same_map_key() {
|
|||
diffs: Some(
|
||||
MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap!( "bird".into() => hashmap!(
|
||||
"1@ac11".try_into().unwrap() => "magpie".into(),
|
||||
"2@ac22".try_into().unwrap() => "blackbird".into(),
|
||||
|
@ -218,7 +218,7 @@ fn delete_key_from_map() {
|
|||
can_redo: false,
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"bird".into() => hashmap!{}
|
||||
},
|
||||
|
@ -243,7 +243,7 @@ fn create_nested_maps() {
|
|||
message: None,
|
||||
operations: vec![
|
||||
Operation {
|
||||
action: OpType::Make(ObjType::Map),
|
||||
action: OpType::Make(ObjType::Map(MapType::Map)),
|
||||
obj: ObjectID::Root,
|
||||
key: Key::Map("birds".into()),
|
||||
pred: Vec::new(),
|
||||
|
@ -270,12 +270,12 @@ fn create_nested_maps() {
|
|||
version: 1,
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
"1@d6226fcd55204b82b396f2473da3e26f".try_into().unwrap() => Diff::Map(MapDiff{
|
||||
object_id: "1@d6226fcd55204b82b396f2473da3e26f".try_into().unwrap(),
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap!{
|
||||
"wrens".into() => hashmap!{
|
||||
"2@d6226fcd55204b82b396f2473da3e26f".try_into().unwrap() => Diff::Value(Value::F64(3.0))
|
||||
|
@ -304,7 +304,7 @@ fn test_assign_to_nested_keys_in_map() {
|
|||
deps: Vec::new(),
|
||||
operations: vec![
|
||||
Operation {
|
||||
action: OpType::Make(ObjType::Map),
|
||||
action: OpType::Make(ObjType::Map(MapType::Map)),
|
||||
obj: ObjectID::Root,
|
||||
key: "birds".into(),
|
||||
pred: Vec::new(),
|
||||
|
@ -350,12 +350,12 @@ fn test_assign_to_nested_keys_in_map() {
|
|||
deps: vec![change2.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
"1@3c39c994039042778f4779a01a59a917".try_into().unwrap() => Diff::Map(MapDiff{
|
||||
object_id: "1@3c39c994039042778f4779a01a59a917".try_into().unwrap(),
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap!{
|
||||
"sparrows".into() => hashmap!{
|
||||
"3@3c39c994039042778f4779a01a59a917".try_into().unwrap() => Diff::Value(Value::F64(15.0))
|
||||
|
@ -384,7 +384,7 @@ fn test_create_lists() {
|
|||
deps: Vec::new(),
|
||||
operations: vec![
|
||||
Operation {
|
||||
action: OpType::Make(ObjType::List),
|
||||
action: OpType::Make(ObjType::Sequence(SequenceType::List)),
|
||||
obj: ObjectID::Root,
|
||||
key: "birds".into(),
|
||||
pred: Vec::new(),
|
||||
|
@ -413,12 +413,12 @@ fn test_create_lists() {
|
|||
deps: vec![change.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
"1@f82cb62dabe64372ab87466b77792010".try_into().unwrap() => Diff::Seq(SeqDiff{
|
||||
object_id: "1@f82cb62dabe64372ab87466b77792010".try_into().unwrap(),
|
||||
obj_type: ObjType::List,
|
||||
obj_type: SequenceType::List,
|
||||
edits: vec![DiffEdit::Insert{ index: 0 }],
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
|
@ -448,7 +448,7 @@ fn test_apply_updates_inside_lists() {
|
|||
deps: Vec::new(),
|
||||
operations: vec![
|
||||
Operation {
|
||||
action: OpType::Make(ObjType::List),
|
||||
action: OpType::Make(ObjType::Sequence(SequenceType::List)),
|
||||
obj: ObjectID::Root,
|
||||
key: "birds".into(),
|
||||
pred: Vec::new(),
|
||||
|
@ -494,12 +494,12 @@ fn test_apply_updates_inside_lists() {
|
|||
seq: None,
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
"1@4ee4a0d033b841c4b26d73d70a879547".try_into().unwrap() => Diff::Seq(SeqDiff{
|
||||
object_id: "1@4ee4a0d033b841c4b26d73d70a879547".try_into().unwrap(),
|
||||
obj_type: ObjType::List,
|
||||
obj_type: SequenceType::List,
|
||||
edits: Vec::new(),
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
|
@ -530,7 +530,7 @@ fn test_delete_list_elements() {
|
|||
deps: Vec::new(),
|
||||
operations: vec![
|
||||
Operation {
|
||||
action: OpType::Make(ObjType::List),
|
||||
action: OpType::Make(ObjType::Sequence(SequenceType::List)),
|
||||
obj: ObjectID::Root,
|
||||
key: "birds".into(),
|
||||
pred: Vec::new(),
|
||||
|
@ -578,12 +578,12 @@ fn test_delete_list_elements() {
|
|||
deps: vec![change2.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
"1@8a3d4716fdca49f4aa5835901f2034c7".try_into().unwrap() => Diff::Seq(SeqDiff{
|
||||
object_id: "1@8a3d4716fdca49f4aa5835901f2034c7".try_into().unwrap(),
|
||||
obj_type: ObjType::List,
|
||||
obj_type: SequenceType::List,
|
||||
props: hashmap!{},
|
||||
edits: vec![DiffEdit::Remove{index: 0}]
|
||||
})
|
||||
|
@ -609,7 +609,7 @@ fn test_handle_list_element_insertion_and_deletion_in_same_change() {
|
|||
message: None,
|
||||
deps: Vec::new(),
|
||||
operations: vec![Operation {
|
||||
action: OpType::Make(ObjType::List),
|
||||
action: OpType::Make(ObjType::Sequence(SequenceType::List)),
|
||||
obj: ObjectID::Root,
|
||||
key: "birds".into(),
|
||||
pred: Vec::new(),
|
||||
|
@ -658,12 +658,12 @@ fn test_handle_list_element_insertion_and_deletion_in_same_change() {
|
|||
deps: vec![change2.hash, change1.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
"1@ca95bc759404486bbe7b9dd2be779fa8".try_into().unwrap() => Diff::Seq(SeqDiff{
|
||||
object_id: "1@ca95bc759404486bbe7b9dd2be779fa8".try_into().unwrap(),
|
||||
obj_type: ObjType::List,
|
||||
obj_type: SequenceType::List,
|
||||
edits: vec![
|
||||
DiffEdit::Insert{index: 0},
|
||||
DiffEdit::Remove{index: 0},
|
||||
|
@ -693,7 +693,7 @@ fn test_handle_changes_within_conflicted_objects() {
|
|||
message: None,
|
||||
deps: Vec::new(),
|
||||
operations: vec![Operation {
|
||||
action: OpType::Make(ObjType::List),
|
||||
action: OpType::Make(ObjType::Sequence(SequenceType::List)),
|
||||
obj: ObjectID::Root,
|
||||
key: "conflict".into(),
|
||||
pred: Vec::new(),
|
||||
|
@ -710,7 +710,7 @@ fn test_handle_changes_within_conflicted_objects() {
|
|||
message: None,
|
||||
deps: Vec::new(),
|
||||
operations: vec![Operation {
|
||||
action: OpType::Make(ObjType::Map),
|
||||
action: OpType::Make(ObjType::Map(MapType::Map)),
|
||||
obj: ObjectID::Root,
|
||||
key: "conflict".into(),
|
||||
pred: Vec::new(),
|
||||
|
@ -749,16 +749,16 @@ fn test_handle_changes_within_conflicted_objects() {
|
|||
deps: vec![change1.hash, change3.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"conflict".into() => hashmap!{
|
||||
"1@9f17517523e54ee888e9cd51dfd7a572".try_into().unwrap() => Diff::Unchanged(ObjDiff{
|
||||
object_id: "1@9f17517523e54ee888e9cd51dfd7a572".try_into().unwrap(),
|
||||
obj_type: ObjType::List,
|
||||
obj_type: ObjType::Sequence(SequenceType::List),
|
||||
}),
|
||||
"1@83768a19a13842beb6dde8c68a662fad".try_into().unwrap() => Diff::Map(MapDiff{
|
||||
object_id: "1@83768a19a13842beb6dde8c68a662fad".try_into().unwrap(),
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap!{
|
||||
"sparrow".into() => hashmap!{
|
||||
"2@83768a19a13842beb6dde8c68a662fad".try_into().unwrap() => Diff::Value(Value::F64(12.0))
|
||||
|
@ -809,7 +809,7 @@ fn test_support_date_objects_at_root() {
|
|||
deps: vec![change.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"now".into() => hashmap!{
|
||||
"1@955afa3bbcc140b3b4bac8836479d650".try_into().unwrap() => Diff::Value(Value::Timestamp(1_586_528_122_277))
|
||||
|
@ -835,7 +835,7 @@ fn test_support_date_objects_in_a_list() {
|
|||
message: None,
|
||||
operations: vec![
|
||||
Operation {
|
||||
action: OpType::Make(ObjType::List),
|
||||
action: OpType::Make(ObjType::Sequence(SequenceType::List)),
|
||||
obj: ObjectID::Root,
|
||||
key: "list".into(),
|
||||
pred: Vec::new(),
|
||||
|
@ -864,12 +864,12 @@ fn test_support_date_objects_in_a_list() {
|
|||
seq: None,
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"list".into() => hashmap!{
|
||||
"1@27d467ecb1a640fb9bed448ce7cf6a44".try_into().unwrap() => Diff::Seq(SeqDiff{
|
||||
object_id: "1@27d467ecb1a640fb9bed448ce7cf6a44".try_into().unwrap(),
|
||||
obj_type: ObjType::List,
|
||||
obj_type: SequenceType::List,
|
||||
edits: vec![DiffEdit::Insert{index: 0}],
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
|
|
|
@ -3,8 +3,8 @@ use automerge_backend::{Backend, UnencodedChange};
|
|||
use automerge_backend::{OpType, Operation};
|
||||
use automerge_protocol as protocol;
|
||||
use automerge_protocol::{
|
||||
ActorID, ChangeHash, DataType, Diff, DiffEdit, ElementID, MapDiff, ObjType, ObjectID, Op,
|
||||
Patch, Request, RequestType, SeqDiff,
|
||||
ActorID, ChangeHash, DataType, Diff, DiffEdit, ElementID, MapDiff, MapType, ObjType, ObjectID,
|
||||
Op, Patch, Request, RequestType, SeqDiff, SequenceType,
|
||||
};
|
||||
use maplit::hashmap;
|
||||
use std::convert::TryInto;
|
||||
|
@ -67,7 +67,7 @@ fn test_apply_local_change() {
|
|||
deps: vec![changes[0].hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"bird".into() => hashmap!{
|
||||
"1@eb738e04ef8848ce8b77309b6c7f7e39".try_into().unwrap() => Diff::Value("magpie".into())
|
||||
|
@ -271,7 +271,7 @@ fn test_transform_list_indexes_into_element_ids() {
|
|||
message: None,
|
||||
deps: Vec::new(),
|
||||
operations: vec![Operation {
|
||||
action: OpType::Make(ObjType::List),
|
||||
action: OpType::Make(ObjType::Sequence(SequenceType::List)),
|
||||
key: "birds".into(),
|
||||
obj: ObjectID::Root,
|
||||
pred: Vec::new(),
|
||||
|
@ -522,12 +522,12 @@ fn test_handle_list_insertion_and_deletion_in_same_change() {
|
|||
deps: Vec::new(),
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
"1@0723d2a1940744868ffd6b294ada813f".try_into().unwrap() => Diff::Seq(SeqDiff{
|
||||
object_id: "1@0723d2a1940744868ffd6b294ada813f".try_into().unwrap(),
|
||||
obj_type: ObjType::List,
|
||||
obj_type: SequenceType::List,
|
||||
edits: vec![
|
||||
DiffEdit::Insert{index: 0},
|
||||
DiffEdit::Remove{index: 0},
|
||||
|
@ -559,7 +559,7 @@ fn test_handle_list_insertion_and_deletion_in_same_change() {
|
|||
deps: Vec::new(),
|
||||
operations: vec![Operation {
|
||||
obj: ObjectID::Root,
|
||||
action: OpType::Make(ObjType::List),
|
||||
action: OpType::Make(ObjType::Sequence(SequenceType::List)),
|
||||
key: "birds".into(),
|
||||
insert: false,
|
||||
pred: Vec::new(),
|
||||
|
|
|
@ -2,7 +2,8 @@ extern crate automerge_backend;
|
|||
use automerge_backend::{Backend, UnencodedChange};
|
||||
use automerge_backend::{OpType, Operation};
|
||||
use automerge_protocol::{
|
||||
ActorID, Diff, DiffEdit, ElementID, MapDiff, ObjType, ObjectID, Patch, SeqDiff, Value,
|
||||
ActorID, Diff, DiffEdit, ElementID, MapDiff, MapType, ObjType, ObjectID, Patch, SeqDiff,
|
||||
SequenceType, Value,
|
||||
};
|
||||
use maplit::hashmap;
|
||||
use std::convert::TryInto;
|
||||
|
@ -56,7 +57,7 @@ fn test_include_most_recent_value_for_key() {
|
|||
deps: vec![change2.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"bird".into() => hashmap!{
|
||||
"2@ec28cfbcdb9e4f32ad24b3c776e651b0".try_into().unwrap() => Diff::Value("blackbird".into())
|
||||
|
@ -122,7 +123,7 @@ fn test_includes_conflicting_values_for_key() {
|
|||
deps: vec![change1.hash, change2.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"bird".into() => hashmap!{
|
||||
"1@111111".try_into().unwrap() => Diff::Value("magpie".into()),
|
||||
|
@ -187,7 +188,7 @@ fn test_handles_counter_increment_at_keys_in_a_map() {
|
|||
deps: vec![change2.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"counter".into() => hashmap!{
|
||||
"1@46c92088e4484ae5945dc63bf606a4a5".try_into().unwrap() => Diff::Value(Value::Counter(3))
|
||||
|
@ -214,7 +215,7 @@ fn test_creates_nested_maps() {
|
|||
deps: Vec::new(),
|
||||
operations: vec![
|
||||
Operation {
|
||||
action: OpType::Make(ObjType::Map),
|
||||
action: OpType::Make(ObjType::Map(MapType::Map)),
|
||||
obj: ObjectID::Root,
|
||||
key: "birds".into(),
|
||||
pred: Vec::new(),
|
||||
|
@ -269,12 +270,12 @@ fn test_creates_nested_maps() {
|
|||
deps: vec![change2.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
"1@06148f9422cb40579fd02f1975c34a51".try_into().unwrap() => Diff::Map(MapDiff{
|
||||
object_id: "1@06148f9422cb40579fd02f1975c34a51".try_into().unwrap(),
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap!{
|
||||
"sparrows".into() => hashmap!{
|
||||
"4@06148f9422cb40579fd02f1975c34a51".try_into().unwrap() => Diff::Value(Value::F64(15.0))
|
||||
|
@ -304,7 +305,7 @@ fn test_create_lists() {
|
|||
deps: Vec::new(),
|
||||
operations: vec![
|
||||
Operation {
|
||||
action: OpType::Make(ObjType::List),
|
||||
action: OpType::Make(ObjType::Sequence(SequenceType::List)),
|
||||
obj: ObjectID::Root,
|
||||
key: "birds".into(),
|
||||
pred: Vec::new(),
|
||||
|
@ -333,12 +334,12 @@ fn test_create_lists() {
|
|||
deps: vec![change1.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
"1@90bf7df682f747fa82ac604b35010906".try_into().unwrap() => Diff::Seq(SeqDiff{
|
||||
object_id: "1@90bf7df682f747fa82ac604b35010906".try_into().unwrap(),
|
||||
obj_type: ObjType::List,
|
||||
obj_type: SequenceType::List,
|
||||
edits: vec![DiffEdit::Insert { index :0 }],
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
|
@ -369,14 +370,14 @@ fn test_includes_latests_state_of_list() {
|
|||
deps: Vec::new(),
|
||||
operations: vec![
|
||||
Operation {
|
||||
action: OpType::Make(ObjType::List),
|
||||
action: OpType::Make(ObjType::Sequence(SequenceType::List)),
|
||||
obj: ObjectID::Root,
|
||||
key: "todos".into(),
|
||||
pred: Vec::new(),
|
||||
insert: false,
|
||||
},
|
||||
Operation {
|
||||
action: OpType::Make(ObjType::Map),
|
||||
action: OpType::Make(ObjType::Map(MapType::Map)),
|
||||
obj: "1@6caaa2e433de42ae9c3fa65c9ff3f03e".try_into().unwrap(),
|
||||
key: ElementID::Head.into(),
|
||||
insert: true,
|
||||
|
@ -412,18 +413,18 @@ fn test_includes_latests_state_of_list() {
|
|||
deps: vec![change1.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"todos".into() => hashmap!{
|
||||
"1@6caaa2e433de42ae9c3fa65c9ff3f03e".try_into().unwrap() => Diff::Seq(SeqDiff{
|
||||
object_id: "1@6caaa2e433de42ae9c3fa65c9ff3f03e".try_into().unwrap(),
|
||||
obj_type: ObjType::List,
|
||||
obj_type: SequenceType::List,
|
||||
edits: vec![DiffEdit::Insert{index: 0}],
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
"2@6caaa2e433de42ae9c3fa65c9ff3f03e".try_into().unwrap() => Diff::Map(MapDiff{
|
||||
object_id: "2@6caaa2e433de42ae9c3fa65c9ff3f03e".try_into().unwrap(),
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap!{
|
||||
"title".into() => hashmap!{
|
||||
"3@6caaa2e433de42ae9c3fa65c9ff3f03e".try_into().unwrap() => Diff::Value("water plants".into()),
|
||||
|
@ -479,7 +480,7 @@ fn test_includes_date_objects_at_root() {
|
|||
deps: vec![change1.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"now".into() => hashmap!{
|
||||
"1@90f5dd5d4f524e95ad5929e08d1194f1".try_into().unwrap() => Diff::Value(Value::Timestamp(1_586_541_033_457))
|
||||
|
@ -506,7 +507,7 @@ fn test_includes_date_objects_in_a_list() {
|
|||
deps: Vec::new(),
|
||||
operations: vec![
|
||||
Operation {
|
||||
action: OpType::Make(ObjType::List),
|
||||
action: OpType::Make(ObjType::Sequence(SequenceType::List)),
|
||||
obj: ObjectID::Root,
|
||||
key: "list".into(),
|
||||
pred: Vec::new(),
|
||||
|
@ -535,12 +536,12 @@ fn test_includes_date_objects_in_a_list() {
|
|||
deps: vec![change1.hash],
|
||||
diffs: Some(Diff::Map(MapDiff {
|
||||
object_id: ObjectID::Root,
|
||||
obj_type: ObjType::Map,
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"list".into() => hashmap!{
|
||||
"1@08b050f976a249349021a2e63d99c8e8".try_into().unwrap() => Diff::Seq(SeqDiff{
|
||||
object_id: "1@08b050f976a249349021a2e63d99c8e8".try_into().unwrap(),
|
||||
obj_type: ObjType::List,
|
||||
obj_type: SequenceType::List,
|
||||
edits: vec![DiffEdit::Insert {index: 0}],
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use automerge_protocol::{Diff, DiffEdit, MapDiff, ObjType, ObjectID, OpID, SeqDiff};
|
||||
use automerge_protocol::{
|
||||
Diff, DiffEdit, MapDiff, MapType, ObjType, ObjectID, OpID, SeqDiff, SequenceType,
|
||||
};
|
||||
//use crate::AutomergeFrontendError;
|
||||
use crate::object::{Object, Values};
|
||||
use crate::{AutomergeFrontendError, MapType, SequenceType, Value};
|
||||
use crate::{AutomergeFrontendError, Value};
|
||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||
|
||||
/// A `ChangeContext` represents some kind of change which has not been applied
|
||||
|
@ -136,7 +138,7 @@ impl<'a> ChangeContext<'a> {
|
|||
props,
|
||||
}) => {
|
||||
match obj_type {
|
||||
ObjType::Map => {
|
||||
MapType::Map => {
|
||||
let obj = Self::get_or_create_object(
|
||||
object_id,
|
||||
original_objects,
|
||||
|
@ -173,7 +175,7 @@ impl<'a> ChangeContext<'a> {
|
|||
};
|
||||
Ok(obj)
|
||||
}
|
||||
ObjType::Table => {
|
||||
MapType::Table => {
|
||||
let obj = Self::get_or_create_object(
|
||||
&object_id,
|
||||
original_objects,
|
||||
|
@ -214,7 +216,6 @@ impl<'a> ChangeContext<'a> {
|
|||
};
|
||||
Ok(obj)
|
||||
}
|
||||
_ => panic!("Invalid object type (not map or table) inside MapDiff"),
|
||||
}
|
||||
}
|
||||
Diff::Seq(SeqDiff {
|
||||
|
@ -224,7 +225,7 @@ impl<'a> ChangeContext<'a> {
|
|||
props,
|
||||
}) => {
|
||||
match obj_type {
|
||||
ObjType::List => {
|
||||
SequenceType::List => {
|
||||
let obj = Self::get_or_create_object(
|
||||
object_id,
|
||||
original_objects,
|
||||
|
@ -266,7 +267,7 @@ impl<'a> ChangeContext<'a> {
|
|||
};
|
||||
Ok(obj)
|
||||
}
|
||||
ObjType::Text => {
|
||||
SequenceType::Text => {
|
||||
let obj = Self::get_or_create_object(
|
||||
&object_id,
|
||||
original_objects,
|
||||
|
@ -308,7 +309,6 @@ impl<'a> ChangeContext<'a> {
|
|||
};
|
||||
Ok(obj)
|
||||
}
|
||||
_ => panic!("Invalid object type (not map or table) inside MapDiff"),
|
||||
}
|
||||
}
|
||||
Diff::Value(v) => Ok(Rc::new(RefCell::new(Object::Primitive(v.clone())))),
|
||||
|
@ -319,16 +319,16 @@ impl<'a> ChangeContext<'a> {
|
|||
original_objects,
|
||||
updated,
|
||||
|| match subdiff.obj_type {
|
||||
ObjType::Map => {
|
||||
ObjType::Map(MapType::Map) => {
|
||||
Object::Map(object_id.clone(), HashMap::new(), MapType::Map)
|
||||
}
|
||||
ObjType::Table => {
|
||||
ObjType::Map(MapType::Table) => {
|
||||
Object::Map(object_id.clone(), HashMap::new(), MapType::Table)
|
||||
}
|
||||
ObjType::List => {
|
||||
ObjType::Sequence(SequenceType::List) => {
|
||||
Object::Sequence(object_id.clone(), Vec::new(), SequenceType::List)
|
||||
}
|
||||
ObjType::Text => {
|
||||
ObjType::Sequence(SequenceType::Text) => {
|
||||
Object::Sequence(object_id.clone(), Vec::new(), SequenceType::Text)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use automerge_protocol::{ActorID, ObjectID, Op, OpID, Patch, Request, RequestType};
|
||||
use automerge_protocol::{ActorID, MapType, ObjectID, Op, OpID, Patch, Request, RequestType};
|
||||
|
||||
mod change_context;
|
||||
mod error;
|
||||
|
@ -14,7 +14,7 @@ use std::convert::TryFrom;
|
|||
use std::str::FromStr;
|
||||
use std::time;
|
||||
use std::{collections::HashMap, rc::Rc};
|
||||
pub use value::{Conflicts, MapType, SequenceType, Value};
|
||||
pub use value::{Conflicts, Value};
|
||||
|
||||
/// Tracks the possible states of the frontend
|
||||
///
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::change_context::ChangeContext;
|
||||
use crate::object::Object;
|
||||
use crate::value::{random_op_id, value_to_op_requests, MapType, SequenceType};
|
||||
use crate::value::{random_op_id, value_to_op_requests};
|
||||
use crate::{AutomergeFrontendError, Value};
|
||||
use automerge_protocol as amp;
|
||||
use maplit::hashmap;
|
||||
|
@ -247,8 +247,8 @@ impl<'a, 'b> MutationTracker<'a, 'b> {
|
|||
// the enclosing diffs
|
||||
#[derive(Debug)]
|
||||
enum Intermediate {
|
||||
Map(amp::ObjectID, MapType, String, Option<amp::OpID>),
|
||||
Seq(amp::ObjectID, SequenceType, usize, Option<amp::OpID>),
|
||||
Map(amp::ObjectID, amp::MapType, String, Option<amp::OpID>),
|
||||
Seq(amp::ObjectID, amp::SequenceType, usize, Option<amp::OpID>),
|
||||
};
|
||||
let mut intermediates: Vec<Intermediate> = Vec::new();
|
||||
|
||||
|
@ -265,7 +265,7 @@ impl<'a, 'b> MutationTracker<'a, 'b> {
|
|||
if let Some(target) = vals.get(k) {
|
||||
intermediates.push(Intermediate::Map(
|
||||
oid.clone(),
|
||||
map_type.clone(),
|
||||
*map_type,
|
||||
k.clone(),
|
||||
current_obj.default_op_id_for_key(amp::RequestKey::Str(k.clone())),
|
||||
));
|
||||
|
@ -277,7 +277,7 @@ impl<'a, 'b> MutationTracker<'a, 'b> {
|
|||
if stack.is_empty() {
|
||||
intermediates.push(Intermediate::Map(
|
||||
oid.clone(),
|
||||
map_type.clone(),
|
||||
*map_type,
|
||||
k.clone(),
|
||||
current_obj.default_op_id_for_key(amp::RequestKey::Str(k.clone())),
|
||||
))
|
||||
|
@ -290,7 +290,7 @@ impl<'a, 'b> MutationTracker<'a, 'b> {
|
|||
if let Some(Some(target)) = vals.get(*i) {
|
||||
intermediates.push(Intermediate::Seq(
|
||||
oid.clone(),
|
||||
seq_type.clone(),
|
||||
*seq_type,
|
||||
*i,
|
||||
current_obj.default_op_id_for_key(amp::RequestKey::Num(*i as u64)),
|
||||
));
|
||||
|
@ -304,7 +304,7 @@ impl<'a, 'b> MutationTracker<'a, 'b> {
|
|||
if stack.is_empty() {
|
||||
intermediates.push(Intermediate::Seq(
|
||||
oid.clone(),
|
||||
seq_type.clone(),
|
||||
*seq_type,
|
||||
*i,
|
||||
current_obj.default_op_id_for_key(amp::RequestKey::Num(*i as u64)),
|
||||
))
|
||||
|
@ -326,12 +326,12 @@ impl<'a, 'b> MutationTracker<'a, 'b> {
|
|||
.rfold(subdiff, |diff_so_far, intermediate| match intermediate {
|
||||
Intermediate::Map(oid, map_type, k, opid) => amp::Diff::Map(amp::MapDiff {
|
||||
object_id: oid,
|
||||
obj_type: map_type.to_obj_type(),
|
||||
obj_type: map_type,
|
||||
props: hashmap! {k => hashmap!{opid.unwrap_or_else(random_op_id) => diff_so_far}},
|
||||
}),
|
||||
Intermediate::Seq(oid, seq_type, index, opid) => amp::Diff::Seq(amp::SeqDiff {
|
||||
object_id: oid,
|
||||
obj_type: seq_type.to_obj_type(),
|
||||
obj_type: seq_type,
|
||||
edits: Vec::new(),
|
||||
props: hashmap! {index => hashmap!{opid.unwrap_or_else(random_op_id) => diff_so_far}},
|
||||
}),
|
||||
|
@ -343,7 +343,7 @@ impl<'a, 'b> MutationTracker<'a, 'b> {
|
|||
/// the root object
|
||||
fn wrap_root_assignment(&mut self, value: &Value) -> Result<(), AutomergeFrontendError> {
|
||||
match value {
|
||||
Value::Map(kvs, MapType::Map) => {
|
||||
Value::Map(kvs, amp::MapType::Map) => {
|
||||
for (k, v) in kvs.iter() {
|
||||
self.add_change(LocalChange::set(Path::root().key(k), v.clone()))?;
|
||||
}
|
||||
|
@ -412,14 +412,14 @@ impl<'a, 'b> MutableDocument for MutationTracker<'a, 'b> {
|
|||
let diff = match &*parent_obj {
|
||||
Object::Map(oid, _, map_type) => amp::Diff::Map(amp::MapDiff {
|
||||
object_id: oid.clone(),
|
||||
obj_type: map_type.to_obj_type(),
|
||||
obj_type: *map_type,
|
||||
props: hashmap! {change.path.name().unwrap().to_string() => HashMap::new()},
|
||||
}),
|
||||
Object::Sequence(oid, _, seq_type) => {
|
||||
if let Some(PathElement::Index(i)) = change.path.name() {
|
||||
amp::Diff::Seq(amp::SeqDiff {
|
||||
object_id: oid.clone(),
|
||||
obj_type: seq_type.to_obj_type(),
|
||||
obj_type: *seq_type,
|
||||
edits: vec![amp::DiffEdit::Remove { index: *i }],
|
||||
props: hashmap! {*i => HashMap::new()},
|
||||
})
|
||||
|
@ -497,7 +497,7 @@ impl<'a, 'b> MutableDocument for MutationTracker<'a, 'b> {
|
|||
);
|
||||
let seqdiff = amp::Diff::Seq(amp::SeqDiff {
|
||||
object_id: oid.clone(),
|
||||
obj_type: seq_type.to_obj_type(),
|
||||
obj_type: *seq_type,
|
||||
edits: vec![amp::DiffEdit::Insert { index: *index }],
|
||||
props: hashmap! {
|
||||
*index => hashmap!{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{MapType, SequenceType, Value};
|
||||
use crate::Value;
|
||||
use automerge_protocol as amp;
|
||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||
|
||||
|
@ -42,8 +42,8 @@ impl Values {
|
|||
/// Internal data type used to represent the values of an automerge document
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Object {
|
||||
Sequence(amp::ObjectID, Vec<Option<Values>>, SequenceType),
|
||||
Map(amp::ObjectID, HashMap<String, Values>, MapType),
|
||||
Sequence(amp::ObjectID, Vec<Option<Values>>, amp::SequenceType),
|
||||
Map(amp::ObjectID, HashMap<String, Values>, amp::MapType),
|
||||
Primitive(amp::Value),
|
||||
}
|
||||
|
||||
|
@ -54,13 +54,13 @@ impl Object {
|
|||
vals.iter()
|
||||
.filter_map(|v| v.clone().map(|v2| v2.to_value()))
|
||||
.collect(),
|
||||
seq_type.clone(),
|
||||
*seq_type,
|
||||
),
|
||||
Object::Map(_, vals, map_type) => Value::Map(
|
||||
vals.iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_value()))
|
||||
.collect(),
|
||||
map_type.clone(),
|
||||
*map_type,
|
||||
),
|
||||
Object::Primitive(v) => Value::Primitive(v.clone()),
|
||||
}
|
||||
|
|
|
@ -4,36 +4,6 @@ use maplit::hashmap;
|
|||
use serde::Serialize;
|
||||
use std::{borrow::Borrow, collections::HashMap};
|
||||
|
||||
#[derive(Serialize, Clone, Debug, PartialEq)]
|
||||
pub enum MapType {
|
||||
Map,
|
||||
Table,
|
||||
}
|
||||
|
||||
impl MapType {
|
||||
pub(crate) fn to_obj_type(&self) -> amp::ObjType {
|
||||
match self {
|
||||
MapType::Map => amp::ObjType::Map,
|
||||
MapType::Table => amp::ObjType::Table,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, Debug, PartialEq)]
|
||||
pub enum SequenceType {
|
||||
List,
|
||||
Text,
|
||||
}
|
||||
|
||||
impl SequenceType {
|
||||
pub(crate) fn to_obj_type(&self) -> amp::ObjType {
|
||||
match self {
|
||||
SequenceType::List => amp::ObjType::List,
|
||||
SequenceType::Text => amp::ObjType::Text,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, Debug, PartialEq)]
|
||||
pub struct Conflicts(HashMap<amp::OpID, Value>);
|
||||
|
||||
|
@ -46,8 +16,8 @@ impl From<HashMap<amp::OpID, Value>> for Conflicts {
|
|||
#[derive(Serialize, Clone, Debug, PartialEq)]
|
||||
#[serde(untagged)]
|
||||
pub enum Value {
|
||||
Map(HashMap<String, Value>, MapType),
|
||||
Sequence(Vec<Value>, SequenceType),
|
||||
Map(HashMap<String, Value>, amp::MapType),
|
||||
Sequence(Vec<Value>, amp::SequenceType),
|
||||
Primitive(amp::Value),
|
||||
}
|
||||
|
||||
|
@ -76,7 +46,7 @@ where
|
|||
fn from(v: Vec<T>) -> Self {
|
||||
Value::Sequence(
|
||||
v.into_iter().map(|t| t.into()).collect(),
|
||||
SequenceType::List,
|
||||
amp::SequenceType::List,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +61,7 @@ where
|
|||
h.into_iter()
|
||||
.map(|(k, v)| (k.borrow().to_string(), v.into()))
|
||||
.collect(),
|
||||
MapType::Map,
|
||||
amp::MapType::Map,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -104,11 +74,11 @@ impl Value {
|
|||
.iter()
|
||||
.map(|(k, v)| (k.clone(), Value::from_json(v)))
|
||||
.collect();
|
||||
Value::Map(result, MapType::Map)
|
||||
Value::Map(result, amp::MapType::Map)
|
||||
}
|
||||
serde_json::Value::Array(vs) => Value::Sequence(
|
||||
vs.iter().map(Value::from_json).collect(),
|
||||
SequenceType::List,
|
||||
amp::SequenceType::List,
|
||||
),
|
||||
serde_json::Value::String(s) => Value::Primitive(amp::Value::Str(s.clone())),
|
||||
serde_json::Value::Number(n) => {
|
||||
|
@ -126,14 +96,15 @@ impl Value {
|
|||
map.iter().map(|(k, v)| (k.clone(), v.to_json())).collect();
|
||||
serde_json::Value::Object(result)
|
||||
}
|
||||
Value::Sequence(elements, SequenceType::List) => {
|
||||
Value::Sequence(elements, amp::SequenceType::List) => {
|
||||
serde_json::Value::Array(elements.iter().map(|v| v.to_json()).collect())
|
||||
}
|
||||
Value::Sequence(elements, SequenceType::Text) => serde_json::Value::String(
|
||||
Value::Sequence(elements, amp::SequenceType::Text) => serde_json::Value::String(
|
||||
elements
|
||||
.iter()
|
||||
.map(|v| match v {
|
||||
Value::Primitive(amp::Value::Str(c)) => c.as_str(),
|
||||
// TODO fix panic
|
||||
_ => panic!("Non string element in text sequence"),
|
||||
})
|
||||
.collect(),
|
||||
|
@ -179,8 +150,8 @@ pub(crate) fn value_to_op_requests(
|
|||
match v {
|
||||
Value::Sequence(vs, seq_type) => {
|
||||
let make_action = match seq_type {
|
||||
SequenceType::List => amp::OpType::MakeList,
|
||||
SequenceType::Text => amp::OpType::MakeText,
|
||||
amp::SequenceType::List => amp::OpType::MakeList,
|
||||
amp::SequenceType::Text => amp::OpType::MakeText,
|
||||
};
|
||||
let list_id = new_object_id();
|
||||
let make_op = amp::Op {
|
||||
|
@ -211,10 +182,7 @@ pub(crate) fn value_to_op_requests(
|
|||
.map(|(index, _)| amp::DiffEdit::Insert { index })
|
||||
.collect(),
|
||||
object_id: list_id,
|
||||
obj_type: match seq_type {
|
||||
SequenceType::List => amp::ObjType::List,
|
||||
SequenceType::Text => amp::ObjType::Text,
|
||||
},
|
||||
obj_type: *seq_type,
|
||||
props: child_requests_and_diffs
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
|
@ -227,8 +195,8 @@ pub(crate) fn value_to_op_requests(
|
|||
}
|
||||
Value::Map(kvs, map_type) => {
|
||||
let make_action = match map_type {
|
||||
MapType::Map => amp::OpType::MakeMap,
|
||||
MapType::Table => amp::OpType::MakeTable,
|
||||
amp::MapType::Map => amp::OpType::MakeMap,
|
||||
amp::MapType::Table => amp::OpType::MakeTable,
|
||||
};
|
||||
let map_id = new_object_id();
|
||||
let make_op = amp::Op {
|
||||
|
@ -257,10 +225,7 @@ pub(crate) fn value_to_op_requests(
|
|||
.collect();
|
||||
let child_diff = amp::MapDiff {
|
||||
object_id: map_id,
|
||||
obj_type: match map_type {
|
||||
MapType::Map => amp::ObjType::Map,
|
||||
MapType::Table => amp::ObjType::Table,
|
||||
},
|
||||
obj_type: *map_type,
|
||||
props: child_requests_and_diffs
|
||||
.into_iter()
|
||||
.map(|(k, (_, diff_link))| (k, hashmap! {random_op_id() => diff_link}))
|
||||
|
|
|
@ -17,10 +17,10 @@ fn set_object_root_properties() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"bird".into() => hashmap!{
|
||||
actor.op_id_at(1).into() => "magpie".into()
|
||||
actor.op_id_at(1) => "magpie".into()
|
||||
}
|
||||
},
|
||||
})),
|
||||
|
@ -60,11 +60,11 @@ fn reveal_conflicts_on_root_properties() {
|
|||
deps: Vec::new(),
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"favouriteBird".into() => hashmap!{
|
||||
actor1.op_id_at(1).into() => amp::Diff::Value("robin".into()),
|
||||
actor2.op_id_at(1).into() => amp::Diff::Value("wagtail".into()),
|
||||
actor1.op_id_at(1) => amp::Diff::Value("robin".into()),
|
||||
actor2.op_id_at(1) => amp::Diff::Value("wagtail".into()),
|
||||
}
|
||||
},
|
||||
})),
|
||||
|
@ -103,15 +103,15 @@ fn create_nested_maps() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
actor.op_id_at(1).into() => amp::Diff::Map(amp::MapDiff{
|
||||
actor.op_id_at(1) => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: actor.op_id_at(2).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"wrens".into() => hashmap!{
|
||||
actor.op_id_at(2).into() => amp::Diff::Value(amp::Value::Int(3))
|
||||
actor.op_id_at(2) => amp::Diff::Value(amp::Value::Int(3))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -142,15 +142,15 @@ fn apply_updates_inside_nested_maps() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
actor.op_id_at(1).into() => amp::Diff::Map(amp::MapDiff{
|
||||
actor.op_id_at(1) => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: actor.op_id_at(2).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"wrens".into() => hashmap!{
|
||||
actor.op_id_at(2).into() => amp::Diff::Value(amp::Value::Int(3))
|
||||
actor.op_id_at(2) => amp::Diff::Value(amp::Value::Int(3))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -175,15 +175,15 @@ fn apply_updates_inside_nested_maps() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
actor.op_id_at(1).into() => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: birds_id.into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
actor.op_id_at(1) => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: birds_id,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"sparrows".into() => hashmap!{
|
||||
actor.op_id_at(3).into() => amp::Diff::Value(amp::Value::Int(15))
|
||||
actor.op_id_at(3) => amp::Diff::Value(amp::Value::Int(15))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -229,24 +229,24 @@ fn apply_updates_inside_map_conflicts() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"favouriteBirds".into() => hashmap!{
|
||||
actor1.op_id_at(1).into() => amp::Diff::Map(amp::MapDiff{
|
||||
actor1.op_id_at(1) => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: actor1.op_id_at(1).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"blackbirds".into() => hashmap!{
|
||||
actor1.op_id_at(2).into() => amp::Diff::Value(amp::Value::Int(1)),
|
||||
actor1.op_id_at(2) => amp::Diff::Value(amp::Value::Int(1)),
|
||||
}
|
||||
},
|
||||
}),
|
||||
actor2.op_id_at(1).into() => amp::Diff::Map(amp::MapDiff{
|
||||
actor2.op_id_at(1) => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: actor2.op_id_at(1).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"wrens".into() => hashmap!{
|
||||
actor2.op_id_at(2).into() => amp::Diff::Value(amp::Value::Int(3)),
|
||||
actor2.op_id_at(2) => amp::Diff::Value(amp::Value::Int(3)),
|
||||
}
|
||||
},
|
||||
})
|
||||
|
@ -287,21 +287,21 @@ fn apply_updates_inside_map_conflicts() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"favouriteBirds".into() => hashmap!{
|
||||
actor1.op_id_at(1).into() => amp::Diff::Map(amp::MapDiff{
|
||||
actor1.op_id_at(1) => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: actor1.op_id_at(1).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"blackbirds".into() => hashmap!{
|
||||
actor1.op_id_at(3).into() => amp::Diff::Value(amp::Value::Int(2)),
|
||||
actor1.op_id_at(3) => amp::Diff::Value(amp::Value::Int(2)),
|
||||
}
|
||||
},
|
||||
}),
|
||||
actor2.op_id_at(1).into() => amp::Diff::Unchanged(amp::ObjDiff{
|
||||
actor2.op_id_at(1) => amp::Diff::Unchanged(amp::ObjDiff{
|
||||
object_id: actor2.op_id_at(1).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::ObjType::Map(amp::MapType::Map),
|
||||
})
|
||||
}
|
||||
},
|
||||
|
@ -344,13 +344,13 @@ fn delete_keys_in_maps() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"magpies".into() => hashmap!{
|
||||
actor.op_id_at(1).into() => amp::Diff::Value(amp::Value::Int(2))
|
||||
actor.op_id_at(1) => amp::Diff::Value(amp::Value::Int(2))
|
||||
},
|
||||
"sparrows".into() => hashmap!{
|
||||
actor.op_id_at(2).into() => amp::Diff::Value(amp::Value::Int(15))
|
||||
actor.op_id_at(2) => amp::Diff::Value(amp::Value::Int(15))
|
||||
}
|
||||
},
|
||||
})),
|
||||
|
@ -375,7 +375,7 @@ fn delete_keys_in_maps() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"magpies".into() => hashmap!{}
|
||||
},
|
||||
|
@ -405,16 +405,16 @@ fn create_lists() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
actor.op_id_at(1).into() => amp::Diff::Seq(amp::SeqDiff{
|
||||
actor.op_id_at(1) => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: actor.op_id_at(1).into(),
|
||||
obj_type: amp::ObjType::List,
|
||||
obj_type: amp::SequenceType::List,
|
||||
edits: vec![amp::DiffEdit::Insert { index: 0 }],
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
actor.op_id_at(2).into() => amp::Diff::Value("chaffinch".into())
|
||||
actor.op_id_at(2) => amp::Diff::Value("chaffinch".into())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -446,16 +446,16 @@ fn apply_updates_inside_lists() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
actor.op_id_at(1).into() => amp::Diff::Seq(amp::SeqDiff{
|
||||
actor.op_id_at(1) => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: actor.op_id_at(1).into(),
|
||||
obj_type: amp::ObjType::List,
|
||||
obj_type: amp::SequenceType::List,
|
||||
edits: vec![amp::DiffEdit::Insert { index: 0 }],
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
actor.op_id_at(2).into() => amp::Diff::Value("chaffinch".into())
|
||||
actor.op_id_at(2) => amp::Diff::Value("chaffinch".into())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -477,16 +477,16 @@ fn apply_updates_inside_lists() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
actor.op_id_at(1).into() => amp::Diff::Seq(amp::SeqDiff{
|
||||
actor.op_id_at(1) => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: actor.op_id_at(1).into(),
|
||||
obj_type: amp::ObjType::List,
|
||||
obj_type: amp::SequenceType::List,
|
||||
edits: vec![],
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
actor.op_id_at(3).into() => amp::Diff::Value("greenfinch".into())
|
||||
actor.op_id_at(3) => amp::Diff::Value("greenfinch".into())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -532,36 +532,36 @@ fn apply_updates_inside_list_conflicts() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
other_actor.op_id_at(1).into() => amp::Diff::Seq(amp::SeqDiff{
|
||||
other_actor.op_id_at(1) => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: other_actor.op_id_at(1).into(),
|
||||
obj_type: amp::ObjType::List,
|
||||
obj_type: amp::SequenceType::List,
|
||||
edits: vec![amp::DiffEdit::Insert{ index: 0}],
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
actor1.op_id_at(2).into() => amp::Diff::Map(amp::MapDiff{
|
||||
actor1.op_id_at(2) => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: actor1.op_id_at(2).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"species".into() => hashmap!{
|
||||
actor1.op_id_at(3).into() => amp::Diff::Value("woodpecker".into()),
|
||||
actor1.op_id_at(3) => amp::Diff::Value("woodpecker".into()),
|
||||
},
|
||||
"numSeen".into() => hashmap!{
|
||||
actor1.op_id_at(4).into() => amp::Diff::Value(amp::Value::Int(1)),
|
||||
actor1.op_id_at(4) => amp::Diff::Value(amp::Value::Int(1)),
|
||||
},
|
||||
}
|
||||
}),
|
||||
actor2.op_id_at(2).into() => amp::Diff::Map(amp::MapDiff{
|
||||
actor2.op_id_at(2) => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: actor2.op_id_at(2).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"species".into() => hashmap!{
|
||||
actor2.op_id_at(3).into() => amp::Diff::Value("lapwing".into()),
|
||||
actor2.op_id_at(3) => amp::Diff::Value("lapwing".into()),
|
||||
},
|
||||
"numSeen".into() => hashmap!{
|
||||
actor2.op_id_at(4).into() => amp::Diff::Value(amp::Value::Int(2)),
|
||||
actor2.op_id_at(4) => amp::Diff::Value(amp::Value::Int(2)),
|
||||
},
|
||||
}
|
||||
}),
|
||||
|
@ -611,27 +611,27 @@ fn apply_updates_inside_list_conflicts() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
other_actor.op_id_at(1).into() => amp::Diff::Seq(amp::SeqDiff{
|
||||
other_actor.op_id_at(1) => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: other_actor.op_id_at(1).into(),
|
||||
obj_type: amp::ObjType::List,
|
||||
obj_type: amp::SequenceType::List,
|
||||
edits: Vec::new(),
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
actor1.op_id_at(2).into() => amp::Diff::Map(amp::MapDiff{
|
||||
actor1.op_id_at(2) => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: actor1.op_id_at(2).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"numSeen".into() => hashmap!{
|
||||
actor1.op_id_at(5).into() => amp::Diff::Value(amp::Value::Int(2)),
|
||||
actor1.op_id_at(5) => amp::Diff::Value(amp::Value::Int(2)),
|
||||
},
|
||||
}
|
||||
}),
|
||||
actor2.op_id_at(2).into() => amp::Diff::Unchanged(amp::ObjDiff{
|
||||
actor2.op_id_at(2) => amp::Diff::Unchanged(amp::ObjDiff{
|
||||
object_id: actor2.op_id_at(2).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::ObjType::Map(amp::MapType::Map),
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
@ -683,19 +683,19 @@ fn delete_list_elements() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
actor.op_id_at(1).into() => amp::Diff::Seq(amp::SeqDiff{
|
||||
actor.op_id_at(1) => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: actor.op_id_at(1).into(),
|
||||
obj_type: amp::ObjType::List,
|
||||
obj_type: amp::SequenceType::List,
|
||||
edits: vec![amp::DiffEdit::Insert { index: 0 }, amp::DiffEdit::Insert { index: 1 }],
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
actor.op_id_at(2).into() => amp::Diff::Value("chaffinch".into())
|
||||
actor.op_id_at(2) => amp::Diff::Value("chaffinch".into())
|
||||
},
|
||||
1 => hashmap!{
|
||||
actor.op_id_at(3).into() => amp::Diff::Value("goldfinch".into())
|
||||
actor.op_id_at(3) => amp::Diff::Value("goldfinch".into())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -721,12 +721,12 @@ fn delete_list_elements() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
actor.op_id_at(1).into() => amp::Diff::Seq(amp::SeqDiff{
|
||||
actor.op_id_at(1) => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: actor.op_id_at(1).into(),
|
||||
obj_type: amp::ObjType::List,
|
||||
obj_type: amp::SequenceType::List,
|
||||
edits: vec![amp::DiffEdit::Remove{ index: 0 }],
|
||||
props: hashmap!{}
|
||||
})
|
||||
|
@ -754,35 +754,35 @@ fn apply_updates_at_different_levels_of_object_tree() {
|
|||
deps: Vec::new(),
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"counts".into() => hashmap!{
|
||||
actor.op_id_at(1).into() => amp::Diff::Map(amp::MapDiff{
|
||||
actor.op_id_at(1) => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: actor.op_id_at(1).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"magpie".into() => hashmap!{
|
||||
actor.op_id_at(2).into() => amp::Diff::Value(amp::Value::Int(2))
|
||||
actor.op_id_at(2) => amp::Diff::Value(amp::Value::Int(2))
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
"details".into() => hashmap!{
|
||||
actor.op_id_at(3).into() => amp::Diff::Seq(amp::SeqDiff{
|
||||
actor.op_id_at(3) => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: actor.op_id_at(3).into(),
|
||||
obj_type: amp::ObjType::List,
|
||||
obj_type: amp::SequenceType::List,
|
||||
edits: vec![amp::DiffEdit::Insert{ index: 0 }],
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
actor.op_id_at(4).into() => amp::Diff::Map(amp::MapDiff{
|
||||
actor.op_id_at(4) => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: actor.op_id_at(4).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"species".into() => hashmap!{
|
||||
actor.op_id_at(5).into() => amp::Diff::Value("magpie".into())
|
||||
actor.op_id_at(5) => amp::Diff::Value("magpie".into())
|
||||
},
|
||||
"family".into() => hashmap!{
|
||||
actor.op_id_at(6).into() => amp::Diff::Value("Corvidae".into())
|
||||
actor.op_id_at(6) => amp::Diff::Value("Corvidae".into())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -818,12 +818,12 @@ fn apply_updates_at_different_levels_of_object_tree() {
|
|||
deps: Vec::new(),
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"counts".into() => hashmap!{
|
||||
actor.op_id_at(1) => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: actor.op_id_at(1).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"magpie".into() => hashmap!{
|
||||
actor.op_id_at(7) => amp::Diff::Value(amp::Value::Int(3))
|
||||
|
@ -834,13 +834,13 @@ fn apply_updates_at_different_levels_of_object_tree() {
|
|||
"details".into() => hashmap!{
|
||||
actor.op_id_at(3) => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: actor.op_id_at(3).into(),
|
||||
obj_type: amp::ObjType::List,
|
||||
obj_type: amp::SequenceType::List,
|
||||
edits: Vec::new(),
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
actor.op_id_at(4) => amp::Diff::Map(amp::MapDiff{
|
||||
object_id: actor.op_id_at(4).into(),
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"species".into() => hashmap!{
|
||||
actor.op_id_at(8) => amp::Diff::Value("Eurasian magpie".into())
|
||||
|
|
|
@ -28,7 +28,7 @@ fn use_version_and_sequence_number_from_backend() {
|
|||
deps: Vec::new(),
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"blackbirds".into() => hashmap!{
|
||||
random_op_id() => amp::Diff::Value(amp::Value::F64(24.0))
|
||||
|
@ -120,7 +120,7 @@ fn remove_pending_requests_once_handled() {
|
|||
deps: Vec::new(),
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"blackbirds".into() => hashmap!{
|
||||
random_op_id() => amp::Diff::Value(amp::Value::Int(24))
|
||||
|
@ -154,7 +154,7 @@ fn remove_pending_requests_once_handled() {
|
|||
deps: Vec::new(),
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"partridges".into() => hashmap!{
|
||||
random_op_id() => amp::Diff::Value(amp::Value::Int(1))
|
||||
|
@ -214,7 +214,7 @@ fn leave_request_queue_unchanged_on_remote_changes() {
|
|||
deps: Vec::new(),
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"pheasants".into() => hashmap!{
|
||||
random_op_id() => amp::Diff::Value(amp::Value::Int(2))
|
||||
|
@ -248,7 +248,7 @@ fn leave_request_queue_unchanged_on_remote_changes() {
|
|||
deps: Vec::new(),
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"blackbirds".into() => hashmap!{
|
||||
random_op_id() => amp::Diff::Value(amp::Value::Int(24))
|
||||
|
@ -300,7 +300,7 @@ fn dont_allow_out_of_order_request_patches() {
|
|||
can_redo: false,
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"partridges".to_string() => hashmap!{
|
||||
random_op_id() => amp::Diff::Value(amp::Value::Int(1))
|
||||
|
@ -345,12 +345,12 @@ fn handle_concurrent_insertions_into_lists() {
|
|||
deps: Vec::new(),
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".to_string() => hashmap!{
|
||||
doc.actor_id.op_id_at(1).into() => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: birds_id.clone().into(),
|
||||
obj_type: amp::ObjType::List,
|
||||
doc.actor_id.op_id_at(1) => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: birds_id.clone(),
|
||||
obj_type: amp::SequenceType::List,
|
||||
edits: vec![amp::DiffEdit::Insert{ index: 0 }],
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
|
@ -411,16 +411,16 @@ fn handle_concurrent_insertions_into_lists() {
|
|||
deps: Vec::new(),
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff {
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap! {
|
||||
"birds".into() => hashmap!{
|
||||
doc.actor_id.op_id_at(1).into() => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: birds_id.clone().into(),
|
||||
obj_type: amp::ObjType::List,
|
||||
doc.actor_id.op_id_at(1) => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: birds_id.clone(),
|
||||
obj_type: amp::SequenceType::List,
|
||||
edits: vec![amp::DiffEdit::Insert{ index: 1 }],
|
||||
props: hashmap!{
|
||||
1 => hashmap!{
|
||||
remote.op_id_at(1).into() => amp::Diff::Value("bullfinch".into())
|
||||
remote.op_id_at(1) => amp::Diff::Value("bullfinch".into())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -452,19 +452,19 @@ fn handle_concurrent_insertions_into_lists() {
|
|||
deps: Vec::new(),
|
||||
diffs: Some(amp::Diff::Map(amp::MapDiff{
|
||||
object_id: amp::ObjectID::Root,
|
||||
obj_type: amp::ObjType::Map,
|
||||
obj_type: amp::MapType::Map,
|
||||
props: hashmap!{
|
||||
"birds".to_string() => hashmap!{
|
||||
doc.actor_id.op_id_at(1).into() => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: birds_id.into(),
|
||||
obj_type: amp::ObjType::List,
|
||||
doc.actor_id.op_id_at(1) => amp::Diff::Seq(amp::SeqDiff{
|
||||
object_id: birds_id,
|
||||
obj_type: amp::SequenceType::List,
|
||||
edits: vec![amp::DiffEdit::Insert { index: 0 }, amp::DiffEdit::Insert{ index: 2 }],
|
||||
props: hashmap!{
|
||||
0 => hashmap!{
|
||||
doc.actor_id.op_id_at(2).into() => amp::Diff::Value("chaffinch".into()),
|
||||
doc.actor_id.op_id_at(2) => amp::Diff::Value("chaffinch".into()),
|
||||
},
|
||||
2 => hashmap!{
|
||||
doc.actor_id.op_id_at(3).into() => amp::Diff::Value("greenfinch".into()),
|
||||
doc.actor_id.op_id_at(3) => amp::Diff::Value("greenfinch".into()),
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use automerge_frontend::{
|
||||
AutomergeFrontendError, Frontend, LocalChange, MapType, Path, SequenceType, Value,
|
||||
};
|
||||
use automerge_frontend::{AutomergeFrontendError, Frontend, LocalChange, Path, Value};
|
||||
use automerge_protocol as amp;
|
||||
use maplit::hashmap;
|
||||
|
||||
|
@ -272,7 +270,7 @@ fn create_lists() {
|
|||
.change(None, |doc| {
|
||||
doc.add_change(LocalChange::set(
|
||||
Path::root().key("birds"),
|
||||
Value::Sequence(vec!["chaffinch".into()], SequenceType::List),
|
||||
Value::Sequence(vec!["chaffinch".into()], amp::SequenceType::List),
|
||||
))?;
|
||||
Ok(())
|
||||
})
|
||||
|
@ -340,7 +338,7 @@ fn apply_updates_inside_lists() {
|
|||
.change(None, |doc| {
|
||||
doc.add_change(LocalChange::set(
|
||||
Path::root().key("birds"),
|
||||
Value::Sequence(vec!["chaffinch".into()], SequenceType::List),
|
||||
Value::Sequence(vec!["chaffinch".into()], amp::SequenceType::List),
|
||||
))?;
|
||||
Ok(())
|
||||
})
|
||||
|
@ -474,7 +472,7 @@ fn handle_counters_inside_maps() {
|
|||
hashmap! {
|
||||
"wrens".into() => Value::Primitive(amp::Value::Counter(0))
|
||||
},
|
||||
MapType::Map
|
||||
amp::MapType::Map
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -484,7 +482,7 @@ fn handle_counters_inside_maps() {
|
|||
hashmap! {
|
||||
"wrens".into() => Value::Primitive(amp::Value::Counter(1))
|
||||
},
|
||||
MapType::Map
|
||||
amp::MapType::Map
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -564,7 +562,7 @@ fn handle_counters_inside_lists() {
|
|||
hashmap! {
|
||||
"counts".into() => vec![Value::Primitive(amp::Value::Counter(1))].into()
|
||||
},
|
||||
MapType::Map
|
||||
amp::MapType::Map
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -574,7 +572,7 @@ fn handle_counters_inside_lists() {
|
|||
hashmap! {
|
||||
"counts".into() => vec![Value::Primitive(amp::Value::Counter(3))].into()
|
||||
},
|
||||
MapType::Map
|
||||
amp::MapType::Map
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -11,3 +11,7 @@ hex = "^0.4.2"
|
|||
uuid = { version = "^0.5.1", features=["v4"] }
|
||||
thiserror = "1.0.16"
|
||||
serde = { version = "^1.0", features=["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
maplit = "^1.0.2"
|
||||
serde_json = "^1.0"
|
||||
|
|
|
@ -35,12 +35,42 @@ impl ActorID {
|
|||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Copy, Hash)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(rename_all = "camelCase", untagged)]
|
||||
pub enum ObjType {
|
||||
Map(MapType),
|
||||
Sequence(SequenceType),
|
||||
}
|
||||
|
||||
impl ObjType {
|
||||
pub fn map() -> ObjType {
|
||||
ObjType::Map(MapType::Map)
|
||||
}
|
||||
|
||||
pub fn table() -> ObjType {
|
||||
ObjType::Map(MapType::Table)
|
||||
}
|
||||
|
||||
pub fn text() -> ObjType {
|
||||
ObjType::Sequence(SequenceType::Text)
|
||||
}
|
||||
|
||||
pub fn list() -> ObjType {
|
||||
ObjType::Sequence(SequenceType::List)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Copy, Hash)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum MapType {
|
||||
Map,
|
||||
Table,
|
||||
Text,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Copy, Hash)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum SequenceType {
|
||||
List,
|
||||
Text,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Clone)]
|
||||
|
@ -215,10 +245,10 @@ impl Op {
|
|||
|
||||
pub fn obj_type(&self) -> Option<ObjType> {
|
||||
match self.action {
|
||||
OpType::MakeMap => Some(ObjType::Map),
|
||||
OpType::MakeTable => Some(ObjType::Table),
|
||||
OpType::MakeList => Some(ObjType::List),
|
||||
OpType::MakeText => Some(ObjType::Text),
|
||||
OpType::MakeMap => Some(ObjType::Map(MapType::Map)),
|
||||
OpType::MakeTable => Some(ObjType::Map(MapType::Table)),
|
||||
OpType::MakeList => Some(ObjType::Sequence(SequenceType::List)),
|
||||
OpType::MakeText => Some(ObjType::Sequence(SequenceType::Text)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -292,7 +322,7 @@ pub enum Diff {
|
|||
pub struct MapDiff {
|
||||
pub object_id: ObjectID,
|
||||
#[serde(rename = "type")]
|
||||
pub obj_type: ObjType,
|
||||
pub obj_type: MapType,
|
||||
pub props: HashMap<String, HashMap<OpID, Diff>>,
|
||||
}
|
||||
|
||||
|
@ -301,7 +331,7 @@ pub struct MapDiff {
|
|||
pub struct SeqDiff {
|
||||
pub object_id: ObjectID,
|
||||
#[serde(rename = "type")]
|
||||
pub obj_type: ObjType,
|
||||
pub obj_type: SequenceType,
|
||||
pub edits: Vec<DiffEdit>,
|
||||
pub props: HashMap<usize, HashMap<OpID, Diff>>,
|
||||
}
|
||||
|
|
|
@ -87,27 +87,28 @@ impl<'de> Deserialize<'de> for Diff {
|
|||
let object_id = object_id.ok_or_else(|| Error::missing_field("objectId"))?;
|
||||
let obj_type = obj_type.ok_or_else(|| Error::missing_field("type"))?;
|
||||
if let Some(mut props) = props {
|
||||
if obj_type == ObjType::Text || obj_type == ObjType::List {
|
||||
let edits = edits.ok_or_else(|| Error::missing_field("edits"))?;
|
||||
let mut new_props = HashMap::new();
|
||||
for (k, v) in props.drain() {
|
||||
let index = k.parse().map_err(|_| {
|
||||
Error::invalid_type(Unexpected::Str(&k), &"an integer")
|
||||
})?;
|
||||
new_props.insert(index, v);
|
||||
match obj_type {
|
||||
ObjType::Sequence(seq_type) => {
|
||||
let edits = edits.ok_or_else(|| Error::missing_field("edits"))?;
|
||||
let mut new_props = HashMap::new();
|
||||
for (k, v) in props.drain() {
|
||||
let index = k.parse().map_err(|_| {
|
||||
Error::invalid_type(Unexpected::Str(&k), &"an integer")
|
||||
})?;
|
||||
new_props.insert(index, v);
|
||||
}
|
||||
Ok(Diff::Seq(SeqDiff {
|
||||
object_id,
|
||||
obj_type: seq_type,
|
||||
edits,
|
||||
props: new_props,
|
||||
}))
|
||||
}
|
||||
Ok(Diff::Seq(SeqDiff {
|
||||
ObjType::Map(map_type) => Ok(Diff::Map(MapDiff {
|
||||
object_id,
|
||||
obj_type,
|
||||
edits,
|
||||
props: new_props,
|
||||
}))
|
||||
} else {
|
||||
Ok(Diff::Map(MapDiff {
|
||||
object_id,
|
||||
obj_type,
|
||||
obj_type: map_type,
|
||||
props,
|
||||
}))
|
||||
})),
|
||||
}
|
||||
} else {
|
||||
Ok(Diff::Unchanged(ObjDiff {
|
||||
|
@ -141,3 +142,66 @@ fn maybe_add_datatype_to_value(value: Value, datatype: DataType) -> Value {
|
|||
_ => value,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{Diff, MapDiff, MapType, ObjectID, OpID, SeqDiff, SequenceType};
|
||||
use maplit::hashmap;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn map_diff_serialization_round_trip() {
|
||||
let json = serde_json::json!({
|
||||
"objectId": "1@6121f8757d5d46609b665218b2b3a141",
|
||||
"type": "map",
|
||||
"props": {
|
||||
"key": {
|
||||
"1@4a093244de2b4fd0a4203724e15dfc16": {
|
||||
"value": "value"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
let diff = Diff::Map(MapDiff {
|
||||
object_id: ObjectID::from_str("1@6121f8757d5d46609b665218b2b3a141").unwrap(),
|
||||
obj_type: MapType::Map,
|
||||
props: hashmap! {
|
||||
"key".to_string() => hashmap!{
|
||||
OpID::from_str("1@4a093244de2b4fd0a4203724e15dfc16").unwrap() => "value".into()
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
assert_eq!(json, serde_json::to_value(diff.clone()).unwrap());
|
||||
assert_eq!(serde_json::from_value::<Diff>(json).unwrap(), diff);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn seq_diff_serialization_round_trip() {
|
||||
let json = serde_json::json!({
|
||||
"objectId": "1@6121f8757d5d46609b665218b2b3a141",
|
||||
"type": "list",
|
||||
"edits": [],
|
||||
"props": {
|
||||
"0": {
|
||||
"1@4a093244de2b4fd0a4203724e15dfc16": {
|
||||
"value": "value"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
let diff = Diff::Seq(SeqDiff {
|
||||
object_id: ObjectID::from_str("1@6121f8757d5d46609b665218b2b3a141").unwrap(),
|
||||
obj_type: SequenceType::List,
|
||||
edits: Vec::new(),
|
||||
props: hashmap! {
|
||||
0 => hashmap!{
|
||||
OpID::from_str("1@4a093244de2b4fd0a4203724e15dfc16").unwrap() => "value".into()
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
assert_eq!(json, serde_json::to_value(diff.clone()).unwrap());
|
||||
assert_eq!(serde_json::from_value::<Diff>(json).unwrap(), diff);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue