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}