1use serde::{Deserialize, Serialize};
7use std::fmt;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11pub enum MemoryEventType {
12 Allocate,
14 Deallocate,
16 Reallocate,
18 Move,
20 Borrow,
22 Return,
24 Metadata,
26}
27
28impl fmt::Display for MemoryEventType {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 match self {
31 MemoryEventType::Allocate => write!(f, "Allocate"),
32 MemoryEventType::Deallocate => write!(f, "Deallocate"),
33 MemoryEventType::Reallocate => write!(f, "Reallocate"),
34 MemoryEventType::Move => write!(f, "Move"),
35 MemoryEventType::Borrow => write!(f, "Borrow"),
36 MemoryEventType::Return => write!(f, "Return"),
37 MemoryEventType::Metadata => write!(f, "Metadata"),
38 }
39 }
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct MemoryEvent {
48 pub timestamp: u64,
50 pub event_type: MemoryEventType,
52 pub ptr: usize,
54 pub size: usize,
56 pub old_size: Option<usize>,
58 pub thread_id: u64,
60 pub var_name: Option<String>,
62 pub type_name: Option<String>,
64 pub call_stack_hash: Option<u64>,
66 pub thread_name: Option<String>,
68 pub source_file: Option<String>,
70 pub source_line: Option<u32>,
72}
73
74impl MemoryEvent {
75 pub fn allocate(ptr: usize, size: usize, thread_id: u64) -> Self {
77 Self {
78 timestamp: Self::now(),
79 event_type: MemoryEventType::Allocate,
80 ptr,
81 size,
82 old_size: None,
83 thread_id,
84 var_name: None,
85 type_name: None,
86 call_stack_hash: None,
87 thread_name: None,
88 source_file: None,
89 source_line: None,
90 }
91 }
92
93 pub fn deallocate(ptr: usize, size: usize, thread_id: u64) -> Self {
95 Self {
96 timestamp: Self::now(),
97 event_type: MemoryEventType::Deallocate,
98 ptr,
99 size,
100 old_size: None,
101 thread_id,
102 var_name: None,
103 type_name: None,
104 call_stack_hash: None,
105 thread_name: None,
106 source_file: None,
107 source_line: None,
108 }
109 }
110
111 pub fn reallocate(ptr: usize, old_size: usize, new_size: usize, thread_id: u64) -> Self {
113 Self {
114 timestamp: Self::now(),
115 event_type: MemoryEventType::Reallocate,
116 ptr,
117 size: new_size,
118 old_size: Some(old_size),
119 thread_id,
120 var_name: None,
121 type_name: None,
122 call_stack_hash: None,
123 thread_name: None,
124 source_file: None,
125 source_line: None,
126 }
127 }
128
129 pub fn metadata(var_name: String, type_name: String, thread_id: u64, size: usize) -> Self {
131 Self {
132 timestamp: Self::now(),
133 event_type: MemoryEventType::Metadata,
134 ptr: 0, size,
136 old_size: None,
137 thread_id,
138 var_name: Some(var_name),
139 type_name: Some(type_name),
140 call_stack_hash: None,
141 thread_name: None,
142 source_file: None,
143 source_line: None,
144 }
145 }
146
147 pub fn now() -> u64 {
150 use std::time::{SystemTime, UNIX_EPOCH};
151 SystemTime::now()
152 .duration_since(UNIX_EPOCH)
153 .map(|d| d.as_nanos() as u64)
154 .unwrap_or_default()
155 }
156
157 pub fn with_var_name(mut self, name: String) -> Self {
159 self.var_name = Some(name);
160 self
161 }
162
163 pub fn with_type_name(mut self, name: String) -> Self {
165 self.type_name = Some(name);
166 self
167 }
168
169 pub fn with_source_file(mut self, file: String) -> Self {
171 self.source_file = Some(file);
172 self
173 }
174
175 pub fn with_source_line(mut self, line: u32) -> Self {
177 self.source_line = Some(line);
178 self
179 }
180
181 pub fn with_call_stack_hash(mut self, hash: u64) -> Self {
183 self.call_stack_hash = Some(hash);
184 self
185 }
186
187 pub fn with_thread_name(mut self, name: String) -> Self {
189 self.thread_name = Some(name);
190 self
191 }
192
193 pub fn is_allocation(&self) -> bool {
195 matches!(
196 self.event_type,
197 MemoryEventType::Allocate | MemoryEventType::Reallocate | MemoryEventType::Metadata
198 )
199 }
200
201 pub fn is_deallocation(&self) -> bool {
203 matches!(self.event_type, MemoryEventType::Deallocate)
204 }
205
206 pub fn is_move(&self) -> bool {
208 matches!(self.event_type, MemoryEventType::Move)
209 }
210
211 pub fn is_borrow(&self) -> bool {
213 matches!(self.event_type, MemoryEventType::Borrow)
214 }
215
216 pub fn is_return(&self) -> bool {
218 matches!(self.event_type, MemoryEventType::Return)
219 }
220}