proto.rs

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