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                is_primary: diagnostic.is_primary,
146            })
147            .collect(),
148    }
149}
150
151pub fn deserialize_operation(message: proto::Operation) -> Result<Operation> {
152    Ok(
153        match message
154            .variant
155            .ok_or_else(|| anyhow!("missing operation variant"))?
156        {
157            proto::operation::Variant::Edit(edit) => {
158                Operation::Buffer(buffer::Operation::Edit(deserialize_edit_operation(edit)))
159            }
160            proto::operation::Variant::Undo(undo) => Operation::Buffer(buffer::Operation::Undo {
161                lamport_timestamp: clock::Lamport {
162                    replica_id: undo.replica_id as ReplicaId,
163                    value: undo.lamport_timestamp,
164                },
165                undo: UndoOperation {
166                    id: clock::Local {
167                        replica_id: undo.replica_id as ReplicaId,
168                        value: undo.local_timestamp,
169                    },
170                    counts: undo
171                        .counts
172                        .into_iter()
173                        .map(|c| {
174                            (
175                                clock::Local {
176                                    replica_id: c.replica_id as ReplicaId,
177                                    value: c.local_timestamp,
178                                },
179                                c.count,
180                            )
181                        })
182                        .collect(),
183                    ranges: undo
184                        .ranges
185                        .into_iter()
186                        .map(|r| FullOffset(r.start as usize)..FullOffset(r.end as usize))
187                        .collect(),
188                    version: undo.version.into(),
189                },
190            }),
191            proto::operation::Variant::UpdateSelections(message) => {
192                let version = message.version.into();
193                let entries = message
194                    .selections
195                    .iter()
196                    .map(|selection| {
197                        let range = (FullOffset(selection.start as usize), Bias::Left)
198                            ..(FullOffset(selection.end as usize), Bias::Right);
199                        let state = SelectionState {
200                            id: selection.id as usize,
201                            reversed: selection.reversed,
202                            goal: SelectionGoal::None,
203                        };
204                        (range, state)
205                    })
206                    .collect();
207                let selections = AnchorRangeMap::from_full_offset_ranges(version, entries);
208
209                Operation::Buffer(buffer::Operation::UpdateSelections {
210                    set_id: clock::Lamport {
211                        replica_id: message.replica_id as ReplicaId,
212                        value: message.local_timestamp,
213                    },
214                    lamport_timestamp: clock::Lamport {
215                        replica_id: message.replica_id as ReplicaId,
216                        value: message.lamport_timestamp,
217                    },
218                    selections: Arc::from(selections),
219                })
220            }
221            proto::operation::Variant::RemoveSelections(message) => {
222                Operation::Buffer(buffer::Operation::RemoveSelections {
223                    set_id: clock::Lamport {
224                        replica_id: message.replica_id as ReplicaId,
225                        value: message.local_timestamp,
226                    },
227                    lamport_timestamp: clock::Lamport {
228                        replica_id: message.replica_id as ReplicaId,
229                        value: message.lamport_timestamp,
230                    },
231                })
232            }
233            proto::operation::Variant::SetActiveSelections(message) => {
234                Operation::Buffer(buffer::Operation::SetActiveSelections {
235                    set_id: message.local_timestamp.map(|value| clock::Lamport {
236                        replica_id: message.replica_id as ReplicaId,
237                        value,
238                    }),
239                    lamport_timestamp: clock::Lamport {
240                        replica_id: message.replica_id as ReplicaId,
241                        value: message.lamport_timestamp,
242                    },
243                })
244            }
245            proto::operation::Variant::UpdateDiagnostics(message) => {
246                Operation::UpdateDiagnostics(deserialize_diagnostics(message))
247            }
248        },
249    )
250}
251
252pub fn deserialize_edit_operation(edit: proto::operation::Edit) -> EditOperation {
253    let ranges = edit
254        .ranges
255        .into_iter()
256        .map(|range| FullOffset(range.start as usize)..FullOffset(range.end as usize))
257        .collect();
258    EditOperation {
259        timestamp: InsertionTimestamp {
260            replica_id: edit.replica_id as ReplicaId,
261            local: edit.local_timestamp,
262            lamport: edit.lamport_timestamp,
263        },
264        version: edit.version.into(),
265        ranges,
266        new_text: edit.new_text,
267    }
268}
269
270pub fn deserialize_selection_set(set: proto::SelectionSet) -> SelectionSet {
271    SelectionSet {
272        id: clock::Lamport {
273            replica_id: set.replica_id as u16,
274            value: set.lamport_timestamp,
275        },
276        active: set.is_active,
277        selections: Arc::new(AnchorRangeMap::from_full_offset_ranges(
278            set.version.into(),
279            set.selections
280                .into_iter()
281                .map(|selection| {
282                    let range = (FullOffset(selection.start as usize), Bias::Left)
283                        ..(FullOffset(selection.end as usize), Bias::Right);
284                    let state = SelectionState {
285                        id: selection.id as usize,
286                        reversed: selection.reversed,
287                        goal: SelectionGoal::None,
288                    };
289                    (range, state)
290                })
291                .collect(),
292        )),
293    }
294}
295
296pub fn deserialize_diagnostics(message: proto::DiagnosticSet) -> AnchorRangeMultimap<Diagnostic> {
297    AnchorRangeMultimap::from_full_offset_ranges(
298        message.version.into(),
299        Bias::Left,
300        Bias::Right,
301        message.diagnostics.into_iter().filter_map(|diagnostic| {
302            Some((
303                FullOffset(diagnostic.start as usize)..FullOffset(diagnostic.end as usize),
304                Diagnostic {
305                    severity: match proto::diagnostic::Severity::from_i32(diagnostic.severity)? {
306                        proto::diagnostic::Severity::Error => DiagnosticSeverity::ERROR,
307                        proto::diagnostic::Severity::Warning => DiagnosticSeverity::WARNING,
308                        proto::diagnostic::Severity::Information => DiagnosticSeverity::INFORMATION,
309                        proto::diagnostic::Severity::Hint => DiagnosticSeverity::HINT,
310                        proto::diagnostic::Severity::None => return None,
311                    },
312                    message: diagnostic.message,
313                    group_id: diagnostic.group_id as usize,
314                    is_primary: diagnostic.is_primary,
315                },
316            ))
317        }),
318    )
319}