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 + vtable_size as usize + table_size as usize
42 + device_id_size + session_id_size + service_size + event_name_size + payload_size + 16;
43 let mut buf = Vec::with_capacity(estimated);
44
45 buf.extend_from_slice(&[0u8; 4]);
47
48 let vtable_start = buf.len();
50 write_u16(&mut buf, vtable_size);
51 write_u16(&mut buf, table_size);
52
53 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();
65 let soffset = (table_start - vtable_start) as i32;
66 write_i32(&mut buf, soffset);
67
68 let device_id_off_pos = buf.len();
70 write_u32(&mut buf, 0);
71
72 let session_id_off_pos = buf.len();
73 write_u32(&mut buf, 0);
74
75 let event_name_off_pos = buf.len();
76 write_u32(&mut buf, 0);
77
78 let payload_off_pos = buf.len();
79 write_u32(&mut buf, 0);
80
81 write_u64(&mut buf, params.timestamp);
83
84 buf.push(params.event_type.as_u8());
86
87 buf.extend_from_slice(&[0u8; 3]);
89
90 let service_off_pos = buf.len();
92 write_u32(&mut buf, 0);
93
94 align4(&mut buf);
96
97 let device_id_start = params.device_id.map(|id| write_byte_vector(&mut buf, id));
99 align4(&mut buf);
100
101 let session_id_start = params.session_id.map(|id| write_byte_vector(&mut buf, id));
103 align4(&mut buf);
104
105 let service_start = params.service.map(|s| write_string(&mut buf, s));
107 align4(&mut buf);
108
109 let event_name_start = params.event_name.map(|name| write_string(&mut buf, name));
111 align4(&mut buf);
112
113 let payload_start = params.payload.map(|data| write_byte_vector(&mut buf, data));
115
116 buf[0..4].copy_from_slice(&(table_start as u32).to_le_bytes());
118
119 if let Some(start) = device_id_start {
120 patch_offset(&mut buf, device_id_off_pos, start);
121 }
122 if let Some(start) = session_id_start {
123 patch_offset(&mut buf, session_id_off_pos, start);
124 }
125 if let Some(start) = service_start {
126 patch_offset(&mut buf, service_off_pos, start);
127 }
128 if let Some(start) = event_name_start {
129 patch_offset(&mut buf, event_name_off_pos, start);
130 }
131 if let Some(start) = payload_start {
132 patch_offset(&mut buf, payload_off_pos, start);
133 }
134
135 buf
136}
137
138pub fn encode_event_data(encoded_events: &[Vec<u8>]) -> Vec<u8> {
146 let vtable_size: u16 = 4 + 2;
148 let table_size: u16 = 8; let events_total: usize = encoded_events.iter().map(|e| e.len() + 4).sum();
151 let estimated = 4 + vtable_size as usize + table_size as usize + 4 + events_total + 64;
152 let mut buf = Vec::with_capacity(estimated);
153
154 buf.extend_from_slice(&[0u8; 4]);
156
157 let vtable_start = buf.len();
159 write_u16(&mut buf, vtable_size);
160 write_u16(&mut buf, table_size);
161 write_u16(&mut buf, 4); buf.extend_from_slice(&[0u8; 2]);
165
166 let table_start = buf.len();
168 let soffset = (table_start - vtable_start) as i32;
169 write_i32(&mut buf, soffset);
170
171 let events_off_pos = buf.len();
172 write_u32(&mut buf, 0);
173
174 align4(&mut buf);
175
176 let events_vec_start = buf.len();
178 let count = encoded_events.len();
179
180 write_u32(&mut buf, count as u32);
182
183 let offsets_start = buf.len();
185 for _ in 0..count {
186 write_u32(&mut buf, 0);
187 }
188
189 align4(&mut buf);
190
191 let mut table_positions = Vec::with_capacity(count);
193 for event_bytes in encoded_events {
194 align4(&mut buf);
195
196 let event_start = buf.len();
197
198 let root_offset = if event_bytes.len() >= 4 {
200 u32::from_le_bytes([event_bytes[0], event_bytes[1], event_bytes[2], event_bytes[3]])
201 as usize
202 } else {
203 0
204 };
205
206 table_positions.push(event_start + root_offset);
207 buf.extend_from_slice(event_bytes);
208 }
209
210 for (i, &table_pos) in table_positions.iter().enumerate() {
212 let offset_pos = offsets_start + i * 4;
213 patch_offset(&mut buf, offset_pos, table_pos);
214 }
215
216 patch_offset(&mut buf, events_off_pos, events_vec_start);
218
219 buf[0..4].copy_from_slice(&(table_start as u32).to_le_bytes());
221
222 buf
223}
224
225pub fn encode_event_data_into(buf: &mut Vec<u8>, events: &[EventParams<'_>]) -> std::ops::Range<usize> {
233 let data_start = buf.len();
234 let count = events.len();
235
236 let root_pos = buf.len();
244 buf.extend_from_slice(&[0u8; 4]);
245
246 let vtable_start = buf.len();
247 write_u16(buf, 6); write_u16(buf, 8); write_u16(buf, 4); buf.extend_from_slice(&[0u8; 2]); let table_start = buf.len();
253 write_i32(buf, (table_start - vtable_start) as i32);
254
255 let events_off_pos = buf.len();
256 write_u32(buf, 0);
257
258 align4(buf);
259
260 let events_vec_start = buf.len();
261 write_u32(buf, count as u32);
262
263 let offsets_start = buf.len();
264 for _ in 0..count {
265 write_u32(buf, 0);
266 }
267
268 align4(buf);
269
270 let mut table_positions = Vec::with_capacity(count);
272 for params in events {
273 align4(buf);
274 let event_start = buf.len();
275 encode_event_into(buf, params);
276 let root_offset = u32::from_le_bytes([
277 buf[event_start],
278 buf[event_start + 1],
279 buf[event_start + 2],
280 buf[event_start + 3],
281 ]) as usize;
282 table_positions.push(event_start + root_offset);
283 }
284
285 for (i, &table_pos) in table_positions.iter().enumerate() {
287 patch_offset(buf, offsets_start + i * 4, table_pos);
288 }
289
290 patch_offset(buf, events_off_pos, events_vec_start);
291 buf[root_pos..root_pos + 4].copy_from_slice(&((table_start - data_start) as u32).to_le_bytes());
292
293 data_start..buf.len()
294}
295
296fn encode_event_into(buf: &mut Vec<u8>, params: &EventParams<'_>) {
298 let has_device_id = params.device_id.is_some();
299 let has_session_id = params.session_id.is_some();
300 let has_service = params.service.is_some();
301 let has_event_name = params.event_name.is_some();
302 let has_payload = params.payload.is_some();
303
304 let vtable_size: u16 = 4 + 7 * 2;
305 let table_size: u16 = 4 + 32;
306
307 let root_pos = buf.len();
309 buf.extend_from_slice(&[0u8; 4]);
310
311 let vtable_start = buf.len();
313 write_u16(buf, vtable_size);
314 write_u16(buf, table_size);
315
316 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();
327 let soffset = (table_start - vtable_start) as i32;
328 write_i32(buf, soffset);
329
330 let device_id_off_pos = buf.len();
331 write_u32(buf, 0);
332 let session_id_off_pos = buf.len();
333 write_u32(buf, 0);
334 let event_name_off_pos = buf.len();
335 write_u32(buf, 0);
336 let payload_off_pos = buf.len();
337 write_u32(buf, 0);
338
339 write_u64(buf, params.timestamp);
340 buf.push(params.event_type.as_u8());
341 buf.extend_from_slice(&[0u8; 3]);
342
343 let service_off_pos = buf.len();
344 write_u32(buf, 0);
345
346 align4(buf);
347
348 let device_id_start = params.device_id.map(|id| write_byte_vector(buf, id));
349 align4(buf);
350 let session_id_start = params.session_id.map(|id| write_byte_vector(buf, id));
351 align4(buf);
352 let service_start = params.service.map(|s| write_string(buf, s));
353 align4(buf);
354 let event_name_start = params.event_name.map(|name| write_string(buf, name));
355 align4(buf);
356 let payload_start = params.payload.map(|data| write_byte_vector(buf, data));
357
358 buf[root_pos..root_pos + 4].copy_from_slice(&((table_start - root_pos) as u32).to_le_bytes());
360
361 if let Some(start) = device_id_start {
362 patch_offset(buf, device_id_off_pos, start);
363 }
364 if let Some(start) = session_id_start {
365 patch_offset(buf, session_id_off_pos, start);
366 }
367 if let Some(start) = service_start {
368 patch_offset(buf, service_off_pos, start);
369 }
370 if let Some(start) = event_name_start {
371 patch_offset(buf, event_name_off_pos, start);
372 }
373 if let Some(start) = payload_start {
374 patch_offset(buf, payload_off_pos, start);
375 }
376}