1use crate::{diagnostic_set::DiagnosticEntry, Diagnostic, Operation};
2use anyhow::{anyhow, Result};
3use clock::ReplicaId;
4use lsp::DiagnosticSeverity;
5use rpc::proto;
6use std::sync::Arc;
7use text::*;
8
9pub use proto::{Buffer, SelectionSet};
10
11pub fn serialize_operation(operation: &Operation) -> proto::Operation {
12 proto::Operation {
13 variant: Some(match operation {
14 Operation::Buffer(text::Operation::Edit(edit)) => {
15 proto::operation::Variant::Edit(serialize_edit_operation(edit))
16 }
17 Operation::Buffer(text::Operation::Undo {
18 undo,
19 lamport_timestamp,
20 }) => proto::operation::Variant::Undo(proto::operation::Undo {
21 replica_id: undo.id.replica_id as u32,
22 local_timestamp: undo.id.value,
23 lamport_timestamp: lamport_timestamp.value,
24 ranges: undo
25 .ranges
26 .iter()
27 .map(|r| proto::Range {
28 start: r.start.0 as u64,
29 end: r.end.0 as u64,
30 })
31 .collect(),
32 counts: undo
33 .counts
34 .iter()
35 .map(|(edit_id, count)| proto::operation::UndoCount {
36 replica_id: edit_id.replica_id as u32,
37 local_timestamp: edit_id.value,
38 count: *count,
39 })
40 .collect(),
41 version: From::from(&undo.version),
42 }),
43 Operation::UpdateSelections {
44 replica_id,
45 selections,
46 lamport_timestamp,
47 } => proto::operation::Variant::UpdateSelections(proto::operation::UpdateSelections {
48 replica_id: *replica_id as u32,
49 lamport_timestamp: lamport_timestamp.value,
50 selections: serialize_selections(selections),
51 }),
52 Operation::RemoveSelections {
53 replica_id,
54 lamport_timestamp,
55 } => proto::operation::Variant::RemoveSelections(proto::operation::RemoveSelections {
56 replica_id: *replica_id as u32,
57 lamport_timestamp: lamport_timestamp.value,
58 }),
59 Operation::UpdateDiagnostics {
60 diagnostics,
61 lamport_timestamp,
62 } => proto::operation::Variant::UpdateDiagnostics(proto::UpdateDiagnostics {
63 replica_id: lamport_timestamp.replica_id as u32,
64 lamport_timestamp: lamport_timestamp.value,
65 diagnostics: serialize_diagnostics(diagnostics.iter()),
66 }),
67 }),
68 }
69}
70
71pub fn serialize_edit_operation(operation: &EditOperation) -> proto::operation::Edit {
72 let ranges = operation
73 .ranges
74 .iter()
75 .map(|range| proto::Range {
76 start: range.start.0 as u64,
77 end: range.end.0 as u64,
78 })
79 .collect();
80 proto::operation::Edit {
81 replica_id: operation.timestamp.replica_id as u32,
82 local_timestamp: operation.timestamp.local,
83 lamport_timestamp: operation.timestamp.lamport,
84 version: From::from(&operation.version),
85 ranges,
86 new_text: operation.new_text.clone(),
87 }
88}
89
90pub fn serialize_selections(selections: &Arc<[Selection<Anchor>]>) -> Vec<proto::Selection> {
91 selections
92 .iter()
93 .map(|selection| proto::Selection {
94 id: selection.id as u64,
95 start: Some(serialize_anchor(&selection.start)),
96 end: Some(serialize_anchor(&selection.end)),
97 reversed: selection.reversed,
98 })
99 .collect()
100}
101
102pub fn serialize_diagnostics<'a>(
103 diagnostics: impl IntoIterator<Item = &'a DiagnosticEntry<Anchor>>,
104) -> Vec<proto::Diagnostic> {
105 diagnostics
106 .into_iter()
107 .map(|entry| proto::Diagnostic {
108 start: Some(serialize_anchor(&entry.range.start)),
109 end: Some(serialize_anchor(&entry.range.end)),
110 message: entry.diagnostic.message.clone(),
111 severity: match entry.diagnostic.severity {
112 DiagnosticSeverity::ERROR => proto::diagnostic::Severity::Error,
113 DiagnosticSeverity::WARNING => proto::diagnostic::Severity::Warning,
114 DiagnosticSeverity::INFORMATION => proto::diagnostic::Severity::Information,
115 DiagnosticSeverity::HINT => proto::diagnostic::Severity::Hint,
116 _ => proto::diagnostic::Severity::None,
117 } as i32,
118 group_id: entry.diagnostic.group_id as u64,
119 is_primary: entry.diagnostic.is_primary,
120 is_valid: entry.diagnostic.is_valid,
121 code: entry.diagnostic.code.clone(),
122 source: entry.diagnostic.source.clone(),
123 })
124 .collect()
125}
126
127fn serialize_anchor(anchor: &Anchor) -> proto::Anchor {
128 proto::Anchor {
129 replica_id: anchor.timestamp.replica_id as u32,
130 local_timestamp: anchor.timestamp.value,
131 offset: anchor.offset as u64,
132 bias: match anchor.bias {
133 Bias::Left => proto::Bias::Left as i32,
134 Bias::Right => proto::Bias::Right as i32,
135 },
136 }
137}
138
139pub fn deserialize_operation(message: proto::Operation) -> Result<Operation> {
140 Ok(
141 match message
142 .variant
143 .ok_or_else(|| anyhow!("missing operation variant"))?
144 {
145 proto::operation::Variant::Edit(edit) => {
146 Operation::Buffer(text::Operation::Edit(deserialize_edit_operation(edit)))
147 }
148 proto::operation::Variant::Undo(undo) => Operation::Buffer(text::Operation::Undo {
149 lamport_timestamp: clock::Lamport {
150 replica_id: undo.replica_id as ReplicaId,
151 value: undo.lamport_timestamp,
152 },
153 undo: UndoOperation {
154 id: clock::Local {
155 replica_id: undo.replica_id as ReplicaId,
156 value: undo.local_timestamp,
157 },
158 counts: undo
159 .counts
160 .into_iter()
161 .map(|c| {
162 (
163 clock::Local {
164 replica_id: c.replica_id as ReplicaId,
165 value: c.local_timestamp,
166 },
167 c.count,
168 )
169 })
170 .collect(),
171 ranges: undo
172 .ranges
173 .into_iter()
174 .map(|r| FullOffset(r.start as usize)..FullOffset(r.end as usize))
175 .collect(),
176 version: undo.version.into(),
177 },
178 }),
179 proto::operation::Variant::UpdateSelections(message) => {
180 let selections = message
181 .selections
182 .into_iter()
183 .filter_map(|selection| {
184 Some(Selection {
185 id: selection.id as usize,
186 start: deserialize_anchor(selection.start?)?,
187 end: deserialize_anchor(selection.end?)?,
188 reversed: selection.reversed,
189 goal: SelectionGoal::None,
190 })
191 })
192 .collect::<Vec<_>>();
193
194 Operation::UpdateSelections {
195 replica_id: message.replica_id as ReplicaId,
196 lamport_timestamp: clock::Lamport {
197 replica_id: message.replica_id as ReplicaId,
198 value: message.lamport_timestamp,
199 },
200 selections: Arc::from(selections),
201 }
202 }
203 proto::operation::Variant::RemoveSelections(message) => Operation::RemoveSelections {
204 replica_id: message.replica_id as ReplicaId,
205 lamport_timestamp: clock::Lamport {
206 replica_id: message.replica_id as ReplicaId,
207 value: message.lamport_timestamp,
208 },
209 },
210 proto::operation::Variant::UpdateDiagnostics(message) => Operation::UpdateDiagnostics {
211 diagnostics: Arc::from(deserialize_diagnostics(message.diagnostics)),
212 lamport_timestamp: clock::Lamport {
213 replica_id: message.replica_id as ReplicaId,
214 value: message.lamport_timestamp,
215 },
216 },
217 },
218 )
219}
220
221pub fn deserialize_edit_operation(edit: proto::operation::Edit) -> EditOperation {
222 let ranges = edit
223 .ranges
224 .into_iter()
225 .map(|range| FullOffset(range.start as usize)..FullOffset(range.end as usize))
226 .collect();
227 EditOperation {
228 timestamp: InsertionTimestamp {
229 replica_id: edit.replica_id as ReplicaId,
230 local: edit.local_timestamp,
231 lamport: edit.lamport_timestamp,
232 },
233 version: edit.version.into(),
234 ranges,
235 new_text: edit.new_text,
236 }
237}
238
239pub fn deserialize_selections(selections: Vec<proto::Selection>) -> Arc<[Selection<Anchor>]> {
240 Arc::from(
241 selections
242 .into_iter()
243 .filter_map(|selection| {
244 Some(Selection {
245 id: selection.id as usize,
246 start: deserialize_anchor(selection.start?)?,
247 end: deserialize_anchor(selection.end?)?,
248 reversed: selection.reversed,
249 goal: SelectionGoal::None,
250 })
251 })
252 .collect::<Vec<_>>(),
253 )
254}
255
256pub fn deserialize_diagnostics(
257 diagnostics: Vec<proto::Diagnostic>,
258) -> Vec<DiagnosticEntry<Anchor>> {
259 diagnostics
260 .into_iter()
261 .filter_map(|diagnostic| {
262 Some(DiagnosticEntry {
263 range: deserialize_anchor(diagnostic.start?)?..deserialize_anchor(diagnostic.end?)?,
264 diagnostic: Diagnostic {
265 severity: match proto::diagnostic::Severity::from_i32(diagnostic.severity)? {
266 proto::diagnostic::Severity::Error => DiagnosticSeverity::ERROR,
267 proto::diagnostic::Severity::Warning => DiagnosticSeverity::WARNING,
268 proto::diagnostic::Severity::Information => DiagnosticSeverity::INFORMATION,
269 proto::diagnostic::Severity::Hint => DiagnosticSeverity::HINT,
270 proto::diagnostic::Severity::None => return None,
271 },
272 message: diagnostic.message,
273 group_id: diagnostic.group_id as usize,
274 is_primary: diagnostic.is_primary,
275 code: diagnostic.code,
276 source: diagnostic.source,
277 is_valid: diagnostic.is_valid,
278 },
279 })
280 })
281 .collect()
282}
283
284fn deserialize_anchor(anchor: proto::Anchor) -> Option<Anchor> {
285 Some(Anchor {
286 timestamp: clock::Local {
287 replica_id: anchor.replica_id as ReplicaId,
288 value: anchor.local_timestamp,
289 },
290 offset: anchor.offset as usize,
291 bias: match proto::Bias::from_i32(anchor.bias)? {
292 proto::Bias::Left => Bias::Left,
293 proto::Bias::Right => Bias::Right,
294 },
295 })
296}