use runmat_time::system_time_now;
use std::time::{Duration, SystemTime};
use serde::{Deserialize, Serialize};
pub const SNAPSHOT_MAGIC: &[u8; 7] = b"RUNMAT\0";
pub const SNAPSHOT_VERSION: u32 = 1;
#[derive(Debug, Clone)]
pub struct SnapshotFormat {
pub header: SnapshotHeader,
pub data: Vec<u8>,
pub checksum: Option<Vec<u8>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SnapshotHeader {
pub magic: [u8; 7],
pub version: u32,
pub metadata: SnapshotMetadata,
pub data_info: DataSectionInfo,
pub checksum_info: Option<ChecksumInfo>,
pub header_size: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SnapshotMetadata {
pub created_at: SystemTime,
pub runmat_version: String,
pub tool_version: String,
pub build_config: BuildConfig,
pub performance_metrics: PerformanceMetrics,
pub feature_flags: Vec<String>,
pub target_platform: PlatformInfo,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BuildConfig {
pub optimization_level: String,
pub debug_info: bool,
pub compiler: String,
pub compile_flags: Vec<String>,
pub enabled_features: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceMetrics {
pub creation_time: Duration,
pub builtin_count: u64,
pub hir_cache_entries: u64,
pub bytecode_cache_entries: u64,
pub uncompressed_size: u64,
pub compression_ratio: f64,
pub peak_memory_usage: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlatformInfo {
pub os: String,
pub arch: String,
pub cpu_features: Vec<String>,
pub page_size: usize,
pub cache_line_size: usize,
pub endianness: Endianness,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Endianness {
Little,
Big,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataSectionInfo {
pub compression: CompressionInfo,
pub uncompressed_size: u64,
pub compressed_size: u64,
pub data_offset: u64,
pub alignment: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompressionInfo {
pub algorithm: CompressionAlgorithm,
pub level: u32,
pub parameters: std::collections::HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum CompressionAlgorithm {
None,
Lz4 { fast: bool },
Zstd { dictionary: Option<Vec<u8>> },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChecksumInfo {
pub algorithm: ChecksumAlgorithm,
pub size: usize,
pub offset: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ChecksumAlgorithm {
Sha256,
Blake3,
Crc32,
}
impl SnapshotHeader {
pub fn new(metadata: SnapshotMetadata) -> Self {
Self {
magic: *SNAPSHOT_MAGIC,
version: SNAPSHOT_VERSION,
metadata,
data_info: DataSectionInfo {
compression: CompressionInfo {
algorithm: CompressionAlgorithm::None,
level: 0,
parameters: std::collections::HashMap::new(),
},
uncompressed_size: 0,
compressed_size: 0,
data_offset: 0,
alignment: 8,
},
checksum_info: None,
header_size: 0, }
}
pub fn validate(&self) -> crate::SnapshotResult<()> {
if self.magic != *SNAPSHOT_MAGIC {
return Err(crate::SnapshotError::Corrupted {
reason: "Invalid magic number".to_string(),
});
}
if self.version > SNAPSHOT_VERSION {
return Err(crate::SnapshotError::VersionMismatch {
expected: SNAPSHOT_VERSION.to_string(),
found: self.version.to_string(),
});
}
Ok(())
}
pub fn is_platform_compatible(&self) -> bool {
let current_os = std::env::consts::OS;
let current_arch = std::env::consts::ARCH;
self.metadata.target_platform.os == current_os
&& self.metadata.target_platform.arch == current_arch
}
pub fn estimated_load_time(&self) -> Duration {
let base_time = Duration::from_millis(10); let data_time = Duration::from_nanos(
(self.data_info.compressed_size * 10) / 1024, );
match self.data_info.compression.algorithm {
CompressionAlgorithm::None => base_time + data_time,
CompressionAlgorithm::Lz4 { .. } => base_time + data_time * 2,
CompressionAlgorithm::Zstd { .. } => base_time + data_time * 4,
}
}
}
impl SnapshotMetadata {
pub fn current() -> Self {
Self {
created_at: system_time_now(),
runmat_version: env!("CARGO_PKG_VERSION").to_string(),
tool_version: env!("CARGO_PKG_VERSION").to_string(),
build_config: BuildConfig::current(),
performance_metrics: PerformanceMetrics::default(),
feature_flags: Self::detect_feature_flags(),
target_platform: PlatformInfo::current(),
}
}
#[allow(clippy::vec_init_then_push)] fn detect_feature_flags() -> Vec<String> {
let mut flags = Vec::new();
#[cfg(feature = "compression")]
flags.push("compression".to_string());
#[cfg(feature = "validation")]
flags.push("validation".to_string());
#[cfg(feature = "blas-lapack")]
flags.push("blas-lapack".to_string());
flags
}
pub fn is_compatible(&self) -> bool {
let current_version = env!("CARGO_PKG_VERSION");
let current_major = current_version.split('.').next().unwrap_or("0");
let snapshot_major = self.runmat_version.split('.').next().unwrap_or("0");
current_major == snapshot_major
}
pub fn age(&self) -> Duration {
system_time_now()
.duration_since(self.created_at)
.unwrap_or(Duration::ZERO)
}
}
impl BuildConfig {
pub fn current() -> Self {
Self {
optimization_level: if cfg!(debug_assertions) {
"debug".to_string()
} else {
"release".to_string()
},
debug_info: cfg!(debug_assertions),
compiler: format!(
"rustc {}",
option_env!("RUSTC_VERSION").unwrap_or("unknown")
),
compile_flags: Vec::new(), enabled_features: Vec::new(), }
}
}
impl Default for PerformanceMetrics {
fn default() -> Self {
Self {
creation_time: Duration::ZERO,
builtin_count: 0,
hir_cache_entries: 0,
bytecode_cache_entries: 0,
uncompressed_size: 0,
compression_ratio: 1.0,
peak_memory_usage: 0,
}
}
}
impl PlatformInfo {
pub fn current() -> Self {
Self {
os: std::env::consts::OS.to_string(),
arch: std::env::consts::ARCH.to_string(),
cpu_features: Self::detect_cpu_features(),
page_size: Self::detect_page_size(),
cache_line_size: Self::detect_cache_line_size(),
endianness: if cfg!(target_endian = "little") {
Endianness::Little
} else {
Endianness::Big
},
}
}
#[allow(unused_mut)]
fn detect_cpu_features() -> Vec<String> {
let mut features = Vec::new();
#[cfg(target_arch = "x86_64")]
{
if std::arch::is_x86_feature_detected!("sse4.2") {
features.push("sse4.2".to_string());
}
if std::arch::is_x86_feature_detected!("avx") {
features.push("avx".to_string());
}
if std::arch::is_x86_feature_detected!("avx2") {
features.push("avx2".to_string());
}
if std::arch::is_x86_feature_detected!("fma") {
features.push("fma".to_string());
}
}
#[cfg(target_arch = "aarch64")]
{
if std::arch::is_aarch64_feature_detected!("neon") {
features.push("neon".to_string());
}
}
features
}
fn detect_page_size() -> usize {
#[cfg(unix)]
{
unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
}
#[cfg(not(unix))]
{
4096 }
}
fn detect_cache_line_size() -> usize {
64
}
}
impl SnapshotFormat {
pub fn new(header: SnapshotHeader, data: Vec<u8>) -> Self {
Self {
header,
data,
checksum: None,
}
}
pub fn with_checksum(mut self, algorithm: ChecksumAlgorithm) -> crate::SnapshotResult<Self> {
#[cfg(feature = "validation")]
{
use sha2::{Digest, Sha256};
let checksum = match algorithm {
ChecksumAlgorithm::Sha256 => {
let mut hasher = Sha256::new();
hasher.update(&self.data);
hasher.finalize().to_vec()
}
ChecksumAlgorithm::Blake3 => blake3::hash(&self.data).as_bytes().to_vec(),
ChecksumAlgorithm::Crc32 => {
let crc = crc32fast::hash(&self.data);
crc.to_le_bytes().to_vec()
}
};
self.checksum = Some(checksum.clone());
self.header.checksum_info = Some(ChecksumInfo {
algorithm,
size: checksum.len(),
offset: 0, });
}
#[cfg(not(feature = "validation"))]
{
return Err(crate::SnapshotError::Configuration {
message: "Validation feature not enabled".to_string(),
});
}
Ok(self)
}
pub fn validate_checksum(&self) -> crate::SnapshotResult<bool> {
#[cfg(feature = "validation")]
{
if let (Some(checksum_info), Some(stored_checksum)) =
(&self.header.checksum_info, &self.checksum)
{
use sha2::{Digest, Sha256};
let calculated_checksum = match checksum_info.algorithm {
ChecksumAlgorithm::Sha256 => {
let mut hasher = Sha256::new();
hasher.update(&self.data);
hasher.finalize().to_vec()
}
ChecksumAlgorithm::Blake3 => blake3::hash(&self.data).as_bytes().to_vec(),
ChecksumAlgorithm::Crc32 => {
let crc = crc32fast::hash(&self.data);
crc.to_le_bytes().to_vec()
}
};
Ok(calculated_checksum == *stored_checksum)
} else {
Ok(true) }
}
#[cfg(not(feature = "validation"))]
{
Ok(true) }
}
pub fn total_size(&self) -> usize {
let header_size = bincode::serialized_size(&self.header).unwrap_or(0) as u64;
let data_size = self.data.len() as u64;
let checksum_size = self.checksum.as_ref().map_or(0, |c| c.len()) as u64;
(header_size + data_size + checksum_size) as usize
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_snapshot_header_validation() {
let metadata = SnapshotMetadata::current();
let header = SnapshotHeader::new(metadata);
assert!(header.validate().is_ok());
assert_eq!(header.magic, *SNAPSHOT_MAGIC);
assert_eq!(header.version, SNAPSHOT_VERSION);
}
#[test]
fn test_platform_compatibility() {
let metadata = SnapshotMetadata::current();
let header = SnapshotHeader::new(metadata);
assert!(header.is_platform_compatible());
}
#[test]
fn test_metadata_compatibility() {
let metadata = SnapshotMetadata::current();
assert!(metadata.is_compatible());
}
#[test]
fn test_platform_info() {
let platform = PlatformInfo::current();
assert!(!platform.os.is_empty());
assert!(!platform.arch.is_empty());
assert!(platform.page_size > 0);
assert!(platform.cache_line_size > 0);
}
#[test]
fn test_build_config() {
let config = BuildConfig::current();
assert!(!config.optimization_level.is_empty());
assert!(!config.compiler.is_empty());
}
#[test]
fn test_snapshot_format_creation() {
let metadata = SnapshotMetadata::current();
let header = SnapshotHeader::new(metadata);
let data = vec![1, 2, 3, 4, 5];
let format = SnapshotFormat::new(header, data);
assert_eq!(format.data.len(), 5);
assert!(format.checksum.is_none());
}
#[cfg(feature = "validation")]
#[test]
fn test_checksum_generation() {
let metadata = SnapshotMetadata::current();
let header = SnapshotHeader::new(metadata);
let data = vec![1, 2, 3, 4, 5];
let format = SnapshotFormat::new(header, data);
let format_with_checksum = format.with_checksum(ChecksumAlgorithm::Sha256).unwrap();
assert!(format_with_checksum.checksum.is_some());
assert!(format_with_checksum.header.checksum_info.is_some());
assert!(format_with_checksum.validate_checksum().unwrap());
}
#[test]
fn test_estimated_load_time() {
let metadata = SnapshotMetadata::current();
let mut header = SnapshotHeader::new(metadata);
header.data_info.compressed_size = 1024 * 1024;
let load_time = header.estimated_load_time();
assert!(load_time > Duration::ZERO);
}
}