1use crate::{
2 diagnostic_set::DiagnosticEntry, Completion, CompletionLabel, Diagnostic, Language, Operation,
3};
4use anyhow::{anyhow, Result};
5use clock::ReplicaId;
6use collections::HashSet;
7use lsp::DiagnosticSeverity;
8use rpc::proto;
9use std::sync::Arc;
10use text::*;
11
12pub use proto::{Buffer, BufferState, SelectionSet};
13
14pub fn serialize_operation(operation: &Operation) -> proto::Operation {
15 proto::Operation {
16 variant: Some(match operation {
17 Operation::Buffer(text::Operation::Edit(edit)) => {
18 proto::operation::Variant::Edit(serialize_edit_operation(edit))
19 }
20 Operation::Buffer(text::Operation::Undo {
21 undo,
22 lamport_timestamp,
23 }) => proto::operation::Variant::Undo(proto::operation::Undo {
24 replica_id: undo.id.replica_id as u32,
25 local_timestamp: undo.id.value,
26 lamport_timestamp: lamport_timestamp.value,
27 ranges: undo
28 .ranges
29 .iter()
30 .map(|r| proto::Range {
31 start: r.start.0 as u64,
32 end: r.end.0 as u64,
33 })
34 .collect(),
35 counts: undo
36 .counts
37 .iter()
38 .map(|(edit_id, count)| proto::UndoCount {
39 replica_id: edit_id.replica_id as u32,
40 local_timestamp: edit_id.value,
41 count: *count,
42 })
43 .collect(),
44 version: From::from(&undo.version),
45 }),
46 Operation::UpdateSelections {
47 replica_id,
48 selections,
49 lamport_timestamp,
50 } => proto::operation::Variant::UpdateSelections(proto::operation::UpdateSelections {
51 replica_id: *replica_id as u32,
52 lamport_timestamp: lamport_timestamp.value,
53 selections: serialize_selections(selections),
54 }),
55 Operation::UpdateDiagnostics {
56 diagnostics,
57 lamport_timestamp,
58 } => proto::operation::Variant::UpdateDiagnostics(proto::UpdateDiagnostics {
59 replica_id: lamport_timestamp.replica_id as u32,
60 lamport_timestamp: lamport_timestamp.value,
61 diagnostics: serialize_diagnostics(diagnostics.iter()),
62 }),
63 Operation::UpdateCompletionTriggers { triggers } => {
64 proto::operation::Variant::UpdateCompletionTriggers(
65 proto::operation::UpdateCompletionTriggers {
66 triggers: triggers.clone(),
67 },
68 )
69 }
70 }),
71 }
72}
73
74pub fn serialize_edit_operation(operation: &EditOperation) -> proto::operation::Edit {
75 let ranges = operation
76 .ranges
77 .iter()
78 .map(|range| proto::Range {
79 start: range.start.0 as u64,
80 end: range.end.0 as u64,
81 })
82 .collect();
83 proto::operation::Edit {
84 replica_id: operation.timestamp.replica_id as u32,
85 local_timestamp: operation.timestamp.local,
86 lamport_timestamp: operation.timestamp.lamport,
87 version: From::from(&operation.version),
88 ranges,
89 new_text: operation.new_text.clone(),
90 }
91}
92
93pub fn serialize_undo_map_entry(
94 (edit_id, counts): (&clock::Local, &[(clock::Local, u32)]),
95) -> proto::UndoMapEntry {
96 proto::UndoMapEntry {
97 replica_id: edit_id.replica_id as u32,
98 local_timestamp: edit_id.value,
99 counts: counts
100 .iter()
101 .map(|(undo_id, count)| proto::UndoCount {
102 replica_id: undo_id.replica_id as u32,
103 local_timestamp: undo_id.value,
104 count: *count,
105 })
106 .collect(),
107 }
108}
109
110pub fn serialize_buffer_fragment(fragment: &text::Fragment) -> proto::BufferFragment {
111 proto::BufferFragment {
112 replica_id: fragment.insertion_timestamp.replica_id as u32,
113 local_timestamp: fragment.insertion_timestamp.local,
114 lamport_timestamp: fragment.insertion_timestamp.lamport,
115 insertion_offset: fragment.insertion_offset as u32,
116 len: fragment.len as u32,
117 visible: fragment.visible,
118 deletions: fragment
119 .deletions
120 .iter()
121 .map(|clock| proto::VectorClockEntry {
122 replica_id: clock.replica_id as u32,
123 timestamp: clock.value,
124 })
125 .collect(),
126 max_undos: From::from(&fragment.max_undos),
127 }
128}
129
130pub fn serialize_selections(selections: &Arc<[Selection<Anchor>]>) -> Vec<proto::Selection> {
131 selections
132 .iter()
133 .map(|selection| proto::Selection {
134 id: selection.id as u64,
135 start: Some(serialize_anchor(&selection.start)),
136 end: Some(serialize_anchor(&selection.end)),
137 reversed: selection.reversed,
138 })
139 .collect()
140}
141
142pub fn serialize_diagnostics<'a>(
143 diagnostics: impl IntoIterator<Item = &'a DiagnosticEntry<Anchor>>,
144) -> Vec<proto::Diagnostic> {
145 diagnostics
146 .into_iter()
147 .map(|entry| proto::Diagnostic {
148 start: Some(serialize_anchor(&entry.range.start)),
149 end: Some(serialize_anchor(&entry.range.end)),
150 message: entry.diagnostic.message.clone(),
151 severity: match entry.diagnostic.severity {
152 DiagnosticSeverity::ERROR => proto::diagnostic::Severity::Error,
153 DiagnosticSeverity::WARNING => proto::diagnostic::Severity::Warning,
154 DiagnosticSeverity::INFORMATION => proto::diagnostic::Severity::Information,
155 DiagnosticSeverity::HINT => proto::diagnostic::Severity::Hint,
156 _ => proto::diagnostic::Severity::None,
157 } as i32,
158 group_id: entry.diagnostic.group_id as u64,
159 is_primary: entry.diagnostic.is_primary,
160 is_valid: entry.diagnostic.is_valid,
161 code: entry.diagnostic.code.clone(),
162 is_disk_based: entry.diagnostic.is_disk_based,
163 })
164 .collect()
165}
166
167pub fn serialize_anchor(anchor: &Anchor) -> proto::Anchor {
168 proto::Anchor {
169 replica_id: anchor.timestamp.replica_id as u32,
170 local_timestamp: anchor.timestamp.value,
171 offset: anchor.offset as u64,
172 bias: match anchor.bias {
173 Bias::Left => proto::Bias::Left as i32,
174 Bias::Right => proto::Bias::Right as i32,
175 },
176 }
177}
178
179pub fn deserialize_operation(message: proto::Operation) -> Result<Operation> {
180 Ok(
181 match message
182 .variant
183 .ok_or_else(|| anyhow!("missing operation variant"))?
184 {
185 proto::operation::Variant::Edit(edit) => {
186 Operation::Buffer(text::Operation::Edit(deserialize_edit_operation(edit)))
187 }
188 proto::operation::Variant::Undo(undo) => Operation::Buffer(text::Operation::Undo {
189 lamport_timestamp: clock::Lamport {
190 replica_id: undo.replica_id as ReplicaId,
191 value: undo.lamport_timestamp,
192 },
193 undo: UndoOperation {
194 id: clock::Local {
195 replica_id: undo.replica_id as ReplicaId,
196 value: undo.local_timestamp,
197 },
198 counts: undo
199 .counts
200 .into_iter()
201 .map(|c| {
202 (
203 clock::Local {
204 replica_id: c.replica_id as ReplicaId,
205 value: c.local_timestamp,
206 },
207 c.count,
208 )
209 })
210 .collect(),
211 ranges: undo
212 .ranges
213 .into_iter()
214 .map(|r| FullOffset(r.start as usize)..FullOffset(r.end as usize))
215 .collect(),
216 version: undo.version.into(),
217 },
218 }),
219 proto::operation::Variant::UpdateSelections(message) => {
220 let selections = message
221 .selections
222 .into_iter()
223 .filter_map(|selection| {
224 Some(Selection {
225 id: selection.id as usize,
226 start: deserialize_anchor(selection.start?)?,
227 end: deserialize_anchor(selection.end?)?,
228 reversed: selection.reversed,
229 goal: SelectionGoal::None,
230 })
231 })
232 .collect::<Vec<_>>();
233
234 Operation::UpdateSelections {
235 replica_id: message.replica_id as ReplicaId,
236 lamport_timestamp: clock::Lamport {
237 replica_id: message.replica_id as ReplicaId,
238 value: message.lamport_timestamp,
239 },
240 selections: Arc::from(selections),
241 }
242 }
243 proto::operation::Variant::UpdateDiagnostics(message) => Operation::UpdateDiagnostics {
244 diagnostics: deserialize_diagnostics(message.diagnostics),
245 lamport_timestamp: clock::Lamport {
246 replica_id: message.replica_id as ReplicaId,
247 value: message.lamport_timestamp,
248 },
249 },
250 proto::operation::Variant::UpdateCompletionTriggers(message) => {
251 Operation::UpdateCompletionTriggers {
252 triggers: message.triggers,
253 }
254 }
255 },
256 )
257}
258
259pub fn deserialize_edit_operation(edit: proto::operation::Edit) -> EditOperation {
260 let ranges = edit
261 .ranges
262 .into_iter()
263 .map(|range| FullOffset(range.start as usize)..FullOffset(range.end as usize))
264 .collect();
265 EditOperation {
266 timestamp: InsertionTimestamp {
267 replica_id: edit.replica_id as ReplicaId,
268 local: edit.local_timestamp,
269 lamport: edit.lamport_timestamp,
270 },
271 version: edit.version.into(),
272 ranges,
273 new_text: edit.new_text,
274 }
275}
276
277pub fn deserialize_undo_map_entry(
278 entry: proto::UndoMapEntry,
279) -> (clock::Local, Vec<(clock::Local, u32)>) {
280 (
281 clock::Local {
282 replica_id: entry.replica_id as u16,
283 value: entry.local_timestamp,
284 },
285 entry
286 .counts
287 .into_iter()
288 .map(|undo_count| {
289 (
290 clock::Local {
291 replica_id: undo_count.replica_id as u16,
292 value: undo_count.local_timestamp,
293 },
294 undo_count.count,
295 )
296 })
297 .collect(),
298 )
299}
300
301pub fn deserialize_buffer_fragment(
302 message: proto::BufferFragment,
303 ix: usize,
304 count: usize,
305) -> Fragment {
306 Fragment {
307 id: locator::Locator::from_index(ix, count),
308 insertion_timestamp: InsertionTimestamp {
309 replica_id: message.replica_id as ReplicaId,
310 local: message.local_timestamp,
311 lamport: message.lamport_timestamp,
312 },
313 insertion_offset: message.insertion_offset as usize,
314 len: message.len as usize,
315 visible: message.visible,
316 deletions: HashSet::from_iter(message.deletions.into_iter().map(|entry| clock::Local {
317 replica_id: entry.replica_id as ReplicaId,
318 value: entry.timestamp,
319 })),
320 max_undos: From::from(message.max_undos),
321 }
322}
323
324pub fn deserialize_selections(selections: Vec<proto::Selection>) -> Arc<[Selection<Anchor>]> {
325 Arc::from(
326 selections
327 .into_iter()
328 .filter_map(|selection| {
329 Some(Selection {
330 id: selection.id as usize,
331 start: deserialize_anchor(selection.start?)?,
332 end: deserialize_anchor(selection.end?)?,
333 reversed: selection.reversed,
334 goal: SelectionGoal::None,
335 })
336 })
337 .collect::<Vec<_>>(),
338 )
339}
340
341pub fn deserialize_diagnostics(
342 diagnostics: Vec<proto::Diagnostic>,
343) -> Arc<[DiagnosticEntry<Anchor>]> {
344 diagnostics
345 .into_iter()
346 .filter_map(|diagnostic| {
347 Some(DiagnosticEntry {
348 range: deserialize_anchor(diagnostic.start?)?..deserialize_anchor(diagnostic.end?)?,
349 diagnostic: Diagnostic {
350 severity: match proto::diagnostic::Severity::from_i32(diagnostic.severity)? {
351 proto::diagnostic::Severity::Error => DiagnosticSeverity::ERROR,
352 proto::diagnostic::Severity::Warning => DiagnosticSeverity::WARNING,
353 proto::diagnostic::Severity::Information => DiagnosticSeverity::INFORMATION,
354 proto::diagnostic::Severity::Hint => DiagnosticSeverity::HINT,
355 proto::diagnostic::Severity::None => return None,
356 },
357 message: diagnostic.message,
358 group_id: diagnostic.group_id as usize,
359 code: diagnostic.code,
360 is_valid: diagnostic.is_valid,
361 is_primary: diagnostic.is_primary,
362 is_disk_based: diagnostic.is_disk_based,
363 },
364 })
365 })
366 .collect()
367}
368
369pub fn deserialize_anchor(anchor: proto::Anchor) -> Option<Anchor> {
370 Some(Anchor {
371 timestamp: clock::Local {
372 replica_id: anchor.replica_id as ReplicaId,
373 value: anchor.local_timestamp,
374 },
375 offset: anchor.offset as usize,
376 bias: match proto::Bias::from_i32(anchor.bias)? {
377 proto::Bias::Left => Bias::Left,
378 proto::Bias::Right => Bias::Right,
379 },
380 })
381}
382
383pub fn serialize_completion(completion: &Completion<Anchor>) -> proto::Completion {
384 proto::Completion {
385 old_start: Some(serialize_anchor(&completion.old_range.start)),
386 old_end: Some(serialize_anchor(&completion.old_range.end)),
387 new_text: completion.new_text.clone(),
388 lsp_completion: serde_json::to_vec(&completion.lsp_completion).unwrap(),
389 }
390}
391
392pub fn deserialize_completion(
393 completion: proto::Completion,
394 language: Option<&Arc<Language>>,
395) -> Result<Completion<Anchor>> {
396 let old_start = completion
397 .old_start
398 .and_then(deserialize_anchor)
399 .ok_or_else(|| anyhow!("invalid old start"))?;
400 let old_end = completion
401 .old_end
402 .and_then(deserialize_anchor)
403 .ok_or_else(|| anyhow!("invalid old end"))?;
404 let lsp_completion = serde_json::from_slice(&completion.lsp_completion)?;
405 Ok(Completion {
406 old_range: old_start..old_end,
407 new_text: completion.new_text,
408 label: language
409 .and_then(|l| l.label_for_completion(&lsp_completion))
410 .unwrap_or(CompletionLabel::plain(&lsp_completion)),
411 lsp_completion,
412 })
413}