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}