1use crate::helpers::*;
2use crate::{EventParams, UUID_LENGTH};
3
4pub fn encode_event(params: &EventParams<'_>) -> Vec<u8> {
15 let has_device_id = params.device_id.is_some();
16 let has_session_id = params.session_id.is_some();
17 let has_service = params.service.is_some();
18 let has_event_name = params.event_name.is_some();
19 let has_payload = params.payload.is_some();
20
21 let vtable_size: u16 = 4 + 7 * 2;
23
24 let table_size: u16 = 4 + 32;
34
35 let device_id_size = if has_device_id { 4 + UUID_LENGTH } else { 0 };
36 let session_id_size = if has_session_id { 4 + UUID_LENGTH } else { 0 };
37 let service_size = params.service.map(|s| 4 + s.len() + 1).unwrap_or(0);
38 let event_name_size = params.event_name.map(|s| 4 + s.len() + 1).unwrap_or(0);
39 let payload_size = params.payload.map(|p| 4 + p.len()).unwrap_or(0);
40
41 let estimated = 4
42 + vtable_size as usize
43 + table_size as usize
44 + device_id_size
45 + session_id_size
46 + service_size
47 + event_name_size
48 + payload_size
49 + 16;
50 let mut buf = Vec::with_capacity(estimated);
51
52 buf.extend_from_slice(&[0u8; 4]);
54
55 let vtable_start = buf.len();
57 write_u16(&mut buf, vtable_size);
58 write_u16(&mut buf, table_size);
59
60 write_u16(&mut buf, 28); write_u16(&mut buf, 20); write_u16(&mut buf, if has_service { 32 } else { 0 }); write_u16(&mut buf, if has_device_id { 4 } else { 0 }); write_u16(&mut buf, if has_session_id { 8 } else { 0 }); write_u16(&mut buf, if has_event_name { 12 } else { 0 }); write_u16(&mut buf, if has_payload { 16 } else { 0 }); buf.extend_from_slice(&[0u8; 2]); let table_start = buf.len();
72 let soffset = (table_start - vtable_start) as i32;
73 write_i32(&mut buf, soffset);
74
75 let device_id_off_pos = buf.len();
77 write_u32(&mut buf, 0);
78
79 let session_id_off_pos = buf.len();
80 write_u32(&mut buf, 0);
81
82 let event_name_off_pos = buf.len();
83 write_u32(&mut buf, 0);
84
85 let payload_off_pos = buf.len();
86 write_u32(&mut buf, 0);
87
88 write_u64(&mut buf, params.timestamp);
90
91 buf.push(params.event_type.as_u8());
93
94 buf.extend_from_slice(&[0u8; 3]);
96
97 let service_off_pos = buf.len();
99 write_u32(&mut buf, 0);
100
101 align4(&mut buf);
103
104 let device_id_start = params.device_id.map(|id| write_byte_vector(&mut buf, id));
106 align4(&mut buf);
107
108 let session_id_start = params.session_id.map(|id| write_byte_vector(&mut buf, id));
110 align4(&mut buf);
111
112 let service_start = params.service.map(|s| write_string(&mut buf, s));
114 align4(&mut buf);
115
116 let event_name_start = params.event_name.map(|name| write_string(&mut buf, name));
118 align4(&mut buf);
119
120 let payload_start = params.payload.map(|data| write_byte_vector(&mut buf, data));
122
123 buf[0..4].copy_from_slice(&(table_start as u32).to_le_bytes());
125
126 if let Some(start) = device_id_start {
127 patch_offset(&mut buf, device_id_off_pos, start);
128 }
129 if let Some(start) = session_id_start {
130 patch_offset(&mut buf, session_id_off_pos, start);
131 }
132 if let Some(start) = service_start {
133 patch_offset(&mut buf, service_off_pos, start);
134 }
135 if let Some(start) = event_name_start {
136 patch_offset(&mut buf, event_name_off_pos, start);
137 }
138 if let Some(start) = payload_start {
139 patch_offset(&mut buf, payload_off_pos, start);
140 }
141
142 buf
143}
144
145pub fn encode_event_data(encoded_events: &[Vec<u8>]) -> Vec<u8> {
153 let vtable_size: u16 = 4 + 2;
155 let table_size: u16 = 8; let events_total: usize = encoded_events.iter().map(|e| e.len() + 4).sum();
158 let estimated = 4 + vtable_size as usize + table_size as usize + 4 + events_total + 64;
159 let mut buf = Vec::with_capacity(estimated);
160
161 buf.extend_from_slice(&[0u8; 4]);
163
164 let vtable_start = buf.len();
166 write_u16(&mut buf, vtable_size);
167 write_u16(&mut buf, table_size);
168 write_u16(&mut buf, 4); buf.extend_from_slice(&[0u8; 2]);
172
173 let table_start = buf.len();
175 let soffset = (table_start - vtable_start) as i32;
176 write_i32(&mut buf, soffset);
177
178 let events_off_pos = buf.len();
179 write_u32(&mut buf, 0);
180
181 align4(&mut buf);
182
183 let events_vec_start = buf.len();
185 let count = encoded_events.len();
186
187 write_u32(&mut buf, count as u32);
189
190 let offsets_start = buf.len();
192 for _ in 0..count {
193 write_u32(&mut buf, 0);
194 }
195
196 align4(&mut buf);
197
198 let mut table_positions = Vec::with_capacity(count);
200 for event_bytes in encoded_events {
201 align4(&mut buf);
202
203 let event_start = buf.len();
204
205 let root_offset = if event_bytes.len() >= 4 {
207 u32::from_le_bytes([
208 event_bytes[0],
209 event_bytes[1],
210 event_bytes[2],
211 event_bytes[3],
212 ]) as usize
213 } else {
214 0
215 };
216
217 table_positions.push(event_start + root_offset);
218 buf.extend_from_slice(event_bytes);
219 }
220
221 for (i, &table_pos) in table_positions.iter().enumerate() {
223 let offset_pos = offsets_start + i * 4;
224 patch_offset(&mut buf, offset_pos, table_pos);
225 }
226
227 patch_offset(&mut buf, events_off_pos, events_vec_start);
229
230 buf[0..4].copy_from_slice(&(table_start as u32).to_le_bytes());
232
233 buf
234}
235
236pub fn encode_event_data_into(
244 buf: &mut Vec<u8>,
245 events: &[EventParams<'_>],
246) -> std::ops::Range<usize> {
247 let data_start = buf.len();
248 let count = events.len();
249
250 let root_pos = buf.len();
258 buf.extend_from_slice(&[0u8; 4]);
259
260 let vtable_start = buf.len();
261 write_u16(buf, 6); write_u16(buf, 8); write_u16(buf, 4); buf.extend_from_slice(&[0u8; 2]); let table_start = buf.len();
267 write_i32(buf, (table_start - vtable_start) as i32);
268
269 let events_off_pos = buf.len();
270 write_u32(buf, 0);
271
272 align4(buf);
273
274 let events_vec_start = buf.len();
275 write_u32(buf, count as u32);
276
277 let offsets_start = buf.len();
278 for _ in 0..count {
279 write_u32(buf, 0);
280 }
281
282 align4(buf);
283
284 let mut table_positions = Vec::with_capacity(count);
286 for params in events {
287 align4(buf);
288 let event_start = buf.len();
289 encode_event_into(buf, params);
290 let root_offset = u32::from_le_bytes([
291 buf[event_start],
292 buf[event_start + 1],
293 buf[event_start + 2],
294 buf[event_start + 3],
295 ]) as usize;
296 table_positions.push(event_start + root_offset);
297 }
298
299 for (i, &table_pos) in table_positions.iter().enumerate() {
301 patch_offset(buf, offsets_start + i * 4, table_pos);
302 }
303
304 patch_offset(buf, events_off_pos, events_vec_start);
305 buf[root_pos..root_pos + 4].copy_from_slice(&((table_start - data_start) as u32).to_le_bytes());
306
307 data_start..buf.len()
308}
309
310fn encode_event_into(buf: &mut Vec<u8>, params: &EventParams<'_>) {
312 let has_device_id = params.device_id.is_some();
313 let has_session_id = params.session_id.is_some();
314 let has_service = params.service.is_some();
315 let has_event_name = params.event_name.is_some();
316 let has_payload = params.payload.is_some();
317
318 let vtable_size: u16 = 4 + 7 * 2;
319 let table_size: u16 = 4 + 32;
320
321 let root_pos = buf.len();
323 buf.extend_from_slice(&[0u8; 4]);
324
325 let vtable_start = buf.len();
327 write_u16(buf, vtable_size);
328 write_u16(buf, table_size);
329
330 write_u16(buf, 28); write_u16(buf, 20); write_u16(buf, if has_service { 32 } else { 0 }); write_u16(buf, if has_device_id { 4 } else { 0 }); write_u16(buf, if has_session_id { 8 } else { 0 }); write_u16(buf, if has_event_name { 12 } else { 0 }); write_u16(buf, if has_payload { 16 } else { 0 }); buf.extend_from_slice(&[0u8; 2]); let table_start = buf.len();
341 let soffset = (table_start - vtable_start) as i32;
342 write_i32(buf, soffset);
343
344 let device_id_off_pos = buf.len();
345 write_u32(buf, 0);
346 let session_id_off_pos = buf.len();
347 write_u32(buf, 0);
348 let event_name_off_pos = buf.len();
349 write_u32(buf, 0);
350 let payload_off_pos = buf.len();
351 write_u32(buf, 0);
352
353 write_u64(buf, params.timestamp);
354 buf.push(params.event_type.as_u8());
355 buf.extend_from_slice(&[0u8; 3]);
356
357 let service_off_pos = buf.len();
358 write_u32(buf, 0);
359
360 align4(buf);
361
362 let device_id_start = params.device_id.map(|id| write_byte_vector(buf, id));
363 align4(buf);
364 let session_id_start = params.session_id.map(|id| write_byte_vector(buf, id));
365 align4(buf);
366 let service_start = params.service.map(|s| write_string(buf, s));
367 align4(buf);
368 let event_name_start = params.event_name.map(|name| write_string(buf, name));
369 align4(buf);
370 let payload_start = params.payload.map(|data| write_byte_vector(buf, data));
371
372 buf[root_pos..root_pos + 4].copy_from_slice(&((table_start - root_pos) as u32).to_le_bytes());
374
375 if let Some(start) = device_id_start {
376 patch_offset(buf, device_id_off_pos, start);
377 }
378 if let Some(start) = session_id_start {
379 patch_offset(buf, session_id_off_pos, start);
380 }
381 if let Some(start) = service_start {
382 patch_offset(buf, service_off_pos, start);
383 }
384 if let Some(start) = event_name_start {
385 patch_offset(buf, event_name_off_pos, start);
386 }
387 if let Some(start) = payload_start {
388 patch_offset(buf, payload_off_pos, start);
389 }
390}