use std::io::Write;
use flate2::Compression;
use flate2::write::GzEncoder;
use libpetri_event::net_event::NetEvent;
use crate::debug_session_registry::{DebugSession, build_net_structure};
use crate::net_event_converter::to_event_info;
use super::session_archive::{
SessionArchiveV1, SessionArchiveV2,
};
use super::session_metadata::compute_metadata;
pub struct SessionArchiveWriter;
impl SessionArchiveWriter {
pub fn write(session: &DebugSession) -> Result<Vec<u8>, String> {
Self::write_v2(session)
}
pub fn write_v1(session: &DebugSession) -> Result<Vec<u8>, String> {
let header = SessionArchiveV1 {
version: 1,
session_id: session.session_id.clone(),
net_name: session.net_name.clone(),
dot_diagram: session.dot_diagram.clone(),
start_time: session.start_time.to_string(),
event_count: session.event_store.event_count(),
structure: build_net_structure(session),
};
let header_bytes = serde_json::to_vec(&header).map_err(|e| e.to_string())?;
let events = session.event_store.events();
Self::write_framed(&header_bytes, &events)
}
pub fn write_v2(session: &DebugSession) -> Result<Vec<u8>, String> {
let events = session.event_store.events();
let metadata = compute_metadata(&events);
let header = SessionArchiveV2 {
version: 2,
session_id: session.session_id.clone(),
net_name: session.net_name.clone(),
dot_diagram: session.dot_diagram.clone(),
start_time: session.start_time.to_string(),
end_time: session.end_time.map(|t| t.to_string()),
event_count: events.len(),
tags: session.tags.clone(),
metadata,
structure: build_net_structure(session),
};
let header_bytes = serde_json::to_vec(&header).map_err(|e| e.to_string())?;
Self::write_framed(&header_bytes, &events)
}
fn write_framed(header_bytes: &[u8], events: &[NetEvent]) -> Result<Vec<u8>, String> {
let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
encoder
.write_all(&(header_bytes.len() as u32).to_be_bytes())
.map_err(|e| e.to_string())?;
encoder.write_all(header_bytes).map_err(|e| e.to_string())?;
for event in events {
let event_info = to_event_info(event);
let event_bytes = serde_json::to_vec(&event_info).map_err(|e| e.to_string())?;
encoder
.write_all(&(event_bytes.len() as u32).to_be_bytes())
.map_err(|e| e.to_string())?;
encoder.write_all(&event_bytes).map_err(|e| e.to_string())?;
}
encoder.finish().map_err(|e| e.to_string())
}
}