1#![allow(dead_code)]
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Debug, Serialize, Deserialize, Clone)]
7pub struct CommonProfileData {
8 pub language: String,
9 pub source_file: String,
10 pub timestamp: String,
11
12 pub static_analysis: StaticMetrics,
13
14 #[serde(skip_serializing_if = "Option::is_none")]
15 pub runtime_analysis: Option<RuntimeMetrics>,
16}
17
18#[derive(Debug, Serialize, Deserialize, Clone)]
19pub struct StaticMetrics {
20 pub file_size_bytes: usize,
21 pub line_count: usize,
22 pub function_count: usize,
23 pub class_count: usize,
24 pub import_count: usize,
25 pub complexity_score: u32,
26}
27
28#[derive(Debug, Serialize, Deserialize, Clone)]
29pub struct RuntimeMetrics {
30 pub total_samples: u64,
31 pub execution_duration_secs: u64,
32 pub functions_executed: usize,
33
34 pub function_stats: HashMap<String, FunctionStats>,
35
36 pub hot_functions: Vec<HotFunction>,
37}
38
39#[derive(Debug, Serialize, Deserialize, Clone)]
40pub struct FunctionStats {
41 pub name: String,
42 pub execution_count: u64,
43 pub percentage: f64,
44
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub line_number: Option<usize>,
47
48 #[serde(skip_serializing_if = "Option::is_none")]
49 pub file_path: Option<String>,
50}
51
52#[derive(Debug, Serialize, Deserialize, Clone)]
53pub struct HotFunction {
54 pub rank: usize,
55 pub name: String,
56 pub samples: u64,
57 pub percentage: f64,
58}
59
60impl CommonProfileData {
61 pub fn to_json(&self) -> Result<String, serde_json::Error> {
62 serde_json::to_string(self)
63 }
64
65 pub fn to_json_pretty(&self) -> Result<String, serde_json::Error> {
66 serde_json::to_string_pretty(self)
67 }
68
69 pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
70 serde_json::from_str(json)
71 }
72
73 pub fn to_json_file(&self, path: &str) -> Result<(), std::io::Error> {
74 let json = self.to_json().map_err(std::io::Error::other)?;
75 std::fs::write(path, json)
76 }
77
78 pub fn from_json_file(path: &str) -> Result<Self, std::io::Error> {
79 let content = std::fs::read_to_string(path)?;
80 Self::from_json(&content)
81 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
82 }
83
84 pub fn to_protobuf(&self) -> crate::proto::ProfileData {
85 use crate::proto;
86
87 proto::ProfileData {
88 language: self.language.clone(),
89 source_file: self.source_file.clone(),
90 timestamp: self.timestamp.clone(),
91 static_analysis: Some(proto::StaticMetrics {
92 file_size_bytes: self.static_analysis.file_size_bytes as u64,
93 line_count: self.static_analysis.line_count as u64,
94 function_count: self.static_analysis.function_count as u64,
95 class_count: self.static_analysis.class_count as u64,
96 import_count: self.static_analysis.import_count as u64,
97 complexity_score: self.static_analysis.complexity_score,
98 }),
99 runtime_analysis: self
100 .runtime_analysis
101 .as_ref()
102 .map(|rt| proto::RuntimeMetrics {
103 total_samples: rt.total_samples,
104 execution_duration_secs: rt.execution_duration_secs,
105 functions_executed: rt.functions_executed as u64,
106 function_stats: rt
107 .function_stats
108 .values()
109 .map(|stats| proto::FunctionStats {
110 name: stats.name.clone(),
111 execution_count: stats.execution_count,
112 total_time_ms: 0, avg_time_ms: 0.0, samples: 0, })
116 .collect(),
117 hot_functions: rt
118 .hot_functions
119 .iter()
120 .map(|hf| proto::HotFunction {
121 name: hf.name.clone(),
122 file: String::new(), line: 0, samples: hf.samples,
125 percentage: hf.percentage,
126 })
127 .collect(),
128 }),
129 }
130 }
131}
132
133impl std::fmt::Display for CommonProfileData {
134 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
135 writeln!(f, "=== Profile Data for {} ===", self.language)?;
136 writeln!(f, "Source: {}", self.source_file)?;
137 writeln!(f, "Timestamp: {}", self.timestamp)?;
138 writeln!(f)?;
139
140 writeln!(f, "Static Analysis:")?;
141 writeln!(
142 f,
143 " File Size: {} bytes",
144 self.static_analysis.file_size_bytes
145 )?;
146 writeln!(f, " Lines: {}", self.static_analysis.line_count)?;
147 writeln!(f, " Functions: {}", self.static_analysis.function_count)?;
148 writeln!(f, " Classes: {}", self.static_analysis.class_count)?;
149 writeln!(f, " Imports: {}", self.static_analysis.import_count)?;
150 writeln!(f, " Complexity: {}", self.static_analysis.complexity_score)?;
151
152 if let Some(runtime) = &self.runtime_analysis {
153 writeln!(f)?;
154 writeln!(f, "Runtime Analysis:")?;
155 writeln!(f, " Duration: {} seconds", runtime.execution_duration_secs)?;
156 writeln!(f, " Total Samples: {}", runtime.total_samples)?;
157 writeln!(f, " Functions Executed: {}", runtime.functions_executed)?;
158 writeln!(f)?;
159 writeln!(f, " Top Hot Functions:")?;
160 for hot in &runtime.hot_functions {
161 writeln!(
162 f,
163 " {}. {} - {} samples ({:.2}%)",
164 hot.rank, hot.name, hot.samples, hot.percentage
165 )?;
166 }
167 }
168
169 Ok(())
170 }
171}