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