proto.rs

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