1use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct DiffReport {
11 pub diff_version: String,
13
14 pub generated_at: String,
16
17 pub baseline: ProfileMetadata,
19
20 pub target: ProfileMetadata,
22
23 pub deltas: Deltas,
25
26 pub threshold_violations: Vec<ThresholdViolation>,
28
29 #[serde(default, skip_serializing_if = "Vec::is_empty")]
31 pub insights: Vec<AnalysisInsight>,
32
33 pub summary: DiffSummary,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize, Default)]
39pub struct ProfileMetadata {
40 pub transaction_hash: String,
42
43 pub total_gas: u64,
45
46 pub generated_at: String,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize, Default)]
52pub struct Deltas {
53 pub gas: GasDelta,
55
56 pub hostio: HostIoDelta,
58
59 pub hot_paths: HotPathsDelta,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize, Default)]
65pub struct GasDelta {
66 pub baseline: u64,
68
69 pub target: u64,
71
72 pub absolute_change: i64,
74
75 pub percent_change: f64,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize, Default)]
81pub struct HostIoDelta {
82 pub baseline_total_calls: u64,
84
85 pub target_total_calls: u64,
87
88 pub total_calls_change: i64,
90
91 pub total_calls_percent_change: f64,
93
94 pub by_type_changes: HashMap<String, HostIOTypeChange>,
96
97 pub baseline_total_gas: u64,
99
100 pub target_total_gas: u64,
102
103 pub gas_change: i64,
105
106 pub gas_percent_change: f64,
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize, Default)]
112pub struct HostIOTypeChange {
113 pub baseline: u64,
115
116 pub target: u64,
118
119 pub delta: i64,
121}
122
123#[derive(Debug, Clone, Serialize, Deserialize, Default)]
125pub struct HotPathsDelta {
126 pub common_paths: Vec<HotPathComparison>,
128
129 pub baseline_only: Vec<crate::parser::schema::HotPath>,
131
132 pub target_only: Vec<crate::parser::schema::HotPath>,
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize, Default)]
138pub struct HotPathComparison {
139 pub stack: String,
141
142 pub baseline_gas: u64,
144
145 pub target_gas: u64,
147
148 pub gas_change: i64,
150
151 pub percent_change: f64,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize, Default)]
157pub struct ThresholdViolation {
158 pub metric: String,
160
161 pub threshold: f64,
163
164 pub actual: f64,
166
167 pub severity: String,
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
173pub struct DiffSummary {
174 pub has_regressions: bool,
176
177 pub violation_count: usize,
179
180 pub status: String,
182
183 #[serde(skip_serializing_if = "Option::is_none")]
185 pub warning: Option<String>,
186}
187
188#[derive(Debug, Clone, Serialize, Deserialize)]
190pub struct AnalysisInsight {
191 pub category: String,
193
194 pub description: String,
196
197 pub severity: InsightSeverity,
199
200 pub tag: Option<String>,
202}
203
204#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
206#[serde(rename_all = "lowercase")]
207pub enum InsightSeverity {
208 Info,
210 Low,
212 Medium,
214 High,
216}