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