memscope_rs/metadata/
registry.rs1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::sync::{Arc, Mutex};
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct VariableInfo {
13 pub var_name: String,
15 pub type_name: String,
17 pub timestamp: u64,
19 pub size: usize,
21 pub thread_id: usize,
23 pub memory_usage: u64,
25}
26
27#[derive(Debug)]
29pub struct VariableRegistry {
30 variables: Arc<Mutex<HashMap<usize, VariableInfo>>>,
32}
33
34impl VariableRegistry {
35 pub fn new() -> Self {
37 Self {
38 variables: Arc::new(Mutex::new(HashMap::new())),
39 }
40 }
41
42 pub fn register_variable(
44 &self,
45 address: usize,
46 var_name: String,
47 type_name: String,
48 size: usize,
49 ) {
50 let thread_id = self.hash_thread_id();
51 let timestamp = std::time::SystemTime::now()
52 .duration_since(std::time::UNIX_EPOCH)
53 .unwrap_or_default()
54 .as_nanos() as u64;
55
56 let var_info = VariableInfo {
57 var_name,
58 type_name,
59 timestamp,
60 size,
61 thread_id,
62 memory_usage: size as u64,
63 };
64
65 if let Ok(mut vars) = self.variables.lock() {
66 vars.insert(address, var_info);
67 }
68 }
69
70 pub fn get_variable_info(&self, address: usize) -> Option<VariableInfo> {
72 if let Ok(vars) = self.variables.lock() {
73 vars.get(&address).cloned()
74 } else {
75 None
76 }
77 }
78
79 pub fn get_all_variables(&self) -> Vec<(usize, VariableInfo)> {
81 if let Ok(vars) = self.variables.lock() {
82 vars.iter().map(|(k, v)| (*k, v.clone())).collect()
83 } else {
84 Vec::new()
85 }
86 }
87
88 pub fn clear(&self) {
90 if let Ok(mut vars) = self.variables.lock() {
91 vars.clear();
92 }
93 }
94
95 pub fn len(&self) -> usize {
97 if let Ok(vars) = self.variables.lock() {
98 vars.len()
99 } else {
100 0
101 }
102 }
103
104 pub fn is_empty(&self) -> bool {
106 self.len() == 0
107 }
108
109 fn hash_thread_id(&self) -> usize {
111 crate::utils::current_thread_id_u64() as usize
112 }
113}
114
115impl Default for VariableRegistry {
116 fn default() -> Self {
117 Self::new()
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 #[test]
126 fn test_variable_registry_creation() {
127 let registry = VariableRegistry::new();
128 assert!(registry.is_empty());
129 assert_eq!(registry.len(), 0);
130 }
131
132 #[test]
133 fn test_register_variable() {
134 let registry = VariableRegistry::new();
135 registry.register_variable(0x1000, "test_var".to_string(), "i32".to_string(), 4);
136 assert_eq!(registry.len(), 1);
137
138 let info = registry.get_variable_info(0x1000);
139 assert!(info.is_some());
140 let info = info.unwrap();
141 assert_eq!(info.var_name, "test_var");
142 assert_eq!(info.type_name, "i32");
143 assert_eq!(info.size, 4);
144 }
145
146 #[test]
147 fn test_get_all_variables() {
148 let registry = VariableRegistry::new();
149 registry.register_variable(0x1000, "var1".to_string(), "i32".to_string(), 4);
150 registry.register_variable(0x2000, "var2".to_string(), "String".to_string(), 24);
151
152 let all = registry.get_all_variables();
153 assert_eq!(all.len(), 2);
154 }
155
156 #[test]
157 fn test_clear() {
158 let registry = VariableRegistry::new();
159 registry.register_variable(0x1000, "test".to_string(), "i32".to_string(), 4);
160 assert_eq!(registry.len(), 1);
161
162 registry.clear();
163 assert!(registry.is_empty());
164 }
165}