1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
4pub struct GenericInstance {
5 pub name: String,
6 pub base_type: String,
7 pub underlying_type: String,
8 pub type_parameters: Vec<String>,
9 pub ptr: usize,
10 pub size: usize,
11 pub constraints: Vec<GenericConstraint>,
12 pub is_type_alias: bool,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct GenericConstraint {
17 pub parameter_name: String,
18 pub constraint_type: ConstraintType,
19 pub description: String,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub enum ConstraintType {
24 Trait(String),
25 Lifetime,
26 Sized,
27 Send,
28 Sync,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct InstantiationEvent {
33 pub base_type: String,
34 pub type_parameters: Vec<String>,
35 pub ptr: usize,
36 pub timestamp: u64,
37 pub thread_id: String,
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct ConstraintViolation {
42 pub constraint: GenericConstraint,
43 pub actual_type: String,
44 pub violation_type: ViolationType,
45 pub timestamp: u64,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub enum ViolationType {
50 ConstraintNotSatisfied,
51 LifetimeMismatch,
52 MissingTraitImpl,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct GenericStatistics {
57 pub total_instances: usize,
58 pub unique_base_types: usize,
59 pub total_instantiations: usize,
60 pub constraint_violations: usize,
61 pub most_used_types: Vec<(String, usize)>,
62 pub type_aliases_count: usize,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct TypeAliasInfo {
67 pub alias_name: String,
68 pub underlying_type: String,
69 pub base_type: String,
70 pub type_parameters: Vec<String>,
71 pub usage_count: usize,
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn test_generic_instance_creation() {
80 let instance = GenericInstance {
81 name: "Vec<i32>".to_string(),
82 base_type: "Vec".to_string(),
83 underlying_type: "Vec<i32>".to_string(),
84 type_parameters: vec!["i32".to_string()],
85 ptr: 0x1000,
86 size: 24,
87 constraints: vec![],
88 is_type_alias: false,
89 };
90
91 assert_eq!(instance.name, "Vec<i32>");
92 assert_eq!(instance.base_type, "Vec");
93 assert_eq!(instance.type_parameters.len(), 1);
94 assert!(!instance.is_type_alias);
95 }
96
97 #[test]
98 fn test_generic_instance_with_constraints() {
99 let constraint = GenericConstraint {
100 parameter_name: "T".to_string(),
101 constraint_type: ConstraintType::Trait("Clone".to_string()),
102 description: "T must be Clone".to_string(),
103 };
104
105 let instance = GenericInstance {
106 name: "HashMap<String, i32>".to_string(),
107 base_type: "HashMap".to_string(),
108 underlying_type: "HashMap<String, i32>".to_string(),
109 type_parameters: vec!["String".to_string(), "i32".to_string()],
110 ptr: 0x2000,
111 size: 48,
112 constraints: vec![constraint],
113 is_type_alias: false,
114 };
115
116 assert_eq!(instance.constraints.len(), 1);
117 assert_eq!(instance.constraints[0].parameter_name, "T");
118 }
119
120 #[test]
121 fn test_generic_constraint_creation() {
122 let constraint = GenericConstraint {
123 parameter_name: "T".to_string(),
124 constraint_type: ConstraintType::Send,
125 description: "T must be Send".to_string(),
126 };
127
128 assert_eq!(constraint.parameter_name, "T");
129 assert!(matches!(constraint.constraint_type, ConstraintType::Send));
130 }
131
132 #[test]
133 fn test_constraint_type_variants() {
134 let trait_constraint = ConstraintType::Trait("Debug".to_string());
135 let lifetime_constraint = ConstraintType::Lifetime;
136 let sized_constraint = ConstraintType::Sized;
137 let send_constraint = ConstraintType::Send;
138 let sync_constraint = ConstraintType::Sync;
139
140 assert!(matches!(trait_constraint, ConstraintType::Trait(_)));
141 assert!(matches!(lifetime_constraint, ConstraintType::Lifetime));
142 assert!(matches!(sized_constraint, ConstraintType::Sized));
143 assert!(matches!(send_constraint, ConstraintType::Send));
144 assert!(matches!(sync_constraint, ConstraintType::Sync));
145 }
146
147 #[test]
148 fn test_instantiation_event_creation() {
149 let event = InstantiationEvent {
150 base_type: "Vec".to_string(),
151 type_parameters: vec!["u8".to_string()],
152 ptr: 0x3000,
153 timestamp: 1000,
154 thread_id: "main".to_string(),
155 };
156
157 assert_eq!(event.base_type, "Vec");
158 assert_eq!(event.timestamp, 1000);
159 assert_eq!(event.thread_id, "main");
160 }
161
162 #[test]
163 fn test_constraint_violation_creation() {
164 let constraint = GenericConstraint {
165 parameter_name: "T".to_string(),
166 constraint_type: ConstraintType::Trait("Clone".to_string()),
167 description: "T must be Clone".to_string(),
168 };
169
170 let violation = ConstraintViolation {
171 constraint,
172 actual_type: "MyType".to_string(),
173 violation_type: ViolationType::MissingTraitImpl,
174 timestamp: 2000,
175 };
176
177 assert_eq!(violation.actual_type, "MyType");
178 assert!(matches!(
179 violation.violation_type,
180 ViolationType::MissingTraitImpl
181 ));
182 }
183
184 #[test]
185 fn test_violation_type_variants() {
186 let not_satisfied = ViolationType::ConstraintNotSatisfied;
187 let lifetime_mismatch = ViolationType::LifetimeMismatch;
188 let missing_trait = ViolationType::MissingTraitImpl;
189
190 assert!(matches!(
191 not_satisfied,
192 ViolationType::ConstraintNotSatisfied
193 ));
194 assert!(matches!(lifetime_mismatch, ViolationType::LifetimeMismatch));
195 assert!(matches!(missing_trait, ViolationType::MissingTraitImpl));
196 }
197
198 #[test]
199 fn test_generic_statistics_creation() {
200 let stats = GenericStatistics {
201 total_instances: 100,
202 unique_base_types: 10,
203 total_instantiations: 500,
204 constraint_violations: 5,
205 most_used_types: vec![("Vec<u8>".to_string(), 50)],
206 type_aliases_count: 3,
207 };
208
209 assert_eq!(stats.total_instances, 100);
210 assert_eq!(stats.unique_base_types, 10);
211 assert_eq!(stats.most_used_types.len(), 1);
212 }
213
214 #[test]
215 fn test_generic_statistics_default_values() {
216 let stats = GenericStatistics {
217 total_instances: 0,
218 unique_base_types: 0,
219 total_instantiations: 0,
220 constraint_violations: 0,
221 most_used_types: vec![],
222 type_aliases_count: 0,
223 };
224
225 assert_eq!(stats.total_instances, 0);
226 assert!(stats.most_used_types.is_empty());
227 }
228
229 #[test]
230 fn test_type_alias_info_creation() {
231 let alias = TypeAliasInfo {
232 alias_name: "MyResult".to_string(),
233 underlying_type: "Result<T, MyError>".to_string(),
234 base_type: "Result".to_string(),
235 type_parameters: vec!["T".to_string()],
236 usage_count: 25,
237 };
238
239 assert_eq!(alias.alias_name, "MyResult");
240 assert_eq!(alias.usage_count, 25);
241 }
242
243 #[test]
244 fn test_serialization() {
245 let instance = GenericInstance {
246 name: "Option<i32>".to_string(),
247 base_type: "Option".to_string(),
248 underlying_type: "Option<i32>".to_string(),
249 type_parameters: vec!["i32".to_string()],
250 ptr: 0x1000,
251 size: 4,
252 constraints: vec![],
253 is_type_alias: false,
254 };
255
256 let json = serde_json::to_string(&instance);
257 assert!(json.is_ok());
258
259 let deserialized: Result<GenericInstance, _> = serde_json::from_str(&json.unwrap());
260 assert!(deserialized.is_ok());
261 }
262
263 #[test]
264 fn test_constraint_serialization() {
265 let constraint = GenericConstraint {
266 parameter_name: "T".to_string(),
267 constraint_type: ConstraintType::Trait("Debug".to_string()),
268 description: "Test constraint".to_string(),
269 };
270
271 let json = serde_json::to_string(&constraint);
272 assert!(json.is_ok());
273
274 let deserialized: Result<GenericConstraint, _> = serde_json::from_str(&json.unwrap());
275 assert!(deserialized.is_ok());
276 }
277
278 #[test]
279 fn test_statistics_serialization() {
280 let stats = GenericStatistics {
281 total_instances: 10,
282 unique_base_types: 5,
283 total_instantiations: 20,
284 constraint_violations: 1,
285 most_used_types: vec![("String".to_string(), 100)],
286 type_aliases_count: 2,
287 };
288
289 let json = serde_json::to_string(&stats);
290 assert!(json.is_ok());
291
292 let deserialized: Result<GenericStatistics, _> = serde_json::from_str(&json.unwrap());
293 assert!(deserialized.is_ok());
294 }
295
296 #[test]
297 fn test_instantiation_event_serialization() {
298 let event = InstantiationEvent {
299 base_type: "Box".to_string(),
300 type_parameters: vec!["dyn Any".to_string()],
301 ptr: 0x5000,
302 timestamp: 9999,
303 thread_id: "worker-1".to_string(),
304 };
305
306 let json = serde_json::to_string(&event);
307 assert!(json.is_ok());
308
309 let deserialized: Result<InstantiationEvent, _> = serde_json::from_str(&json.unwrap());
310 assert!(deserialized.is_ok());
311 }
312
313 #[test]
314 fn test_violation_serialization() {
315 let violation = ConstraintViolation {
316 constraint: GenericConstraint {
317 parameter_name: "T".to_string(),
318 constraint_type: ConstraintType::Sync,
319 description: "Must be Sync".to_string(),
320 },
321 actual_type: "Rc<i32>".to_string(),
322 violation_type: ViolationType::ConstraintNotSatisfied,
323 timestamp: 5000,
324 };
325
326 let json = serde_json::to_string(&violation);
327 assert!(json.is_ok());
328
329 let deserialized: Result<ConstraintViolation, _> = serde_json::from_str(&json.unwrap());
330 assert!(deserialized.is_ok());
331 }
332
333 #[test]
334 fn test_type_alias_serialization() {
335 let alias = TypeAliasInfo {
336 alias_name: "IntList".to_string(),
337 underlying_type: "Vec<i32>".to_string(),
338 base_type: "Vec".to_string(),
339 type_parameters: vec!["i32".to_string()],
340 usage_count: 10,
341 };
342
343 let json = serde_json::to_string(&alias);
344 assert!(json.is_ok());
345
346 let deserialized: Result<TypeAliasInfo, _> = serde_json::from_str(&json.unwrap());
347 assert!(deserialized.is_ok());
348 }
349
350 #[test]
351 fn test_generic_instance_debug() {
352 let instance = GenericInstance {
353 name: "Test".to_string(),
354 base_type: "Base".to_string(),
355 underlying_type: "Underlying".to_string(),
356 type_parameters: vec![],
357 ptr: 0,
358 size: 0,
359 constraints: vec![],
360 is_type_alias: false,
361 };
362
363 let debug_str = format!("{:?}", instance);
364 assert!(debug_str.contains("GenericInstance"));
365 }
366
367 #[test]
368 fn test_generic_instance_clone() {
369 let instance = GenericInstance {
370 name: "Original".to_string(),
371 base_type: "Base".to_string(),
372 underlying_type: "Underlying".to_string(),
373 type_parameters: vec!["T".to_string()],
374 ptr: 0x1000,
375 size: 8,
376 constraints: vec![],
377 is_type_alias: true,
378 };
379
380 let cloned = instance.clone();
381 assert_eq!(cloned.name, instance.name);
382 assert_eq!(cloned.ptr, instance.ptr);
383 }
384
385 #[test]
386 fn test_empty_type_parameters() {
387 let instance = GenericInstance {
388 name: "String".to_string(),
389 base_type: "String".to_string(),
390 underlying_type: "String".to_string(),
391 type_parameters: vec![],
392 ptr: 0x1000,
393 size: 24,
394 constraints: vec![],
395 is_type_alias: false,
396 };
397
398 assert!(instance.type_parameters.is_empty());
399 }
400
401 #[test]
402 fn test_multiple_type_parameters() {
403 let instance = GenericInstance {
404 name: "HashMap<K, V>".to_string(),
405 base_type: "HashMap".to_string(),
406 underlying_type: "HashMap<String, i32>".to_string(),
407 type_parameters: vec!["String".to_string(), "i32".to_string()],
408 ptr: 0x2000,
409 size: 48,
410 constraints: vec![],
411 is_type_alias: false,
412 };
413
414 assert_eq!(instance.type_parameters.len(), 2);
415 }
416}