1use std::sync::Arc;
2
3use crate::{diagnostic_set::DiagnosticEntry, Diagnostic, Operation};
4use anyhow::{anyhow, Result};
5use clock::ReplicaId;
6use lsp::DiagnosticSeverity;
7use rpc::proto;
8use text::*;
9
10pub use proto::Buffer;
11
12pub fn serialize_operation(operation: &Operation) -> proto::Operation {
13 proto::Operation {
14 variant: Some(match operation {
15 Operation::Buffer(text::Operation::Edit(edit)) => {
16 proto::operation::Variant::Edit(serialize_edit_operation(edit))
17 }
18 Operation::Buffer(text::Operation::Undo {
19 undo,
20 lamport_timestamp,
21 }) => proto::operation::Variant::Undo(proto::operation::Undo {
22 replica_id: undo.id.replica_id as u32,
23 local_timestamp: undo.id.value,
24 lamport_timestamp: lamport_timestamp.value,
25 ranges: undo
26 .ranges
27 .iter()
28 .map(|r| proto::Range {
29 start: r.start.0 as u64,
30 end: r.end.0 as u64,
31 })
32 .collect(),
33 counts: undo
34 .counts
35 .iter()
36 .map(|(edit_id, count)| proto::operation::UndoCount {
37 replica_id: edit_id.replica_id as u32,
38 local_timestamp: edit_id.value,
39 count: *count,
40 })
41 .collect(),
42 version: From::from(&undo.version),
43 }),
44 Operation::UpdateSelections {
45 replica_id,
46 selections,
47 lamport_timestamp,
48 } => proto::operation::Variant::UpdateSelections(proto::operation::UpdateSelections {
49 replica_id: *replica_id as u32,
50 lamport_timestamp: lamport_timestamp.value,
51 selections: selections
52 .iter()
53 .map(|selection| proto::Selection {
54 id: selection.id as u64,
55 start: Some(serialize_anchor(&selection.start)),
56 end: Some(serialize_anchor(&selection.end)),
57 reversed: selection.reversed,
58 })
59 .collect(),
60 }),
61 Operation::RemoveSelections {
62 replica_id,
63 lamport_timestamp,
64 } => proto::operation::Variant::RemoveSelections(proto::operation::RemoveSelections {
65 replica_id: *replica_id as u32,
66 lamport_timestamp: lamport_timestamp.value,
67 }),
68 Operation::UpdateDiagnostics {
69 diagnostics,
70 lamport_timestamp,
71 } => proto::operation::Variant::UpdateDiagnostics(proto::UpdateDiagnostics {
72 replica_id: lamport_timestamp.replica_id as u32,
73 lamport_timestamp: lamport_timestamp.value,
74 diagnostics: serialize_diagnostics(diagnostics.iter()),
75 }),
76 }),
77 }
78}
79
80pub fn serialize_edit_operation(operation: &EditOperation) -> proto::operation::Edit {
81 let ranges = operation
82 .ranges
83 .iter()
84 .map(|range| proto::Range {
85 start: range.start.0 as u64,
86 end: range.end.0 as u64,
87 })
88 .collect();
89 proto::operation::Edit {
90 replica_id: operation.timestamp.replica_id as u32,
91 local_timestamp: operation.timestamp.local,
92 lamport_timestamp: operation.timestamp.lamport,
93 version: From::from(&operation.version),
94 ranges,
95 new_text: operation.new_text.clone(),
96 }
97}
98
99pub fn serialize_selections(selections: &Arc<[Selection<Anchor>]>) -> Vec<proto::Selection> {
100 selections
101 .iter()
102 .map(|selection| proto::Selection {
103 id: selection.id as u64,
104 start: Some(serialize_anchor(&selection.start)),
105 end: Some(serialize_anchor(&selection.end)),
106 reversed: selection.reversed,
107 })
108 .collect()
109}
110
111pub fn serialize_diagnostics<'a>(
112 diagnostics: impl IntoIterator<Item = &'a DiagnosticEntry<Anchor>>,
113) -> Vec<proto::Diagnostic> {
114 diagnostics
115 .into_iter()
116 .map(|entry| proto::Diagnostic {
117 start: Some(serialize_anchor(&entry.range.start)),
118 end: Some(serialize_anchor(&entry.range.end)),
119 message: entry.diagnostic.message.clone(),
120 severity: match entry.diagnostic.severity {
121 DiagnosticSeverity::ERROR => proto::diagnostic::Severity::Error,
122 DiagnosticSeverity::WARNING => proto::diagnostic::Severity::Warning,
123 DiagnosticSeverity::INFORMATION => proto::diagnostic::Severity::Information,
124 DiagnosticSeverity::HINT => proto::diagnostic::Severity::Hint,
125 _ => proto::diagnostic::Severity::None,
126 } as i32,
127 group_id: entry.diagnostic.group_id as u64,
128 is_primary: entry.diagnostic.is_primary,
129 })
130 .collect()
131}
132
133fn serialize_anchor(anchor: &Anchor) -> proto::Anchor {
134 proto::Anchor {
135 replica_id: anchor.timestamp.replica_id as u32,
136 local_timestamp: anchor.timestamp.value,
137 offset: anchor.offset as u64,
138 bias: match anchor.bias {
139 Bias::Left => proto::Bias::Left as i32,
140 Bias::Right => proto::Bias::Right as i32,
141 },
142 }
143}
144
145pub fn deserialize_operation(message: proto::Operation) -> Result<Operation> {
146 Ok(
147 match message
148 .variant
149 .ok_or_else(|| anyhow!("missing operation variant"))?
150 {
151 proto::operation::Variant::Edit(edit) => {
152 Operation::Buffer(text::Operation::Edit(deserialize_edit_operation(edit)))
153 }
154 proto::operation::Variant::Undo(undo) => Operation::Buffer(text::Operation::Undo {
155 lamport_timestamp: clock::Lamport {
156 replica_id: undo.replica_id as ReplicaId,
157 value: undo.lamport_timestamp,
158 },
159 undo: UndoOperation {
160 id: clock::Local {
161 replica_id: undo.replica_id as ReplicaId,
162 value: undo.local_timestamp,
163 },
164 counts: undo
165 .counts
166 .into_iter()
167 .map(|c| {
168 (
169 clock::Local {
170 replica_id: c.replica_id as ReplicaId,
171 value: c.local_timestamp,
172 },
173 c.count,
174 )
175 })
176 .collect(),
177 ranges: undo
178 .ranges
179 .into_iter()
180 .map(|r| FullOffset(r.start as usize)..FullOffset(r.end as usize))
181 .collect(),
182 version: undo.version.into(),
183 },
184 }),
185 proto::operation::Variant::UpdateSelections(message) => {
186 let selections = message
187 .selections
188 .into_iter()
189 .filter_map(|selection| {
190 Some(Selection {
191 id: selection.id as usize,
192 start: deserialize_anchor(selection.start?)?,
193 end: deserialize_anchor(selection.end?)?,
194 reversed: selection.reversed,
195 goal: SelectionGoal::None,
196 })
197 })
198 .collect::<Vec<_>>();
199
200 Operation::UpdateSelections {
201 replica_id: message.replica_id as ReplicaId,
202 lamport_timestamp: clock::Lamport {
203 replica_id: message.replica_id as ReplicaId,
204 value: message.lamport_timestamp,
205 },
206 selections: Arc::from(selections),
207 }
208 }
209 proto::operation::Variant::RemoveSelections(message) => Operation::RemoveSelections {
210 replica_id: message.replica_id as ReplicaId,
211 lamport_timestamp: clock::Lamport {
212 replica_id: message.replica_id as ReplicaId,
213 value: message.lamport_timestamp,
214 },
215 },
216 proto::operation::Variant::UpdateDiagnostics(message) => Operation::UpdateDiagnostics {
217 diagnostics: Arc::from(deserialize_diagnostics(message.diagnostics)),
218 lamport_timestamp: clock::Lamport {
219 replica_id: message.replica_id as ReplicaId,
220 value: message.lamport_timestamp,
221 },
222 },
223 },
224 )
225}
226
227pub fn deserialize_edit_operation(edit: proto::operation::Edit) -> EditOperation {
228 let ranges = edit
229 .ranges
230 .into_iter()
231 .map(|range| FullOffset(range.start as usize)..FullOffset(range.end as usize))
232 .collect();
233 EditOperation {
234 timestamp: InsertionTimestamp {
235 replica_id: edit.replica_id as ReplicaId,
236 local: edit.local_timestamp,
237 lamport: edit.lamport_timestamp,
238 },
239 version: edit.version.into(),
240 ranges,
241 new_text: edit.new_text,
242 }
243}
244
245pub fn deserialize_selections(selections: Vec<proto::Selection>) -> Arc<[Selection<Anchor>]> {
246 Arc::from(
247 selections
248 .into_iter()
249 .filter_map(|selection| {
250 Some(Selection {
251 id: selection.id as usize,
252 start: deserialize_anchor(selection.start?)?,
253 end: deserialize_anchor(selection.end?)?,
254 reversed: selection.reversed,
255 goal: SelectionGoal::None,
256 })
257 })
258 .collect::<Vec<_>>(),
259 )
260}
261
262pub fn deserialize_diagnostics(
263 diagnostics: Vec<proto::Diagnostic>,
264) -> Vec<DiagnosticEntry<Anchor>> {
265 diagnostics
266 .into_iter()
267 .filter_map(|diagnostic| {
268 Some(DiagnosticEntry {
269 range: deserialize_anchor(diagnostic.start?)?..deserialize_anchor(diagnostic.end?)?,
270 diagnostic: Diagnostic {
271 severity: match proto::diagnostic::Severity::from_i32(diagnostic.severity)? {
272 proto::diagnostic::Severity::Error => DiagnosticSeverity::ERROR,
273 proto::diagnostic::Severity::Warning => DiagnosticSeverity::WARNING,
274 proto::diagnostic::Severity::Information => DiagnosticSeverity::INFORMATION,
275 proto::diagnostic::Severity::Hint => DiagnosticSeverity::HINT,
276 proto::diagnostic::Severity::None => return None,
277 },
278 message: diagnostic.message,
279 group_id: diagnostic.group_id as usize,
280 is_primary: diagnostic.is_primary,
281 },
282 })
283 })
284 .collect()
285}
286
287fn deserialize_anchor(anchor: proto::Anchor) -> Option<Anchor> {
288 Some(Anchor {
289 timestamp: clock::Local {
290 replica_id: anchor.replica_id as ReplicaId,
291 value: anchor.local_timestamp,
292 },
293 offset: anchor.offset as usize,
294 bias: match proto::Bias::from_i32(anchor.bias)? {
295 proto::Bias::Left => Bias::Left,
296 proto::Bias::Right => Bias::Right,
297 },
298 })
299}