use std::hash::{Hash, Hasher};
use std::thread::ThreadId;
use std::time::{SystemTime, UNIX_EPOCH};
pub fn current_timestamp_nanos() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_nanos() as u64
}
pub fn thread_id_to_u64(thread_id: ThreadId) -> u64 {
let mut hasher = std::collections::hash_map::DefaultHasher::new();
thread_id.hash(&mut hasher);
hasher.finish()
}
pub fn current_thread_id_u64() -> u64 {
thread_id_to_u64(std::thread::current().id())
}
pub fn format_bytes(bytes: usize) -> String {
if bytes < 1024 {
format!("{bytes}B")
} else if bytes < 1024 * 1024 {
format!("{:.1}KB", bytes as f64 / 1024.0)
} else if bytes < 1024 * 1024 * 1024 {
format!("{:.1}MB", bytes as f64 / (1024.0 * 1024.0))
} else if bytes < 1024 * 1024 * 1024 * 1024 {
format!("{:.1}GB", bytes as f64 / (1024.0 * 1024.0 * 1024.0))
} else if bytes < 1024 * 1024 * 1024 * 1024 * 1024 {
format!(
"{:.1}TB",
bytes as f64 / (1024.0 * 1024.0 * 1024.0 * 1024.0)
)
} else {
format!(
"{:.1}PB",
bytes as f64 / (1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0)
)
}
}
pub fn simplify_type_name(type_name: &str) -> (String, String) {
if type_name.is_empty() || type_name == "Unknown" {
return ("Unknown Type".to_string(), "Unknown".to_string());
}
let clean_type = type_name.trim();
if clean_type.contains("Vec<") || clean_type.contains("vec::Vec") {
let inner = extract_generic_type(clean_type, "Vec");
(format!("Vec<{inner}>"), "Collections".to_string())
} else if clean_type.contains("HashMap") || clean_type.contains("hash_map") {
("HashMap<K,V>".to_string(), "Collections".to_string())
} else if clean_type.contains("BTreeMap") || clean_type.contains("btree_map") {
("BTreeMap<K,V>".to_string(), "Collections".to_string())
} else if clean_type.contains("BTreeSet") || clean_type.contains("btree_set") {
("BTreeSet<T>".to_string(), "Collections".to_string())
} else if clean_type.contains("HashSet") || clean_type.contains("hash_set") {
("HashSet<T>".to_string(), "Collections".to_string())
} else if clean_type.contains("VecDeque") || clean_type.contains("vec_deque") {
("VecDeque<T>".to_string(), "Collections".to_string())
} else if clean_type.contains("Box<") || clean_type.contains("boxed::Box") {
let inner = extract_generic_type(clean_type, "Box");
if inner.contains("String") || inner.contains("string::String") {
("String".to_string(), "Basic Types".to_string())
} else if inner.contains("HashMap") || inner.contains("hash_map") {
("HashMap<K,V>".to_string(), "Collections".to_string())
} else if inner.contains("BTreeMap") || inner.contains("btree_map") {
("BTreeMap<K,V>".to_string(), "Collections".to_string())
} else if inner.contains("BTreeSet") || inner.contains("btree_set") {
("BTreeSet<T>".to_string(), "Collections".to_string())
} else if inner.contains("HashSet") || inner.contains("hash_set") {
("HashSet<T>".to_string(), "Collections".to_string())
} else if inner.contains("VecDeque") || inner.contains("vec_deque") {
("VecDeque<T>".to_string(), "Collections".to_string())
} else if inner.contains("Vec") || inner.contains("vec::Vec") {
let vec_inner = extract_generic_type(&inner, "Vec");
(format!("Vec<{vec_inner}>"), "Collections".to_string())
} else {
(format!("Box<{inner}>"), "Smart Pointers".to_string())
}
} else if clean_type.contains("Rc<") || clean_type.contains("rc::Rc") {
let inner = extract_generic_type(clean_type, "Rc");
if inner.contains("String") || inner.contains("string::String") {
("String".to_string(), "Basic Types".to_string())
} else {
(format!("Rc<{inner}>"), "Smart Pointers".to_string())
}
} else if clean_type.contains("Arc<") || clean_type.contains("sync::Arc") {
let inner = extract_generic_type(clean_type, "Arc");
if inner.contains("String") || inner.contains("string::String") {
("String".to_string(), "Basic Types".to_string())
} else {
(format!("Arc<{inner}>"), "Smart Pointers".to_string())
}
} else if clean_type.contains("String") || clean_type.contains("string::String") {
("String".to_string(), "Basic Types".to_string())
} else if clean_type.contains("LinkedList") {
("LinkedList<T>".to_string(), "Collections".to_string())
} else if clean_type.contains("&str") || clean_type == "str" {
("&str".to_string(), "Basic Types".to_string())
} else if clean_type.contains("CString") || clean_type.contains("CStr") {
("CString".to_string(), "Basic Types".to_string())
} else if clean_type.contains("OsString") || clean_type.contains("OsStr") {
("OsString".to_string(), "Basic Types".to_string())
} else if clean_type.contains("PathBuf") || clean_type.contains("Path") {
("PathBuf".to_string(), "Basic Types".to_string())
} else if clean_type.contains("Option<") {
("Option<T>".to_string(), "Optionals".to_string())
} else if clean_type.contains("Result<") {
("Result<T,E>".to_string(), "Results".to_string())
} else if clean_type.matches("i32").count() > 0
|| clean_type.matches("u32").count() > 0
|| clean_type.matches("i64").count() > 0
|| clean_type.matches("u64").count() > 0
|| clean_type.matches("f64").count() > 0
|| clean_type.matches("f32").count() > 0
|| clean_type.matches("i8").count() > 0
|| clean_type.matches("u8").count() > 0
|| clean_type.matches("i16").count() > 0
|| clean_type.matches("u16").count() > 0
|| clean_type.matches("isize").count() > 0
|| clean_type.matches("usize").count() > 0
|| clean_type.matches("bool").count() > 0
|| clean_type.matches("char").count() > 0
{
let primitive = clean_type.split("::").last().unwrap_or(clean_type);
(primitive.to_string(), "Basic Types".to_string())
} else if clean_type.contains("[") && clean_type.contains("]") {
("Array".to_string(), "Arrays".to_string())
} else if clean_type.starts_with("(") && clean_type.ends_with(")") {
("Tuple".to_string(), "Tuples".to_string())
} else if clean_type.contains("Mutex<") || clean_type.contains("RwLock<") {
("Mutex/RwLock".to_string(), "Synchronization".to_string())
} else if clean_type.contains("Cell<") || clean_type.contains("RefCell<") {
(
"Cell/RefCell".to_string(),
"Interior Mutability".to_string(),
)
} else if clean_type.contains("Weak<") {
("Weak<T>".to_string(), "Smart Pointers".to_string())
} else if clean_type.starts_with("std::")
|| clean_type.starts_with("alloc::")
|| clean_type.starts_with("core::")
{
let simplified = clean_type.split("::").last().unwrap_or(clean_type);
(simplified.to_string(), "Standard Library".to_string())
} else if clean_type.contains("::") {
let parts: Vec<&str> = clean_type.split("::").collect();
if parts.len() >= 2 {
let type_part = parts.last().unwrap_or(&clean_type);
let category = if parts
.iter()
.any(|&part| part.contains("error") || part.contains("Error"))
|| type_part.ends_with("Error")
|| type_part.contains("Err")
{
"Error Types"
} else if type_part.ends_with("Config") || type_part.ends_with("Settings") {
"Configuration"
} else if type_part.ends_with("Builder") || type_part.ends_with("Factory") {
"Builders"
} else if parts
.iter()
.any(|&part| part == "std" || part == "core" || part == "alloc")
{
"Standard Library"
} else if parts
.iter()
.any(|&part| part.contains("test") || part.contains("mock"))
{
"Test Types"
} else if parts.len() > 2 {
"Library Types"
} else {
"Custom Types"
};
(type_part.to_string(), category.to_string())
} else {
let category = if clean_type.ends_with("Error") || clean_type.contains("Err") {
"Error Types"
} else if clean_type.ends_with("Config") || clean_type.ends_with("Settings") {
"Configuration"
} else if clean_type.ends_with("Builder") || clean_type.ends_with("Factory") {
"Builders"
} else if clean_type.chars().next().is_some_and(|c| c.is_uppercase()) {
"Custom Types"
} else {
"Other Types"
};
(clean_type.to_string(), category.to_string())
}
} else {
if !clean_type.is_empty() {
(clean_type.to_string(), "Custom Types".to_string())
} else {
("Unknown Type".to_string(), "Unknown".to_string())
}
}
}
pub fn extract_generic_type(type_name: &str, container: &str) -> String {
if let Some(start) = type_name.find(&format!("{container}<")) {
let content_start = start + container.len() + 1;
let content = &type_name[content_start..];
let mut depth = 1;
let mut end = 0;
for (i, c) in content.char_indices() {
match c {
'<' => depth += 1,
'>' => {
depth -= 1;
if depth == 0 {
end = i;
break;
}
}
_ => {}
}
}
if end > 0 {
let inner = &content[..end];
return inner.split("::").last().unwrap_or(inner).to_string();
}
}
"?".to_string()
}
pub fn get_simple_type(type_name: &str) -> String {
if type_name.contains("String") {
"String".to_string()
} else if type_name.contains("Vec") {
"Vec".to_string()
} else if type_name.contains("Box") {
"Box".to_string()
} else if type_name.contains("Rc") {
"Rc".to_string()
} else if type_name.contains("Arc") {
"Arc".to_string()
} else if type_name.contains("HashMap") {
"HashMap".to_string()
} else {
type_name
.split("::")
.last()
.unwrap_or("Unknown")
.to_string()
}
}
pub fn get_category_color(category: &str) -> String {
match category {
"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(), }
}
pub fn get_type_gradient_colors(type_name: &str) -> (&'static str, &'static str) {
match type_name {
"String" => ("#00BCD4", "#00ACC1"), "Vec" => ("#2196F3", "#1976D2"), "Box" => ("#F44336", "#D32F2F"), "HashMap" => ("#4CAF50", "#388E3C"), "Rc" => ("#FF9800", "#F57C00"), "Arc" => ("#9C27B0", "#7B1FA2"), _ => ("#607D8B", "#455A64"), }
}
pub fn get_type_color(type_name: &str) -> &'static str {
match type_name {
"String" => "#2ecc71",
"Vec" => "#3498db",
"Box" => "#e74c3c",
"HashMap" => "#f39c12",
"Rc" => "#9b59b6",
"Arc" => "#1abc9c",
_ => "#95a5a6",
}
}
#[derive(Debug, Clone)]
pub struct TypeHierarchy {
pub major_category: String,
pub sub_category: String,
pub specific_type: String,
pub full_type: String,
}
pub fn get_type_category_hierarchy(type_name: &str) -> TypeHierarchy {
if type_name.is_empty() || type_name == "Unknown" {
return TypeHierarchy {
major_category: "Unknown".to_string(),
sub_category: "Unidentified".to_string(),
specific_type: "Unknown Type".to_string(),
full_type: type_name.to_string(),
};
}
if type_name.contains("HashMap") || type_name.contains("hash::map") {
let inner = extract_generic_params(type_name, "HashMap");
TypeHierarchy {
major_category: "Collections".to_string(),
sub_category: "Maps".to_string(),
specific_type: "HashMap".to_string(),
full_type: if inner.is_empty() {
"HashMap".to_string()
} else {
format!("HashMap<{inner}>")
},
}
} else if type_name.contains("BTreeMap") || type_name.contains("btree::map") {
let inner = extract_generic_params(type_name, "BTreeMap");
TypeHierarchy {
major_category: "Collections".to_string(),
sub_category: "Maps".to_string(),
specific_type: "BTreeMap".to_string(),
full_type: if inner.is_empty() {
"BTreeMap".to_string()
} else {
format!("BTreeMap<{inner}>")
},
}
} else if type_name.contains("HashSet") || type_name.contains("hash::set") {
let inner = extract_generic_params(type_name, "HashSet");
TypeHierarchy {
major_category: "Collections".to_string(),
sub_category: "Sets".to_string(),
specific_type: "HashSet".to_string(),
full_type: if inner.is_empty() {
"HashSet".to_string()
} else {
format!("HashSet<{inner}>")
},
}
} else if type_name.contains("Vec") && !type_name.contains("VecDeque") {
let inner = extract_generic_params(type_name, "Vec");
TypeHierarchy {
major_category: "Collections".to_string(),
sub_category: "Sequences".to_string(),
specific_type: "Vec".to_string(),
full_type: if inner.is_empty() {
"Vec".to_string()
} else {
format!("Vec<{inner}>")
},
}
} else if type_name.contains("VecDeque") {
let inner = extract_generic_params(type_name, "VecDeque");
TypeHierarchy {
major_category: "Collections".to_string(),
sub_category: "Sequences".to_string(),
specific_type: "VecDeque".to_string(),
full_type: if inner.is_empty() {
"VecDeque".to_string()
} else {
format!("VecDeque<{inner}>")
},
}
}
else if type_name.contains("String") && !type_name.contains("<") {
TypeHierarchy {
major_category: "Strings".to_string(),
sub_category: "Owned".to_string(),
specific_type: "String".to_string(),
full_type: "String".to_string(),
}
} else if type_name.contains("&str") || (type_name.contains("str") && type_name.contains("&")) {
TypeHierarchy {
major_category: "Strings".to_string(),
sub_category: "Borrowed".to_string(),
specific_type: "&str".to_string(),
full_type: "&str".to_string(),
}
}
else if type_name.contains("Box<") {
let inner = extract_generic_params(type_name, "Box");
TypeHierarchy {
major_category: "Smart Pointers".to_string(),
sub_category: "Owned".to_string(),
specific_type: "Box".to_string(),
full_type: if inner.is_empty() {
"Box".to_string()
} else {
format!("Box<{inner}>")
},
}
} else if type_name.contains("Rc<") {
let inner = extract_generic_params(type_name, "Rc");
TypeHierarchy {
major_category: "Smart Pointers".to_string(),
sub_category: "Reference Counted".to_string(),
specific_type: "Rc".to_string(),
full_type: if inner.is_empty() {
"Rc".to_string()
} else {
format!("Rc<{inner}>")
},
}
} else if type_name.contains("Arc<") {
let inner = extract_generic_params(type_name, "Arc");
TypeHierarchy {
major_category: "Smart Pointers".to_string(),
sub_category: "Thread-Safe Shared".to_string(),
specific_type: "Arc".to_string(),
full_type: if inner.is_empty() {
"Arc".to_string()
} else {
format!("Arc<{inner}>")
},
}
}
else if is_primitive_type(type_name) {
let clean_type = type_name.split("::").last().unwrap_or(type_name);
let sub_cat = if clean_type.contains("i") || clean_type.contains("u") {
"Integers"
} else if clean_type.contains("f") {
"Floats"
} else if clean_type == "bool" {
"Boolean"
} else {
"Other"
};
TypeHierarchy {
major_category: "Primitives".to_string(),
sub_category: sub_cat.to_string(),
specific_type: clean_type.to_string(),
full_type: clean_type.to_string(),
}
}
else {
let simplified = type_name.split("::").last().unwrap_or(type_name);
TypeHierarchy {
major_category: "Custom Types".to_string(),
sub_category: "User Defined".to_string(),
specific_type: simplified.to_string(),
full_type: simplified.to_string(),
}
}
}
pub fn extract_generic_params(type_name: &str, container: &str) -> String {
if let Some(start) = type_name.find(&format!("{container}<")) {
let start = start + container.len() + 1;
if let Some(end) = find_matching_bracket(type_name, start - 1) {
let inner = &type_name[start..end];
return inner.split("::").last().unwrap_or(inner).to_string();
}
}
String::new()
}
fn find_matching_bracket(s: &str, start: usize) -> Option<usize> {
let chars: Vec<char> = s.chars().collect();
if start >= chars.len() || chars[start] != '<' {
return None;
}
let mut depth = 1;
for (i, item) in chars.iter().enumerate().skip(start + 1) {
match item {
'<' => depth += 1,
'>' => {
depth -= 1;
if depth == 0 {
return Some(i);
}
}
_ => {}
}
}
None
}
pub fn is_primitive_type(type_name: &str) -> bool {
let clean_type = type_name.split("::").last().unwrap_or(type_name);
matches!(
clean_type,
"i8" | "i16"
| "i32"
| "i64"
| "i128"
| "isize"
| "u8"
| "u16"
| "u32"
| "u64"
| "u128"
| "usize"
| "f32"
| "f64"
| "bool"
| "char"
)
}
pub fn extract_array_info(type_name: &str) -> String {
if let Some(start) = type_name.find('[') {
if let Some(end) = type_name.find(']') {
if end > start {
return type_name[start..=end].to_string();
}
}
}
"Array".to_string()
}
pub fn extract_std_module(type_name: &str) -> String {
let parts: Vec<&str> = type_name.split("::").collect();
if parts.len() >= 2 {
match parts[1] {
"collections" => "Collections".to_string(),
"sync" => "Synchronization".to_string(),
"thread" => "Threading".to_string(),
"fs" => "File System".to_string(),
"net" => "Networking".to_string(),
"io" => "Input/Output".to_string(),
_ => "Other".to_string(),
}
} else {
"Other".to_string()
}
}
use std::thread;
use std::time::Duration;
pub trait JoinHandleExt<T> {
fn join_timeout(self, timeout: Duration) -> Result<T, Box<dyn std::any::Any + Send + 'static>>;
}
impl<T: Send + 'static> JoinHandleExt<T> for thread::JoinHandle<T> {
fn join_timeout(self, timeout: Duration) -> Result<T, Box<dyn std::any::Any + Send + 'static>> {
if self.is_finished() {
return self.join().map_err(|e| Box::new(e) as _);
}
let (tx, rx) = std::sync::mpsc::channel();
thread::spawn(move || {
let result = self.join();
let _ = tx.send(result);
});
match rx.recv_timeout(timeout) {
Ok(result) => result.map_err(|e| Box::new(e) as _),
Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
Err(Box::new("Thread join timed out") as _)
}
Err(std::sync::mpsc::RecvTimeoutError::Disconnected) => {
Err(Box::new("Thread communication error") as _)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::thread;
use std::time::Duration;
#[test]
fn test_current_timestamp_nanos() {
let timestamp1 = current_timestamp_nanos();
thread::sleep(Duration::from_millis(1));
let timestamp2 = current_timestamp_nanos();
assert!(timestamp2 > timestamp1);
assert!(timestamp1 > 0);
}
#[test]
fn test_format_bytes() {
assert_eq!(format_bytes(0), "0B");
assert_eq!(format_bytes(512), "512B");
assert_eq!(format_bytes(1024), "1.0KB");
assert_eq!(format_bytes(1536), "1.5KB");
assert_eq!(format_bytes(1024 * 1024), "1.0MB");
assert_eq!(format_bytes(1024 * 1024 + 512 * 1024), "1.5MB");
assert_eq!(format_bytes(1024 * 1024 * 1024), "1.0GB");
assert_eq!(format_bytes(1024 * 1024 * 1024 * 2), "2.0GB");
assert_eq!(format_bytes(1024usize.pow(4)), "1.0TB");
assert_eq!(format_bytes(1024usize.pow(4) * 5), "5.0TB");
assert_eq!(format_bytes(1024usize.pow(5)), "1.0PB");
assert_eq!(format_bytes(1024usize.pow(5) * 10), "10.0PB");
}
#[test]
fn test_simplify_type_name_basic_types() {
let (simplified, category) = simplify_type_name("String");
assert_eq!(simplified, "String");
assert_eq!(category, "Basic Types");
let (simplified, category) = simplify_type_name("&str");
assert_eq!(simplified, "&str");
assert_eq!(category, "Basic Types");
let (simplified, category) = simplify_type_name("i32");
assert_eq!(simplified, "i32");
assert_eq!(category, "Basic Types");
let (simplified, category) = simplify_type_name("bool");
assert_eq!(simplified, "bool");
assert_eq!(category, "Basic Types");
}
#[test]
fn test_simplify_type_name_collections() {
let (simplified, category) = simplify_type_name("Vec<i32>");
assert_eq!(simplified, "Vec<i32>");
assert_eq!(category, "Collections");
let (simplified, category) = simplify_type_name("HashMap<String, i32>");
assert_eq!(simplified, "HashMap<K,V>");
assert_eq!(category, "Collections");
let (simplified, category) = simplify_type_name("BTreeMap<String, i32>");
assert_eq!(simplified, "BTreeMap<K,V>");
assert_eq!(category, "Collections");
let (simplified, category) = simplify_type_name("HashSet<String>");
assert_eq!(simplified, "HashSet<T>");
assert_eq!(category, "Collections");
}
#[test]
fn test_simplify_type_name_smart_pointers() {
let (simplified, category) = simplify_type_name("Box<i32>");
assert_eq!(simplified, "Box<i32>");
assert_eq!(category, "Smart Pointers");
let (simplified, category) = simplify_type_name("Rc<String>");
assert_eq!(simplified, "String");
assert_eq!(category, "Basic Types");
let (simplified, category) = simplify_type_name("Arc<Mutex<i32>>");
assert_eq!(simplified, "Arc<Mutex<i32>>");
assert_eq!(category, "Smart Pointers");
let (simplified, category) = simplify_type_name("Box<HashMap<String, i32>>");
assert_eq!(simplified, "HashMap<K,V>");
assert_eq!(category, "Collections");
}
#[test]
fn test_simplify_type_name_special_cases() {
let (simplified, category) = simplify_type_name("");
assert_eq!(simplified, "Unknown Type");
assert_eq!(category, "Unknown");
let (simplified, category) = simplify_type_name("Unknown");
assert_eq!(simplified, "Unknown Type");
assert_eq!(category, "Unknown");
let (simplified, category) = simplify_type_name("Option<i32>");
assert_eq!(simplified, "Option<T>");
assert_eq!(category, "Optionals");
let (simplified, category) = simplify_type_name("Result<String, Error>");
assert_eq!(simplified, "String");
assert_eq!(category, "Basic Types");
}
#[test]
fn test_simplify_type_name_arrays_tuples() {
let (simplified, category) = simplify_type_name("[i32; 10]");
assert_eq!(simplified, "[i32; 10]");
assert_eq!(category, "Basic Types");
let (simplified, category) = simplify_type_name("(i32, String)");
assert_eq!(simplified, "String");
assert_eq!(category, "Basic Types");
}
#[test]
fn test_simplify_type_name_synchronization() {
let (simplified, category) = simplify_type_name("Mutex<i32>");
assert_eq!(simplified, "Mutex<i32>");
assert_eq!(category, "Basic Types");
let (simplified, category) = simplify_type_name("RwLock<String>");
assert_eq!(simplified, "String");
assert_eq!(category, "Basic Types");
let (simplified, category) = simplify_type_name("Cell<i32>");
assert_eq!(simplified, "Cell<i32>");
assert_eq!(category, "Basic Types");
}
#[test]
fn test_simplify_type_name_namespaced() {
let (simplified, category) = simplify_type_name("std::collections::HashMap");
assert_eq!(simplified, "HashMap<K,V>");
assert_eq!(category, "Collections");
let (simplified, category) = simplify_type_name("my_crate::MyStruct");
assert_eq!(simplified, "MyStruct");
assert_eq!(category, "Custom Types");
let (simplified, category) = simplify_type_name("my_crate::error::MyError");
assert_eq!(simplified, "MyError");
assert_eq!(category, "Error Types");
let (simplified, category) = simplify_type_name("my_crate::config::AppConfig");
assert_eq!(simplified, "AppConfig");
assert_eq!(category, "Configuration");
}
#[test]
fn test_extract_generic_type() {
assert_eq!(extract_generic_type("Vec<i32>", "Vec"), "i32");
assert_eq!(extract_generic_type("Box<String>", "Box"), "String");
assert_eq!(
extract_generic_type("HashMap<String, i32>", "HashMap"),
"String, i32"
);
assert_eq!(extract_generic_type("Vec", "Vec"), "?");
assert_eq!(
extract_generic_type("std::vec::Vec<std::string::String>", "Vec"),
"String"
);
}
#[test]
fn test_get_simple_type() {
assert_eq!(get_simple_type("std::string::String"), "String");
assert_eq!(get_simple_type("std::vec::Vec<i32>"), "Vec");
assert_eq!(get_simple_type("std::boxed::Box<String>"), "String");
assert_eq!(get_simple_type("std::rc::Rc<i32>"), "Rc");
assert_eq!(get_simple_type("std::sync::Arc<String>"), "String");
assert_eq!(get_simple_type("std::collections::HashMap<K,V>"), "HashMap");
assert_eq!(get_simple_type("my_crate::MyType"), "MyType");
assert_eq!(get_simple_type("UnknownType"), "UnknownType");
}
#[test]
fn test_get_category_color() {
assert_eq!(get_category_color("Collections"), "#3498db");
assert_eq!(get_category_color("Basic Types"), "#27ae60");
assert_eq!(get_category_color("Smart Pointers"), "#e74c3c");
assert_eq!(get_category_color("Synchronization"), "#e67e22");
assert_eq!(get_category_color("Unknown"), "#bdc3c7");
assert_eq!(get_category_color("NonExistentCategory"), "#7f8c8d");
}
#[test]
fn test_get_type_gradient_colors() {
let (start, end) = get_type_gradient_colors("String");
assert_eq!(start, "#00BCD4");
assert_eq!(end, "#00ACC1");
let (start, end) = get_type_gradient_colors("Vec");
assert_eq!(start, "#2196F3");
assert_eq!(end, "#1976D2");
let (start, end) = get_type_gradient_colors("UnknownType");
assert_eq!(start, "#607D8B");
assert_eq!(end, "#455A64");
}
#[test]
fn test_get_type_color() {
assert_eq!(get_type_color("String"), "#2ecc71");
assert_eq!(get_type_color("Vec"), "#3498db");
assert_eq!(get_type_color("Box"), "#e74c3c");
assert_eq!(get_type_color("HashMap"), "#f39c12");
assert_eq!(get_type_color("Rc"), "#9b59b6");
assert_eq!(get_type_color("Arc"), "#1abc9c");
assert_eq!(get_type_color("UnknownType"), "#95a5a6");
}
#[test]
fn test_get_type_category_hierarchy_collections() {
let hierarchy = get_type_category_hierarchy("HashMap<String, i32>");
assert_eq!(hierarchy.major_category, "Collections");
assert_eq!(hierarchy.sub_category, "Maps");
assert_eq!(hierarchy.specific_type, "HashMap");
assert_eq!(hierarchy.full_type, "HashMap<String, i32>");
let hierarchy = get_type_category_hierarchy("Vec<u8>");
assert_eq!(hierarchy.major_category, "Collections");
assert_eq!(hierarchy.sub_category, "Sequences");
assert_eq!(hierarchy.specific_type, "Vec");
assert_eq!(hierarchy.full_type, "Vec<u8>");
let hierarchy = get_type_category_hierarchy("HashSet<String>");
assert_eq!(hierarchy.major_category, "Collections");
assert_eq!(hierarchy.sub_category, "Sets");
assert_eq!(hierarchy.specific_type, "HashSet");
assert_eq!(hierarchy.full_type, "HashSet<String>");
}
#[test]
fn test_get_type_category_hierarchy_strings() {
let hierarchy = get_type_category_hierarchy("String");
assert_eq!(hierarchy.major_category, "Strings");
assert_eq!(hierarchy.sub_category, "Owned");
assert_eq!(hierarchy.specific_type, "String");
assert_eq!(hierarchy.full_type, "String");
let hierarchy = get_type_category_hierarchy("&str");
assert_eq!(hierarchy.major_category, "Strings");
assert_eq!(hierarchy.sub_category, "Borrowed");
assert_eq!(hierarchy.specific_type, "&str");
assert_eq!(hierarchy.full_type, "&str");
}
#[test]
fn test_get_type_category_hierarchy_smart_pointers() {
let hierarchy = get_type_category_hierarchy("Box<i32>");
assert_eq!(hierarchy.major_category, "Smart Pointers");
assert_eq!(hierarchy.sub_category, "Owned");
assert_eq!(hierarchy.specific_type, "Box");
assert_eq!(hierarchy.full_type, "Box<i32>");
let hierarchy = get_type_category_hierarchy("Rc<String>");
assert_eq!(hierarchy.major_category, "Smart Pointers");
assert_eq!(hierarchy.sub_category, "Reference Counted");
assert_eq!(hierarchy.specific_type, "Rc");
assert_eq!(hierarchy.full_type, "Rc<String>");
let hierarchy = get_type_category_hierarchy("Arc<Mutex<i32>>");
assert_eq!(hierarchy.major_category, "Smart Pointers");
assert_eq!(hierarchy.sub_category, "Thread-Safe Shared");
assert_eq!(hierarchy.specific_type, "Arc");
assert_eq!(hierarchy.full_type, "Arc<Mutex<i32>>");
}
#[test]
fn test_get_type_category_hierarchy_primitives() {
let hierarchy = get_type_category_hierarchy("i32");
assert_eq!(hierarchy.major_category, "Primitives");
assert_eq!(hierarchy.sub_category, "Integers");
assert_eq!(hierarchy.specific_type, "i32");
assert_eq!(hierarchy.full_type, "i32");
let hierarchy = get_type_category_hierarchy("f64");
assert_eq!(hierarchy.major_category, "Primitives");
assert_eq!(hierarchy.sub_category, "Floats");
assert_eq!(hierarchy.specific_type, "f64");
assert_eq!(hierarchy.full_type, "f64");
let hierarchy = get_type_category_hierarchy("bool");
assert_eq!(hierarchy.major_category, "Primitives");
assert_eq!(hierarchy.sub_category, "Boolean");
assert_eq!(hierarchy.specific_type, "bool");
assert_eq!(hierarchy.full_type, "bool");
}
#[test]
fn test_get_type_category_hierarchy_unknown() {
let hierarchy = get_type_category_hierarchy("");
assert_eq!(hierarchy.major_category, "Unknown");
assert_eq!(hierarchy.sub_category, "Unidentified");
assert_eq!(hierarchy.specific_type, "Unknown Type");
let hierarchy = get_type_category_hierarchy("Unknown");
assert_eq!(hierarchy.major_category, "Unknown");
assert_eq!(hierarchy.sub_category, "Unidentified");
assert_eq!(hierarchy.specific_type, "Unknown Type");
}
#[test]
fn test_extract_generic_params() {
assert_eq!(
extract_generic_params("HashMap<String, i32>", "HashMap"),
"String, i32"
);
assert_eq!(extract_generic_params("Vec<u8>", "Vec"), "u8");
assert_eq!(extract_generic_params("Box<String>", "Box"), "String");
assert_eq!(extract_generic_params("Vec", "Vec"), "");
assert_eq!(
extract_generic_params("std::vec::Vec<std::string::String>", "Vec"),
"String"
);
}
#[test]
fn test_find_matching_bracket() {
assert_eq!(find_matching_bracket("Vec<i32>", 3), Some(7));
assert_eq!(
find_matching_bracket("HashMap<String, Vec<i32>>", 7),
Some(24)
);
assert_eq!(find_matching_bracket("Vec<i32", 3), None);
assert_eq!(find_matching_bracket("Vec", 3), None);
}
#[test]
fn test_is_primitive_type() {
assert!(is_primitive_type("i32"));
assert!(is_primitive_type("u64"));
assert!(is_primitive_type("f32"));
assert!(is_primitive_type("bool"));
assert!(is_primitive_type("char"));
assert!(is_primitive_type("isize"));
assert!(is_primitive_type("usize"));
assert!(!is_primitive_type("String"));
assert!(!is_primitive_type("Vec<i32>"));
assert!(!is_primitive_type("CustomType"));
assert!(is_primitive_type("std::primitive::i32"));
assert!(!is_primitive_type("std::string::String"));
}
#[test]
fn test_extract_array_info() {
assert_eq!(extract_array_info("[i32; 10]"), "[i32; 10]");
assert_eq!(extract_array_info("[u8; 256]"), "[u8; 256]");
assert_eq!(extract_array_info("Vec<i32>"), "Array");
assert_eq!(extract_array_info("no_brackets"), "Array");
}
#[test]
fn test_extract_std_module() {
assert_eq!(
extract_std_module("std::collections::HashMap"),
"Collections"
);
assert_eq!(extract_std_module("std::sync::Mutex"), "Synchronization");
assert_eq!(extract_std_module("std::thread::JoinHandle"), "Threading");
assert_eq!(extract_std_module("std::fs::File"), "File System");
assert_eq!(extract_std_module("std::net::TcpStream"), "Networking");
assert_eq!(extract_std_module("std::io::BufReader"), "Input/Output");
assert_eq!(extract_std_module("std::unknown::Type"), "Other");
assert_eq!(extract_std_module("CustomType"), "Other");
}
#[test]
fn test_join_handle_ext_immediate_completion() {
let handle = thread::spawn(|| 42);
thread::sleep(Duration::from_millis(10));
let result = handle.join_timeout(Duration::from_millis(100));
assert!(result.is_ok());
assert_eq!(result.unwrap(), 42);
}
#[test]
fn test_join_handle_ext_timeout() {
let handle = thread::spawn(|| {
thread::sleep(Duration::from_millis(200));
42
});
let result = handle.join_timeout(Duration::from_millis(50));
assert!(result.is_err());
}
#[test]
fn test_join_handle_ext_within_timeout() {
let handle = thread::spawn(|| {
thread::sleep(Duration::from_millis(50));
42
});
let result = handle.join_timeout(Duration::from_millis(200));
assert!(result.is_ok());
assert_eq!(result.unwrap(), 42);
}
#[test]
fn test_type_hierarchy_custom_types() {
let hierarchy = get_type_category_hierarchy("MyCustomType");
assert_eq!(hierarchy.major_category, "Custom Types");
assert_eq!(hierarchy.sub_category, "User Defined");
assert_eq!(hierarchy.specific_type, "MyCustomType");
assert_eq!(hierarchy.full_type, "MyCustomType");
}
#[test]
fn test_simplify_type_name_edge_cases() {
let (simplified, category) = simplify_type_name(" String ");
assert_eq!(simplified, "String");
assert_eq!(category, "Basic Types");
let (simplified, category) = simplify_type_name("Box<Vec<HashMap<String, i32>>>");
assert_eq!(simplified, "Vec<HashMap<String, i32>>");
assert_eq!(category, "Collections");
let (simplified, category) = simplify_type_name("Weak<String>");
assert_eq!(simplified, "String");
assert_eq!(category, "Basic Types");
}
}