125 lines
3.7 KiB
Rust
125 lines
3.7 KiB
Rust
use std::cmp::Ordering;
|
|
|
|
use automerge_protocol as amp;
|
|
|
|
use crate::{
|
|
expanded_op::ExpandedOp,
|
|
internal::{ActorId, ElementId, InternalOp, Key, ObjectId, OpId},
|
|
};
|
|
|
|
#[derive(PartialEq, Debug, Clone, Default)]
|
|
pub(crate) struct ActorMap(Vec<amp::ActorId>);
|
|
|
|
impl ActorMap {
|
|
pub fn import_key(&mut self, key: &::Key) -> Key {
|
|
match key {
|
|
amp::Key::Map(string) => Key::Map(string.to_string()),
|
|
amp::Key::Seq(eid) => Key::Seq(self.import_element_id(eid)),
|
|
}
|
|
}
|
|
|
|
pub fn import_actor(&mut self, actor: &::ActorId) -> ActorId {
|
|
if let Some(idx) = self.0.iter().position(|a| a == actor) {
|
|
ActorId(idx)
|
|
} else {
|
|
self.0.push(actor.clone());
|
|
ActorId(self.0.len() - 1)
|
|
}
|
|
}
|
|
|
|
pub fn import_opid(&mut self, opid: &::OpId) -> OpId {
|
|
OpId(opid.0, self.import_actor(&opid.1))
|
|
}
|
|
|
|
pub fn import_obj(&mut self, obj: &::ObjectId) -> ObjectId {
|
|
match obj {
|
|
amp::ObjectId::Root => ObjectId::Root,
|
|
amp::ObjectId::Id(ref opid) => ObjectId::Id(self.import_opid(opid)),
|
|
}
|
|
}
|
|
|
|
pub fn import_element_id(&mut self, eid: &::ElementId) -> ElementId {
|
|
match eid {
|
|
amp::ElementId::Head => ElementId::Head,
|
|
amp::ElementId::Id(ref opid) => ElementId::Id(self.import_opid(opid)),
|
|
}
|
|
}
|
|
|
|
pub fn import_op(&mut self, op: ExpandedOp) -> InternalOp {
|
|
let pred: Vec<OpId> = op.pred.iter().map(|id| self.import_opid(id)).collect();
|
|
InternalOp {
|
|
action: op.action,
|
|
obj: self.import_obj(&op.obj),
|
|
key: self.import_key(&op.key),
|
|
pred,
|
|
insert: op.insert,
|
|
}
|
|
}
|
|
|
|
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))
|
|
}
|
|
|
|
pub fn export_obj(&self, obj: &ObjectId) -> amp::ObjectId {
|
|
match obj {
|
|
ObjectId::Root => amp::ObjectId::Root,
|
|
ObjectId::Id(opid) => amp::ObjectId::Id(self.export_opid(opid)),
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn index_of(&mut self, actor: &::ActorId) -> usize {
|
|
if let Some(index) = self.0.iter().position(|a| a == actor) {
|
|
return index;
|
|
}
|
|
self.0.push(actor.clone());
|
|
self.0.len() - 1
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn actor_for(&self, index: usize) -> Option<&::ActorId> {
|
|
self.0.get(index)
|
|
}
|
|
|
|
pub fn cmp(&self, eid1: &ElementId, eid2: &ElementId) -> Ordering {
|
|
match (eid1, eid2) {
|
|
(ElementId::Head, ElementId::Head) => Ordering::Equal,
|
|
(ElementId::Head, _) => Ordering::Less,
|
|
(_, ElementId::Head) => Ordering::Greater,
|
|
(ElementId::Id(opid1), ElementId::Id(opid2)) => self.cmp_opid(opid1, opid2),
|
|
}
|
|
}
|
|
|
|
pub fn opid_to_string(&self, id: &OpId) -> String {
|
|
format!("{}@{}", id.0, self.export_actor(id.1).to_hex_string())
|
|
}
|
|
|
|
pub fn elementid_to_string(&self, eid: &ElementId) -> String {
|
|
match eid {
|
|
ElementId::Head => "_head".into(),
|
|
ElementId::Id(id) => self.opid_to_string(id),
|
|
}
|
|
}
|
|
|
|
pub fn key_to_string(&self, key: &Key) -> String {
|
|
match &key {
|
|
Key::Map(s) => s.clone(),
|
|
Key::Seq(eid) => self.elementid_to_string(eid),
|
|
}
|
|
}
|
|
|
|
fn cmp_opid(&self, op1: &OpId, op2: &OpId) -> Ordering {
|
|
if op1.0 == op2.0 {
|
|
let actor1 = &self.0[(op1.1).0];
|
|
let actor2 = &self.0[(op2.1).0];
|
|
actor1.cmp(actor2)
|
|
//op1.1.cmp(&op2.1)
|
|
} else {
|
|
op1.0.cmp(&op2.0)
|
|
}
|
|
}
|
|
}
|