use crate::LogEntryParams;
use crate::UUID_LENGTH;
use crate::helpers::*;
pub fn encode_log_entry(params: &LogEntryParams<'_>) -> Vec<u8> {
let has_session_id = params.session_id.is_some();
let has_source = params.source.is_some();
let has_service = params.service.is_some();
let has_payload = params.payload.is_some();
let vtable_size: u16 = 4 + 7 * 2;
let table_size: u16 = 4 + 28;
let session_id_size = if has_session_id { 4 + UUID_LENGTH } else { 0 };
let source_size = params.source.map(|s| 4 + s.len() + 1).unwrap_or(0);
let service_size = params.service.map(|s| 4 + s.len() + 1).unwrap_or(0);
let payload_size = params.payload.map(|p| 4 + p.len()).unwrap_or(0);
let estimated = 4
+ vtable_size as usize
+ table_size as usize
+ session_id_size
+ source_size
+ service_size
+ payload_size
+ 16;
let mut buf = Vec::with_capacity(estimated);
buf.extend_from_slice(&[0u8; 4]);
let vtable_start = buf.len();
write_u16(&mut buf, vtable_size);
write_u16(&mut buf, table_size);
write_u16(&mut buf, 28); write_u16(&mut buf, if has_session_id { 4 } else { 0 }); write_u16(&mut buf, 29); write_u16(&mut buf, 20); write_u16(&mut buf, if has_source { 8 } else { 0 }); write_u16(&mut buf, if has_service { 12 } else { 0 }); write_u16(&mut buf, if has_payload { 16 } else { 0 });
buf.extend_from_slice(&[0u8; 2]);
let table_start = buf.len();
let soffset = (table_start - vtable_start) as i32;
write_i32(&mut buf, soffset);
let session_id_off_pos = buf.len();
write_u32(&mut buf, 0);
let source_off_pos = buf.len();
write_u32(&mut buf, 0);
let service_off_pos = buf.len();
write_u32(&mut buf, 0);
let payload_off_pos = buf.len();
write_u32(&mut buf, 0);
write_u64(&mut buf, params.timestamp);
buf.push(params.event_type.as_u8());
buf.push(params.level.as_u8());
buf.extend_from_slice(&[0u8; 2]);
align4(&mut buf);
let session_id_start = params.session_id.map(|id| write_byte_vector(&mut buf, id));
align4(&mut buf);
let source_start = params.source.map(|s| write_string(&mut buf, s));
align4(&mut buf);
let service_start = params.service.map(|s| write_string(&mut buf, s));
align4(&mut buf);
let payload_start = params.payload.map(|data| write_byte_vector(&mut buf, data));
buf[0..4].copy_from_slice(&(table_start as u32).to_le_bytes());
if let Some(start) = session_id_start {
patch_offset(&mut buf, session_id_off_pos, start);
}
if let Some(start) = source_start {
patch_offset(&mut buf, source_off_pos, start);
}
if let Some(start) = service_start {
patch_offset(&mut buf, service_off_pos, start);
}
if let Some(start) = payload_start {
patch_offset(&mut buf, payload_off_pos, start);
}
buf
}
pub fn encode_log_data(encoded_logs: &[Vec<u8>]) -> Vec<u8> {
let vtable_size: u16 = 4 + 2;
let table_size: u16 = 8;
let logs_total: usize = encoded_logs.iter().map(|l| l.len() + 4).sum();
let estimated = 4 + vtable_size as usize + table_size as usize + 4 + logs_total + 64;
let mut buf = Vec::with_capacity(estimated);
buf.extend_from_slice(&[0u8; 4]);
let vtable_start = buf.len();
write_u16(&mut buf, vtable_size);
write_u16(&mut buf, table_size);
write_u16(&mut buf, 4);
buf.extend_from_slice(&[0u8; 2]);
let table_start = buf.len();
let soffset = (table_start - vtable_start) as i32;
write_i32(&mut buf, soffset);
let logs_off_pos = buf.len();
write_u32(&mut buf, 0);
align4(&mut buf);
let logs_vec_start = buf.len();
let count = encoded_logs.len();
write_u32(&mut buf, count as u32);
let offsets_start = buf.len();
for _ in 0..count {
write_u32(&mut buf, 0);
}
align4(&mut buf);
let mut table_positions = Vec::with_capacity(count);
for log_bytes in encoded_logs {
align4(&mut buf);
let log_start = buf.len();
let root_offset = if log_bytes.len() >= 4 {
u32::from_le_bytes([log_bytes[0], log_bytes[1], log_bytes[2], log_bytes[3]]) as usize
} else {
0
};
table_positions.push(log_start + root_offset);
buf.extend_from_slice(log_bytes);
}
for (i, &table_pos) in table_positions.iter().enumerate() {
let offset_pos = offsets_start + i * 4;
patch_offset(&mut buf, offset_pos, table_pos);
}
patch_offset(&mut buf, logs_off_pos, logs_vec_start);
buf[0..4].copy_from_slice(&(table_start as u32).to_le_bytes());
buf
}
pub fn encode_log_data_into(
buf: &mut Vec<u8>,
logs: &[LogEntryParams<'_>],
) -> std::ops::Range<usize> {
let data_start = buf.len();
let count = logs.len();
let root_pos = buf.len();
buf.extend_from_slice(&[0u8; 4]);
let vtable_start = buf.len();
write_u16(buf, 6); write_u16(buf, 8); write_u16(buf, 4); buf.extend_from_slice(&[0u8; 2]);
let table_start = buf.len();
write_i32(buf, (table_start - vtable_start) as i32);
let logs_off_pos = buf.len();
write_u32(buf, 0);
align4(buf);
let logs_vec_start = buf.len();
write_u32(buf, count as u32);
let offsets_start = buf.len();
for _ in 0..count {
write_u32(buf, 0);
}
align4(buf);
let mut table_positions = Vec::with_capacity(count);
for params in logs {
align4(buf);
let entry_start = buf.len();
encode_log_entry_into(buf, params);
let root_offset = u32::from_le_bytes([
buf[entry_start],
buf[entry_start + 1],
buf[entry_start + 2],
buf[entry_start + 3],
]) as usize;
table_positions.push(entry_start + root_offset);
}
for (i, &table_pos) in table_positions.iter().enumerate() {
patch_offset(buf, offsets_start + i * 4, table_pos);
}
patch_offset(buf, logs_off_pos, logs_vec_start);
buf[root_pos..root_pos + 4].copy_from_slice(&((table_start - data_start) as u32).to_le_bytes());
data_start..buf.len()
}
fn encode_log_entry_into(buf: &mut Vec<u8>, params: &LogEntryParams<'_>) {
let has_session_id = params.session_id.is_some();
let has_source = params.source.is_some();
let has_service = params.service.is_some();
let has_payload = params.payload.is_some();
let vtable_size: u16 = 4 + 7 * 2;
let table_size: u16 = 4 + 28;
let root_pos = buf.len();
buf.extend_from_slice(&[0u8; 4]);
let vtable_start = buf.len();
write_u16(buf, vtable_size);
write_u16(buf, table_size);
write_u16(buf, 28);
write_u16(buf, if has_session_id { 4 } else { 0 });
write_u16(buf, 29);
write_u16(buf, 20);
write_u16(buf, if has_source { 8 } else { 0 });
write_u16(buf, if has_service { 12 } else { 0 });
write_u16(buf, if has_payload { 16 } else { 0 });
buf.extend_from_slice(&[0u8; 2]);
let table_start = buf.len();
let soffset = (table_start - vtable_start) as i32;
write_i32(buf, soffset);
let session_id_off_pos = buf.len();
write_u32(buf, 0);
let source_off_pos = buf.len();
write_u32(buf, 0);
let service_off_pos = buf.len();
write_u32(buf, 0);
let payload_off_pos = buf.len();
write_u32(buf, 0);
write_u64(buf, params.timestamp);
buf.push(params.event_type.as_u8());
buf.push(params.level.as_u8());
buf.extend_from_slice(&[0u8; 2]);
align4(buf);
let session_id_start = params.session_id.map(|id| write_byte_vector(buf, id));
align4(buf);
let source_start = params.source.map(|s| write_string(buf, s));
align4(buf);
let service_start = params.service.map(|s| write_string(buf, s));
align4(buf);
let payload_start = params.payload.map(|data| write_byte_vector(buf, data));
buf[root_pos..root_pos + 4].copy_from_slice(&((table_start - root_pos) as u32).to_le_bytes());
if let Some(start) = session_id_start {
patch_offset(buf, session_id_off_pos, start);
}
if let Some(start) = source_start {
patch_offset(buf, source_off_pos, start);
}
if let Some(start) = service_start {
patch_offset(buf, service_off_pos, start);
}
if let Some(start) = payload_start {
patch_offset(buf, payload_off_pos, start);
}
}