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