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