proto.rs

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