proto.rs

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