1use std::time::{SystemTime, UNIX_EPOCH};
4
5pub fn current_timestamp_nanos() -> u64 {
7 SystemTime::now()
8 .duration_since(UNIX_EPOCH)
9 .unwrap_or_default()
10 .as_nanos() as u64
11}
12
13pub fn format_bytes(bytes: usize) -> String {
15 if bytes < 1024 {
16 format!("{bytes}B")
17 } else if bytes < 1024 * 1024 {
18 format!("{:.1}KB", bytes as f64 / 1024.0)
19 } else {
20 format!("{:.1}MB", bytes as f64 / (1024.0 * 1024.0))
21 }
22}
23
24pub fn simplify_type_name(type_name: &str) -> (String, String) {
26 if type_name.is_empty() || type_name == "Unknown" {
28 return ("Unknown Type".to_string(), "Unknown".to_string());
29 }
30
31 let clean_type = type_name.trim();
33
34 if clean_type.contains("Vec<") || clean_type.contains("vec::Vec") {
36 let inner = extract_generic_type(clean_type, "Vec");
37 (format!("Vec<{inner}>"), "Collections".to_string())
38 } else if clean_type.contains("String") || clean_type.contains("string::String") {
39 ("String".to_string(), "Basic Types".to_string())
40 } else if clean_type.contains("Box<") || clean_type.contains("boxed::Box") {
41 let inner = extract_generic_type(clean_type, "Box");
42 if inner.contains("HashMap") || inner.contains("hash_map") {
44 ("HashMap<K,V>".to_string(), "Collections".to_string())
45 } else if inner.contains("BTreeMap") || inner.contains("btree_map") {
46 ("BTreeMap<K,V>".to_string(), "Collections".to_string())
47 } else if inner.contains("BTreeSet") || inner.contains("btree_set") {
48 ("BTreeSet<T>".to_string(), "Collections".to_string())
49 } else if inner.contains("HashSet") || inner.contains("hash_set") {
50 ("HashSet<T>".to_string(), "Collections".to_string())
51 } else if inner.contains("VecDeque") || inner.contains("vec_deque") {
52 ("VecDeque<T>".to_string(), "Collections".to_string())
53 } else if inner.contains("Vec") || inner.contains("vec::Vec") {
54 let vec_inner = extract_generic_type(&inner, "Vec");
55 (format!("Vec<{vec_inner}>"), "Collections".to_string())
56 } else {
57 (format!("Box<{inner}>"), "Smart Pointers".to_string())
58 }
59 } else if clean_type.contains("Rc<") || clean_type.contains("rc::Rc") {
60 let inner = extract_generic_type(clean_type, "Rc");
61 (format!("Rc<{inner}>"), "Smart Pointers".to_string())
62 } else if clean_type.contains("Arc<") || clean_type.contains("sync::Arc") {
63 let inner = extract_generic_type(clean_type, "Arc");
64 (format!("Arc<{inner}>"), "Smart Pointers".to_string())
65 } else if clean_type.contains("HashMap") || clean_type.contains("hash_map") {
66 ("HashMap<K,V>".to_string(), "Collections".to_string())
67 } else if clean_type.contains("BTreeMap") || clean_type.contains("btree_map") {
68 ("BTreeMap<K,V>".to_string(), "Collections".to_string())
69 } else if clean_type.contains("BTreeSet") || clean_type.contains("btree_set") {
70 ("BTreeSet<T>".to_string(), "Collections".to_string())
71 } else if clean_type.contains("HashSet") || clean_type.contains("hash_set") {
72 ("HashSet<T>".to_string(), "Collections".to_string())
73 } else if clean_type.contains("VecDeque") || clean_type.contains("vec_deque") {
74 ("VecDeque<T>".to_string(), "Collections".to_string())
75 } else if clean_type.contains("LinkedList") {
76 ("LinkedList<T>".to_string(), "Collections".to_string())
77 } else if clean_type.contains("&str") || clean_type == "str" {
78 ("&str".to_string(), "Basic Types".to_string())
79 } else if clean_type.contains("CString") || clean_type.contains("CStr") {
80 ("CString".to_string(), "Basic Types".to_string())
81 } else if clean_type.contains("OsString") || clean_type.contains("OsStr") {
82 ("OsString".to_string(), "Basic Types".to_string())
83 } else if clean_type.contains("PathBuf") || clean_type.contains("Path") {
84 ("PathBuf".to_string(), "Basic Types".to_string())
85 } else if clean_type.matches("i32").count() > 0
86 || clean_type.matches("u32").count() > 0
87 || clean_type.matches("i64").count() > 0
88 || clean_type.matches("u64").count() > 0
89 || clean_type.matches("f64").count() > 0
90 || clean_type.matches("f32").count() > 0
91 || clean_type.matches("i8").count() > 0
92 || clean_type.matches("u8").count() > 0
93 || clean_type.matches("i16").count() > 0
94 || clean_type.matches("u16").count() > 0
95 || clean_type.matches("isize").count() > 0
96 || clean_type.matches("usize").count() > 0
97 || clean_type.matches("bool").count() > 0
98 || clean_type.matches("char").count() > 0
99 {
100 let primitive = clean_type.split("::").last().unwrap_or(clean_type);
101 (primitive.to_string(), "Basic Types".to_string())
102 } else if clean_type.contains("[") && clean_type.contains("]") {
103 ("Array".to_string(), "Arrays".to_string())
104 } else if clean_type.starts_with("(") && clean_type.ends_with(")") {
105 ("Tuple".to_string(), "Tuples".to_string())
106 } else if clean_type.contains("Option<") {
107 ("Option<T>".to_string(), "Optionals".to_string())
108 } else if clean_type.contains("Result<") {
109 ("Result<T,E>".to_string(), "Results".to_string())
110 } else if clean_type.contains("Mutex<") || clean_type.contains("RwLock<") {
111 ("Mutex/RwLock".to_string(), "Synchronization".to_string())
112 } else if clean_type.contains("Cell<") || clean_type.contains("RefCell<") {
113 (
114 "Cell/RefCell".to_string(),
115 "Interior Mutability".to_string(),
116 )
117 } else if clean_type.contains("Weak<") {
118 ("Weak<T>".to_string(), "Smart Pointers".to_string())
119 } else if clean_type.starts_with("std::")
120 || clean_type.starts_with("alloc::")
121 || clean_type.starts_with("core::")
122 {
123 let simplified = clean_type.split("::").last().unwrap_or(clean_type);
124 (simplified.to_string(), "Standard Library".to_string())
125 } else if clean_type.contains("::") {
126 let parts: Vec<&str> = clean_type.split("::").collect();
128 if parts.len() >= 2 {
129 let type_part = parts.last().unwrap_or(&clean_type);
131
132 let category = if parts
134 .iter()
135 .any(|&part| part.contains("error") || part.contains("Error"))
136 || type_part.ends_with("Error")
137 || type_part.contains("Err")
138 {
139 "Error Types"
140 } else if type_part.ends_with("Config") || type_part.ends_with("Settings") {
141 "Configuration"
142 } else if type_part.ends_with("Builder") || type_part.ends_with("Factory") {
143 "Builders"
144 } else if parts
145 .iter()
146 .any(|&part| part == "std" || part == "core" || part == "alloc")
147 {
148 "Standard Library"
149 } else if parts
150 .iter()
151 .any(|&part| part.contains("test") || part.contains("mock"))
152 {
153 "Test Types"
154 } else if parts.len() > 2 {
155 "Library Types"
157 } else {
158 "Custom Types"
159 };
160
161 (type_part.to_string(), category.to_string())
162 } else {
163 let category = if clean_type.ends_with("Error") || clean_type.contains("Err") {
165 "Error Types"
166 } else if clean_type.ends_with("Config") || clean_type.ends_with("Settings") {
167 "Configuration"
168 } else if clean_type.ends_with("Builder") || clean_type.ends_with("Factory") {
169 "Builders"
170 } else if clean_type.chars().next().is_some_and(|c| c.is_uppercase()) {
171 "Custom Types"
173 } else {
174 "Other Types"
176 };
177
178 (clean_type.to_string(), category.to_string())
179 }
180 } else {
181 if !clean_type.is_empty() {
183 (clean_type.to_string(), "Custom Types".to_string())
184 } else {
185 ("Unknown Type".to_string(), "Unknown".to_string())
186 }
187 }
188}
189
190pub fn extract_generic_type(type_name: &str, container: &str) -> String {
192 if let Some(start) = type_name.find(&format!("{container}<")) {
193 let start = start + container.len() + 1;
194 if let Some(end) = type_name[start..].rfind('>') {
195 let inner = &type_name[start..start + end];
196 return inner.split("::").last().unwrap_or(inner).to_string();
198 }
199 }
200 "?".to_string()
201}
202
203pub fn get_simple_type(type_name: &str) -> String {
205 if type_name.contains("String") {
206 "String".to_string()
207 } else if type_name.contains("Vec") {
208 "Vec".to_string()
209 } else if type_name.contains("Box") {
210 "Box".to_string()
211 } else if type_name.contains("Rc") {
212 "Rc".to_string()
213 } else if type_name.contains("Arc") {
214 "Arc".to_string()
215 } else if type_name.contains("HashMap") {
216 "HashMap".to_string()
217 } else {
218 type_name
219 .split("::")
220 .last()
221 .unwrap_or("Unknown")
222 .to_string()
223 }
224}
225
226pub fn get_category_color(category: &str) -> String {
228 match category {
229 "Collections" => "#3498db".to_string(), "Basic Types" => "#27ae60".to_string(), "Strings" => "#27ae60".to_string(), "Text" => "#27ae60".to_string(), "Smart Pointers" => "#e74c3c".to_string(), "Reference Counted" => "#f39c12".to_string(), "Thread-Safe Shared" => "#9b59b6".to_string(), "Primitives" => "#1abc9c".to_string(), "Arrays" => "#34495e".to_string(), "Tuples" => "#16a085".to_string(), "Optionals" => "#8e44ad".to_string(), "Results" => "#d35400".to_string(), "Standard Library" => "#2980b9".to_string(), "Custom Types" => "#c0392b".to_string(), "Synchronization" => "#e67e22".to_string(), "Interior Mutability" => "#95a5a6".to_string(), "Error Types" => "#e74c3c".to_string(), "Configuration" => "#3498db".to_string(), "Builders" => "#9b59b6".to_string(), "Runtime/System Allocation" => "#bdc3c7".to_string(), "Unknown" => "#bdc3c7".to_string(), _ => "#7f8c8d".to_string(), }
252}
253
254pub fn get_type_gradient_colors(type_name: &str) -> (&'static str, &'static str) {
256 match type_name {
257 "String" => ("#00BCD4", "#00ACC1"), "Vec" => ("#2196F3", "#1976D2"), "Box" => ("#F44336", "#D32F2F"), "HashMap" => ("#4CAF50", "#388E3C"), "Rc" => ("#FF9800", "#F57C00"), "Arc" => ("#9C27B0", "#7B1FA2"), _ => ("#607D8B", "#455A64"), }
265}
266
267pub fn get_type_color(type_name: &str) -> &'static str {
269 match type_name {
270 "String" => "#2ecc71",
271 "Vec" => "#3498db",
272 "Box" => "#e74c3c",
273 "HashMap" => "#f39c12",
274 "Rc" => "#9b59b6",
275 "Arc" => "#1abc9c",
276 _ => "#95a5a6",
277 }
278}
279
280#[derive(Debug, Clone)]
282pub struct TypeHierarchy {
283 pub major_category: String,
285 pub sub_category: String,
287 pub specific_type: String,
289 pub full_type: String,
291}
292
293pub fn get_type_category_hierarchy(type_name: &str) -> TypeHierarchy {
295 if type_name.is_empty() || type_name == "Unknown" {
297 return TypeHierarchy {
298 major_category: "Unknown".to_string(),
299 sub_category: "Unidentified".to_string(),
300 specific_type: "Unknown Type".to_string(),
301 full_type: type_name.to_string(),
302 };
303 }
304
305 if type_name.contains("HashMap") || type_name.contains("hash::map") {
307 let inner = extract_generic_params(type_name, "HashMap");
308 TypeHierarchy {
309 major_category: "Collections".to_string(),
310 sub_category: "Maps".to_string(),
311 specific_type: "HashMap".to_string(),
312 full_type: if inner.is_empty() {
313 "HashMap".to_string()
314 } else {
315 format!("HashMap<{inner}>")
316 },
317 }
318 } else if type_name.contains("BTreeMap") || type_name.contains("btree::map") {
319 let inner = extract_generic_params(type_name, "BTreeMap");
320 TypeHierarchy {
321 major_category: "Collections".to_string(),
322 sub_category: "Maps".to_string(),
323 specific_type: "BTreeMap".to_string(),
324 full_type: if inner.is_empty() {
325 "BTreeMap".to_string()
326 } else {
327 format!("BTreeMap<{inner}>")
328 },
329 }
330 } else if type_name.contains("HashSet") || type_name.contains("hash::set") {
331 let inner = extract_generic_params(type_name, "HashSet");
332 TypeHierarchy {
333 major_category: "Collections".to_string(),
334 sub_category: "Sets".to_string(),
335 specific_type: "HashSet".to_string(),
336 full_type: if inner.is_empty() {
337 "HashSet".to_string()
338 } else {
339 format!("HashSet<{inner}>")
340 },
341 }
342 } else if type_name.contains("Vec") && !type_name.contains("VecDeque") {
343 let inner = extract_generic_params(type_name, "Vec");
344 TypeHierarchy {
345 major_category: "Collections".to_string(),
346 sub_category: "Sequences".to_string(),
347 specific_type: "Vec".to_string(),
348 full_type: if inner.is_empty() {
349 "Vec".to_string()
350 } else {
351 format!("Vec<{inner}>")
352 },
353 }
354 } else if type_name.contains("VecDeque") {
355 let inner = extract_generic_params(type_name, "VecDeque");
356 TypeHierarchy {
357 major_category: "Collections".to_string(),
358 sub_category: "Sequences".to_string(),
359 specific_type: "VecDeque".to_string(),
360 full_type: if inner.is_empty() {
361 "VecDeque".to_string()
362 } else {
363 format!("VecDeque<{inner}>")
364 },
365 }
366 }
367 else if type_name.contains("String") && !type_name.contains("<") {
369 TypeHierarchy {
370 major_category: "Strings".to_string(),
371 sub_category: "Owned".to_string(),
372 specific_type: "String".to_string(),
373 full_type: "String".to_string(),
374 }
375 } else if type_name.contains("&str") || (type_name.contains("str") && type_name.contains("&")) {
376 TypeHierarchy {
377 major_category: "Strings".to_string(),
378 sub_category: "Borrowed".to_string(),
379 specific_type: "&str".to_string(),
380 full_type: "&str".to_string(),
381 }
382 }
383 else if type_name.contains("Box<") {
385 let inner = extract_generic_params(type_name, "Box");
386 TypeHierarchy {
387 major_category: "Smart Pointers".to_string(),
388 sub_category: "Owned".to_string(),
389 specific_type: "Box".to_string(),
390 full_type: if inner.is_empty() {
391 "Box".to_string()
392 } else {
393 format!("Box<{inner}>")
394 },
395 }
396 } else if type_name.contains("Rc<") {
397 let inner = extract_generic_params(type_name, "Rc");
398 TypeHierarchy {
399 major_category: "Smart Pointers".to_string(),
400 sub_category: "Reference Counted".to_string(),
401 specific_type: "Rc".to_string(),
402 full_type: if inner.is_empty() {
403 "Rc".to_string()
404 } else {
405 format!("Rc<{inner}>")
406 },
407 }
408 } else if type_name.contains("Arc<") {
409 let inner = extract_generic_params(type_name, "Arc");
410 TypeHierarchy {
411 major_category: "Smart Pointers".to_string(),
412 sub_category: "Thread-Safe Shared".to_string(),
413 specific_type: "Arc".to_string(),
414 full_type: if inner.is_empty() {
415 "Arc".to_string()
416 } else {
417 format!("Arc<{inner}>")
418 },
419 }
420 }
421 else if is_primitive_type(type_name) {
423 let clean_type = type_name.split("::").last().unwrap_or(type_name);
424 let sub_cat = if clean_type.contains("i") || clean_type.contains("u") {
425 "Integers"
426 } else if clean_type.contains("f") {
427 "Floats"
428 } else if clean_type == "bool" {
429 "Boolean"
430 } else {
431 "Other"
432 };
433 TypeHierarchy {
434 major_category: "Primitives".to_string(),
435 sub_category: sub_cat.to_string(),
436 specific_type: clean_type.to_string(),
437 full_type: clean_type.to_string(),
438 }
439 }
440 else {
442 let simplified = type_name.split("::").last().unwrap_or(type_name);
443 TypeHierarchy {
444 major_category: "Custom Types".to_string(),
445 sub_category: "User Defined".to_string(),
446 specific_type: simplified.to_string(),
447 full_type: simplified.to_string(),
448 }
449 }
450}
451
452pub fn extract_generic_params(type_name: &str, container: &str) -> String {
454 if let Some(start) = type_name.find(&format!("{container}<")) {
455 let start = start + container.len() + 1;
456 if let Some(end) = find_matching_bracket(type_name, start - 1) {
457 let inner = &type_name[start..end];
458 return inner.split("::").last().unwrap_or(inner).to_string();
460 }
461 }
462 String::new()
463}
464
465fn find_matching_bracket(s: &str, start: usize) -> Option<usize> {
467 let chars: Vec<char> = s.chars().collect();
468 if start >= chars.len() || chars[start] != '<' {
469 return None;
470 }
471
472 let mut depth = 1;
473 for (i, item) in chars.iter().enumerate().skip(start + 1) {
474 match item {
475 '<' => depth += 1,
476 '>' => {
477 depth -= 1;
478 if depth == 0 {
479 return Some(i);
480 }
481 }
482 _ => {}
483 }
484 }
485 None
486}
487
488pub fn is_primitive_type(type_name: &str) -> bool {
490 let clean_type = type_name.split("::").last().unwrap_or(type_name);
491 matches!(
492 clean_type,
493 "i8" | "i16"
494 | "i32"
495 | "i64"
496 | "i128"
497 | "isize"
498 | "u8"
499 | "u16"
500 | "u32"
501 | "u64"
502 | "u128"
503 | "usize"
504 | "f32"
505 | "f64"
506 | "bool"
507 | "char"
508 )
509}
510
511pub fn extract_array_info(type_name: &str) -> String {
513 if let Some(start) = type_name.find('[') {
514 if let Some(end) = type_name.find(']') {
515 return type_name[start..=end].to_string();
516 }
517 }
518 "Array".to_string()
519}
520
521pub fn extract_std_module(type_name: &str) -> String {
523 let parts: Vec<&str> = type_name.split("::").collect();
524 if parts.len() >= 2 {
525 match parts[1] {
526 "collections" => "Collections".to_string(),
527 "sync" => "Synchronization".to_string(),
528 "thread" => "Threading".to_string(),
529 "fs" => "File System".to_string(),
530 "net" => "Networking".to_string(),
531 "io" => "Input/Output".to_string(),
532 _ => "Other".to_string(),
533 }
534 } else {
535 "Other".to_string()
536 }
537}
538
539use std::sync::{
544 atomic::{AtomicBool, Ordering},
545 Arc,
546};
547use std::thread;
548use std::time::Duration;
549
550pub trait JoinHandleExt<T> {
552 fn join_timeout(self, timeout: Duration) -> Result<T, Box<dyn std::any::Any + Send + 'static>>;
554}
555
556impl<T: Send + 'static> JoinHandleExt<T> for thread::JoinHandle<T> {
557 fn join_timeout(self, timeout: Duration) -> Result<T, Box<dyn std::any::Any + Send + 'static>> {
558 if self.is_finished() {
560 return self.join().map_err(|e| Box::new(e) as _);
561 }
562
563 let completed = Arc::new(AtomicBool::new(false));
565 let completed_clone = completed.clone();
566
567 let handle = thread::spawn(move || {
569 let result = self.join();
570 completed_clone.store(true, Ordering::SeqCst);
571 result
572 });
573
574 let start = std::time::Instant::now();
576 while !completed.load(Ordering::SeqCst) && start.elapsed() < timeout {
577 thread::sleep(Duration::from_millis(10));
578 }
579
580 if completed.load(Ordering::SeqCst) {
581 match handle.join() {
583 Ok(result) => result.map_err(|e| Box::new(e) as _),
584 Err(_) => Err(Box::new("Watcher thread panicked") as _),
585 }
586 } else {
587 Err(Box::new("Thread join timed out") as _)
590 }
591 }
592}
593
594#[cfg(test)]
595mod tests {
596 use super::*;
597 use std::thread;
598 use std::time::Duration;
599
600 #[test]
601 fn test_current_timestamp_nanos() {
602 let timestamp1 = current_timestamp_nanos();
603 thread::sleep(Duration::from_millis(1));
604 let timestamp2 = current_timestamp_nanos();
605
606 assert!(timestamp2 > timestamp1);
607 assert!(timestamp1 > 0);
608 }
609
610 #[test]
611 fn test_format_bytes() {
612 assert_eq!(format_bytes(0), "0B");
613 assert_eq!(format_bytes(512), "512B");
614 assert_eq!(format_bytes(1024), "1.0KB");
615 assert_eq!(format_bytes(1536), "1.5KB");
616 assert_eq!(format_bytes(1024 * 1024), "1.0MB");
617 assert_eq!(format_bytes(1024 * 1024 + 512 * 1024), "1.5MB");
618 }
619
620 #[test]
621 fn test_simplify_type_name_basic_types() {
622 let (simplified, category) = simplify_type_name("String");
623 assert_eq!(simplified, "String");
624 assert_eq!(category, "Basic Types");
625
626 let (simplified, category) = simplify_type_name("&str");
627 assert_eq!(simplified, "&str");
628 assert_eq!(category, "Basic Types");
629
630 let (simplified, category) = simplify_type_name("i32");
631 assert_eq!(simplified, "i32");
632 assert_eq!(category, "Basic Types");
633
634 let (simplified, category) = simplify_type_name("bool");
635 assert_eq!(simplified, "bool");
636 assert_eq!(category, "Basic Types");
637 }
638
639 #[test]
640 fn test_simplify_type_name_collections() {
641 let (simplified, category) = simplify_type_name("Vec<i32>");
642 assert_eq!(simplified, "Vec<i32>");
643 assert_eq!(category, "Collections");
644
645 let (simplified, category) = simplify_type_name("HashMap<String, i32>");
647 assert_eq!(simplified, "String");
648 assert_eq!(category, "Basic Types");
649
650 let (simplified, category) = simplify_type_name("BTreeMap<String, i32>");
651 assert_eq!(simplified, "String");
652 assert_eq!(category, "Basic Types");
653
654 let (simplified, category) = simplify_type_name("HashSet<String>");
655 assert_eq!(simplified, "String");
656 assert_eq!(category, "Basic Types");
657 }
658
659 #[test]
660 fn test_simplify_type_name_smart_pointers() {
661 let (simplified, category) = simplify_type_name("Box<i32>");
662 assert_eq!(simplified, "Box<i32>");
663 assert_eq!(category, "Smart Pointers");
664
665 let (simplified, category) = simplify_type_name("Rc<String>");
667 assert_eq!(simplified, "String");
668 assert_eq!(category, "Basic Types");
669
670 let (simplified, category) = simplify_type_name("Arc<Mutex<i32>>");
672 assert_eq!(simplified, "Arc<Mutex<i32>>");
673 assert_eq!(category, "Smart Pointers");
674
675 let (simplified, category) = simplify_type_name("Box<HashMap<String, i32>>");
677 assert_eq!(simplified, "String");
678 assert_eq!(category, "Basic Types");
679 }
680
681 #[test]
682 fn test_simplify_type_name_special_cases() {
683 let (simplified, category) = simplify_type_name("");
684 assert_eq!(simplified, "Unknown Type");
685 assert_eq!(category, "Unknown");
686
687 let (simplified, category) = simplify_type_name("Unknown");
688 assert_eq!(simplified, "Unknown Type");
689 assert_eq!(category, "Unknown");
690
691 let (simplified, category) = simplify_type_name("Option<i32>");
693 assert_eq!(simplified, "Option<i32>");
694 assert_eq!(category, "Basic Types");
695
696 let (simplified, category) = simplify_type_name("Result<String, Error>");
698 assert_eq!(simplified, "String");
699 assert_eq!(category, "Basic Types");
700 }
701
702 #[test]
703 fn test_simplify_type_name_arrays_tuples() {
704 let (simplified, category) = simplify_type_name("[i32; 10]");
706 assert_eq!(simplified, "[i32; 10]");
707 assert_eq!(category, "Basic Types");
708
709 let (simplified, category) = simplify_type_name("(i32, String)");
711 assert_eq!(simplified, "String");
712 assert_eq!(category, "Basic Types");
713 }
714
715 #[test]
716 fn test_simplify_type_name_synchronization() {
717 let (simplified, category) = simplify_type_name("Mutex<i32>");
719 assert_eq!(simplified, "Mutex<i32>");
720 assert_eq!(category, "Basic Types");
721
722 let (simplified, category) = simplify_type_name("RwLock<String>");
724 assert_eq!(simplified, "String");
725 assert_eq!(category, "Basic Types");
726
727 let (simplified, category) = simplify_type_name("Cell<i32>");
728 assert_eq!(simplified, "Cell<i32>");
729 assert_eq!(category, "Basic Types");
730 }
731
732 #[test]
733 fn test_simplify_type_name_namespaced() {
734 let (simplified, category) = simplify_type_name("std::collections::HashMap");
736 assert_eq!(simplified, "HashMap<K,V>");
737 assert_eq!(category, "Collections");
738
739 let (simplified, category) = simplify_type_name("my_crate::MyStruct");
740 assert_eq!(simplified, "MyStruct");
741 assert_eq!(category, "Custom Types");
742
743 let (simplified, category) = simplify_type_name("my_crate::error::MyError");
744 assert_eq!(simplified, "MyError");
745 assert_eq!(category, "Error Types");
746
747 let (simplified, category) = simplify_type_name("my_crate::config::AppConfig");
748 assert_eq!(simplified, "AppConfig");
749 assert_eq!(category, "Configuration");
750 }
751
752 #[test]
753 fn test_extract_generic_type() {
754 assert_eq!(extract_generic_type("Vec<i32>", "Vec"), "i32");
755 assert_eq!(extract_generic_type("Box<String>", "Box"), "String");
756 assert_eq!(
757 extract_generic_type("HashMap<String, i32>", "HashMap"),
758 "String, i32"
759 );
760 assert_eq!(extract_generic_type("Vec", "Vec"), "?");
761 assert_eq!(
762 extract_generic_type("std::vec::Vec<std::string::String>", "Vec"),
763 "String"
764 );
765 }
766
767 #[test]
768 fn test_get_simple_type() {
769 assert_eq!(get_simple_type("std::string::String"), "String");
770 assert_eq!(get_simple_type("std::vec::Vec<i32>"), "Vec");
771 assert_eq!(get_simple_type("std::boxed::Box<String>"), "String");
773 assert_eq!(get_simple_type("std::rc::Rc<i32>"), "Rc");
774 assert_eq!(get_simple_type("std::sync::Arc<String>"), "String");
775 assert_eq!(get_simple_type("std::collections::HashMap<K,V>"), "HashMap");
776 assert_eq!(get_simple_type("my_crate::MyType"), "MyType");
777 assert_eq!(get_simple_type("UnknownType"), "UnknownType");
778 }
779
780 #[test]
781 fn test_get_category_color() {
782 assert_eq!(get_category_color("Collections"), "#3498db");
783 assert_eq!(get_category_color("Basic Types"), "#27ae60");
784 assert_eq!(get_category_color("Smart Pointers"), "#e74c3c");
785 assert_eq!(get_category_color("Synchronization"), "#e67e22");
786 assert_eq!(get_category_color("Unknown"), "#bdc3c7");
787 assert_eq!(get_category_color("NonExistentCategory"), "#7f8c8d");
788 }
789
790 #[test]
791 fn test_get_type_gradient_colors() {
792 let (start, end) = get_type_gradient_colors("String");
793 assert_eq!(start, "#00BCD4");
794 assert_eq!(end, "#00ACC1");
795
796 let (start, end) = get_type_gradient_colors("Vec");
797 assert_eq!(start, "#2196F3");
798 assert_eq!(end, "#1976D2");
799
800 let (start, end) = get_type_gradient_colors("UnknownType");
801 assert_eq!(start, "#607D8B");
802 assert_eq!(end, "#455A64");
803 }
804
805 #[test]
806 fn test_get_type_color() {
807 assert_eq!(get_type_color("String"), "#2ecc71");
808 assert_eq!(get_type_color("Vec"), "#3498db");
809 assert_eq!(get_type_color("Box"), "#e74c3c");
810 assert_eq!(get_type_color("HashMap"), "#f39c12");
811 assert_eq!(get_type_color("Rc"), "#9b59b6");
812 assert_eq!(get_type_color("Arc"), "#1abc9c");
813 assert_eq!(get_type_color("UnknownType"), "#95a5a6");
814 }
815
816 #[test]
817 fn test_get_type_category_hierarchy_collections() {
818 let hierarchy = get_type_category_hierarchy("HashMap<String, i32>");
819 assert_eq!(hierarchy.major_category, "Collections");
820 assert_eq!(hierarchy.sub_category, "Maps");
821 assert_eq!(hierarchy.specific_type, "HashMap");
822 assert_eq!(hierarchy.full_type, "HashMap<String, i32>");
823
824 let hierarchy = get_type_category_hierarchy("Vec<u8>");
825 assert_eq!(hierarchy.major_category, "Collections");
826 assert_eq!(hierarchy.sub_category, "Sequences");
827 assert_eq!(hierarchy.specific_type, "Vec");
828 assert_eq!(hierarchy.full_type, "Vec<u8>");
829
830 let hierarchy = get_type_category_hierarchy("HashSet<String>");
831 assert_eq!(hierarchy.major_category, "Collections");
832 assert_eq!(hierarchy.sub_category, "Sets");
833 assert_eq!(hierarchy.specific_type, "HashSet");
834 assert_eq!(hierarchy.full_type, "HashSet<String>");
835 }
836
837 #[test]
838 fn test_get_type_category_hierarchy_strings() {
839 let hierarchy = get_type_category_hierarchy("String");
840 assert_eq!(hierarchy.major_category, "Strings");
841 assert_eq!(hierarchy.sub_category, "Owned");
842 assert_eq!(hierarchy.specific_type, "String");
843 assert_eq!(hierarchy.full_type, "String");
844
845 let hierarchy = get_type_category_hierarchy("&str");
846 assert_eq!(hierarchy.major_category, "Strings");
847 assert_eq!(hierarchy.sub_category, "Borrowed");
848 assert_eq!(hierarchy.specific_type, "&str");
849 assert_eq!(hierarchy.full_type, "&str");
850 }
851
852 #[test]
853 fn test_get_type_category_hierarchy_smart_pointers() {
854 let hierarchy = get_type_category_hierarchy("Box<i32>");
855 assert_eq!(hierarchy.major_category, "Smart Pointers");
856 assert_eq!(hierarchy.sub_category, "Owned");
857 assert_eq!(hierarchy.specific_type, "Box");
858 assert_eq!(hierarchy.full_type, "Box<i32>");
859
860 let hierarchy = get_type_category_hierarchy("Rc<String>");
861 assert_eq!(hierarchy.major_category, "Smart Pointers");
862 assert_eq!(hierarchy.sub_category, "Reference Counted");
863 assert_eq!(hierarchy.specific_type, "Rc");
864 assert_eq!(hierarchy.full_type, "Rc<String>");
865
866 let hierarchy = get_type_category_hierarchy("Arc<Mutex<i32>>");
867 assert_eq!(hierarchy.major_category, "Smart Pointers");
868 assert_eq!(hierarchy.sub_category, "Thread-Safe Shared");
869 assert_eq!(hierarchy.specific_type, "Arc");
870 assert_eq!(hierarchy.full_type, "Arc<Mutex<i32>>");
871 }
872
873 #[test]
874 fn test_get_type_category_hierarchy_primitives() {
875 let hierarchy = get_type_category_hierarchy("i32");
876 assert_eq!(hierarchy.major_category, "Primitives");
877 assert_eq!(hierarchy.sub_category, "Integers");
878 assert_eq!(hierarchy.specific_type, "i32");
879 assert_eq!(hierarchy.full_type, "i32");
880
881 let hierarchy = get_type_category_hierarchy("f64");
882 assert_eq!(hierarchy.major_category, "Primitives");
883 assert_eq!(hierarchy.sub_category, "Floats");
884 assert_eq!(hierarchy.specific_type, "f64");
885 assert_eq!(hierarchy.full_type, "f64");
886
887 let hierarchy = get_type_category_hierarchy("bool");
888 assert_eq!(hierarchy.major_category, "Primitives");
889 assert_eq!(hierarchy.sub_category, "Boolean");
890 assert_eq!(hierarchy.specific_type, "bool");
891 assert_eq!(hierarchy.full_type, "bool");
892 }
893
894 #[test]
895 fn test_get_type_category_hierarchy_unknown() {
896 let hierarchy = get_type_category_hierarchy("");
897 assert_eq!(hierarchy.major_category, "Unknown");
898 assert_eq!(hierarchy.sub_category, "Unidentified");
899 assert_eq!(hierarchy.specific_type, "Unknown Type");
900
901 let hierarchy = get_type_category_hierarchy("Unknown");
902 assert_eq!(hierarchy.major_category, "Unknown");
903 assert_eq!(hierarchy.sub_category, "Unidentified");
904 assert_eq!(hierarchy.specific_type, "Unknown Type");
905 }
906
907 #[test]
908 fn test_extract_generic_params() {
909 assert_eq!(
910 extract_generic_params("HashMap<String, i32>", "HashMap"),
911 "String, i32"
912 );
913 assert_eq!(extract_generic_params("Vec<u8>", "Vec"), "u8");
914 assert_eq!(extract_generic_params("Box<String>", "Box"), "String");
915 assert_eq!(extract_generic_params("Vec", "Vec"), "");
916 assert_eq!(
917 extract_generic_params("std::vec::Vec<std::string::String>", "Vec"),
918 "String"
919 );
920 }
921
922 #[test]
923 fn test_find_matching_bracket() {
924 assert_eq!(find_matching_bracket("Vec<i32>", 3), Some(7));
925 assert_eq!(
926 find_matching_bracket("HashMap<String, Vec<i32>>", 7),
927 Some(24)
928 );
929 assert_eq!(find_matching_bracket("Vec<i32", 3), None);
930 assert_eq!(find_matching_bracket("Vec", 3), None);
931 }
932
933 #[test]
934 fn test_is_primitive_type() {
935 assert!(is_primitive_type("i32"));
936 assert!(is_primitive_type("u64"));
937 assert!(is_primitive_type("f32"));
938 assert!(is_primitive_type("bool"));
939 assert!(is_primitive_type("char"));
940 assert!(is_primitive_type("isize"));
941 assert!(is_primitive_type("usize"));
942
943 assert!(!is_primitive_type("String"));
944 assert!(!is_primitive_type("Vec<i32>"));
945 assert!(!is_primitive_type("CustomType"));
946
947 assert!(is_primitive_type("std::primitive::i32"));
949 assert!(!is_primitive_type("std::string::String"));
950 }
951
952 #[test]
953 fn test_extract_array_info() {
954 assert_eq!(extract_array_info("[i32; 10]"), "[i32; 10]");
955 assert_eq!(extract_array_info("[u8; 256]"), "[u8; 256]");
956 assert_eq!(extract_array_info("Vec<i32>"), "Array");
957 assert_eq!(extract_array_info("no_brackets"), "Array");
958 }
959
960 #[test]
961 fn test_extract_std_module() {
962 assert_eq!(
963 extract_std_module("std::collections::HashMap"),
964 "Collections"
965 );
966 assert_eq!(extract_std_module("std::sync::Mutex"), "Synchronization");
967 assert_eq!(extract_std_module("std::thread::JoinHandle"), "Threading");
968 assert_eq!(extract_std_module("std::fs::File"), "File System");
969 assert_eq!(extract_std_module("std::net::TcpStream"), "Networking");
970 assert_eq!(extract_std_module("std::io::BufReader"), "Input/Output");
971 assert_eq!(extract_std_module("std::unknown::Type"), "Other");
972 assert_eq!(extract_std_module("CustomType"), "Other");
973 }
974
975 #[test]
976 fn test_join_handle_ext_immediate_completion() {
977 let handle = thread::spawn(|| 42);
978
979 thread::sleep(Duration::from_millis(10));
981
982 let result = handle.join_timeout(Duration::from_millis(100));
983 assert!(result.is_ok());
984 assert_eq!(result.unwrap(), 42);
985 }
986
987 #[test]
988 fn test_join_handle_ext_timeout() {
989 let handle = thread::spawn(|| {
990 thread::sleep(Duration::from_millis(200));
991 42
992 });
993
994 let result = handle.join_timeout(Duration::from_millis(50));
995 assert!(result.is_err());
996 }
997
998 #[test]
999 fn test_join_handle_ext_within_timeout() {
1000 let handle = thread::spawn(|| {
1001 thread::sleep(Duration::from_millis(50));
1002 42
1003 });
1004
1005 let result = handle.join_timeout(Duration::from_millis(200));
1006 assert!(result.is_ok());
1007 assert_eq!(result.unwrap(), 42);
1008 }
1009
1010 #[test]
1011 fn test_type_hierarchy_custom_types() {
1012 let hierarchy = get_type_category_hierarchy("MyCustomType");
1013 assert_eq!(hierarchy.major_category, "Custom Types");
1014 assert_eq!(hierarchy.sub_category, "User Defined");
1015 assert_eq!(hierarchy.specific_type, "MyCustomType");
1016 assert_eq!(hierarchy.full_type, "MyCustomType");
1017 }
1018
1019 #[test]
1020 fn test_simplify_type_name_edge_cases() {
1021 let (simplified, category) = simplify_type_name(" String ");
1023 assert_eq!(simplified, "String");
1024 assert_eq!(category, "Basic Types");
1025
1026 let (simplified, category) = simplify_type_name("Box<Vec<HashMap<String, i32>>>");
1028 assert_eq!(simplified, "Vec<HashMap<String, i32>>>");
1029 assert_eq!(category, "Collections");
1030
1031 let (simplified, category) = simplify_type_name("Weak<String>");
1033 assert_eq!(simplified, "String");
1034 assert_eq!(category, "Basic Types");
1035 }
1036}