proto.rs

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