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