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            })
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(buffer::Operation::Edit(deserialize_edit_operation(edit)))
157            }
158            proto::operation::Variant::Undo(undo) => Operation::Buffer(buffer::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), Bias::Left)
196                            ..(FullOffset(selection.end as usize), Bias::Right);
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(version, entries);
206
207                Operation::Buffer(buffer::Operation::UpdateSelections {
208                    set_id: clock::Lamport {
209                        replica_id: message.replica_id as ReplicaId,
210                        value: message.local_timestamp,
211                    },
212                    lamport_timestamp: clock::Lamport {
213                        replica_id: message.replica_id as ReplicaId,
214                        value: message.lamport_timestamp,
215                    },
216                    selections: Arc::from(selections),
217                })
218            }
219            proto::operation::Variant::RemoveSelections(message) => {
220                Operation::Buffer(buffer::Operation::RemoveSelections {
221                    set_id: clock::Lamport {
222                        replica_id: message.replica_id as ReplicaId,
223                        value: message.local_timestamp,
224                    },
225                    lamport_timestamp: clock::Lamport {
226                        replica_id: message.replica_id as ReplicaId,
227                        value: message.lamport_timestamp,
228                    },
229                })
230            }
231            proto::operation::Variant::SetActiveSelections(message) => {
232                Operation::Buffer(buffer::Operation::SetActiveSelections {
233                    set_id: message.local_timestamp.map(|value| clock::Lamport {
234                        replica_id: message.replica_id as ReplicaId,
235                        value,
236                    }),
237                    lamport_timestamp: clock::Lamport {
238                        replica_id: message.replica_id as ReplicaId,
239                        value: message.lamport_timestamp,
240                    },
241                })
242            }
243            proto::operation::Variant::UpdateDiagnostics(message) => {
244                Operation::UpdateDiagnostics(deserialize_diagnostics(message))
245            }
246        },
247    )
248}
249
250pub fn deserialize_edit_operation(edit: proto::operation::Edit) -> EditOperation {
251    let ranges = edit
252        .ranges
253        .into_iter()
254        .map(|range| FullOffset(range.start as usize)..FullOffset(range.end as usize))
255        .collect();
256    EditOperation {
257        timestamp: InsertionTimestamp {
258            replica_id: edit.replica_id as ReplicaId,
259            local: edit.local_timestamp,
260            lamport: edit.lamport_timestamp,
261        },
262        version: edit.version.into(),
263        ranges,
264        new_text: edit.new_text,
265    }
266}
267
268pub fn deserialize_selection_set(set: proto::SelectionSet) -> SelectionSet {
269    SelectionSet {
270        id: clock::Lamport {
271            replica_id: set.replica_id as u16,
272            value: set.lamport_timestamp,
273        },
274        active: set.is_active,
275        selections: Arc::new(AnchorRangeMap::from_full_offset_ranges(
276            set.version.into(),
277            set.selections
278                .into_iter()
279                .map(|selection| {
280                    let range = (FullOffset(selection.start as usize), Bias::Left)
281                        ..(FullOffset(selection.end as usize), Bias::Right);
282                    let state = SelectionState {
283                        id: selection.id as usize,
284                        reversed: selection.reversed,
285                        goal: SelectionGoal::None,
286                    };
287                    (range, state)
288                })
289                .collect(),
290        )),
291    }
292}
293
294pub fn deserialize_diagnostics(message: proto::DiagnosticSet) -> AnchorRangeMultimap<Diagnostic> {
295    AnchorRangeMultimap::from_full_offset_ranges(
296        message.version.into(),
297        Bias::Left,
298        Bias::Right,
299        message.diagnostics.into_iter().filter_map(|diagnostic| {
300            Some((
301                FullOffset(diagnostic.start as usize)..FullOffset(diagnostic.end as usize),
302                Diagnostic {
303                    severity: match proto::diagnostic::Severity::from_i32(diagnostic.severity)? {
304                        proto::diagnostic::Severity::Error => DiagnosticSeverity::ERROR,
305                        proto::diagnostic::Severity::Warning => DiagnosticSeverity::WARNING,
306                        proto::diagnostic::Severity::Information => DiagnosticSeverity::INFORMATION,
307                        proto::diagnostic::Severity::Hint => DiagnosticSeverity::HINT,
308                        proto::diagnostic::Severity::None => return None,
309                    },
310                    message: diagnostic.message,
311                },
312            ))
313        }),
314    )
315}