use serde::{Deserialize, Serialize};
use super::scope::{AllocationEventType, ScopeEventType};
use super::stats::TypeMemoryUsage;
#[derive(Debug, Clone, Serialize)]
pub struct TimelineData {
pub time_range: TimeRange,
pub allocation_events: Vec<AllocationEvent>,
pub scope_events: Vec<ScopeEvent>,
pub memory_snapshots: Vec<MemorySnapshot>,
}
#[derive(Debug, Clone, Serialize)]
pub struct TimeRange {
pub start_time: u64,
pub end_time: u64,
pub duration_ms: u64,
}
#[derive(Debug, Clone, Serialize)]
pub struct MemorySnapshot {
pub timestamp: u64,
pub total_memory: usize,
pub active_allocations: usize,
pub fragmentation_ratio: f64,
pub top_types: Vec<TypeMemoryUsage>,
}
#[derive(Debug, Clone, Serialize)]
pub struct AllocationEvent {
pub timestamp: u64,
pub event_type: AllocationEventType,
pub ptr: usize,
pub size: usize,
pub var_name: Option<String>,
pub type_name: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ScopeEvent {
pub timestamp: u64,
pub event_type: ScopeEventType,
pub scope_name: String,
pub memory_usage: usize,
pub variable_count: usize,
}
#[derive(Debug, Clone, Serialize)]
pub struct StackTraceData {
pub hotspots: Vec<StackTraceHotspot>,
pub allocation_patterns: Vec<AllocationPattern>,
pub total_samples: usize,
}
#[derive(Debug, Clone, Serialize)]
pub struct StackTraceHotspot {
pub function_name: String,
pub allocation_count: usize,
pub total_bytes: usize,
pub average_size: f64,
pub percentage: f64,
}
#[derive(Debug, Clone, Serialize)]
pub struct AllocationPattern {
pub pattern_type: String,
pub frequency: usize,
pub total_bytes: usize,
pub description: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StackFrame {
pub function_name: String,
pub file_name: Option<String>,
pub line_number: Option<u32>,
pub module_path: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
pub enum SafetyViolation {
PotentialLeak {
ptr: usize,
size: usize,
age_ms: u64,
description: String,
},
UseAfterFree {
ptr: usize,
description: String,
},
DoubleFree {
ptr: usize,
description: String,
},
BufferOverflow {
ptr: usize,
size: usize,
description: String,
},
}
#[derive(Debug, Clone, Serialize)]
pub struct AllocationHotspot {
pub location: HotspotLocation,
pub allocation_count: usize,
pub total_bytes: usize,
pub average_size: f64,
pub frequency: f64,
}
#[derive(Debug, Clone, Serialize)]
pub struct HotspotLocation {
pub function_name: String,
pub file_path: Option<String>,
pub line_number: Option<u32>,
pub module_path: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_timeline_data() {
let timeline = TimelineData {
time_range: TimeRange {
start_time: 0,
end_time: 1000,
duration_ms: 1000,
},
allocation_events: vec![],
scope_events: vec![],
memory_snapshots: vec![],
};
assert_eq!(timeline.time_range.duration_ms, 1000);
}
#[test]
fn test_memory_snapshot() {
let snapshot = MemorySnapshot {
timestamp: 100,
total_memory: 1024 * 1024,
active_allocations: 10,
fragmentation_ratio: 0.1,
top_types: vec![],
};
assert_eq!(snapshot.active_allocations, 10);
}
#[test]
fn test_safety_violation() {
let violation = SafetyViolation::PotentialLeak {
ptr: 0x1000,
size: 1024,
age_ms: 5000,
description: "test leak".to_string(),
};
assert!(matches!(violation, SafetyViolation::PotentialLeak { .. }));
}
}