Make transactions serializable to enable edits on behalf of other users

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Antonio Scandurra 2022-02-08 19:46:12 +01:00
parent 6768288da8
commit 7d8641afb6
9 changed files with 325 additions and 291 deletions

View file

@ -25,14 +25,7 @@ pub fn serialize_operation(operation: &Operation) -> proto::Operation {
replica_id: undo.id.replica_id as u32,
local_timestamp: undo.id.value,
lamport_timestamp: lamport_timestamp.value,
ranges: undo
.ranges
.iter()
.map(|r| proto::Range {
start: r.start.0 as u64,
end: r.end.0 as u64,
})
.collect(),
ranges: undo.ranges.iter().map(serialize_range).collect(),
counts: undo
.counts
.iter()
@ -75,20 +68,12 @@ pub fn serialize_operation(operation: &Operation) -> proto::Operation {
}
pub fn serialize_edit_operation(operation: &EditOperation) -> proto::operation::Edit {
let ranges = operation
.ranges
.iter()
.map(|range| proto::Range {
start: range.start.0 as u64,
end: range.end.0 as u64,
})
.collect();
proto::operation::Edit {
replica_id: operation.timestamp.replica_id as u32,
local_timestamp: operation.timestamp.local,
lamport_timestamp: operation.timestamp.lamport,
version: From::from(&operation.version),
ranges,
ranges: operation.ranges.iter().map(serialize_range).collect(),
new_text: operation.new_text.clone(),
}
}
@ -211,11 +196,7 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<Operation> {
)
})
.collect(),
ranges: undo
.ranges
.into_iter()
.map(|r| FullOffset(r.start as usize)..FullOffset(r.end as usize))
.collect(),
ranges: undo.ranges.into_iter().map(deserialize_range).collect(),
version: undo.version.into(),
},
}),
@ -263,11 +244,6 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<Operation> {
}
pub fn deserialize_edit_operation(edit: proto::operation::Edit) -> EditOperation {
let ranges = edit
.ranges
.into_iter()
.map(|range| FullOffset(range.start as usize)..FullOffset(range.end as usize))
.collect();
EditOperation {
timestamp: InsertionTimestamp {
replica_id: edit.replica_id as ReplicaId,
@ -275,7 +251,7 @@ pub fn deserialize_edit_operation(edit: proto::operation::Edit) -> EditOperation
lamport: edit.lamport_timestamp,
},
version: edit.version.into(),
ranges,
ranges: edit.ranges.into_iter().map(deserialize_range).collect(),
new_text: edit.new_text,
}
}
@ -469,42 +445,64 @@ pub fn deserialize_code_action(action: proto::CodeAction) -> Result<CodeAction<A
})
}
pub fn serialize_code_action_edit(
edit_id: clock::Local,
old_range: &Range<Anchor>,
) -> proto::CodeActionEdit {
proto::CodeActionEdit {
id: Some(serialize_edit_id(edit_id)),
old_start: Some(serialize_anchor(&old_range.start)),
old_end: Some(serialize_anchor(&old_range.end)),
pub fn serialize_transaction(transaction: &Transaction) -> proto::Transaction {
proto::Transaction {
id: Some(serialize_local_timestamp(transaction.id)),
edit_ids: transaction
.edit_ids
.iter()
.copied()
.map(serialize_local_timestamp)
.collect(),
start: (&transaction.start).into(),
end: (&transaction.end).into(),
ranges: transaction.ranges.iter().map(serialize_range).collect(),
}
}
pub fn deserialize_code_action_edit(
edit: proto::CodeActionEdit,
) -> Result<(Range<Anchor>, clock::Local)> {
let old_start = edit
.old_start
.and_then(deserialize_anchor)
.ok_or_else(|| anyhow!("invalid old_start"))?;
let old_end = edit
.old_end
.and_then(deserialize_anchor)
.ok_or_else(|| anyhow!("invalid old_end"))?;
let edit_id = deserialize_edit_id(edit.id.ok_or_else(|| anyhow!("invalid edit_id"))?);
Ok((old_start..old_end, edit_id))
pub fn deserialize_transaction(transaction: proto::Transaction) -> Result<Transaction> {
Ok(Transaction {
id: deserialize_local_timestamp(
transaction
.id
.ok_or_else(|| anyhow!("missing transaction id"))?,
),
edit_ids: transaction
.edit_ids
.into_iter()
.map(deserialize_local_timestamp)
.collect(),
start: transaction.start.into(),
end: transaction.end.into(),
ranges: transaction
.ranges
.into_iter()
.map(deserialize_range)
.collect(),
})
}
pub fn serialize_edit_id(edit_id: clock::Local) -> proto::EditId {
proto::EditId {
replica_id: edit_id.replica_id as u32,
local_timestamp: edit_id.value,
pub fn serialize_local_timestamp(timestamp: clock::Local) -> proto::LocalTimestamp {
proto::LocalTimestamp {
replica_id: timestamp.replica_id as u32,
value: timestamp.value,
}
}
pub fn deserialize_edit_id(edit_id: proto::EditId) -> clock::Local {
pub fn deserialize_local_timestamp(timestamp: proto::LocalTimestamp) -> clock::Local {
clock::Local {
replica_id: edit_id.replica_id as ReplicaId,
value: edit_id.local_timestamp,
replica_id: timestamp.replica_id as ReplicaId,
value: timestamp.value,
}
}
pub fn serialize_range(range: &Range<FullOffset>) -> proto::Range {
proto::Range {
start: range.start.0 as u64,
end: range.end.0 as u64,
}
}
pub fn deserialize_range(range: proto::Range) -> Range<FullOffset> {
FullOffset(range.start as usize)..FullOffset(range.end as usize)
}