1use crate::helpers::*;
2use crate::{EventParams, UUID_LENGTH};
3
4pub fn encode_event(params: &EventParams<'_>) -> Vec<u8> {
14 let has_device_id = params.device_id.is_some();
15 let has_session_id = params.session_id.is_some();
16 let has_event_name = params.event_name.is_some();
17 let has_payload = params.payload.is_some();
18
19 let vtable_size: u16 = 4 + 6 * 2;
21
22 let table_size: u16 = 4 + 28;
31
32 let device_id_size = if has_device_id { 4 + UUID_LENGTH } else { 0 };
33 let session_id_size = if has_session_id { 4 + UUID_LENGTH } else { 0 };
34 let event_name_size = params.event_name.map(|s| 4 + s.len() + 1).unwrap_or(0);
35 let payload_size = params.payload.map(|p| 4 + p.len()).unwrap_or(0);
36
37 let estimated = 4 + vtable_size as usize + table_size as usize
38 + device_id_size + session_id_size + event_name_size + payload_size + 16;
39 let mut buf = Vec::with_capacity(estimated);
40
41 buf.extend_from_slice(&[0u8; 4]);
43
44 let vtable_start = buf.len();
46 write_u16(&mut buf, vtable_size);
47 write_u16(&mut buf, table_size);
48
49 write_u16(&mut buf, 28); write_u16(&mut buf, 20); 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 }); let table_start = buf.len();
59 let soffset = (table_start - vtable_start) as i32;
60 write_i32(&mut buf, soffset);
61
62 let device_id_off_pos = buf.len();
64 write_u32(&mut buf, 0);
65
66 let session_id_off_pos = buf.len();
67 write_u32(&mut buf, 0);
68
69 let event_name_off_pos = buf.len();
70 write_u32(&mut buf, 0);
71
72 let payload_off_pos = buf.len();
73 write_u32(&mut buf, 0);
74
75 write_u64(&mut buf, params.timestamp);
77
78 buf.push(params.event_type.as_u8());
80
81 buf.extend_from_slice(&[0u8; 3]);
83
84 align4(&mut buf);
86
87 let device_id_start = params.device_id.map(|id| write_byte_vector(&mut buf, id));
89 align4(&mut buf);
90
91 let session_id_start = params.session_id.map(|id| write_byte_vector(&mut buf, id));
93 align4(&mut buf);
94
95 let event_name_start = params.event_name.map(|name| write_string(&mut buf, name));
97 align4(&mut buf);
98
99 let payload_start = params.payload.map(|data| write_byte_vector(&mut buf, data));
101
102 buf[0..4].copy_from_slice(&(table_start as u32).to_le_bytes());
104
105 if let Some(start) = device_id_start {
106 patch_offset(&mut buf, device_id_off_pos, start);
107 }
108 if let Some(start) = session_id_start {
109 patch_offset(&mut buf, session_id_off_pos, start);
110 }
111 if let Some(start) = event_name_start {
112 patch_offset(&mut buf, event_name_off_pos, start);
113 }
114 if let Some(start) = payload_start {
115 patch_offset(&mut buf, payload_off_pos, start);
116 }
117
118 buf
119}
120
121pub fn encode_event_data(encoded_events: &[Vec<u8>]) -> Vec<u8> {
129 let vtable_size: u16 = 4 + 2;
131 let table_size: u16 = 8; let events_total: usize = encoded_events.iter().map(|e| e.len() + 4).sum();
134 let estimated = 4 + vtable_size as usize + table_size as usize + 4 + events_total + 64;
135 let mut buf = Vec::with_capacity(estimated);
136
137 buf.extend_from_slice(&[0u8; 4]);
139
140 let vtable_start = buf.len();
142 write_u16(&mut buf, vtable_size);
143 write_u16(&mut buf, table_size);
144 write_u16(&mut buf, 4); buf.extend_from_slice(&[0u8; 2]);
148
149 let table_start = buf.len();
151 let soffset = (table_start - vtable_start) as i32;
152 write_i32(&mut buf, soffset);
153
154 let events_off_pos = buf.len();
155 write_u32(&mut buf, 0);
156
157 align4(&mut buf);
158
159 let events_vec_start = buf.len();
161 let count = encoded_events.len();
162
163 write_u32(&mut buf, count as u32);
165
166 let offsets_start = buf.len();
168 for _ in 0..count {
169 write_u32(&mut buf, 0);
170 }
171
172 align4(&mut buf);
173
174 let mut table_positions = Vec::with_capacity(count);
176 for event_bytes in encoded_events {
177 align4(&mut buf);
178
179 let event_start = buf.len();
180
181 let root_offset = if event_bytes.len() >= 4 {
183 u32::from_le_bytes([event_bytes[0], event_bytes[1], event_bytes[2], event_bytes[3]])
184 as usize
185 } else {
186 0
187 };
188
189 table_positions.push(event_start + root_offset);
190 buf.extend_from_slice(event_bytes);
191 }
192
193 for (i, &table_pos) in table_positions.iter().enumerate() {
195 let offset_pos = offsets_start + i * 4;
196 patch_offset(&mut buf, offset_pos, table_pos);
197 }
198
199 patch_offset(&mut buf, events_off_pos, events_vec_start);
201
202 buf[0..4].copy_from_slice(&(table_start as u32).to_le_bytes());
204
205 buf
206}
207
208pub fn encode_event_data_into(buf: &mut Vec<u8>, events: &[EventParams<'_>]) -> std::ops::Range<usize> {
216 let data_start = buf.len();
217 let count = events.len();
218
219 let root_pos = buf.len();
227 buf.extend_from_slice(&[0u8; 4]);
228
229 let vtable_start = buf.len();
230 write_u16(buf, 6); write_u16(buf, 8); write_u16(buf, 4); buf.extend_from_slice(&[0u8; 2]); let table_start = buf.len();
236 write_i32(buf, (table_start - vtable_start) as i32);
237
238 let events_off_pos = buf.len();
239 write_u32(buf, 0);
240
241 align4(buf);
242
243 let events_vec_start = buf.len();
244 write_u32(buf, count as u32);
245
246 let offsets_start = buf.len();
247 for _ in 0..count {
248 write_u32(buf, 0);
249 }
250
251 align4(buf);
252
253 let mut table_positions = Vec::with_capacity(count);
255 for params in events {
256 align4(buf);
257 let event_start = buf.len();
258 encode_event_into(buf, params);
259 let root_offset = u32::from_le_bytes([
260 buf[event_start],
261 buf[event_start + 1],
262 buf[event_start + 2],
263 buf[event_start + 3],
264 ]) as usize;
265 table_positions.push(event_start + root_offset);
266 }
267
268 for (i, &table_pos) in table_positions.iter().enumerate() {
270 patch_offset(buf, offsets_start + i * 4, table_pos);
271 }
272
273 patch_offset(buf, events_off_pos, events_vec_start);
274 buf[root_pos..root_pos + 4].copy_from_slice(&((table_start - data_start) as u32).to_le_bytes());
275
276 data_start..buf.len()
277}
278
279fn encode_event_into(buf: &mut Vec<u8>, params: &EventParams<'_>) {
281 let has_device_id = params.device_id.is_some();
282 let has_session_id = params.session_id.is_some();
283 let has_event_name = params.event_name.is_some();
284 let has_payload = params.payload.is_some();
285
286 let vtable_size: u16 = 4 + 6 * 2;
287 let table_size: u16 = 4 + 28;
288
289 let root_pos = buf.len();
291 buf.extend_from_slice(&[0u8; 4]);
292
293 let vtable_start = buf.len();
295 write_u16(buf, vtable_size);
296 write_u16(buf, table_size);
297
298 write_u16(buf, 28);
299 write_u16(buf, 20);
300 write_u16(buf, if has_device_id { 4 } else { 0 });
301 write_u16(buf, if has_session_id { 8 } else { 0 });
302 write_u16(buf, if has_event_name { 12 } else { 0 });
303 write_u16(buf, if has_payload { 16 } else { 0 });
304
305 let table_start = buf.len();
307 let soffset = (table_start - vtable_start) as i32;
308 write_i32(buf, soffset);
309
310 let device_id_off_pos = buf.len();
311 write_u32(buf, 0);
312 let session_id_off_pos = buf.len();
313 write_u32(buf, 0);
314 let event_name_off_pos = buf.len();
315 write_u32(buf, 0);
316 let payload_off_pos = buf.len();
317 write_u32(buf, 0);
318
319 write_u64(buf, params.timestamp);
320 buf.push(params.event_type.as_u8());
321 buf.extend_from_slice(&[0u8; 3]);
322
323 align4(buf);
324
325 let device_id_start = params.device_id.map(|id| write_byte_vector(buf, id));
326 align4(buf);
327 let session_id_start = params.session_id.map(|id| write_byte_vector(buf, id));
328 align4(buf);
329 let event_name_start = params.event_name.map(|name| write_string(buf, name));
330 align4(buf);
331 let payload_start = params.payload.map(|data| write_byte_vector(buf, data));
332
333 buf[root_pos..root_pos + 4].copy_from_slice(&((table_start - root_pos) as u32).to_le_bytes());
335
336 if let Some(start) = device_id_start {
337 patch_offset(buf, device_id_off_pos, start);
338 }
339 if let Some(start) = session_id_start {
340 patch_offset(buf, session_id_off_pos, start);
341 }
342 if let Some(start) = event_name_start {
343 patch_offset(buf, event_name_off_pos, start);
344 }
345 if let Some(start) = payload_start {
346 patch_offset(buf, payload_off_pos, start);
347 }
348}