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::Left);
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}